]>
Commit | Line | Data |
---|---|---|
539ed16e | 1 | // $Id$ |
2 | ||
3 | /************************************************************************** | |
4 | * This file is property of and copyright by the ALICE HLT Project * | |
5 | * ALICE Experiment at CERN, All rights reserved. * | |
6 | * * | |
7 | * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no> * | |
8 | * for The ALICE HLT Project. * | |
9 | * * | |
10 | * Permission to use, copy, modify and distribute this software and its * | |
11 | * documentation strictly for non-commercial purposes is hereby granted * | |
12 | * without fee, provided that the above copyright notice appears in all * | |
13 | * copies and that both the copyright notice and this permission notice * | |
14 | * appear in the supporting documentation. The authors make no claims * | |
15 | * about the suitability of this software for any purpose. It is * | |
16 | * provided "as is" without express or implied warranty. * | |
17 | **************************************************************************/ | |
18 | ||
19 | /** @file testAliHLTDataBuffer.C | |
20 | @author Matthias Richter | |
21 | @date | |
22 | @brief Test program for the AliHLTDataBuffer class | |
23 | */ | |
24 | ||
25 | #ifndef __CINT__ | |
26 | #include "TDatime.h" | |
27 | #include "TRandom.h" | |
28 | #include "AliHLTDataTypes.h" | |
29 | #include "algorithm" | |
30 | #include "TObjArray.h" | |
31 | #include "TObjString.h" | |
32 | #include "TString.h" | |
33 | #include "AliHLTDAQ.h" | |
34 | #include <cstdio> | |
35 | #include <cstring> | |
36 | #include <iostream> | |
37 | #include <cerrno> | |
38 | #include "AliHLTDataBuffer.h" | |
39 | #endif | |
40 | ||
41 | using namespace std; | |
42 | ||
43 | int gVerbosity=0; | |
21288ff1 | 44 | const int gPagesize=1024*1024; |
539ed16e | 45 | |
48dedf26 | 46 | template<class T> |
47 | int testLoop(vector<T>& descriptions, int nofLevels, int nofCycles); | |
539ed16e | 48 | int GetRandom(int min, int max); |
49 | ||
48dedf26 | 50 | class AliHLTRandomBuffer { |
51 | public: | |
52 | AliHLTRandomBuffer(): fpBuffer(NULL), fBufferSize(0), fInstances() {} | |
53 | AliHLTRandomBuffer(AliHLTUInt32_t size): fpBuffer(NULL), fBufferSize(0), fInstances() {Init(size);} | |
54 | AliHLTRandomBuffer(const AliHLTRandomBuffer&): fpBuffer(NULL), fBufferSize(0), fInstances() {} | |
55 | AliHLTRandomBuffer& operator=(const AliHLTRandomBuffer& src) {if (&src!=this) {fpBuffer=NULL; fBufferSize=0;} return *this;} | |
56 | ~AliHLTRandomBuffer() {} | |
57 | ||
58 | int Init(AliHLTUInt32_t size) { | |
59 | if (fpBuffer) return -EINPROGRESS; | |
60 | ||
61 | fpBuffer=new AliHLTUInt8_t[size]; | |
62 | if (!fpBuffer) return -ENOMEM; | |
63 | fBufferSize=size; | |
64 | ||
65 | int words=size/sizeof(AliHLTUInt32_t); | |
66 | AliHLTUInt32_t* pTgt=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer); | |
67 | for (int i=0; i<words; i++, pTgt++) *pTgt=GetRandom(0, 0x7fffffff); | |
68 | return 0; | |
69 | } | |
70 | ||
71 | struct AliHLTRandomBufferInstance { | |
72 | int fId; | |
73 | AliHLTUInt32_t fOffset; | |
74 | AliHLTUInt32_t fSize; | |
75 | }; | |
76 | ||
77 | int CreateInstance(AliHLTUInt32_t size) { | |
78 | if (size>fBufferSize) return -ENOSPC; | |
79 | ||
80 | AliHLTRandomBufferInstance instance; | |
81 | instance.fId=fInstances.size()>0?fInstances.back().fId+1:0; | |
82 | instance.fOffset=GetRandom(0, fBufferSize-size); | |
83 | instance.fSize=size; | |
84 | fInstances.push_back(instance); | |
85 | return instance.fId; | |
86 | } | |
87 | ||
88 | int ReleaseInstance(int id) { | |
89 | for (vector<AliHLTRandomBufferInstance>::iterator instance=fInstances.begin(); | |
90 | instance!=fInstances.end(); instance++) { | |
91 | if (instance->fId==id) { | |
92 | fInstances.erase(instance); | |
93 | return 0; | |
94 | } | |
95 | } | |
96 | return -ENOENT; | |
97 | } | |
98 | ||
99 | const AliHLTUInt8_t* GetBuffer(int id) { | |
100 | for (vector<AliHLTRandomBufferInstance>::iterator instance=fInstances.begin(); | |
101 | instance!=fInstances.end(); instance++) { | |
102 | if (instance->fId==id) { | |
103 | ||
104 | return fpBuffer+instance->fOffset; | |
105 | } | |
106 | } | |
107 | return NULL; | |
108 | } | |
109 | ||
110 | bool CompareBuffer(const AliHLTUInt8_t* buffer, AliHLTUInt32_t size, int id) { | |
111 | if (!buffer) return false; | |
112 | for (vector<AliHLTRandomBufferInstance>::iterator instance=fInstances.begin(); | |
113 | instance!=fInstances.end(); instance++) { | |
114 | if (instance->fId==id) { | |
115 | if (instance->fSize!=size) { | |
116 | cout << "CompareBuffer ("<< instance->fId << "): size missmatch: " << size << ", expected " << instance->fSize << endl; | |
117 | return false; | |
118 | } | |
119 | return memcmp(buffer, fpBuffer+instance->fOffset, size)==0; | |
120 | } | |
121 | } | |
122 | return false; | |
123 | } | |
124 | ||
125 | void Print(const char* /*option*/) { | |
126 | cout << "AliHLTRandomBufferInstance " << this << ": buffer " << (void*)fpBuffer << " size " << fBufferSize << endl; | |
127 | if (!fpBuffer) return; | |
128 | ||
129 | int words=fBufferSize/sizeof(AliHLTUInt32_t); | |
130 | int lines=words/4; | |
131 | AliHLTUInt32_t* pTgt=reinterpret_cast<AliHLTUInt32_t*>(fpBuffer); | |
132 | for (int line=0; line<lines; line++) { | |
133 | for (int i=0; i<4; i++, pTgt++) cout << hex << " 0x" << (*pTgt); | |
134 | cout << endl; | |
135 | } | |
136 | if (words*sizeof(AliHLTUInt32_t)!=fBufferSize) cout << "some remaining bytes left due to alignment" << endl; | |
137 | } | |
138 | ||
139 | private: | |
140 | AliHLTUInt8_t* fpBuffer; | |
141 | AliHLTUInt32_t fBufferSize; | |
142 | ||
143 | vector<AliHLTRandomBufferInstance> fInstances; | |
144 | }; | |
145 | ||
146 | AliHLTRandomBuffer gData(2*gPagesize); | |
147 | ||
148 | /** | |
149 | * @class AliHLTTestRawPage | |
150 | * Helper class for testing cycles of memory allocation, buffer modification, and | |
151 | * cleanup with the AliHLTRawPage within the function testLoop. | |
152 | */ | |
153 | class AliHLTTestRawPage { | |
154 | public: | |
155 | AliHLTTestRawPage() : fBuffer(NULL) {} | |
156 | AliHLTTestRawPage(const AliHLTTestRawPage& src) : fBuffer(src.fBuffer) {} | |
157 | AliHLTTestRawPage& operator=(const AliHLTTestRawPage& src) { | |
158 | fBuffer=src.fBuffer; | |
159 | return *this; | |
160 | } | |
161 | ||
162 | ~AliHLTTestRawPage() {} | |
163 | ||
164 | bool IsAllocated() {return fBuffer!=NULL;} | |
165 | bool Alloc(AliHLTUInt32_t size, int verbosity) { | |
166 | fBuffer=AliHLTDataBuffer::AliHLTRawPage::GlobalAlloc(size); | |
167 | if (!fBuffer) return false; | |
168 | if (verbosity>1) { | |
169 | printf("allocated raw buffer %p from page %p\n", fBuffer, AliHLTDataBuffer::AliHLTRawPage::FindPage(fBuffer)); | |
170 | fBuffer->Print("min"); | |
171 | } | |
172 | return true; | |
173 | } | |
174 | ||
175 | AliHLTUInt8_t* GetPointer() {return fBuffer?fBuffer->GetPointer():NULL;} | |
176 | ||
177 | bool SetSize(AliHLTUInt32_t size, int verbosity) { | |
178 | AliHLTDataBuffer::AliHLTRawPage* rawpage=AliHLTDataBuffer::AliHLTRawPage::FindPage(fBuffer); | |
179 | if (rawpage) { | |
180 | if (rawpage->SetSize(fBuffer, size)==0) { | |
181 | if (verbosity>1) { | |
182 | cout << "setting size for raw buffer " << fBuffer << " of page " << rawpage << endl; | |
183 | fBuffer->Print("min"); | |
184 | } | |
185 | return true; | |
186 | } else { | |
187 | cerr << "failed to set size for raw buffer " << fBuffer << endl; | |
188 | } | |
189 | } else { | |
190 | cerr << "can not find raw page for buffer " << fBuffer << endl; | |
191 | } | |
192 | ||
193 | return false; | |
194 | } | |
195 | ||
196 | bool Free(int verbosity) { | |
197 | AliHLTDataBuffer::AliHLTRawPage* rawpage=AliHLTDataBuffer::AliHLTRawPage::FindPage(fBuffer); | |
198 | if (rawpage) { | |
199 | if (rawpage->Free(fBuffer)==0) { | |
200 | if (verbosity>1) cout << "released raw buffer " << fBuffer << " from page " << rawpage << endl; | |
201 | fBuffer=NULL; | |
202 | return true; | |
203 | } else { | |
204 | cerr << "failed to release raw buffer " << fBuffer << endl; | |
205 | } | |
206 | } else { | |
207 | cerr << "can not find raw page for buffer " << fBuffer << endl; | |
208 | } | |
209 | return false; | |
210 | } | |
211 | ||
212 | AliHLTUInt32_t GetTotalSize() {return fBuffer?fBuffer->GetTotalSize():0;} | |
213 | ||
214 | bool GlobalClean(int verbosity) { | |
215 | int nofPages=0; | |
216 | for (AliHLTDataBuffer::AliHLTRawPage* rawpage=AliHLTDataBuffer::AliHLTRawPage::NextPage(NULL); | |
217 | rawpage!=NULL; | |
218 | rawpage=AliHLTDataBuffer::AliHLTRawPage::NextPage(rawpage)) { | |
219 | nofPages++; | |
220 | } | |
221 | if (verbosity>=1) { | |
222 | cout << "total number of pages: " << nofPages << endl; | |
223 | } | |
224 | ||
225 | AliHLTDataBuffer::AliHLTRawPage::GlobalClean(); | |
226 | return true; | |
227 | } | |
228 | ||
229 | void Print(const char* options) { | |
230 | if (strcmp(options, "pages")==0 || | |
231 | strcmp(options, "global")==0) { | |
232 | AliHLTDataBuffer::AliHLTRawPage::NextPage(NULL)->Print("global"); | |
233 | return; | |
234 | } | |
235 | } | |
236 | private: | |
237 | AliHLTDataBuffer::AliHLTRawBuffer* fBuffer; | |
238 | }; | |
239 | ||
240 | struct testRawPageDescription { | |
241 | testRawPageDescription() : fLevel(0), fBufferSize(0), fDataId(-1), fTest() {}; | |
539ed16e | 242 | int fLevel; |
243 | AliHLTUInt32_t fBufferSize; | |
48dedf26 | 244 | int fDataId; |
245 | AliHLTTestRawPage fTest; | |
539ed16e | 246 | }; |
247 | ||
48dedf26 | 248 | class AliHLTDataBufferWrapper : public AliHLTDataBuffer { |
249 | public: | |
250 | int ResetDataBuffer() { | |
251 | return AliHLTDataBuffer::ResetDataBuffer(); | |
252 | } | |
253 | }; | |
254 | ||
255 | /** | |
256 | * @class AliHLTTestDataBuffer | |
257 | * Helper class for testing cycles of memory allocation, buffer modification, and | |
258 | * cleanup with the AliHLTDataBuffer within the function testLoop. | |
259 | */ | |
260 | class AliHLTTestDataBuffer { | |
261 | public: | |
262 | AliHLTTestDataBuffer() : fInstance(NULL), fBuffer(NULL), fSize(0) {} | |
263 | AliHLTTestDataBuffer(const AliHLTTestDataBuffer&) : fInstance(NULL), fBuffer(NULL), fSize(0) {} ; | |
264 | AliHLTTestDataBuffer& operator=(const AliHLTTestDataBuffer&) { | |
265 | fInstance=NULL; | |
266 | fBuffer=NULL; | |
267 | fSize=0; | |
268 | return *this; | |
269 | } | |
270 | ||
271 | bool IsAllocated() {return fBuffer!=NULL;} | |
272 | bool Alloc(AliHLTUInt32_t size, int verbosity) { | |
273 | if (!fInstance) { | |
274 | fInstance=new AliHLTDataBufferWrapper; | |
275 | if (!fInstance) return false; | |
276 | fInstance->SetGlobalLoggingLevel(verbosity>1?kHLTLogAll:(AliHLTComponentLogSeverity)0x7c); | |
277 | } | |
278 | ||
279 | fBuffer=fInstance->GetTargetBuffer(size); | |
280 | if (!fBuffer) return false; | |
281 | fSize=size; | |
282 | if (verbosity>1) { | |
283 | cout << "allocated data buffer" << this << endl; | |
284 | } | |
285 | return true; | |
286 | } | |
287 | ||
288 | AliHLTUInt8_t* GetPointer() {return fBuffer;} | |
289 | ||
290 | bool SetSize(AliHLTUInt32_t size, int verbosity) { | |
291 | if (!fInstance) return false; | |
21288ff1 | 292 | AliHLTComponentBlockData bd; |
293 | AliHLTComponent::FillBlockData(bd); | |
294 | bd.fSize=size; | |
295 | bd.fOffset=0; | |
296 | fInstance->SetSegments(fBuffer, &bd, 1); | |
297 | ||
48dedf26 | 298 | if (verbosity>1) { |
299 | cout << "setting size for data buffer " << this << ": allocated size " << fSize << " -> " << size << endl; | |
300 | } | |
301 | fSize=size; | |
302 | return true; | |
303 | } | |
539ed16e | 304 | |
48dedf26 | 305 | bool Free(int verbosity) { |
306 | if (!fInstance) return false; | |
307 | fSize=0; | |
308 | if (fInstance->ResetDataBuffer()==0) { | |
309 | if (verbosity>1) cout << "released data buffer " << this << endl; | |
310 | fBuffer=NULL; | |
311 | return true; | |
312 | } else { | |
313 | cerr << "failed to release raw buffer " << fBuffer << endl; | |
314 | } | |
315 | ||
316 | return false; | |
317 | } | |
318 | ||
319 | AliHLTUInt32_t GetTotalSize() {return fSize;} | |
320 | ||
321 | bool GlobalClean(int verbosity) { | |
322 | if (!fInstance) return false; | |
323 | if (verbosity>=1) { | |
324 | fInstance->PrintStatistics(); | |
325 | } | |
326 | delete fInstance; | |
21288ff1 | 327 | |
328 | AliHLTDataBuffer::AliHLTRawPage::GlobalClean(); | |
48dedf26 | 329 | return true; |
330 | } | |
331 | ||
332 | void Print(const char* options) { | |
333 | if (strcmp(options, "pages")==0 || | |
334 | strcmp(options, "global")==0) { | |
335 | fInstance->PrintStatistics(); | |
21288ff1 | 336 | AliHLTDataBuffer::AliHLTRawPage::NextPage(NULL)->Print("global"); |
337 | return; | |
48dedf26 | 338 | } |
339 | } | |
340 | private: | |
341 | AliHLTDataBufferWrapper* fInstance; | |
342 | AliHLTUInt8_t* fBuffer; | |
343 | AliHLTUInt32_t fSize; | |
344 | }; | |
345 | ||
346 | struct testDataBufferDescription { | |
347 | testDataBufferDescription() : fLevel(0), fBufferSize(0), fDataId(-1), fTest() {}; | |
348 | int fLevel; | |
349 | AliHLTUInt32_t fBufferSize; | |
350 | int fDataId; | |
351 | AliHLTTestDataBuffer fTest; | |
352 | }; | |
353 | ||
354 | template<class T,class S> | |
355 | int CopyDescription(vector<T>& target, vector<S>& source) | |
356 | { | |
357 | target.clear(); | |
358 | for (unsigned i=0; i<source.size(); i++) { | |
359 | T clone; | |
360 | clone.fLevel=source[i].fLevel; | |
361 | clone.fBufferSize=source[i].fBufferSize; | |
362 | clone.fDataId=source[i].fDataId; | |
363 | target.push_back(clone); | |
364 | } | |
539ed16e | 365 | return 0; |
366 | } | |
367 | ||
48dedf26 | 368 | template<class T> |
369 | int fillTestSample(int levels, int processes, vector<T>& descriptions) | |
539ed16e | 370 | { |
371 | int availableProcesses=processes; | |
372 | for (int level=0; level<levels; level++) { | |
373 | int levelprocesses=GetRandom(availableProcesses/2, availableProcesses-(levels-level)); | |
374 | for (int process=0; process<levelprocesses; process++) { | |
48dedf26 | 375 | T desc; |
539ed16e | 376 | desc.fLevel=level; |
21288ff1 | 377 | desc.fBufferSize=GetRandom(1024, 2*gPagesize); |
48dedf26 | 378 | //desc.fTest.Clear(); |
539ed16e | 379 | descriptions.push_back(desc); |
380 | } | |
381 | availableProcesses-=levelprocesses; | |
382 | } | |
383 | return 0; | |
384 | } | |
385 | ||
48dedf26 | 386 | template<class T> |
387 | int allocateBuffers(vector<T>& descriptions, | |
539ed16e | 388 | int level=-1) |
389 | { | |
390 | for (unsigned i=0; i<descriptions.size(); i++) { | |
391 | if (level>=0 && descriptions[i].fLevel<level) continue; | |
392 | if (level>=0 && descriptions[i].fLevel>level) break; | |
48dedf26 | 393 | if (descriptions[i].fTest.IsAllocated()) { |
539ed16e | 394 | cerr << "warning: buffer already allocated" << endl; |
395 | continue; | |
396 | } | |
397 | ||
48dedf26 | 398 | if (descriptions[i].fTest.Alloc(GetRandom(descriptions[i].fBufferSize/2, descriptions[i].fBufferSize), gVerbosity)) { |
539ed16e | 399 | } |
48dedf26 | 400 | |
401 | if (!descriptions[i].fTest.IsAllocated()) { | |
539ed16e | 402 | cerr << "failed to allocate buffer for process " << i << endl; |
403 | return -EFAULT; | |
404 | } | |
405 | } | |
406 | return 0; | |
407 | } | |
408 | ||
48dedf26 | 409 | template<class T> |
410 | int setBufferSizes(vector<T>& descriptions, | |
539ed16e | 411 | int level=-1) |
412 | { | |
413 | // set buffer size for all processes of the specified level | |
414 | // buffer size is chosen randomly between 0 and the allocated size | |
415 | vector<unsigned> positions; | |
416 | for (unsigned i=0; i<descriptions.size(); i++) { | |
48dedf26 | 417 | if (!descriptions[i].fTest.IsAllocated()) continue; |
539ed16e | 418 | if (level>=0 && descriptions[i].fLevel<level) continue; |
419 | if (level>=0 && descriptions[i].fLevel>level) break; | |
420 | positions.push_back(i); | |
421 | } | |
422 | ||
423 | random_shuffle(positions.begin(), positions.end()); | |
424 | for (vector<unsigned>::iterator position=positions.begin(); | |
425 | position!=positions.end(); position++) { | |
48dedf26 | 426 | AliHLTUInt32_t datasize=GetRandom(0, descriptions[*position].fTest.GetTotalSize()); |
427 | descriptions[*position].fDataId=gData.CreateInstance(datasize); | |
428 | const AliHLTUInt8_t* pSrc=gData.GetBuffer(descriptions[*position].fDataId); | |
429 | if (!pSrc) { | |
430 | cout << "error creating data instance" << endl; | |
431 | return -1; | |
539ed16e | 432 | } |
48dedf26 | 433 | AliHLTUInt8_t* pTgt=descriptions[*position].fTest.GetPointer(); |
434 | if (!pTgt) { | |
435 | cout << "error target buffer" << endl; | |
436 | return -1; | |
437 | } | |
438 | memcpy(pTgt, pSrc, datasize); | |
439 | if (descriptions[*position].fTest.SetSize(datasize, gVerbosity)) { | |
440 | if (gVerbosity>1) cout << " process " << *position << " level " << descriptions[*position].fLevel << endl; | |
441 | } else { | |
442 | cout << "failed allocation for process " << *position << " level " << descriptions[*position].fLevel << endl; | |
443 | return -1; | |
539ed16e | 444 | } |
445 | } | |
446 | return 0; | |
447 | } | |
48dedf26 | 448 | |
449 | template<class T> | |
450 | int releaseBuffers(vector<T>& descriptions, | |
539ed16e | 451 | int level=-1) |
452 | { | |
453 | // find the processes to be releases according to the specified level | |
454 | // shuffle the processes and then release in this random order | |
455 | vector<unsigned> positions; | |
456 | for (unsigned i=0; i<descriptions.size(); i++) { | |
48dedf26 | 457 | if (!descriptions[i].fTest.IsAllocated()) continue; |
539ed16e | 458 | if (level>=0 && descriptions[i].fLevel<level) continue; |
459 | if (level>=0 && descriptions[i].fLevel>level) break; | |
460 | positions.push_back(i); | |
461 | } | |
462 | ||
463 | random_shuffle(positions.begin(), positions.end()); | |
464 | for (vector<unsigned>::iterator position=positions.begin(); | |
465 | position!=positions.end(); position++) { | |
48dedf26 | 466 | if (!gData.CompareBuffer(descriptions[*position].fTest.GetPointer(), descriptions[*position].fTest.GetTotalSize(), descriptions[*position].fDataId)) { |
467 | cout << "data comparison failed for process " << *position << " level " << descriptions[*position].fLevel << endl; | |
468 | return -1; | |
539ed16e | 469 | } |
48dedf26 | 470 | gData.ReleaseInstance(descriptions[*position].fDataId); |
471 | if (descriptions[*position].fTest.Free(gVerbosity)) { | |
472 | if (gVerbosity>1) cout << " process " << *position << " level " << descriptions[*position].fLevel << endl; | |
473 | } else { | |
474 | cout << "failed deallocation for process " << *position << " level " << descriptions[*position].fLevel << endl; | |
475 | return -1; | |
539ed16e | 476 | } |
477 | } | |
478 | return 0; | |
479 | } | |
48dedf26 | 480 | |
481 | template<class T> | |
482 | int testLoop(vector<T>& descriptions, int nofLevels, int nofCycles) | |
539ed16e | 483 | { |
48dedf26 | 484 | // test the buffer allocation and deallocation from the AliHLTRawPage |
485 | // | |
486 | // build a hierarchy of processes like in a real chain, in the first | |
487 | // implementation it is only a linear tree | |
488 | // the number of levels and processes are randomly chosen from a certain range | |
489 | // processes are distributed among the levels such that there is a decreasing | |
490 | // number of processes but at least one process | |
491 | // | |
492 | // The test cycle consists of the following steps | |
493 | // - loop over all levels | |
494 | // - allocation of a maximum buffer for every process of the current level | |
495 | // - set the buffer size to be used for every process of the current level | |
496 | // - release buffers of the previous level | |
497 | // - check all created raw pages and throw error, if | |
498 | // - not all buffers released | |
499 | // - not all memory released | |
500 | // - still fragmented | |
501 | // | |
539ed16e | 502 | int iResult=0; |
539ed16e | 503 | |
48dedf26 | 504 | AliHLTDataBuffer::AliHLTRawPage* rawpage=NULL; |
505 | for (int cycle=0; cycle<nofCycles && iResult>=0; cycle++) { | |
539ed16e | 506 | for (int level=0; level<=nofLevels; level++) { |
507 | // allocate buffers | |
508 | if (level<nofLevels) { | |
48dedf26 | 509 | if ((iResult=allocateBuffers(descriptions, level))<0) { |
539ed16e | 510 | cerr << "failed to allocate buffers" << endl; |
511 | return iResult; | |
512 | } | |
513 | } | |
514 | ||
48dedf26 | 515 | if (gVerbosity>1) { |
516 | cout << "finished allocation - level " << level << " "; | |
517 | descriptions[0].fTest.Print("pages"); | |
539ed16e | 518 | } |
519 | ||
520 | if (level<nofLevels) { | |
48dedf26 | 521 | if ((iResult=setBufferSizes(descriptions, level))<0) { |
539ed16e | 522 | cerr << "failed setting buffers" << endl; |
523 | return iResult; | |
524 | } | |
525 | } | |
526 | ||
48dedf26 | 527 | if (gVerbosity>1) { |
528 | cout << "finished size modification - level " << level << " "; | |
529 | descriptions[0].fTest.Print("pages"); | |
539ed16e | 530 | } |
531 | ||
532 | if (level>0) { | |
48dedf26 | 533 | if ((iResult=releaseBuffers(descriptions, level-1))<0) { |
539ed16e | 534 | cerr << "failed to release buffers" << endl; |
535 | return iResult; | |
536 | } | |
537 | } | |
538 | } | |
539 | ||
48dedf26 | 540 | if (gVerbosity>1) { |
541 | cout << "status of released pages: " << endl << " "; | |
542 | descriptions[0].fTest.Print("pages"); | |
543 | } | |
544 | for (rawpage=AliHLTDataBuffer::AliHLTRawPage::NextPage(NULL); | |
545 | rawpage!=NULL; | |
546 | rawpage=AliHLTDataBuffer::AliHLTRawPage::NextPage(rawpage)) { | |
547 | if (rawpage->IsUsed()) { | |
548 | cerr << "page " << rawpage << " has used buffers" << endl; | |
549 | iResult=-EFAULT; | |
550 | } else if (rawpage->Size()!=rawpage->Capacity()) { | |
551 | cerr << "page " << rawpage << " not completely released" << endl; | |
552 | iResult=-EFAULT; | |
553 | } else if (rawpage->IsFragmented()) { | |
554 | cerr << "page " << rawpage << " is still fragmented" << endl; | |
555 | iResult=-EFAULT; | |
539ed16e | 556 | } |
557 | } | |
48dedf26 | 558 | AliHLTDataBuffer::SetGlobalEventCount(cycle); |
539ed16e | 559 | } |
560 | ||
48dedf26 | 561 | if (iResult<0) { |
562 | descriptions[0].fTest.Print("pages"); | |
563 | } | |
564 | ||
565 | descriptions[0].fTest.GlobalClean(gVerbosity); | |
566 | ||
567 | return iResult; | |
539ed16e | 568 | } |
569 | ||
570 | /** | |
571 | * Get a random number in the given range. | |
572 | */ | |
573 | int GetRandom(int min, int max) | |
574 | { | |
575 | if (max-min<2) return min; | |
576 | static TRandom rand; | |
577 | static bool seedSet=false; | |
578 | if (!seedSet) { | |
579 | TDatime dt; | |
580 | rand.SetSeed(dt.Get()); | |
581 | seedSet=true; | |
582 | } | |
583 | return min+rand.Integer(max-min); | |
584 | } | |
585 | ||
48dedf26 | 586 | int testAliHLTDataBuffer() |
587 | { | |
588 | int iResult=0; | |
589 | const int iMaxLevels=10; | |
590 | int nofLevels=GetRandom(3,iMaxLevels); | |
591 | int nofProcesses=GetRandom(nofLevels,2*iMaxLevels); | |
21288ff1 | 592 | int nofCycles=GetRandom(100,1000); |
48dedf26 | 593 | |
594 | vector<testDataBufferDescription> descriptions; | |
595 | ||
596 | if ((iResult=fillTestSample(nofLevels, nofProcesses, descriptions))<0) { | |
597 | cerr << "failed to fill test sample" << endl; | |
598 | return iResult; | |
599 | } | |
600 | ||
601 | // adjust to the level of the last entry | |
602 | nofLevels=descriptions[descriptions.size()-1].fLevel; | |
603 | ||
604 | if (gVerbosity>0) { | |
605 | cout << " Test setup: " << nofLevels << " levels/ " << nofProcesses << " processes/ " << nofCycles << " cycle(s)" << endl; | |
606 | cout << " Pagesize: " << gPagesize << endl; | |
607 | for (unsigned i=0; i<descriptions.size(); i++) { | |
608 | cout << " process " << i << ": level " << descriptions[i].fLevel << " max size " << descriptions[i].fBufferSize << endl; | |
609 | } | |
610 | } | |
611 | ||
612 | if ((iResult=testLoop(descriptions, nofLevels, nofCycles))<0) return iResult; | |
613 | ||
614 | if (gVerbosity>0) { | |
615 | cout << "checking memory allocation using AliHLTRawPage directly ..." << endl; | |
616 | } | |
617 | vector<testRawPageDescription> rawpagedesc; | |
618 | CopyDescription(rawpagedesc, descriptions); | |
619 | if ((iResult=testLoop(rawpagedesc, nofLevels, nofCycles))<0) return iResult; | |
620 | ||
621 | return 0; | |
622 | } | |
623 | ||
539ed16e | 624 | ///////////////////////////////////////////////////////////////////////// |
625 | ///////////////////////////////////////////////////////////////////////// | |
626 | // | |
627 | // main functions | |
628 | ||
629 | int main(int /*argc*/, const char** /*argv*/) | |
630 | { | |
631 | int iResult=0; | |
48dedf26 | 632 | const int nofCycles=10; |
633 | for (int cycle=0; cycle<nofCycles && iResult>=0; cycle++) { | |
634 | iResult=testAliHLTDataBuffer(); | |
635 | if (((cycle+1)*100/nofCycles)%10==0) { | |
636 | cout << (cycle+1)*100/nofCycles << "% complete" << endl; | |
637 | } | |
638 | } | |
639 | ||
539ed16e | 640 | return iResult; |
641 | } |