1 /* Copyright (C) 2014 InfiniDB, Inc.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 // $Id: tdriver-filter.cpp 9210 2013-01-21 14:10:42Z rdempsey $
19
20 #include <list>
21 #include <sstream>
22 #include <pthread.h>
23 #include <iomanip>
24 #include <cppunit/extensions/HelperMacros.h>
25 #include <cppunit/extensions/TestFactoryRegistry.h>
26 #include <cppunit/ui/text/TestRunner.h>
27
28 #include "fifo.h"
29 #include "constantdatalist.h"
30
31 #include "calpontsystemcatalog.h"
32 using namespace joblist;
33
34 #include "filteroperation.h"
35
36
37 #include <boost/any.hpp>
38 #include <boost/function.hpp>
39 #include "bytestream.h"
40 #include <time.h>
41 #include <sys/time.h>
42
43 #define DEBUG
44
45 using namespace std;
46 using namespace joblist;
47 using namespace messageqcpp;
48
49 // Timer class used by this tdriver to output elapsed times, etc.
50 class Timer
51 {
52 public:
start(const string & message)53 void start(const string& message)
54 {
55 if (!fHeaderDisplayed)
56 {
57 header();
58 fHeaderDisplayed = true;
59 }
60
61 gettimeofday(&fTvStart, 0);
62 cout << timestr() << " Start " << message << endl;
63 }
64
stop(const string & message)65 void stop(const string& message)
66 {
67 time_t now;
68 time(&now);
69 string secondsElapsed;
70 getTimeElapsed(secondsElapsed);
71 cout << timestr() << " " << secondsElapsed << " Stop " << message << endl;
72 }
73
Timer()74 Timer() : fHeaderDisplayed(false) {}
75
76 private:
77
78 struct timeval fTvStart;
79 bool fHeaderDisplayed;
80
getTimeElapsed(string & seconds)81 double getTimeElapsed(string& seconds)
82 {
83 struct timeval tvStop;
84 gettimeofday(&tvStop, 0);
85 double secondsElapsed =
86 (tvStop.tv_sec + (tvStop.tv_usec / 1000000.0)) -
87 (fTvStart.tv_sec + (fTvStart.tv_usec / 1000000.0));
88 ostringstream oss;
89 oss << secondsElapsed;
90 seconds = oss.str();
91 seconds.resize(8, '0');
92 return secondsElapsed;
93 }
94
timestr()95 string timestr()
96 {
97 struct tm tm;
98 struct timeval tv;
99
100 gettimeofday(&tv, 0);
101 localtime_r(&tv.tv_sec, &tm);
102
103 ostringstream oss;
104 oss << setfill('0')
105 << setw(2) << tm.tm_hour << ':'
106 << setw(2) << tm.tm_min << ':'
107 << setw(2) << tm.tm_sec << '.'
108 << setw(6) << tv.tv_usec
109 ;
110 return oss.str();
111 }
112
header()113 void header()
114 {
115 cout << endl;
116 cout << "Time Seconds Activity" << endl;
117 }
118 };
119
120 class FilterDriver : public CppUnit::TestFixture
121 {
122
123 CPPUNIT_TEST_SUITE(FilterDriver);
124
125 CPPUNIT_TEST(DOUBLE_TIME_TEST);
126
127 CPPUNIT_TEST_SUITE_END();
128
129 private:
130 // Creates two fifos with numRows and performs the passed comparison against their values.
131 // The first fifo will contain values 0..numRows-1.
132 // The second fifo will contain values numrows-1..0.
133 // Both bands will containt the same rids.
134 // Outputs timing results for loading each fifo, doing the comparison, and iterating over the results.
135 // Outputs the number of qualifying rows.
136 // Asserts that the number of qualifying rows is correct.
filterTest(const FilterOperation::FilterOperator & fo,const int & numRows)137 void filterTest(const FilterOperation::FilterOperator& fo, const int& numRows)
138 {
139 Timer timer;
140 cout << endl;
141 cout << "------------------------------------------------------------" << endl;
142 int i;
143 ElementType element;
144
145 stringstream ss;
146 ss << "loading first fifo with " << numRows << " rows.";
147 string message = ss.str();
148 timer.start(message);
149 FIFO<ElementType> fifo1(1, numRows);
150
151 for (i = 0; i < numRows; i++)
152 {
153 element.first = i;
154 element.second = i;
155 fifo1.insert(element);
156 }
157
158 fifo1.endOfInput();
159 timer.stop(message);
160
161 stringstream ss2;
162 ss2.flush();
163 ss2 << "loading second fifo with " << numRows << " rows.";
164 message = ss2.str();
165 timer.start(message);
166
167 FIFO<ElementType> fifo2(1, numRows);
168
169 for (i = 0; i < numRows; i++)
170 {
171 element.first = i;
172 element.second = numRows - (i + 1);
173 fifo2.insert(element);
174 }
175
176 fifo2.endOfInput();
177 timer.stop(message);
178
179 FIFO<ElementType> fifo3(1, numRows);
180
181 DataList<ElementType>* dl1 = (DataList<ElementType>*) &fifo1;
182 DataList<ElementType>* dl2 = (DataList<ElementType>*) &fifo2;
183 DataList<ElementType>* dl3 = (DataList<ElementType>*) &fifo3;
184 int assertCount;
185
186 switch (fo)
187 {
188 case FilterOperation::GT:
189 message = "GT Test";
190 assertCount = numRows / 2;
191 break;
192
193 case FilterOperation::LT:
194 message = "LT Test";
195 assertCount = numRows / 2;
196 break;
197
198 case FilterOperation::GTE:
199 message = "GTE Test";
200 assertCount = (numRows / 2);
201
202 if (numRows % 2 > 0)
203 assertCount++;
204
205 break;
206
207 case FilterOperation::LTE:
208 message = "LTE Test";
209 assertCount = (numRows / 2);
210
211 if (numRows % 2 > 0)
212 assertCount++;
213
214 break;
215
216 case FilterOperation::EQ:
217 message = "EQ Test";
218 assertCount = numRows % 2;
219 break;
220
221 case FilterOperation::NE:
222 message = "NE Test";
223 assertCount = numRows - numRows % 2;
224 break;
225
226 default:
227 break;
228 }
229
230 timer.start(message);
231 FilterOperation filterOperation;
232 filterOperation.filter(fo, *dl1, *dl2, *dl3);
233 timer.stop(message);
234 fifo3.endOfInput();
235
236 timer.start("iterating over result datalist");
237 bool more;
238 int it;
239 it = fifo3.getIterator();
240 int count = 0;
241
242 do
243 {
244 more = fifo3.next(it, &element);
245
246 if (more)
247 {
248 count++;
249 // cout << element.fRid << " " << element.fValue << endl;
250 }
251 }
252 while (more);
253
254 timer.stop("iterating over result datalist");
255
256 cout << count << " rows qualified." << endl;
257 idbassert(count == assertCount);
258 }
259
260 // Creates two string fifos with numRows and performs the passed comparison against their values.
261 // The first fifo will contain values 0..numRows-1.
262 // The second fifo will contain values numrows-1..0.
263 // Both bands will containt the same rids.
264 // Outputs timing results for loading each fifo, doing the comparison, and iterating over the results.
265 // Outputs the number of qualifying rows.
266 // Asserts that the number of qualifying rows is correct.
stringFilterTest(const FilterOperation::FilterOperator & fo,const int & numRows)267 void stringFilterTest(const FilterOperation::FilterOperator& fo, const int& numRows)
268 {
269 Timer timer;
270 cout << endl;
271 cout << "------------------------------------------------------------" << endl;
272 int i;
273 StringElementType element;
274
275 stringstream ss;
276 ss << "loading first fifo with " << numRows << " rows with StringElementType.";
277 string message = ss.str();
278 timer.start(message);
279 FIFO<StringElementType> fifo1(1, numRows);
280
281 for (i = 0; i < numRows; i++)
282 {
283 element.first = i;
284 element.second = i;
285 fifo1.insert(element);
286 }
287
288 fifo1.endOfInput();
289 timer.stop(message);
290
291 stringstream ss2;
292 ss2.flush();
293 ss2 << "loading second fifo with " << numRows << " rows with StringElementType.";
294 message = ss2.str();
295 timer.start(message);
296
297 FIFO<StringElementType> fifo2(1, numRows);
298
299 for (i = 0; i < numRows; i++)
300 {
301 element.first = i;
302 element.second = numRows - (i + 1);
303 fifo2.insert(element);
304 }
305
306 fifo2.endOfInput();
307 timer.stop(message);
308
309 FIFO<StringElementType> fifo3(1, numRows);
310
311 DataList<StringElementType>* dl1 = (DataList<StringElementType>*) &fifo1;
312 DataList<StringElementType>* dl2 = (DataList<StringElementType>*) &fifo2;
313 DataList<StringElementType>* dl3 = (DataList<StringElementType>*) &fifo3;
314 int assertCount;
315
316 switch (fo)
317 {
318 case FilterOperation::GT:
319 message = "GT Test";
320 assertCount = numRows / 2;
321 break;
322
323 case FilterOperation::LT:
324 message = "LT Test";
325 assertCount = numRows / 2;
326 break;
327
328 case FilterOperation::GTE:
329 message = "GTE Test";
330 assertCount = (numRows / 2);
331
332 if (numRows % 2 > 0)
333 assertCount++;
334
335 break;
336
337 case FilterOperation::LTE:
338 message = "LTE Test";
339 assertCount = (numRows / 2);
340
341 if (numRows % 2 > 0)
342 assertCount++;
343
344 break;
345
346 case FilterOperation::EQ:
347 message = "EQ Test";
348 assertCount = numRows % 2;
349 break;
350
351 case FilterOperation::NE:
352 message = "NE Test";
353 assertCount = numRows - numRows % 2;
354 break;
355
356 default:
357 break;
358 }
359
360 timer.start(message);
361 FilterOperation filterOperation;
362 filterOperation.filter(fo, *dl1, *dl2, *dl3);
363 timer.stop(message);
364 fifo3.endOfInput();
365
366 timer.start("iterating over result datalist");
367 bool more;
368 int it;
369 it = fifo3.getIterator();
370 int count = 0;
371
372 do
373 {
374 more = fifo3.next(it, &element);
375
376 if (more)
377 {
378 count++;
379 // cout << element.fRid << " " << element.fValue << endl;
380 }
381 }
382 while (more);
383
384 timer.stop("iterating over result datalist");
385
386 cout << count << " rows qualified." << endl;
387 idbassert(count == assertCount);
388 }
389
390 // Creates two double fifos with numRows and performs the passed comparison against their values.
391 // The first fifo will contain values 0..numRows-1.
392 // The second fifo will contain values numrows-1..0.
393 // Both bands will containt the same rids.
394 // Outputs timing results for loading each fifo, doing the comparison, and iterating over the results.
395 // Outputs the number of qualifying rows.
396 // Asserts that the number of qualifying rows is correct.
doubleFilterTest(const FilterOperation::FilterOperator & fo,const int & numRows)397 void doubleFilterTest(const FilterOperation::FilterOperator& fo, const int& numRows)
398 {
399 Timer timer;
400 cout << endl;
401 cout << "------------------------------------------------------------" << endl;
402 int i;
403 DoubleElementType element;
404
405 stringstream ss;
406 ss << "loading first fifo with " << numRows << " rows of DoubleElementType.";
407 string message = ss.str();
408 timer.start(message);
409 FIFO<DoubleElementType> fifo1(1, numRows);
410
411 for (i = 0; i < numRows; i++)
412 {
413 element.first = i;
414 element.second = i + 0.1;
415 fifo1.insert(element);
416 }
417
418 fifo1.endOfInput();
419 timer.stop(message);
420
421 stringstream ss2;
422 ss2.flush();
423 ss2 << "loading second fifo with " << numRows << " rows.";
424 message = ss2.str();
425 timer.start(message);
426
427 FIFO<DoubleElementType> fifo2(1, numRows);
428
429 for (i = 0; i < numRows; i++)
430 {
431 element.first = i;
432 element.second = numRows - (i + 1) + 0.1;
433 fifo2.insert(element);
434 }
435
436 fifo2.endOfInput();
437 timer.stop(message);
438
439 FIFO<DoubleElementType> fifo3(1, numRows);
440
441 DataList<DoubleElementType>* dl1 = (DataList<DoubleElementType>*) &fifo1;
442 DataList<DoubleElementType>* dl2 = (DataList<DoubleElementType>*) &fifo2;
443 DataList<DoubleElementType>* dl3 = (DataList<DoubleElementType>*) &fifo3;
444 int assertCount;
445
446 switch (fo)
447 {
448 case FilterOperation::GT:
449 message = "GT Test";
450 assertCount = numRows / 2;
451 break;
452
453 case FilterOperation::LT:
454 message = "LT Test";
455 assertCount = numRows / 2;
456 break;
457
458 case FilterOperation::GTE:
459 message = "GTE Test";
460 assertCount = (numRows / 2);
461
462 if (numRows % 2 > 0)
463 assertCount++;
464
465 break;
466
467 case FilterOperation::LTE:
468 message = "LTE Test";
469 assertCount = (numRows / 2);
470
471 if (numRows % 2 > 0)
472 assertCount++;
473
474 break;
475
476 case FilterOperation::EQ:
477 message = "EQ Test";
478 assertCount = numRows % 2;
479 break;
480
481 case FilterOperation::NE:
482 message = "NE Test";
483 assertCount = numRows - numRows % 2;
484 break;
485
486 default:
487 break;
488 }
489
490 timer.start(message);
491 FilterOperation filterOperation;
492 filterOperation.filter(fo, *dl1, *dl2, *dl3);
493 timer.stop(message);
494 fifo3.endOfInput();
495
496 timer.start("iterating over result datalist");
497 bool more;
498 int it;
499 it = fifo3.getIterator();
500 int count = 0;
501
502 do
503 {
504 more = fifo3.next(it, &element);
505
506 if (more)
507 {
508 count++;
509 // cout << element.fRid << " " << element.fValue << endl;
510 }
511 }
512 while (more);
513
514 timer.stop("iterating over result datalist");
515
516 cout << count << " rows qualified." << endl;
517 idbassert(count == assertCount);
518 }
519
520 public:
521
TIME_TEST()522 void TIME_TEST()
523 {
524 int numRows = 1000 * 1000 * 2;
525 filterTest(FilterOperation::GT, numRows);
526 filterTest(FilterOperation::LT, numRows);
527 filterTest(FilterOperation::LTE, numRows);
528 filterTest(FilterOperation::GTE, numRows);
529 filterTest(FilterOperation::EQ, numRows);
530 filterTest(FilterOperation::NE, numRows);
531 }
532
STRING_TIME_TEST()533 void STRING_TIME_TEST()
534 {
535 int numRows = 1000 * 1000 * 2;
536 stringFilterTest(FilterOperation::GT, numRows);
537 stringFilterTest(FilterOperation::LT, numRows);
538 stringFilterTest(FilterOperation::LTE, numRows);
539 stringFilterTest(FilterOperation::GTE, numRows);
540 stringFilterTest(FilterOperation::EQ, numRows);
541 stringFilterTest(FilterOperation::NE, numRows);
542 }
543
DOUBLE_TIME_TEST()544 void DOUBLE_TIME_TEST()
545 {
546 int numRows = 1000 * 1000 * 2;
547 doubleFilterTest(FilterOperation::GT, numRows);
548 doubleFilterTest(FilterOperation::LT, numRows);
549 doubleFilterTest(FilterOperation::LTE, numRows);
550 doubleFilterTest(FilterOperation::GTE, numRows);
551 doubleFilterTest(FilterOperation::EQ, numRows);
552 doubleFilterTest(FilterOperation::NE, numRows);
553 }
554
QUICK_TEST()555 void QUICK_TEST()
556 {
557 float f = 1.1;
558 double d = 1.2;
559 uint64_t i = 1;
560 uint64_t* i_ptr = &i;
561 double* d_ptr = &d;
562 uint64_t* i2_ptr = (uint64_t*) d_ptr;
563 float* f_ptr = &f;
564 i_ptr = (uint64_t*) f_ptr;
565
566 cout << "*i_ptr=" << *i_ptr << endl;
567 cout << "*i2_ptr=" << *i2_ptr << endl;
568 f_ptr = (float*) i_ptr;
569
570 cout << "*f_ptr=" << *f_ptr << endl;
571
572 cout << endl;
573
574 if (d > i)
575 cout << "1.2 is greater than 1." << endl;
576
577 if (f > i)
578 cout << "1.1 is greater than 1." << endl;
579
580 if (d > f)
581 cout << "1.2 is greater than 1.1" << endl;
582
583 if (*i_ptr < *i2_ptr)
584 cout << "1.1 < 1.2 when represented as uint64_t." << endl;
585
586 cout << "sizeof(f) = " << sizeof(f) << endl;
587 cout << "sizeof(i) = " << sizeof(i) << endl;
588 cout << "sizeof(d) = " << sizeof(d) << endl;
589
590 double dbl = 9.7;
591 double dbl2 = 1.3;
592 i_ptr = (uint64_t*) &dbl;
593 i2_ptr = (uint64_t*) &dbl2;
594 cout << endl;
595 cout << "9.7 as int is " << *i_ptr << endl;
596 cout << "9.7 as int is " << *i2_ptr << endl;
597 cout << "1.2 < 9.7 is " << (*i_ptr < *i2_ptr) << endl;
598 }
599 };
600
601 CPPUNIT_TEST_SUITE_REGISTRATION(FilterDriver);
602
603
main(int argc,char ** argv)604 int main( int argc, char** argv)
605 {
606 CppUnit::TextUi::TestRunner runner;
607 CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
608 runner.addTest( registry.makeTest() );
609 bool wasSuccessful = runner.run( "", false );
610 return (wasSuccessful ? 0 : 1);
611 }
612
613
614