]>
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; | |
44 | const int gPagesize=1024*1024*10; | |
45 | ||
46 | int testAliHLTRawPage(); | |
47 | int GetRandom(int min, int max); | |
48 | ||
49 | struct testProcessDescription { | |
50 | int fLevel; | |
51 | AliHLTUInt32_t fBufferSize; | |
52 | AliHLTDataBuffer::AliHLTRawBuffer* fRawBuffer; | |
53 | }; | |
54 | ||
55 | int testAliHLTDataBuffer() | |
56 | { | |
57 | int iResult=0; | |
58 | if ((iResult=testAliHLTRawPage())<0) return iResult; | |
59 | ||
60 | return 0; | |
61 | } | |
62 | ||
63 | int fillTestSample(int levels, int processes, vector<testProcessDescription>& descriptions) | |
64 | { | |
65 | int availableProcesses=processes; | |
66 | for (int level=0; level<levels; level++) { | |
67 | int levelprocesses=GetRandom(availableProcesses/2, availableProcesses-(levels-level)); | |
68 | for (int process=0; process<levelprocesses; process++) { | |
69 | testProcessDescription desc; | |
70 | desc.fLevel=level; | |
71 | desc.fBufferSize=GetRandom(1024, 3*gPagesize/processes); | |
72 | desc.fRawBuffer=NULL; | |
73 | descriptions.push_back(desc); | |
74 | } | |
75 | availableProcesses-=levelprocesses; | |
76 | } | |
77 | return 0; | |
78 | } | |
79 | ||
80 | int allocateBuffers(vector<testProcessDescription>& descriptions, | |
81 | vector<AliHLTDataBuffer::AliHLTRawPage*>& pages, | |
82 | int level=-1) | |
83 | { | |
84 | for (unsigned i=0; i<descriptions.size(); i++) { | |
85 | if (level>=0 && descriptions[i].fLevel<level) continue; | |
86 | if (level>=0 && descriptions[i].fLevel>level) break; | |
87 | if (descriptions[i].fRawBuffer) { | |
88 | cerr << "warning: buffer already allocated" << endl; | |
89 | continue; | |
90 | } | |
91 | ||
92 | vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=pages.begin(); | |
93 | for (page=pages.begin();page!=pages.end(); page++) { | |
94 | if ((descriptions[i].fRawBuffer=(*page)->Alloc(GetRandom(descriptions[i].fBufferSize/2, descriptions[i].fBufferSize)))!=NULL) { | |
95 | if (gVerbosity>1) { | |
96 | printf("allocated raw buffer %p from page %p\n", descriptions[i].fRawBuffer, *page); | |
97 | descriptions[i].fRawBuffer->Print("min"); | |
98 | } | |
99 | break; | |
100 | } | |
101 | } | |
102 | if (!descriptions[i].fRawBuffer) { | |
103 | AliHLTDataBuffer::AliHLTRawPage* rawpage=new AliHLTDataBuffer::AliHLTRawPage(gPagesize); | |
104 | if (!rawpage) { | |
105 | cerr << "can not create raw page" << endl; | |
106 | return -ENOMEM; | |
107 | } | |
108 | pages.push_back(rawpage); | |
109 | if ((descriptions[i].fRawBuffer=rawpage->Alloc(GetRandom(descriptions[i].fBufferSize/2, descriptions[i].fBufferSize)))!=NULL) { | |
110 | if (gVerbosity>1) { | |
111 | printf("allocated raw buffer %p from page %p\n", descriptions[i].fRawBuffer, rawpage); | |
112 | descriptions[i].fRawBuffer->Print("min"); | |
113 | } | |
114 | } | |
115 | } | |
116 | if (!descriptions[i].fRawBuffer) { | |
117 | cerr << "failed to allocate buffer for process " << i << endl; | |
118 | return -EFAULT; | |
119 | } | |
120 | } | |
121 | return 0; | |
122 | } | |
123 | ||
124 | int setBufferSizes(vector<testProcessDescription>& descriptions, | |
125 | vector<AliHLTDataBuffer::AliHLTRawPage*>& pages, | |
126 | int level=-1) | |
127 | { | |
128 | // set buffer size for all processes of the specified level | |
129 | // buffer size is chosen randomly between 0 and the allocated size | |
130 | vector<unsigned> positions; | |
131 | for (unsigned i=0; i<descriptions.size(); i++) { | |
132 | if (!descriptions[i].fRawBuffer) continue; | |
133 | if (level>=0 && descriptions[i].fLevel<level) continue; | |
134 | if (level>=0 && descriptions[i].fLevel>level) break; | |
135 | positions.push_back(i); | |
136 | } | |
137 | ||
138 | random_shuffle(positions.begin(), positions.end()); | |
139 | for (vector<unsigned>::iterator position=positions.begin(); | |
140 | position!=positions.end(); position++) { | |
141 | vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=pages.begin(); | |
142 | for (; page!=pages.end(); page++) { | |
143 | if ((*page)->SetSize(descriptions[*position].fRawBuffer, GetRandom(0, descriptions[*position].fBufferSize))==0) { | |
144 | if (gVerbosity>1) { | |
145 | cout << "setting size for raw buffer " << descriptions[*position].fRawBuffer << " of page " << *page << ", process level " << descriptions[*position].fLevel << endl; | |
146 | descriptions[*position].fRawBuffer->Print("min"); | |
147 | } | |
148 | break; | |
149 | } | |
150 | } | |
151 | if (page==pages.end()) { | |
152 | cerr << "failed to set size for raw buffer " << descriptions[*position].fRawBuffer << "of process " << *position << endl; | |
153 | return -EFAULT; | |
154 | } | |
155 | } | |
156 | return 0; | |
157 | } | |
158 | ||
159 | int releaseBuffers(vector<testProcessDescription>& descriptions, | |
160 | vector<AliHLTDataBuffer::AliHLTRawPage*>& pages, | |
161 | int level=-1) | |
162 | { | |
163 | // find the processes to be releases according to the specified level | |
164 | // shuffle the processes and then release in this random order | |
165 | vector<unsigned> positions; | |
166 | for (unsigned i=0; i<descriptions.size(); i++) { | |
167 | if (!descriptions[i].fRawBuffer) continue; | |
168 | if (level>=0 && descriptions[i].fLevel<level) continue; | |
169 | if (level>=0 && descriptions[i].fLevel>level) break; | |
170 | positions.push_back(i); | |
171 | } | |
172 | ||
173 | random_shuffle(positions.begin(), positions.end()); | |
174 | for (vector<unsigned>::iterator position=positions.begin(); | |
175 | position!=positions.end(); position++) { | |
176 | vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=pages.begin(); | |
177 | for (; page!=pages.end(); page++) { | |
178 | if ((*page)->Free(descriptions[*position].fRawBuffer)==0) { | |
179 | if (gVerbosity>1) cout << "released raw buffer " << descriptions[*position].fRawBuffer << " from page " << *page << ", process level " << descriptions[*position].fLevel << endl; | |
180 | descriptions[*position].fRawBuffer=NULL; | |
181 | break; | |
182 | } | |
183 | } | |
184 | if (page==pages.end()) { | |
185 | cerr << "failed to release raw buffer " << descriptions[*position].fRawBuffer << "of process " << *position << endl; | |
186 | return -EFAULT; | |
187 | } | |
188 | } | |
189 | return 0; | |
190 | } | |
191 | ||
192 | int testAliHLTRawPage() | |
193 | { | |
194 | int iResult=0; | |
195 | int nofLevels=GetRandom(3,5); | |
196 | int nofProcesses=GetRandom(nofLevels,10); | |
197 | int nofCycles=GetRandom(5,10); | |
198 | ||
199 | vector<testProcessDescription> descriptions; | |
200 | if ((iResult=fillTestSample(nofLevels, nofProcesses, descriptions))<0) { | |
201 | cerr << "failed to fill test sample" << endl; | |
202 | return iResult; | |
203 | } | |
204 | ||
205 | if (gVerbosity>1) { | |
206 | for (unsigned i=0; i<descriptions.size(); i++) { | |
207 | cout << "process " << i << ": level " << descriptions[i].fLevel << " max size " << descriptions[i].fBufferSize << endl; | |
208 | } | |
209 | } | |
210 | ||
211 | vector<AliHLTDataBuffer::AliHLTRawPage*> pages; | |
212 | vector<AliHLTDataBuffer::AliHLTRawPage*>::iterator page=pages.end(); | |
213 | for (int cycle=0; cycle<nofCycles; cycle++) { | |
214 | unsigned process=0; | |
215 | for (int level=0; level<=nofLevels; level++) { | |
216 | // allocate buffers | |
217 | if (level<nofLevels) { | |
218 | if ((iResult=allocateBuffers(descriptions, pages, level))<0) { | |
219 | cerr << "failed to allocate buffers" << endl; | |
220 | return iResult; | |
221 | } | |
222 | } | |
223 | ||
224 | if (gVerbosity>0) cout << "level " << level << " - status of pages: " << pages.size() << endl; | |
225 | for (page=pages.begin();page!=pages.end(); page++) { | |
226 | if (gVerbosity>0) (*page)->Print(""); | |
227 | } | |
228 | ||
229 | if (level<nofLevels) { | |
230 | if ((iResult=setBufferSizes(descriptions, pages, level))<0) { | |
231 | cerr << "failed setting buffers" << endl; | |
232 | return iResult; | |
233 | } | |
234 | } | |
235 | ||
236 | if (gVerbosity>0) cout << "level " << level << " - status of pages: " << pages.size() << endl; | |
237 | for (page=pages.begin();page!=pages.end(); page++) { | |
238 | if (gVerbosity>0) (*page)->Print(""); | |
239 | } | |
240 | ||
241 | if (level>0) { | |
242 | if ((iResult=releaseBuffers(descriptions, pages, level-1))<0) { | |
243 | cerr << "failed to release buffers" << endl; | |
244 | return iResult; | |
245 | } | |
246 | } | |
247 | } | |
248 | ||
249 | if (gVerbosity>0) | |
250 | cout << "status of released pages:" << endl; | |
251 | for (page=pages.begin();page!=pages.end(); page++) { | |
252 | if (gVerbosity>0) (*page)->Print(""); | |
253 | if ((*page)->IsUsed()) { | |
254 | cerr << "page " << *page << " has used buffers" << endl; | |
255 | return -EFAULT; | |
256 | } | |
257 | if ((*page)->Size()!=(*page)->Capacity()) { | |
258 | cerr << "page " << *page << " not completely released" << endl; | |
259 | return -EFAULT; | |
260 | } | |
261 | if ((*page)->IsFragmented()) { | |
262 | cerr << "page " << *page << " is still fragmented" << endl; | |
263 | return -EFAULT; | |
264 | } | |
265 | } | |
266 | } | |
267 | ||
268 | return 0; | |
269 | } | |
270 | ||
271 | /** | |
272 | * Get a random number in the given range. | |
273 | */ | |
274 | int GetRandom(int min, int max) | |
275 | { | |
276 | if (max-min<2) return min; | |
277 | static TRandom rand; | |
278 | static bool seedSet=false; | |
279 | if (!seedSet) { | |
280 | TDatime dt; | |
281 | rand.SetSeed(dt.Get()); | |
282 | seedSet=true; | |
283 | } | |
284 | return min+rand.Integer(max-min); | |
285 | } | |
286 | ||
287 | ///////////////////////////////////////////////////////////////////////// | |
288 | ///////////////////////////////////////////////////////////////////////// | |
289 | // | |
290 | // main functions | |
291 | ||
292 | int main(int /*argc*/, const char** /*argv*/) | |
293 | { | |
294 | int iResult=0; | |
295 | iResult=testAliHLTDataBuffer(); | |
296 | return iResult; | |
297 | } |