Line data Source code
1 : // $Id$
2 : /**************************************************************************
3 : * This file is property of and copyright by the ALICE HLT Project *
4 : * ALICE Experiment at CERN, All rights reserved. *
5 : * *
6 : * Primary Authors: Artur Szostak <artursz@iafrica.com> *
7 : * for The ALICE HLT Project. *
8 : * *
9 : * Permission to use, copy, modify and distribute this software and its *
10 : * documentation strictly for non-commercial purposes is hereby granted *
11 : * without fee, provided that the above copyright notice appears in all *
12 : * copies and that both the copyright notice and this permission notice *
13 : * appear in the supporting documentation. The authors make no claims *
14 : * about the suitability of this software for any purpose. It is *
15 : * provided "as is" without express or implied warranty. *
16 : **************************************************************************/
17 :
18 : /// @file AliHLTCorruptorComponent.cxx
19 : /// @author Artur Szostak <artursz@iafrica.com>
20 : /// @date 5 Aug 2010
21 : /// @brief Implementation of the AliHLTCorruptorComponent class.
22 : ///
23 : /// The AliHLTCorruptorComponent is used to generate corruption of various kind
24 : /// in the input data blocks it sees. The blocks will be copied to the output
25 : /// but with various bit flips and garbage inserted.
26 : /// This kind of component is used for testing purposes.
27 :
28 : #include "AliHLTCorruptorComponent.h"
29 : #include "TRandom3.h"
30 : #include <cstdlib>
31 : #include <cstring>
32 : #include <cerrno>
33 :
34 8 : ClassImp(AliHLTCorruptorComponent)
35 :
36 :
37 : AliHLTCorruptorComponent::AliHLTCorruptorComponent() :
38 3 : AliHLTProcessor(),
39 3 : fBufferMultiplier(2.),
40 3 : fBlockIdList(),
41 3 : fCorruptionInfoList(),
42 3 : fPatterns()
43 15 : {
44 : // Default constructor.
45 6 : }
46 :
47 :
48 : AliHLTCorruptorComponent::~AliHLTCorruptorComponent()
49 18 : {
50 : // Default destructor.
51 9 : }
52 :
53 :
54 : const char* AliHLTCorruptorComponent::GetComponentID()
55 : {
56 : // Returns the component ID.
57 582 : return "CorruptorComponent";
58 : }
59 :
60 :
61 : void AliHLTCorruptorComponent::GetInputDataTypes(AliHLTComponentDataTypeList& list)
62 : {
63 : // Returns the list of input data types that are handled.
64 0 : list.push_back(kAliHLTAnyDataType);
65 0 : }
66 :
67 :
68 : AliHLTComponentDataType AliHLTCorruptorComponent::GetOutputDataType()
69 : {
70 : // Returns kAliHLTMultipleDataType.
71 0 : return kAliHLTMultipleDataType;
72 : }
73 :
74 :
75 : int AliHLTCorruptorComponent::GetOutputDataTypes(AliHLTComponentDataTypeList& list)
76 : {
77 : // Returns the list of output data blocks handled.
78 0 : list.push_back(kAliHLTAnyDataType);
79 0 : return int(list.size());
80 : }
81 :
82 :
83 : void AliHLTCorruptorComponent::GetOutputDataSize(unsigned long& constBase, double& inputMultiplier)
84 : {
85 : // Returns the buffer size requirements.
86 :
87 : unsigned long total = 0;
88 0 : for (size_t i = 0; i < fCorruptionInfoList.size(); ++i)
89 : {
90 0 : AliCorruptionInfo& info = fCorruptionInfoList[i];
91 0 : if (info.fType == kInsert)
92 : {
93 0 : total += (info.fLastPattern - info.fFirstPattern) / sizeof(AliPattern) * sizeof(AliHLTUInt64_t);
94 0 : }
95 0 : else if (info.fType == kInsertRandom)
96 : {
97 0 : total += info.fMaxBits / 8 + 1;
98 0 : }
99 : }
100 :
101 0 : constBase = total;
102 0 : inputMultiplier = fBufferMultiplier;
103 0 : }
104 :
105 :
106 : AliHLTComponent* AliHLTCorruptorComponent::Spawn()
107 : {
108 : // Creates a new instance of the component.
109 0 : return new AliHLTCorruptorComponent;
110 0 : }
111 :
112 :
113 : bool AliHLTCorruptorComponent::ConvertToPositiveInt(const char* value, AliHLTUInt64_t& num, bool printErrors) const
114 : {
115 : // Converts a string value to a positive integer.
116 :
117 0 : char* err = NULL;
118 0 : errno = 0;
119 0 : unsigned long long tmpnum = strtoull(value, &err, 0);
120 0 : if (err == NULL or *err != '\0')
121 : {
122 0 : if (printErrors) HLTError("Cannot convert '%s' to a positive integer.", value);
123 0 : return false;
124 : }
125 0 : if (errno == ERANGE)
126 : {
127 0 : if (printErrors) HLTError("The specified value '%s' is out of range.", value);
128 0 : return false;
129 : }
130 0 : num = tmpnum;
131 0 : return true;
132 0 : }
133 :
134 :
135 : bool AliHLTCorruptorComponent::ConvertToBitPosition(
136 : const char* value, AliHLTUInt64_t& pos, bool& relative, bool printErrors
137 : ) const
138 : {
139 : // Converts a string value to a bit position.
140 :
141 0 : if (strcmp(value, "min") == 0)
142 : {
143 : // Special case where the value is the special symbol "min".
144 0 : pos = 0;
145 0 : relative = false;
146 0 : return true;
147 : }
148 0 : if (strcmp(value, "max") == 0)
149 : {
150 : // Special case where the value is the special symbol "max".
151 0 : pos = 0xFFFFFFFFFFFFFFFFull;
152 0 : relative = false;
153 0 : return true;
154 : }
155 :
156 0 : int valuelength = strlen(value);
157 : const char* valstr = value;
158 0 : relative = false;
159 : // Check if the position is relative.
160 0 : if (valuelength >= 3 and value[0] == 'm' and value[1] == 'i' and value[2] == 'n')
161 : {
162 0 : if (valuelength >= 4 and value[3] == '-')
163 : {
164 0 : if (printErrors)
165 : {
166 0 : HLTError("Cannot use 'min-' in option '%s' since that would be outside the buffer."
167 : " Should use 'min+' instead.",
168 : value
169 : );
170 0 : return false;
171 : }
172 : }
173 0 : else if (valuelength >= 4 and value[3] == '+')
174 : {
175 : // Value starting with min+ does not need anything special because
176 : // min is always == 0. Just adjust the value string pointer to
177 : // skip this part of the string.
178 0 : valstr = value + 4;
179 0 : }
180 : }
181 0 : else if (valuelength >= 3 and value[0] == 'm' and value[1] == 'a' and value[2] == 'x')
182 : {
183 0 : if (valuelength >= 4 and value[3] == '+')
184 : {
185 0 : if (printErrors)
186 : {
187 0 : HLTError("Cannot use 'max+' in option '%s' since that would be outside the buffer."
188 : " Should use 'max-' instead.",
189 : value
190 : );
191 0 : return false;
192 : }
193 : }
194 0 : else if (valuelength >= 4 and value[3] == '-')
195 : {
196 : // Need to mark the result as a relative value and skip the
197 : // first part of the string.
198 0 : relative = true;
199 0 : valstr = value + 4;
200 0 : }
201 : }
202 :
203 : // Find the location of ':' if any, to mark the start of the byte and bit strings.
204 0 : int bytestrlen = strlen(valstr);
205 0 : const char* bitstr = valstr + bytestrlen;
206 0 : for (int i = 0; valstr[i] != 0x0; ++i)
207 : {
208 0 : if (valstr[i] == ':')
209 : {
210 : bytestrlen = i;
211 0 : bitstr = valstr + (i+1);
212 0 : break;
213 : }
214 : }
215 0 : TString bytestr(valstr, bytestrlen);
216 :
217 0 : char* err = NULL;
218 0 : errno = 0;
219 0 : unsigned long long bytenum = strtoull(bytestr.Data(), &err, 0);
220 0 : if (err == NULL or *err != '\0')
221 : {
222 0 : if (printErrors)
223 : {
224 0 : HLTError("Cannot convert '%s' given in option '%s' to a positive integer.",
225 : bytestr.Data(), value
226 : );
227 : }
228 0 : return false;
229 : }
230 0 : if (errno == ERANGE or bytenum > 0x1FFFFFFFFFFFFFFFull)
231 : {
232 0 : if (printErrors)
233 : {
234 0 : HLTError("The specified byte number '%s' given in option '%s' is out of range."
235 : " The value should be in the range [0..%lld].",
236 : bytestr.Data(), value, 0x1FFFFFFFFFFFFFFFull
237 : );
238 : }
239 0 : return false;
240 : }
241 0 : err = NULL;
242 0 : unsigned long bitnum = strtoul(bitstr, &err, 0);
243 0 : if (err == NULL or *err != '\0')
244 : {
245 0 : if (printErrors)
246 : {
247 0 : HLTError("Cannot convert '%s' given in option '%s' to a positive integer.",
248 : bitstr, value
249 : );
250 : }
251 0 : return false;
252 : }
253 0 : if (errno == ERANGE or bitnum > 7)
254 : {
255 0 : if (printErrors)
256 : {
257 0 : HLTError("The specified bit number '%s' given in option '%s' is out of range."
258 : " The value should be in the range [0..7].",
259 : bitstr, value
260 : );
261 : }
262 0 : return false;
263 : }
264 0 : pos = (bytenum << 3) | (bitnum & 0x7);
265 0 : return true;
266 0 : }
267 :
268 :
269 : bool AliHLTCorruptorComponent::ConvertToPercentage(const char* value, double& num, bool printErrors) const
270 : {
271 : // Converts a string value as a percentage to a floating point number in the range [0..1].
272 :
273 0 : TString str = value;
274 : bool percent = false;
275 0 : if (str.Length() > 0 and str[str.Length()-1] == '%')
276 : {
277 : percent = true;
278 0 : str[str.Length()-1] = '\0';
279 0 : }
280 0 : char* err = NULL;
281 0 : errno = 0;
282 0 : double tmpnum = strtod(str.Data(), &err);
283 0 : if (err == NULL or *err != '\0')
284 : {
285 0 : if (printErrors) HLTError("Cannot convert '%s' to a valid floating point value.", value);
286 0 : return false;
287 : }
288 0 : if (errno == ERANGE or tmpnum < 0. or (tmpnum > 100. and percent) or (tmpnum > 1. and not percent))
289 : {
290 0 : if (printErrors)
291 : {
292 0 : int range = percent ? 100 : 1;
293 0 : HLTError("The specified value '%s' is outside the range [0..%d]", value, range);
294 0 : }
295 0 : return false;
296 : }
297 0 : num = percent ? tmpnum / 100. : tmpnum;
298 0 : return true;
299 0 : }
300 :
301 :
302 : bool AliHLTCorruptorComponent::ConvertToPattern(const char* value, AliPattern& pattern, bool printErrors) const
303 : {
304 : // Coverts a string value into a pattern structure.
305 :
306 0 : if (strcmp(value, "removed") == 0)
307 : {
308 : // Special case where the pattern is the special symbol to used remove bits.
309 0 : pattern.fPattern = 0;
310 0 : pattern.fWidth = 0;
311 0 : pattern.fUseRemoved = true;
312 0 : return true;
313 : }
314 :
315 : // Find the location of '/' if any, to mark the start of the pattern and width fields.
316 0 : int patstrlen = strlen(value);
317 0 : const char* widthstr = value + patstrlen;
318 0 : for (int i = 0; value[i] != 0x0; ++i)
319 : {
320 0 : if (value[i] == '/')
321 : {
322 : patstrlen = i;
323 0 : widthstr = value + (i+1);
324 0 : break;
325 : }
326 : }
327 0 : TString patstr(value, patstrlen);
328 :
329 0 : char* err = NULL;
330 0 : errno = 0;
331 0 : AliHLTUInt64_t patnum = AliHLTUInt64_t( strtoull(patstr.Data(), &err, 0) );
332 0 : if (err == NULL or *err != '\0')
333 : {
334 0 : if (printErrors)
335 : {
336 0 : HLTError("Cannot convert '%s' given in pattern '%s' to a positive integer.",
337 : patstr.Data(), value
338 : );
339 : }
340 0 : return false;
341 : }
342 0 : if (errno == ERANGE)
343 : {
344 0 : if (printErrors)
345 : {
346 0 : HLTError("The specified pattern '%s' is out of range."
347 : "Cannot be bigger than a 64 bit integer.",
348 : value
349 : );
350 : }
351 0 : return false;
352 : }
353 : unsigned long widthnum = 1;
354 0 : if (*widthstr != '\0') // check if widthstr string is not empty
355 : {
356 0 : err = NULL;
357 0 : widthnum = strtoul(widthstr, &err, 0);
358 0 : if (err == NULL or *err != '\0')
359 : {
360 0 : if (printErrors)
361 : {
362 0 : HLTError("Cannot convert the width '%s' given in pattern '%s'"
363 : " to a positive integer.",
364 : widthstr, value
365 : );
366 : }
367 0 : return false;
368 : }
369 0 : if (errno == ERANGE or widthnum < 1 or 64 < widthnum)
370 : {
371 0 : if (printErrors)
372 : {
373 0 : HLTError("The specified width '%s' given in pattern '%s' is out of range."
374 : " The value should be in the range [1..64].",
375 : widthstr, value
376 : );
377 : }
378 0 : return false;
379 : }
380 : }
381 : else
382 : {
383 : // Find the width of the pattern if not explicitly given.
384 : // This is done by finding the most significant set bit.
385 0 : for (int i = 63; i >= 0; --i)
386 : {
387 0 : if (((patnum >> i) & 0x1) == 0x1)
388 : {
389 0 : widthnum = i+1;
390 0 : break;
391 : }
392 : }
393 : }
394 0 : pattern.fPattern = patnum;
395 0 : pattern.fWidth = AliHLTUInt8_t(widthnum);
396 0 : pattern.fUseRemoved = false;
397 0 : return true;
398 0 : }
399 :
400 :
401 : bool AliHLTCorruptorComponent::AddBlockTypeId(const char* type)
402 : {
403 : // Sets the block type ID to filter on.
404 :
405 0 : if (strlen(type) > (unsigned)kAliHLTComponentDataTypefIDsize)
406 : {
407 0 : HLTError("The specified block type '%s' must not be longer than %d characters.",
408 : type, kAliHLTComponentDataTypefIDsize
409 : );
410 0 : return false;
411 : }
412 0 : if (fBlockIdList.size() > 0 and not fBlockIdList[fBlockIdList.size()-1].fTypeSet)
413 : {
414 0 : fBlockIdList[fBlockIdList.size()-1].fType =
415 0 : AliHLTComponentDataTypeInitializer(
416 : type,
417 0 : fBlockIdList[fBlockIdList.size()-1].fType.fOrigin
418 : );
419 0 : fBlockIdList[fBlockIdList.size()-1].fTypeSet = true;
420 0 : }
421 : else
422 : {
423 0 : AliBlockId id;
424 0 : id.fType = AliHLTComponentDataTypeInitializer(type, kAliHLTDataOriginAny);
425 0 : id.fSpec = kAliHLTVoidDataSpec;
426 0 : id.fTypeSet = true;
427 0 : id.fOriginSet = false;
428 0 : id.fSpecSet = false;
429 0 : fBlockIdList.push_back(id);
430 0 : }
431 0 : return true;
432 0 : }
433 :
434 :
435 : bool AliHLTCorruptorComponent::AddBlockOrigin(const char* origin)
436 : {
437 : // Sets the block origin to filter on.
438 :
439 0 : if (strlen(origin) > (unsigned)kAliHLTComponentDataTypefOriginSize)
440 : {
441 0 : HLTError("The specified origin '%s' must not be longer than %d characters.",
442 : origin, kAliHLTComponentDataTypefOriginSize
443 : );
444 0 : return false;
445 : }
446 0 : if (fBlockIdList.size() > 0 and not fBlockIdList[fBlockIdList.size()-1].fOriginSet)
447 : {
448 0 : fBlockIdList[fBlockIdList.size()-1].fType =
449 0 : AliHLTComponentDataTypeInitializer(
450 0 : fBlockIdList[fBlockIdList.size()-1].fType.fID,
451 : origin
452 : );
453 0 : fBlockIdList[fBlockIdList.size()-1].fOriginSet = true;
454 0 : }
455 : else
456 : {
457 0 : AliBlockId id;
458 0 : id.fType = AliHLTComponentDataTypeInitializer(kAliHLTAnyDataTypeID, origin);
459 0 : id.fSpec = kAliHLTVoidDataSpec;
460 0 : id.fTypeSet = false;
461 0 : id.fOriginSet = true;
462 0 : id.fSpecSet = false;
463 0 : fBlockIdList.push_back(id);
464 0 : }
465 0 : return true;
466 0 : }
467 :
468 :
469 : bool AliHLTCorruptorComponent::AddBlockSpec(const char* spec)
470 : {
471 : // Sets the block specification to filter on.
472 :
473 0 : char* err = NULL;
474 0 : errno = 0;
475 0 : unsigned long long num = strtoull(spec, &err, 0);
476 0 : if (err == NULL or *err != '\0')
477 : {
478 0 : HLTError("Cannot convert '%s' to a specification number.", spec);
479 0 : return false;
480 : }
481 0 : if (num > 0xFFFFFFFF or errno == ERANGE)
482 : {
483 0 : HLTError("The specification number is not an unsigned 32-bit value or out of range.");
484 0 : return false;
485 : }
486 0 : AliHLTUInt32_t specVal = AliHLTUInt32_t(num);
487 :
488 0 : if (fBlockIdList.size() > 0 and not fBlockIdList[fBlockIdList.size()-1].fSpecSet)
489 : {
490 0 : fBlockIdList[fBlockIdList.size()-1].fSpec = specVal;
491 0 : fBlockIdList[fBlockIdList.size()-1].fSpecSet = true;
492 0 : }
493 : else
494 : {
495 0 : AliBlockId id;
496 0 : id.fType = AliHLTComponentDataTypeInitializer(kAliHLTAnyDataTypeID, kAliHLTDataOriginAny);
497 0 : id.fSpec = specVal;
498 0 : id.fTypeSet = false;
499 0 : id.fOriginSet = false;
500 0 : id.fSpecSet = true;
501 0 : fBlockIdList.push_back(id);
502 0 : }
503 :
504 : return true;
505 0 : }
506 :
507 :
508 : void AliHLTCorruptorComponent::AddCorruptionCommand(
509 : AliCorruptionType type,
510 : AliHLTUInt64_t minrange,
511 : AliHLTUInt64_t maxrange,
512 : AliHLTUInt64_t alignment,
513 : bool minRangeRelative,
514 : bool maxRangeRelative,
515 : bool userate,
516 : double rate,
517 : AliHLTUInt64_t minerrors,
518 : AliHLTUInt64_t maxerrors,
519 : AliHLTUInt64_t burstlength,
520 : AliHLTUInt64_t burstcount,
521 : AliHLTUInt64_t minbits,
522 : AliHLTUInt64_t maxbits,
523 : size_t firstpattern,
524 : size_t lastpattern
525 : )
526 : {
527 : // Adds a new entry into the corruptions list to apply.
528 :
529 0 : AliCorruptionInfo info;
530 0 : memset(&info, 0x0, sizeof(info));
531 0 : info.fType = type;
532 0 : info.fMinRange = minrange;
533 0 : info.fMaxRange = maxrange;
534 0 : info.fAlignment = alignment;
535 0 : info.fMinRangeRelative = minRangeRelative;
536 0 : info.fMaxRangeRelative = maxRangeRelative;
537 0 : info.fUseRate = userate;
538 0 : if (userate)
539 : {
540 0 : info.fRate = rate;
541 0 : }
542 : else
543 : {
544 0 : info.fMinErrors = minerrors;
545 0 : info.fMaxErrors = maxerrors;
546 : }
547 0 : switch (type)
548 : {
549 : case kBurstErrors:
550 0 : info.fBurstErrorLength = burstlength;
551 0 : info.fBurstErrorCount = burstcount;
552 0 : break;
553 : case kReplace:
554 0 : info.fFirstPattern = firstpattern;
555 0 : info.fLastPattern = lastpattern;
556 0 : break;
557 : case kReplaceRandom:
558 0 : info.fMinBits = minbits;
559 0 : info.fMaxBits = maxbits;
560 0 : break;
561 : case kInsert:
562 0 : info.fFirstPattern = firstpattern;
563 0 : info.fLastPattern = lastpattern;
564 0 : break;
565 : case kInsertRandom:
566 0 : info.fMinBits = minbits;
567 0 : info.fMaxBits = maxbits;
568 0 : break;
569 : case kRemove:
570 0 : info.fMinBits = minbits;
571 0 : info.fMaxBits = maxbits;
572 0 : break;
573 : default:
574 : // Nothing to do.
575 : break;
576 : }
577 0 : fCorruptionInfoList.push_back(info);
578 0 : }
579 :
580 :
581 : int AliHLTCorruptorComponent::CheckForCommandWithPatterns(
582 : const char* name, AliCorruptionType type,
583 : int& i, int argc, const char** argv,
584 : AliHLTUInt64_t minrange,
585 : AliHLTUInt64_t maxrange,
586 : AliHLTUInt64_t alignment,
587 : bool minRangeRelative,
588 : bool maxRangeRelative,
589 : bool userate,
590 : double errorrate,
591 : AliHLTUInt64_t minerrors,
592 : AliHLTUInt64_t maxerrors
593 : )
594 : {
595 : // Check for a particular command line option that has pattern parameters.
596 :
597 0 : AliPattern pattern = {0, 0, false};
598 0 : if (strcmp(argv[i], name) == 0)
599 : {
600 : // Check for at least 1 pattern.
601 0 : if (argc <= i+1)
602 : {
603 0 : HLTError("At least one pattern must be specified for %s.", name);
604 0 : return -EINVAL;
605 : }
606 0 : if (not ConvertToPattern(argv[i+1], pattern)) return -EPROTO;
607 : // Mark the pattern found as the first pattern and add it.
608 0 : size_t firstpattern = fPatterns.size();
609 0 : fPatterns.push_back(pattern);
610 0 : ++i;
611 : // Now check for more patterns. Do not print any error messages,
612 : // since here we assume that if the string is not a pattern string
613 : // then it might be another command.
614 0 : while (i+1 < argc and ConvertToPattern(argv[i+1], pattern, false))
615 : {
616 0 : fPatterns.push_back(pattern);
617 0 : ++i;
618 : }
619 : // Mark the last pattern and add corruption command.
620 0 : size_t lastpattern = fPatterns.size();
621 0 : AddCorruptionCommand(
622 : type, minrange, maxrange, alignment,
623 0 : minRangeRelative, maxRangeRelative, userate,
624 : errorrate, minerrors, maxerrors, 0, 0, 0, 0,
625 : firstpattern, lastpattern
626 : );
627 : return 1;
628 : }
629 0 : return 0;
630 0 : }
631 :
632 :
633 : int AliHLTCorruptorComponent::CheckForCommandWithMinMax(
634 : const char* name, AliCorruptionType type,
635 : int& i, int argc, const char** argv,
636 : AliHLTUInt64_t minrange,
637 : AliHLTUInt64_t maxrange,
638 : AliHLTUInt64_t alignment,
639 : bool minRangeRelative,
640 : bool maxRangeRelative,
641 : bool userate,
642 : double errorrate,
643 : AliHLTUInt64_t minerrors,
644 : AliHLTUInt64_t maxerrors
645 : )
646 : {
647 : // Check for a particular command line option that has 2 (min/max) parameters.
648 :
649 0 : if (strcmp(argv[i], name) == 0)
650 : {
651 0 : if (argc <= i+1)
652 : {
653 0 : HLTError("Minimum number of bits to replace not specified for %s.", name);
654 0 : return -EINVAL;
655 : }
656 0 : AliHLTUInt64_t minbits = 0;
657 0 : if (strcmp(argv[i+1], "min") == 0)
658 : {
659 0 : minbits = 0;
660 0 : }
661 0 : else if (strcmp(argv[i+1], "max") == 0)
662 : {
663 0 : minbits = 0xFFFFFFFFFFFFFFFFull;
664 0 : }
665 : else
666 : {
667 0 : if (not ConvertToPositiveInt(argv[i+1], minbits)) return -EPROTO;
668 : }
669 0 : if (argc <= i+2)
670 : {
671 0 : HLTError("Maximum number of bits to replace not specified for %s.", name);
672 0 : return -EINVAL;
673 : }
674 0 : AliHLTUInt64_t maxbits = 0;
675 0 : if (strcmp(argv[i+2], "min") == 0)
676 : {
677 0 : maxbits = 0;
678 0 : }
679 0 : else if (strcmp(argv[i+2], "max") == 0)
680 : {
681 0 : maxbits = 0xFFFFFFFFFFFFFFFFull;
682 0 : }
683 : else
684 : {
685 0 : if (not ConvertToPositiveInt(argv[i+2], maxbits)) return -EPROTO;
686 : }
687 0 : if (maxbits < minbits)
688 : {
689 0 : HLTError("Maximum value (%s) is smaller than minimum (%s).", argv[i+2], argv[i+1]);
690 0 : return -EPROTO;
691 : }
692 0 : AddCorruptionCommand(
693 : type, minrange, maxrange, alignment,
694 0 : minRangeRelative, maxRangeRelative, userate,
695 : errorrate, minerrors, maxerrors, 0, 0, minbits, maxbits
696 : );
697 0 : i += 2;
698 0 : return 1;
699 0 : }
700 0 : return 0;
701 0 : }
702 :
703 :
704 : Int_t AliHLTCorruptorComponent::DoInit(int argc, const char** argv)
705 : {
706 : // Initialises the corruptor component from the command line.
707 :
708 : int result = 0;
709 0 : fBlockIdList.clear();
710 0 : fCorruptionInfoList.clear();
711 0 : fPatterns.clear();
712 0 : AliHLTUInt64_t minpos = 0;
713 0 : AliHLTUInt64_t maxpos = 0xFFFFFFFFFFFFFFFFull;
714 0 : AliHLTUInt64_t alignment = 1;
715 0 : bool minposrel = false;
716 0 : bool maxposrel = false;
717 : bool useErrorRate = true;
718 0 : double errorrate = 0.001;
719 0 : AliHLTUInt64_t minerrors = 1;
720 0 : AliHLTUInt64_t maxerrors = 1;
721 : bool seedSet = false;
722 : UInt_t seed = 0;
723 :
724 0 : for (int i = 0; i < argc; ++i)
725 : {
726 0 : if (strcmp(argv[i], "-seed") == 0)
727 : {
728 0 : if (seedSet)
729 : {
730 0 : HLTError("The option \"-seed\" has already been used with"
731 : " the value %u. Can only use this option once",
732 : seed
733 : );
734 0 : return -EINVAL;
735 : }
736 0 : if (argc <= i+1)
737 : {
738 0 : HLTError("The random number generator seed was not specified for -seed.");
739 0 : return -EINVAL;
740 : }
741 0 : AliHLTUInt64_t tmpseed = 0;
742 0 : if (not ConvertToPositiveInt(argv[i+1], tmpseed)) return -EPROTO;
743 0 : if (tmpseed > 0xFFFFFFFF)
744 : {
745 0 : HLTError("The random number generator seed value cannot be larger than %u.", 0xFFFFFFFF);
746 0 : return -EPROTO;
747 : }
748 0 : seed = UInt_t(tmpseed);
749 : seedSet = true;
750 0 : ++i;
751 0 : continue;
752 0 : }
753 :
754 0 : if (strcmp(argv[i], "-datatype") == 0)
755 : {
756 0 : if (argc <= i+1)
757 : {
758 0 : HLTError("The data type identifier was not specified for -datatype.");
759 0 : return -EINVAL;
760 : }
761 0 : if (not AddBlockTypeId(argv[i+1])) return -EPROTO;
762 0 : if (argc <= i+2)
763 : {
764 0 : HLTError("The origin identifier was not specified for -datatype.");
765 0 : return -EINVAL;
766 : }
767 0 : if (not AddBlockOrigin(argv[i+2])) return -EPROTO;
768 0 : i += 2;
769 0 : continue;
770 : }
771 :
772 0 : if (strcmp(argv[i], "-origin") == 0)
773 : {
774 0 : if (argc <= i+1)
775 : {
776 0 : HLTError("The origin identifier was not specified for -origin.");
777 0 : return -EINVAL;
778 : }
779 0 : if (not AddBlockOrigin(argv[i+1])) return -EPROTO;
780 0 : ++i;
781 0 : continue;
782 : }
783 :
784 0 : if (strcmp(argv[i], "-typeid") == 0)
785 : {
786 0 : if (argc <= i+1)
787 : {
788 0 : HLTError("The data type identifier was not specified for -typeid.");
789 0 : return -EINVAL;
790 : }
791 0 : if (not AddBlockTypeId(argv[i+1])) return -EPROTO;
792 0 : ++i;
793 0 : continue;
794 : }
795 :
796 0 : if (strcmp(argv[i], "-dataspec") == 0)
797 : {
798 0 : if (argc <= i+1)
799 : {
800 0 : HLTError("The data specification was not specified for -dataspec.");
801 0 : return -EINVAL;
802 : }
803 0 : if (not AddBlockSpec(argv[i+1])) return -EPROTO;
804 0 : ++i;
805 0 : continue;
806 : }
807 :
808 0 : if (strcmp(argv[i], "-range") == 0)
809 : {
810 0 : if (argc <= i+1)
811 : {
812 0 : HLTError("Minimum byte/bit position not given for -range.");
813 0 : return -EINVAL;
814 : }
815 0 : if (not ConvertToBitPosition(argv[i+1], minpos, minposrel)) return -EPROTO;
816 0 : if (argc <= i+2)
817 : {
818 0 : HLTError("Maximum byte/bit position not given for -range.");
819 0 : return -EINVAL;
820 : }
821 0 : if (not ConvertToBitPosition(argv[i+2], maxpos, maxposrel)) return -EPROTO;
822 0 : if (minposrel == maxposrel and maxpos < minpos)
823 : {
824 0 : HLTError("Maximum position (%s) is smaller than minimum position (%s).",
825 : argv[i+2], argv[i+1]
826 : );
827 0 : return -EPROTO;
828 : }
829 0 : i += 2;
830 0 : continue;
831 : }
832 :
833 0 : if (strcmp(argv[i], "-alignment") == 0)
834 : {
835 0 : if (argc <= i+1)
836 : {
837 0 : HLTError("The alignment value was not specified for -errorrate.");
838 0 : return -EINVAL;
839 : }
840 0 : if (not ConvertToPositiveInt(argv[i+1], alignment)) return -EPROTO;
841 0 : if (alignment == 0)
842 : {
843 0 : HLTError("The alignment value cannot be zero.");
844 0 : return -EPROTO;
845 : }
846 0 : ++i;
847 0 : continue;
848 : }
849 :
850 0 : if (strcmp(argv[i], "-errorrate") == 0)
851 : {
852 0 : if (argc <= i+1)
853 : {
854 0 : HLTError("The current error rate to use was not specified for -errorrate.");
855 0 : return -EINVAL;
856 : }
857 0 : if (not ConvertToPercentage(argv[i+1], errorrate)) return -EPROTO;
858 : useErrorRate = true;
859 0 : ++i;
860 0 : continue;
861 : }
862 :
863 0 : if (strcmp(argv[i], "-errorcount") == 0)
864 : {
865 0 : if (argc <= i+1)
866 : {
867 0 : HLTError("Minimum number of errors not specified for -errorcount.");
868 0 : return -EINVAL;
869 : }
870 0 : if (not ConvertToPositiveInt(argv[i+1], minerrors)) return -EPROTO;
871 0 : if (argc <= i+2)
872 : {
873 0 : HLTError("Maximum number of errors not specified for -errorcount.");
874 0 : return -EINVAL;
875 : }
876 0 : if (not ConvertToPositiveInt(argv[i+2], maxerrors)) return -EPROTO;
877 0 : if (maxerrors < minerrors)
878 : {
879 0 : HLTError("Maximum error count (%s) is smaller than minimum (%s).",
880 : argv[i+2], argv[i+1]
881 : );
882 0 : return -EPROTO;
883 : }
884 : useErrorRate = false;
885 0 : i += 2;
886 0 : continue;
887 : }
888 :
889 0 : if (strcmp(argv[i], "-singleflips") == 0)
890 : {
891 0 : AddCorruptionCommand(
892 0 : kSingleFlips, minpos, maxpos, alignment,
893 0 : minposrel, maxposrel, useErrorRate,
894 0 : errorrate, minerrors, maxerrors
895 : );
896 0 : continue;
897 : }
898 :
899 0 : if (strcmp(argv[i], "-bursterrors") == 0)
900 : {
901 0 : if (argc <= i+1)
902 : {
903 0 : HLTError("Maximum burst error length not specified for -bursterrors.");
904 0 : return -EINVAL;
905 : }
906 0 : AliHLTUInt64_t burstLength;
907 0 : if (not ConvertToPositiveInt(argv[i+1], burstLength)) return -EPROTO;
908 0 : if (argc <= i+2)
909 : {
910 0 : HLTError("Number of bit flips in a burst error not specified for -bursterrors.");
911 0 : return -EINVAL;
912 : }
913 0 : AliHLTUInt64_t burstCount;
914 0 : if (not ConvertToPositiveInt(argv[i+2], burstCount)) return -EPROTO;
915 0 : AddCorruptionCommand(
916 0 : kBurstErrors, minpos, maxpos, alignment,
917 0 : minposrel, maxposrel, useErrorRate, errorrate,
918 0 : minerrors, maxerrors, burstLength, burstCount
919 : );
920 0 : i += 2;
921 0 : continue;
922 0 : }
923 :
924 0 : result = CheckForCommandWithPatterns("-replace", kReplace,
925 0 : i, argc, argv, minpos, maxpos, alignment,
926 0 : minposrel, maxposrel, useErrorRate,
927 0 : errorrate, minerrors, maxerrors
928 : );
929 0 : if (result == 1) continue;
930 0 : if (result < 0) return result;
931 :
932 0 : result = CheckForCommandWithPatterns("-insert", kInsert,
933 0 : i, argc, argv, minpos, maxpos, alignment,
934 0 : minposrel, maxposrel, useErrorRate,
935 0 : errorrate, minerrors, maxerrors
936 : );
937 0 : if (result == 1) continue;
938 0 : if (result < 0) return result;
939 :
940 0 : result = CheckForCommandWithMinMax("-replace-random", kReplaceRandom,
941 0 : i, argc, argv, minpos, maxpos, alignment,
942 0 : minposrel, maxposrel, useErrorRate,
943 0 : errorrate, minerrors, maxerrors
944 : );
945 0 : if (result == 1) continue;
946 0 : if (result < 0) return result;
947 :
948 0 : result = CheckForCommandWithMinMax("-insert-random", kInsertRandom,
949 0 : i, argc, argv, minpos, maxpos, alignment,
950 0 : minposrel, maxposrel, useErrorRate,
951 0 : errorrate, minerrors, maxerrors
952 : );
953 0 : if (result == 1) continue;
954 0 : if (result < 0) return result;
955 :
956 0 : result = CheckForCommandWithMinMax("-remove", kRemove,
957 0 : i, argc, argv, minpos, maxpos, alignment,
958 0 : minposrel, maxposrel, useErrorRate,
959 0 : errorrate, minerrors, maxerrors
960 : );
961 0 : if (result == 1) continue;
962 0 : if (result < 0) return result;
963 :
964 0 : HLTError("Unknown option '%s'.", argv[i]);
965 0 : return -EINVAL;
966 : } // for loop
967 :
968 : // If no errors were specified then set to 1% single bit corruption.
969 0 : if (fCorruptionInfoList.size() == 0)
970 : {
971 0 : minpos = 0;
972 0 : maxpos = 0xFFFFFFFFFFFFFFFFull;
973 0 : alignment = 1;
974 : useErrorRate = true;
975 0 : errorrate = 0.001;
976 0 : AddCorruptionCommand(
977 0 : kSingleFlips, minpos, maxpos, alignment, useErrorRate, errorrate
978 : );
979 0 : }
980 :
981 0 : gRandom->SetSeed(0); // Use current time.
982 :
983 0 : HLTInfo("Starting Corruptor Component.");
984 0 : return 0;
985 0 : }
986 :
987 :
988 : Int_t AliHLTCorruptorComponent::DoDeinit()
989 : {
990 : // Cleans up the corruptor component.
991 0 : fBlockIdList.clear();
992 0 : return 0;
993 : }
994 :
995 :
996 : bool AliHLTCorruptorComponent::ShouldProcess(const AliHLTComponentBlockData* block) const
997 : {
998 0 : if (fBlockIdList.size() == 0) return true;
999 0 : for (size_t i = 0; i < fBlockIdList.size(); ++i)
1000 : {
1001 0 : AliBlockId id = fBlockIdList[i];
1002 0 : AliHLTComponentDataType type = AliHLTComponentDataTypeInitializer(
1003 0 : id.fTypeSet ? id.fType : kAliHLTAnyDataType,
1004 0 : id.fOriginSet ? id.fType.fOrigin : kAliHLTDataOriginAny
1005 : );
1006 0 : if (type != block->fDataType) continue;
1007 0 : if (id.fSpecSet and id.fSpec != block->fSpecification) continue;
1008 0 : return true;
1009 0 : }
1010 0 : return false;
1011 0 : }
1012 :
1013 :
1014 : void AliHLTCorruptorComponent::ApplyCorruption(std::vector<bool>& bits) const
1015 : {
1016 : // Applies corruption to the bit string.
1017 :
1018 0 : std::vector<bool> removed;
1019 0 : std::vector<bool> pattern;
1020 0 : for (size_t i = 0; i < fCorruptionInfoList.size(); ++i)
1021 : {
1022 0 : AliCorruptionInfo info = fCorruptionInfoList[i];
1023 : #ifdef DEBUG
1024 : const char* cmdtype = NULL;
1025 : switch (info.fType)
1026 : {
1027 : case kSingleFlips: cmdtype = "kSingleFlips"; break;
1028 : case kBurstErrors: cmdtype = "kBurstErrors"; break;
1029 : case kReplace: cmdtype = "kReplace"; break;
1030 : case kReplaceRandom: cmdtype = "kReplaceRandom"; break;
1031 : case kInsert: cmdtype = "kInsert"; break;
1032 : case kInsertRandom: cmdtype = "kInsertRandom"; break;
1033 : case kRemove: cmdtype = "kRemove"; break;
1034 : default: cmdtype = "UNKNOWN"; break;
1035 : }
1036 : HLTDebug("Processing corruption command %u of %u, fType = %s,"
1037 : " fMinRange = %llu, fMaxRange = %llu, fAlignment = %llu,"
1038 : " fUseRate = %s, fRate = %.16f, fMinErrors = %llu, fMaxErrors = %llu"
1039 : " fBurstErrorLength = %llu, fBurstErrorCount = %llu,"
1040 : " fMinBits = %llu, fMaxBits = %llu, fFirstPattern = %llu, fLastPattern = %llu.",
1041 : i, fCorruptionInfoList.size(), cmdtype,
1042 : info.fMinRange, info.fMaxRange, info.fAlignment,
1043 : (info.fUseRate ? "true" : "false"), info.fRate,
1044 : info.fMinErrors, info.fMaxErrors,
1045 : info.fBurstErrorLength, info.fBurstErrorCount,
1046 : info.fMinBits, info.fMaxBits,
1047 : AliHLTUInt64_t(info.fFirstPattern), AliHLTUInt64_t(info.fLastPattern)
1048 : );
1049 : #endif // DEBUG
1050 :
1051 : // Calculate the range (and adjust for buffer size)
1052 0 : AliHLTUInt64_t minrange = info.fMinRangeRelative ? bits.size() - info.fMinRange : info.fMinRange;
1053 0 : AliHLTUInt64_t maxrange = info.fMaxRangeRelative ? bits.size() - info.fMaxRange : info.fMaxRange;
1054 0 : if (minrange == 0xFFFFFFFFFFFFFFFFull)
1055 : {
1056 0 : if (info.fType == kInsert or info.fType == kInsertRandom or bits.size() == 0)
1057 : {
1058 0 : minrange = bits.size();
1059 0 : }
1060 : else
1061 : {
1062 0 : minrange = bits.size() - 1;
1063 : }
1064 : }
1065 0 : if (maxrange == 0xFFFFFFFFFFFFFFFFull)
1066 : {
1067 0 : if (info.fType == kInsert or info.fType == kInsertRandom or bits.size() == 0)
1068 : {
1069 0 : maxrange = bits.size();
1070 0 : }
1071 : else
1072 : {
1073 0 : maxrange = bits.size() - 1;
1074 : }
1075 : }
1076 0 : if (maxrange < minrange) maxrange = minrange;
1077 :
1078 : // Select the correct number of errors to generate.
1079 : AliHLTUInt64_t errorcount = 0;
1080 0 : if (info.fUseRate)
1081 : {
1082 0 : errorcount = AliHLTUInt64_t(bits.size() * info.fRate);
1083 0 : }
1084 : else
1085 : {
1086 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1087 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1088 0 : errorcount = rnum % (info.fMaxErrors - info.fMinErrors + 1) + info.fMinErrors;
1089 : }
1090 :
1091 : // Build the pattern bits for a replace or insert command.
1092 0 : if (info.fType == kReplace or info.fType == kInsert)
1093 : {
1094 0 : pattern.clear();
1095 0 : for (size_t k = info.fFirstPattern; k < info.fLastPattern; ++k)
1096 : {
1097 0 : const AliPattern& pat = fPatterns[k];
1098 0 : if (pat.fUseRemoved)
1099 : {
1100 0 : pattern.insert(pattern.end(), removed.begin(), removed.end());
1101 0 : }
1102 : else
1103 : {
1104 0 : for (AliHLTUInt8_t j = 0; j < pat.fWidth; ++j)
1105 : {
1106 0 : pattern.push_back( ((pat.fPattern >> j) & 0x1) == 0x1 );
1107 : }
1108 : }
1109 : }
1110 0 : }
1111 :
1112 : // Find a random value for the number of bits to use for the corresponding
1113 : // replace-random, insert-random and remove commands.
1114 : AliHLTUInt64_t bitcount = 0;
1115 0 : if (info.fType == kReplaceRandom or info.fType == kInsertRandom or info.fType == kRemove)
1116 : {
1117 : AliHLTUInt64_t minbits = info.fMinBits;
1118 : AliHLTUInt64_t maxbits = info.fMaxBits;
1119 0 : if (minbits == 0xFFFFFFFFFFFFFFFFull) minbits = bits.size();
1120 0 : if (maxbits == 0xFFFFFFFFFFFFFFFFull) maxbits = bits.size();
1121 0 : if (maxbits < minbits) maxbits = minbits;
1122 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1123 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1124 0 : bitcount = rnum % (maxbits - minbits + 1) + minbits;
1125 0 : }
1126 :
1127 0 : switch (info.fType)
1128 : {
1129 : case kSingleFlips:
1130 0 : for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
1131 : {
1132 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1133 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1134 0 : AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
1135 0 : pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
1136 0 : if (not (pos < bits.size())) continue;
1137 0 : bits[pos] = not bits[pos];
1138 0 : }
1139 0 : break;
1140 : case kBurstErrors:
1141 0 : for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
1142 : {
1143 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1144 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1145 0 : AliHLTUInt64_t firstpos = rnum % (maxrange - minrange + 1) + minrange;
1146 0 : firstpos = ((firstpos - minrange) / info.fAlignment) * info.fAlignment + minrange;
1147 0 : AliHLTUInt64_t lastpos = firstpos + info.fBurstErrorLength;
1148 0 : if (lastpos < firstpos)
1149 : {
1150 0 : HLTWarning("Burst error length %llu is too large and caused an overflow.",
1151 : info.fBurstErrorLength
1152 : );
1153 : lastpos = firstpos;
1154 0 : }
1155 0 : if (lastpos == firstpos) continue;
1156 0 : for (AliHLTUInt64_t j = 0; j < info.fBurstErrorCount; ++j)
1157 : {
1158 0 : rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1159 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1160 0 : AliHLTUInt64_t pos = rnum % (lastpos - firstpos) + firstpos;
1161 0 : if (not (pos < bits.size())) continue;
1162 0 : bits[pos] = not bits[pos];
1163 0 : }
1164 0 : }
1165 0 : break;
1166 : case kReplace:
1167 0 : for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
1168 : {
1169 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1170 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1171 0 : AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
1172 0 : pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
1173 0 : for (UInt_t j = pos; j < pos + pattern.size() and j < bits.size(); ++j)
1174 : {
1175 0 : bits[j] = pattern[j-pos];
1176 : }
1177 : }
1178 0 : break;
1179 : case kReplaceRandom:
1180 0 : for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
1181 : {
1182 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1183 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1184 0 : AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
1185 0 : pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
1186 0 : for (UInt_t j = pos; j < pos + bitcount and j < bits.size(); ++j)
1187 : {
1188 0 : bits[j] = gRandom->Integer(2) == 1;
1189 : }
1190 : }
1191 0 : break;
1192 : case kInsert:
1193 0 : for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
1194 : {
1195 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1196 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1197 0 : AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
1198 0 : pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
1199 0 : if (not (pos <= bits.size())) continue;
1200 0 : bits.insert(bits.begin() + pos, pattern.begin(), pattern.end());
1201 0 : }
1202 0 : break;
1203 : case kInsertRandom:
1204 0 : for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
1205 : {
1206 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1207 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1208 0 : AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
1209 0 : pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
1210 0 : if (not (pos <= bits.size())) continue;
1211 0 : std::vector<bool> newbits;
1212 0 : for (UInt_t j = 0; j < bitcount; ++j)
1213 : {
1214 0 : newbits.push_back(gRandom->Integer(2) == 1);
1215 : }
1216 0 : bits.insert(bits.begin() + pos, newbits.begin(), newbits.end());
1217 0 : }
1218 0 : break;
1219 : case kRemove:
1220 0 : removed.clear();
1221 0 : for (AliHLTUInt64_t n = 0; n < errorcount; ++n)
1222 : {
1223 0 : AliHLTUInt64_t rnum = (AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF)) << 32)
1224 0 : | AliHLTUInt64_t(gRandom->Integer(0xFFFFFFFF));
1225 0 : AliHLTUInt64_t pos = rnum % (maxrange - minrange + 1) + minrange;
1226 0 : pos = ((pos - minrange) / info.fAlignment) * info.fAlignment + minrange;
1227 0 : if (not (pos < bits.size())) continue;
1228 0 : AliHLTUInt64_t end = pos + bitcount;
1229 0 : if (end > bits.size()) end = bits.size();
1230 0 : removed.insert(removed.begin(), bits.begin() + pos, bits.begin() + end);
1231 0 : bits.erase(bits.begin() + pos, bits.begin() + end);
1232 0 : }
1233 0 : break;
1234 : default:
1235 0 : HLTWarning("Received an unknown corruption type. There must be a program bug!");
1236 0 : continue;
1237 : }
1238 0 : }
1239 0 : }
1240 :
1241 :
1242 : int AliHLTCorruptorComponent::DoEvent(
1243 : const AliHLTComponentEventData& evtData,
1244 : const AliHLTComponentBlockData* blocks,
1245 : AliHLTComponentTriggerData& /*trigData*/,
1246 : AliHLTUInt8_t* outputPtr,
1247 : AliHLTUInt32_t& size,
1248 : AliHLTComponentBlockDataList& outputBlocks
1249 : )
1250 : {
1251 : // Processes the input data blocks.
1252 : // The data blocks will be copied to the output and corrupted in some way.
1253 :
1254 : AliHLTUInt8_t* output = outputPtr;
1255 : AliHLTUInt32_t totalSize = 0;
1256 :
1257 0 : for (AliHLTUInt32_t n = 0; n < evtData.fBlockCnt; ++n)
1258 : {
1259 : HLTDebug("Processing block %d, of type '%s' with specification 0x%8.8X.",
1260 : n, DataType2Text(blocks[n].fDataType).c_str(), blocks[n].fSpecification
1261 : );
1262 0 : if (not ShouldProcess(blocks + n))
1263 : {
1264 0 : Forward();
1265 0 : continue;
1266 : }
1267 :
1268 : // Convert data block buffer to a bit string.
1269 0 : std::vector<bool> bits;
1270 0 : const AliHLTUInt8_t* buffer = reinterpret_cast<const AliHLTUInt8_t*>(blocks[n].fPtr);
1271 0 : for (AliHLTUInt32_t i = 0; i < blocks[n].fSize; ++i)
1272 : {
1273 0 : for (AliHLTUInt8_t j = 0; j < 8; ++j)
1274 : {
1275 0 : bits.push_back( ((buffer[i] >> j) & 0x1) == 0x1 );
1276 : }
1277 : }
1278 :
1279 0 : ApplyCorruption(bits);
1280 :
1281 : // Convert bit string back to a data buffer.
1282 0 : if (bits.size() > 0xFFFFFFFFull * 8)
1283 : {
1284 0 : HLTWarning("The internal bit string representation is too large for the output buffer. Skipping block.");
1285 0 : continue;
1286 : }
1287 0 : AliHLTUInt32_t blockSize = bits.size() / 8;
1288 0 : if (bits.size() % 8 > 0) ++blockSize;
1289 :
1290 0 : if (totalSize + blockSize > size)
1291 : {
1292 0 : HLTError("Out of buffer space. Require %d bytes but have %d bytes of buffer space.",
1293 : totalSize + blockSize, size
1294 : );
1295 0 : fBufferMultiplier *= 8;
1296 0 : return -ENOSPC;
1297 : }
1298 :
1299 0 : memset(output, 0x0, blockSize);
1300 0 : for (size_t i = 0; i < bits.size(); ++i)
1301 : {
1302 0 : AliHLTUInt32_t byte = i / 8;
1303 0 : AliHLTUInt32_t bit = i % 8;
1304 0 : output[byte] = output[byte] | (bits[i] << bit);
1305 : }
1306 :
1307 0 : AliHLTComponentBlockData bd;
1308 0 : FillBlockData(bd);
1309 0 : bd.fPtr = outputPtr;
1310 0 : bd.fOffset = totalSize;
1311 0 : bd.fSize = blockSize;
1312 0 : bd.fDataType = blocks[n].fDataType;
1313 0 : bd.fSpecification = blocks[n].fSpecification;
1314 0 : outputBlocks.push_back(bd);
1315 :
1316 : totalSize += blockSize;
1317 0 : output += blockSize;
1318 0 : }
1319 :
1320 0 : size = totalSize; // Set the correct output size.
1321 0 : return 0;
1322 0 : }
|