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 /*********************************************************************
19 * $Id: tdriver.cpp 1823 2013-01-21 14:13:09Z rdempsey $
20 *
21 ********************************************************************/
22
23 #include <iostream>
24 #include <pthread.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/ipc.h>
28 #include <sys/sem.h>
29 #include <sys/shm.h>
30 #include <stdexcept>
31 #include <signal.h>
32 #include <values.h>
33 #include <cppunit/extensions/HelperMacros.h>
34
35 #include "brm.h"
36 #include "lbidresourcegraph.h"
37
38 #ifdef NO_TESTS
39 #undef CPPUNIT_ASSERT
40 #define CPPUNIT_ASSERT(a)
41 #endif
42
43 using namespace BRM;
44 using namespace std;
45 using namespace config;
46
47 pthread_mutex_t mutex;
48
keepalive(int signum)49 void keepalive(int signum)
50 {
51 cerr << "Yes, it's still going..." << endl;
52 alarm(290);
53 }
54
dummy_1(void * arg)55 void* dummy_1(void* arg)
56 {
57 LBIDResourceGraph* rg = (LBIDResourceGraph*) arg;
58 int err;
59 VER_t txn = 2;
60
61 pthread_mutex_lock(&mutex);
62 err = rg->reserveRange(0, 2000, txn, mutex);
63 CPPUNIT_ASSERT(err == 0);
64 rg->releaseResources(txn);
65 pthread_mutex_unlock(&mutex);
66 return NULL;
67 }
68
dummy_deadlock(void * arg)69 void* dummy_deadlock(void* arg)
70 {
71 LBIDResourceGraph* rg = (LBIDResourceGraph*) arg;
72 int err;
73 VER_t txn = 2;
74
75 pthread_mutex_lock(&mutex);
76 err = rg->reserveRange(1001, 2000, txn, mutex);
77 CPPUNIT_ASSERT(err == 0);
78 err = rg->reserveRange(0, 1000, txn, mutex);
79 CPPUNIT_ASSERT(err == 0);
80 rg->releaseResources(txn);
81 CPPUNIT_ASSERT(err == 0);
82 pthread_mutex_unlock(&mutex);
83 return NULL;
84 }
85
fragd_range_helper(void * arg)86 void* fragd_range_helper(void* arg)
87 {
88 LBIDResourceGraph* rg = (LBIDResourceGraph*) arg;
89 set<ResourceNode*, RNLess<ResourceNode*> >* resources;
90 map<VER_t, TransactionNode*>* txns;
91 int err;
92 VER_t txn = 2;
93
94 pthread_mutex_lock(&mutex);
95 resources = rg->getResources();
96 txns = rg->getTxns();
97 CPPUNIT_ASSERT(resources->size() == 2);
98 CPPUNIT_ASSERT(txns->size() == 1);
99 err = rg->reserveRange(0, 5000, txn, mutex);
100
101 // blocks, main thread releases
102
103 CPPUNIT_ASSERT(err == 0);
104 CPPUNIT_ASSERT(resources->size() == 5);
105 CPPUNIT_ASSERT(txns->size() == 1);
106 rg->releaseResources(txn);
107 pthread_mutex_unlock(&mutex);
108
109 return NULL;
110 }
111
overlapping_range_helper(void * arg)112 void* overlapping_range_helper(void* arg)
113 {
114 LBIDResourceGraph* rg = (LBIDResourceGraph*) arg;
115 set<ResourceNode*, RNLess<ResourceNode*> >* resources;
116 set<ResourceNode*, RNLess<ResourceNode*> >::const_iterator it;
117 map<VER_t, TransactionNode*>* txns;
118 int err;
119 VER_t txn = 2;
120
121 pthread_mutex_lock(&mutex);
122 resources = rg->getResources();
123 txns = rg->getTxns();
124 CPPUNIT_ASSERT(resources->size() == 2);
125 CPPUNIT_ASSERT(txns->size() == 1);
126 err = rg->reserveRange(1100, 3900, txn, mutex);
127
128 // blocks, main thread releases
129
130 CPPUNIT_ASSERT(err == 0);
131 CPPUNIT_ASSERT(resources->size() == 3);
132 it = resources->begin();
133 CPPUNIT_ASSERT((*it)->start() == 1100);
134 CPPUNIT_ASSERT((*it)->end() == 2000);
135 it++;
136 CPPUNIT_ASSERT((*it)->start() == 2001);
137 CPPUNIT_ASSERT((*it)->end() == 3000);
138 it++;
139 CPPUNIT_ASSERT((*it)->start() == 3001);
140 CPPUNIT_ASSERT((*it)->end() == 3900);
141 CPPUNIT_ASSERT(txns->size() == 1);
142 rg->releaseResources(txn);
143 pthread_mutex_unlock(&mutex);
144
145 return NULL;
146 }
147
148 class BRMTest : public CppUnit::TestFixture
149 {
150
151 CPPUNIT_TEST_SUITE(BRMTest);
152 CPPUNIT_TEST(masterSegmentTest_goodbad);
153 CPPUNIT_TEST(extentMap_good_1);
154 #ifdef PARTITIONING
155 CPPUNIT_TEST(extentMap_range_1);
156 #endif
157 CPPUNIT_TEST(extentMap_freelist);
158 // CPPUNIT_TEST(extentMap_overfill);
159 //CPPUNIT_TEST(many_ExtentMap_instances); //Jean unsuggested this case since writeengine use singleton
160 CPPUNIT_TEST(copyLocks_good_1);
161 CPPUNIT_TEST(vbbm_good_1);
162 CPPUNIT_TEST(vbbm_good_1);
163 CPPUNIT_TEST(vss_good_1);
164 CPPUNIT_TEST(vss_good_1);
165 //CPPUNIT_TEST(brm_extentmap_good_1);//fix for bug 640, this test case has a bug
166 #ifdef PARTITIONING
167 CPPUNIT_TEST(brm_extentmap_range_1);
168 #endif
169 CPPUNIT_TEST(brm_good_2);
170 CPPUNIT_TEST(brm_good_3);
171 CPPUNIT_TEST(brm_deleteOID);
172 CPPUNIT_TEST(brm_HWM);
173 CPPUNIT_TEST(resource_graph_1);
174 CPPUNIT_TEST(resource_graph_fragd_range);
175 CPPUNIT_TEST(resource_graph_deadlock);
176 CPPUNIT_TEST(resource_graph_overlapping_ranges);
177
178 CPPUNIT_TEST_SUITE_END();
179
180 private:
181 public:
182
masterSegmentTest_goodbad()183 void masterSegmentTest_goodbad()
184 {
185 MasterSegmentTable mst;
186 struct MSTEntry* mt;
187
188 // cerr << "MST goodbad" << endl;
189
190 mt = mst.getTable_write(MasterSegmentTable::EMTable, false);
191 CPPUNIT_ASSERT(mt != NULL);
192 mt = mst.getTable_write(MasterSegmentTable::EMTable, false);
193 CPPUNIT_ASSERT(mt == NULL);
194 mt = mst.getTable_write(MasterSegmentTable::EMFreeList, false);
195 CPPUNIT_ASSERT(mt != NULL);
196 mt = mst.getTable_write(MasterSegmentTable::EMFreeList, false);
197 CPPUNIT_ASSERT(mt == NULL);
198 mt = mst.getTable_write(MasterSegmentTable::VBBMSegment, false);
199 CPPUNIT_ASSERT(mt != NULL);
200 mt = mst.getTable_write(MasterSegmentTable::VBBMSegment, false);
201 CPPUNIT_ASSERT(mt == NULL);
202
203 mst.releaseTable_write(MasterSegmentTable::EMTable);
204 mst.releaseTable_write(MasterSegmentTable::EMFreeList);
205 mst.releaseTable_write(MasterSegmentTable::VBBMSegment);
206
207 mt = mst.getTable_write(MasterSegmentTable::EMTable, false);
208 CPPUNIT_ASSERT(mt != NULL);
209 mt = mst.getTable_write(MasterSegmentTable::EMFreeList, false);
210 CPPUNIT_ASSERT(mt != NULL);
211 mt = mst.getTable_write(MasterSegmentTable::VBBMSegment, false);
212 CPPUNIT_ASSERT(mt != NULL);
213 mt = mst.getTable_write(MasterSegmentTable::EMTable, false);
214 CPPUNIT_ASSERT(mt == NULL);
215 mt = mst.getTable_write(MasterSegmentTable::EMFreeList, false);
216 CPPUNIT_ASSERT(mt == NULL);
217 mt = mst.getTable_write(MasterSegmentTable::VBBMSegment, false);
218 CPPUNIT_ASSERT(mt == NULL);
219 mst.releaseTable_write(MasterSegmentTable::EMTable);
220 mst.releaseTable_write(MasterSegmentTable::EMFreeList);
221 mst.releaseTable_write(MasterSegmentTable::VBBMSegment);
222
223 mt = mst.getTable_read(MasterSegmentTable::EMTable, false);
224 CPPUNIT_ASSERT(mt != NULL);
225 mt = mst.getTable_read(MasterSegmentTable::EMTable, false);
226 CPPUNIT_ASSERT(mt != NULL);
227 mt = mst.getTable_read(MasterSegmentTable::EMTable, false);
228 CPPUNIT_ASSERT(mt != NULL);
229 mt = mst.getTable_write(MasterSegmentTable::EMTable, false);
230 CPPUNIT_ASSERT(mt == NULL);
231 mst.releaseTable_read(MasterSegmentTable::EMTable);
232 mst.releaseTable_read(MasterSegmentTable::EMTable);
233 mst.releaseTable_read(MasterSegmentTable::EMTable);
234
235 mt = mst.getTable_write(MasterSegmentTable::EMTable, false);
236 CPPUNIT_ASSERT(mt != NULL);
237 mt = mst.getTable_read(MasterSegmentTable::EMTable, false);
238 CPPUNIT_ASSERT(mt == NULL);
239 mst.releaseTable_write(MasterSegmentTable::EMTable);
240 Config::deleteInstanceMap();
241 }
242
extentMap_good_1()243 void extentMap_good_1()
244 {
245 ExtentMap em;
246 int i, err, oid, iterations = 1300; // (EM_INITIAL_SIZE + 3*EM_INCREMENT)
247 int caughtException = 0, allocdSize;
248 uint32_t fbo, hwm;
249 BRM::HWM_t hwm2;
250 BRM::VER_t txnID;
251 vector<LBID_t> lbids;
252 const uint32_t extentSize = em.getExtentSize();
253
254 // cerr << "em_good_1" << endl;
255
256 for (i = 1; i < iterations; i++)
257 {
258 em.createExtent(extentSize, i, lbids, allocdSize);
259 em.confirmChanges();
260 CPPUNIT_ASSERT(lbids.size() == 1);
261 CPPUNIT_ASSERT((uint32_t)allocdSize == extentSize);
262 CPPUNIT_ASSERT(lbids.back() == static_cast<LBID_t>((i - 1)*extentSize));
263 }
264
265 em.checkConsistency();
266 em.save(string("EMImage"));
267 em.load(string("EMImage"));
268 em.checkConsistency();
269
270 for (i = 1; i < iterations; i++)
271 {
272 err = em.lookup(static_cast<LBID_t>((i - 1) * extentSize), oid, fbo);
273 CPPUNIT_ASSERT(err == 0);
274 CPPUNIT_ASSERT(oid == i);
275 CPPUNIT_ASSERT(fbo == 0);
276
277 if (i != 1)
278 {
279 err = em.lookup(static_cast<LBID_t>((i - 1) * extentSize - 1), oid, fbo);
280 CPPUNIT_ASSERT(err == 0);
281 CPPUNIT_ASSERT(oid == i - 1);
282 CPPUNIT_ASSERT(fbo == extentSize - 1);
283 }
284
285 if (i != iterations - 1)
286 {
287 err = em.lookup(static_cast<LBID_t>((i - 1) * extentSize + 1), oid, fbo);
288 CPPUNIT_ASSERT(err == 0);
289 CPPUNIT_ASSERT(oid == i);
290 CPPUNIT_ASSERT(fbo == 1);
291 }
292 }
293
294 em.checkConsistency();
295
296 err = em.lookup(static_cast<LBID_t>(i * extentSize), oid, fbo);
297 CPPUNIT_ASSERT(err == -1);
298
299 for (i = 1; i < iterations; i++)
300 {
301 err = em.getBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
302 hwm2, txnID);
303 CPPUNIT_ASSERT(err == 0);
304 CPPUNIT_ASSERT(hwm2 == 0);
305 CPPUNIT_ASSERT(txnID == 0);
306 err = em.setBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
307 i, i + 1);
308 em.confirmChanges();
309 CPPUNIT_ASSERT(err == 0);
310 err = em.getBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
311 hwm2, txnID);
312 CPPUNIT_ASSERT(err == 0);
313 CPPUNIT_ASSERT(hwm2 == static_cast<LBID_t>(i));
314 CPPUNIT_ASSERT(txnID == static_cast<VER_t>(i + 1));
315
316 hwm = em.getHWM(i);
317 CPPUNIT_ASSERT(hwm == 0);
318 em.setHWM(i, ((uint32_t)i > (extentSize - 1) ? extentSize - 1 : i));
319 em.confirmChanges();
320 hwm = em.getHWM(i);
321 CPPUNIT_ASSERT(hwm == static_cast<uint32_t>((uint32_t)i > extentSize - 1 ? extentSize - 1 : i));
322 }
323
324 em.checkConsistency();
325
326 #ifdef BRM_DEBUG
327 caughtException = 0;
328
329 try
330 {
331 em.setHWM(i, hwm);
332 }
333 catch (std::invalid_argument e)
334 {
335 caughtException = 1;
336 }
337
338 em.undoChanges();
339 CPPUNIT_ASSERT(caughtException == 1);
340 #endif
341
342 for (i = 1; i < iterations; i++)
343 {
344 em.deleteOID(i);
345 em.confirmChanges();
346 }
347
348 #ifdef BRM_DEBUG
349 caughtException = 0;
350
351 try
352 {
353 em.deleteOID(i);
354 }
355 catch (std::invalid_argument& e)
356 {
357 caughtException = 1;
358 }
359
360 em.undoChanges();
361 CPPUNIT_ASSERT(caughtException == 1);
362 #endif
363
364 em.checkConsistency();
365 Config::deleteInstanceMap();
366 }
367
368 #ifdef PARTITIONING
extentMap_range_1()369 void extentMap_range_1()
370 {
371 ExtentMap em;
372 int i, err, iterations = 1300; // (EM_INITIAL_SIZE + 3*EM_INCREMENT)
373 int caughtException = 0, allocdSize;
374 uint32_t hwm;
375 BRM::HWM_t hwm2;
376 BRM::VER_t txnID;
377 vector<LBID_t> lbids;
378 const uint32_t extentSize = em.getExtentSize();
379
380 for (i = 1; i < iterations; i++)
381 {
382 em.createRangeExtent(extentSize, i, lbids, allocdSize, EMRangePartition_t(0, 10, true, true));
383 em.confirmChanges();
384 CPPUNIT_ASSERT(lbids.size() == 1);
385 CPPUNIT_ASSERT((uint32_t)allocdSize == extentSize);
386 CPPUNIT_ASSERT(lbids.back() == static_cast<LBID_t>((i - 1)*extentSize));
387 }
388
389 em.checkConsistency();
390 em.save(string("EMImage"));
391 em.load(string("EMImage"));
392 em.checkConsistency();
393
394 LBIDRange_v lbidList;
395
396 for (i = 1; i < iterations; i++)
397 {
398
399 err = em.lookup(i, 1, lbidList);
400 CPPUNIT_ASSERT(lbidList.size() == 1);
401 CPPUNIT_ASSERT(err == lbidList.size());
402
403 err = em.lookup(i, i + 10, lbidList);
404 CPPUNIT_ASSERT(lbidList.size() == 0);
405 CPPUNIT_ASSERT(err == lbidList.size());
406
407 err = em.lookup(i * 10000, 1, lbidList);
408 CPPUNIT_ASSERT(lbidList.size() == 0);
409 CPPUNIT_ASSERT(err == lbidList.size());
410 }
411
412 em.checkConsistency();
413
414 err = em.lookup(i, 99, lbidList);
415 CPPUNIT_ASSERT(err == 0);
416 CPPUNIT_ASSERT(lbidList.size() == 0);
417
418 #ifdef BRM_DEBUG
419 caughtException = 0;
420
421 try
422 {
423 em.setHWM(i, hwm);
424 }
425 catch (std::invalid_argument e)
426 {
427 caughtException = 1;
428 }
429
430 em.undoChanges();
431 CPPUNIT_ASSERT(caughtException == 1);
432 #endif
433
434 for (i = 1; i < iterations; i++)
435 {
436 em.deleteOID(i);
437 em.confirmChanges();
438 }
439
440 #ifdef BRM_DEBUG
441 caughtException = 0;
442
443 try
444 {
445 em.deleteOID(i);
446 }
447 catch (std::invalid_argument& e)
448 {
449 caughtException = 1;
450 }
451
452 em.undoChanges();
453 CPPUNIT_ASSERT(caughtException == 1);
454 #endif
455
456 em.checkConsistency();
457 Config::deleteInstanceMap();
458 }
459 #endif
460
extentMap_freelist()461 void extentMap_freelist()
462 {
463 ExtentMap em;
464 int i, allocdSize, iterations = 1400; // (EM_INITIAL_SIZE + 4*EM_INCREMENT)
465 vector<LBID_t> lbids;
466 const int extentSize = em.getExtentSize();
467
468 // cerr << "em_freelist" << endl;
469
470 for (i = 1; i < iterations; i++)
471 {
472 em.createExtent(extentSize, i, lbids, allocdSize);
473 em.confirmChanges();
474 CPPUNIT_ASSERT(lbids.back() == static_cast<LBID_t>((i - 1)*extentSize));
475 }
476
477 em.checkConsistency();
478
479 //frag the lbid space to blow up the free list
480 for (i = 1; i < iterations; i += 2)
481 {
482 em.deleteOID(i);
483 em.confirmChanges();
484 }
485
486 em.checkConsistency();
487
488 //fill in the holes
489 for (i = 1; i < iterations; i += 2)
490 {
491 em.createExtent(extentSize, i, lbids, allocdSize);
492 em.confirmChanges();
493 }
494
495 for (i = 1; i < iterations; i += 2)
496 {
497 em.deleteOID(i);
498 em.confirmChanges();
499 }
500
501 for (i = 2; i < iterations; i += 2)
502 {
503 em.deleteOID(i);
504 em.confirmChanges();
505 }
506
507 em.checkConsistency();
508 Config::deleteInstanceMap();
509 }
510
511 /* This test verifies that the ExtentMap stops allocating space when it's full.
512 (Bug #104) It takes a long time to run with the default LBID
513 space characteristics so by default it's disabled.*/
extentMap_overfill()514 void extentMap_overfill()
515 {
516 int i, err, tmp;
517 BlockResolutionManager brm;
518 vector<LBID_t> lbids;
519
520 for (i = 1; i < 67109; i++)
521 {
522 err = brm.createExtent(1024000, i, lbids, tmp);
523 CPPUNIT_ASSERT(err == 0);
524 }
525
526 err = brm.createExtent(1024000, i, lbids, tmp);
527 CPPUNIT_ASSERT(err == -1);
528
529 for (i = 1; i < 67109; i++)
530 {
531 err = brm.deleteOID(i);
532 CPPUNIT_ASSERT(err == 0);
533 }
534
535 err = brm.deleteOID(i);
536 CPPUNIT_ASSERT(err == -1);
537 Config::deleteInstanceMap();
538 }
539
copyLocks_good_1()540 void copyLocks_good_1()
541 {
542 CopyLocks cl;
543 LBIDRange range;
544 int i, iterations = 1000;
545
546 // cerr << "copylocks_good_1" << endl;
547
548 cl.lock(CopyLocks::WRITE);
549 range.start = 5;
550 range.size = 2;
551 cl.lockRange(range, 0);
552 CPPUNIT_ASSERT(cl.isLocked(range) == true);
553 range.start++;
554 CPPUNIT_ASSERT(cl.isLocked(range) == true);
555 range.start++;
556 CPPUNIT_ASSERT(cl.isLocked(range) == false);
557 range.start = 0;
558 CPPUNIT_ASSERT(cl.isLocked(range) == false);
559 range.start = 3;
560 CPPUNIT_ASSERT(cl.isLocked(range) == false);
561 range.start++;
562 CPPUNIT_ASSERT(cl.isLocked(range) == true);
563 range.start = 5;
564 range.size = 1;
565 CPPUNIT_ASSERT(cl.isLocked(range) == true);
566 range.size = 2;
567 cl.releaseRange(range);
568
569 //make sure it can grow
570 for (i = 0; i < iterations * 2; i += 2)
571 {
572 range.start = i;
573 cl.lockRange(range, 0);
574 }
575
576 range.size = 1;
577
578 cl.save(string("CLImage"));
579 cl.load(string("CLImage"));
580
581 for (i = 0; i < iterations * 2; i++)
582 {
583 range.start = i;
584 CPPUNIT_ASSERT(cl.isLocked(range) == true);
585 }
586
587 range.start = i;
588 CPPUNIT_ASSERT(cl.isLocked(range) == false);
589
590 for (i = 0; i < iterations * 2; i += 2)
591 {
592 range.start = i;
593 cl.releaseRange(range);
594 }
595
596 cl.release(CopyLocks::WRITE);
597 Config::deleteInstanceMap();
598 }
599
brm_extentmap_good_1()600 void brm_extentmap_good_1()
601 {
602
603 BlockResolutionManager brm;
604 int i, err, oid, allocdSize,
605 iterations = 1300; // (EM_INITIAL_SIZE + 3*EM_INCREMENT)
606 uint32_t fbo, hwm;
607 vector<LBID_t> lbids;
608 HWM_t hwm2;
609 VER_t txnID;
610 const uint32_t extentSize = brm.getExtentSize();
611
612 // cerr << "brm_extentmap_good_1" << endl;
613
614 for (i = 1; i < iterations; i++)
615 {
616 brm.createExtent(extentSize, i, lbids, allocdSize);
617 CPPUNIT_ASSERT(lbids.back() == static_cast<LBID_t>((i - 1)*extentSize));
618 }
619
620 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
621 brm.saveExtentMap(string("EMImage"));
622 brm.loadExtentMap(string("EMImage"));
623 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
624 ExtentMap em;
625
626 //int32_t seqNum=0;
627 //int64_t max=0;
628 //int64_t min=0;
629 LBID_t lbid;
630 /*
631 for (i = 1; i < iterations; i++) {
632 lbid=(i-1)*extentSize;
633 err=em.updateMaxMin(lbid, 1, 0, seqNum); // sequenceNum=0
634 em.confirmChanges();
635 CPPUNIT_ASSERT(err==0);
636
637 max=-1;
638 min=-1;
639 err=em.getMaxMin(lbid, max, min, seqNum);
640 CPPUNIT_ASSERT(max==1);
641 CPPUNIT_ASSERT(min==0);
642 CPPUNIT_ASSERT(err==2);
643 CPPUNIT_ASSERT(seqNum==0);
644
645 err=em.updateMaxMin(lbid, 4, 2, seqNum); // sequenceNum=0
646 em.confirmChanges();
647 CPPUNIT_ASSERT(err==0);
648
649 max=-1;
650 min=-1;
651 seqNum++;
652 err=em.getMaxMin(lbid, max, min, seqNum);
653 CPPUNIT_ASSERT(max==4);
654 CPPUNIT_ASSERT(min==2);
655 CPPUNIT_ASSERT(err==2);
656 CPPUNIT_ASSERT(seqNum==0);
657
658 err=em.markInvalid(lbid); // sequenceNum=1, valid=1
659 em.confirmChanges();
660 CPPUNIT_ASSERT(err==0);
661
662 seqNum=0; // re-init seqNum
663 err=em.getMaxMin(lbid, max, min, seqNum);
664 CPPUNIT_ASSERT(err==1);
665 CPPUNIT_ASSERT(seqNum==1);
666
667 seqNum=0;
668 }
669 */
670
671 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
672
673 vector<LBID_t> lbidVector;
674 uint32_t offset;
675
676 for (i = 1; i < iterations; i++)
677 {
678 lbid = (i - 1) * extentSize;
679
680 for (int j = 0; (uint32_t)j < extentSize; j++)
681 lbidVector.push_back(lbid + j);
682
683 err = em.markInvalid(lbidVector);
684 em.confirmChanges();
685 CPPUNIT_ASSERT(err == 1);
686 lbidVector.clear();
687 em.lookup(lbid, oid, offset);
688 err = em.markInvalid(oid);
689 em.confirmChanges();
690 CPPUNIT_ASSERT(err == 0);
691 //CPPUNIT_ASSERT(oid==i);
692 oid = -1;
693 offset = 0;
694 }
695
696 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
697
698 for (i = 1; i < iterations; i++)
699 {
700 err = brm.lookup(static_cast<LBID_t>((i - 1) * extentSize), 0, false, oid, fbo);
701 CPPUNIT_ASSERT(err == 0);
702 CPPUNIT_ASSERT(oid == i);
703 CPPUNIT_ASSERT(fbo == 0);
704
705 if (i != 1)
706 {
707 err = brm.lookup(static_cast<LBID_t>((i - 1) * extentSize - 1), 0, false, oid, fbo);
708 CPPUNIT_ASSERT(err == 0);
709 CPPUNIT_ASSERT(oid == i - 1);
710 CPPUNIT_ASSERT(fbo == extentSize - 1);
711 }
712
713 if (i != iterations)
714 {
715 err = brm.lookup(static_cast<LBID_t>((i - 1) * extentSize + 1), 0, false, oid, fbo);
716 CPPUNIT_ASSERT(err == 0);
717 CPPUNIT_ASSERT(oid == i);
718 CPPUNIT_ASSERT(fbo == 1);
719 }
720 }
721
722 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
723
724 err = brm.lookup(static_cast<LBID_t>((i - 1) * extentSize), 0, false, oid, fbo);
725 CPPUNIT_ASSERT(err == -1);
726
727 for (i = 1; i < iterations; i++)
728 {
729 err = brm.getBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
730 hwm2, txnID);
731 CPPUNIT_ASSERT(err == 0);
732 CPPUNIT_ASSERT(hwm2 == 0);
733 CPPUNIT_ASSERT(txnID == 0);
734 err = brm.setBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
735 i, i + 1);
736 CPPUNIT_ASSERT(err == 0);
737 err = brm.getBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
738 hwm2, txnID);
739 CPPUNIT_ASSERT(err == 0);
740 CPPUNIT_ASSERT(hwm2 == static_cast<BRM::LBID_t>(i));
741 CPPUNIT_ASSERT(txnID == static_cast<BRM::VER_t>(i + 1));
742
743 err = brm.getHWM(i, hwm);
744 CPPUNIT_ASSERT(err == 0);
745 CPPUNIT_ASSERT(hwm == 0);
746 err = brm.setHWM(i, ((uint32_t)i > extentSize - 1 ? extentSize - 1 : i));
747 CPPUNIT_ASSERT(err == 0);
748 err = brm.getHWM(i, hwm);
749 CPPUNIT_ASSERT(err == 0);
750 CPPUNIT_ASSERT(hwm == static_cast<uint32_t>((uint32_t)i > extentSize - 1 ? extentSize - 1 : i));
751 }
752
753 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
754
755 #ifdef BRM_DEBUG
756 err = brm.setHWM(i, hwm);
757 CPPUNIT_ASSERT(err == -1);
758 #endif
759
760 for (i = 1; i < iterations; i++)
761 {
762 err = brm.deleteOID(i);
763 CPPUNIT_ASSERT(err == 0);
764 }
765
766 err = brm.deleteOID(i);
767 CPPUNIT_ASSERT(err == -1);
768
769 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
770 Config::deleteInstanceMap();
771 }
772
773 #ifdef PARTITIONING
brm_extentmap_range_1()774 void brm_extentmap_range_1()
775 {
776
777 BlockResolutionManager brm;
778 int i,
779 err,
780 oid,
781 allocdSize,
782 iterations = 1300; // (EM_INITIAL_SIZE + 3*EM_INCREMENT)
783 uint32_t fbo, hwm;
784 vector<LBID_t> lbids;
785 HWM_t hwm2;
786 VER_t txnID;
787 const uint32_t extentSize = brm.getExtentSize();
788 LBIDRange_v lbidList;
789
790 // cerr << "brm_extentmap_range_1" << endl;
791
792 for (i = 1; i < iterations; i++)
793 {
794 brm.createRangeExtent(extentSize, i, lbids, allocdSize,
795 EMRangePartition_t(0, 9, true, true) );
796 CPPUNIT_ASSERT(lbids.back() == static_cast<LBID_t>((i - 1)*extentSize));
797 CPPUNIT_ASSERT(lbids.size() == 1);
798 }
799
800 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
801 brm.saveExtentMap(string("EMImage"));
802 brm.loadExtentMap(string("EMImage"));
803 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
804
805 for (i = 1; i < iterations; i++)
806 {
807
808 err = brm.lookup(i, 1, lbidList);
809 CPPUNIT_ASSERT(err == 0);
810 CPPUNIT_ASSERT(lbidList.size() == 1);
811
812 err = brm.lookup(i, 10, lbidList);
813 CPPUNIT_ASSERT(err == 0);
814 CPPUNIT_ASSERT(lbidList.size() == 0);
815
816 err = brm.lookup(i * 10000, 1, lbidList);
817 CPPUNIT_ASSERT(err == 0);
818 CPPUNIT_ASSERT(lbidList.size() == 0);
819
820 }
821
822 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
823
824 err = brm.lookup(static_cast<LBID_t>((i - 1) * extentSize), 0, false, oid, fbo);
825 CPPUNIT_ASSERT(err == -1);
826
827 for (i = 1; i < iterations; i++)
828 {
829 err = brm.getBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
830 hwm2, txnID);
831 CPPUNIT_ASSERT(err == 0);
832 CPPUNIT_ASSERT(hwm2 == 0);
833 CPPUNIT_ASSERT(txnID == 0);
834 err = brm.setBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
835 i, i + 1);
836 CPPUNIT_ASSERT(err == 0);
837 err = brm.getBulkInsertVars(static_cast<LBID_t>((i - 1) * extentSize),
838 hwm2, txnID);
839 CPPUNIT_ASSERT(err == 0);
840 CPPUNIT_ASSERT(hwm2 == static_cast<BRM::LBID_t>(i));
841 CPPUNIT_ASSERT(txnID == static_cast<BRM::VER_t>(i + 1));
842
843 err = brm.getHWM(i, hwm);
844 CPPUNIT_ASSERT(err == 0);
845 CPPUNIT_ASSERT(hwm == 0);
846 err = brm.setHWM(i, (i > extentSize - 1 ? extentSize - 1 : i));
847 CPPUNIT_ASSERT(err == 0);
848 err = brm.getHWM(i, hwm);
849 CPPUNIT_ASSERT(err == 0);
850 CPPUNIT_ASSERT(hwm == static_cast<uint32_t>(i > extentSize - 1 ? extentSize - 1 : i));
851 }
852
853 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
854
855 #ifdef BRM_DEBUG
856 err = brm.setHWM(i, hwm);
857 CPPUNIT_ASSERT(err == -1);
858 #endif
859
860 for (i = 1; i < iterations; i++)
861 {
862 err = brm.deleteOID(i);
863 CPPUNIT_ASSERT(err == 0);
864 }
865
866 err = brm.deleteOID(i);
867 CPPUNIT_ASSERT(err == -1);
868 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
869 Config::deleteInstanceMap();
870 }
871 #endif
872
brm_good_2()873 void brm_good_2()
874 {
875 BlockResolutionManager brm;
876 VBBM vbbm;
877 VSS vss;
878 CopyLocks cl;
879 int i, err, size;
880 vector<LBID_t> lbids;
881 vector<EMEntry> extents;
882 LBIDRange_v ranges;
883 LBIDRange_v::iterator lbidRangeIT;
884 vector<VBRange> vbRanges, vbRanges2;
885 vector<VBRange>::iterator vbRangesIT;
886 EMEntry em;
887 OID_t oid;
888 uint32_t fbo;
889 LBIDRange range;
890 VBRange vbRange;
891 VER_t verID;
892 bool vbFlag;
893
894 // Buildbot times out on the getBlocks() call during leakcheck b/c it takes
895 // > 5 mins for some reason. Have to ping it before 300 seconds go by.
896 void (*oldsig)(int);
897
898 // cerr << "brm_good_2" << endl;
899
900 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
901
902 oldsig = signal(SIGALRM, keepalive);
903 alarm(290);
904
905 err = brm.lookup(0, 0, false, oid, fbo);
906 CPPUNIT_ASSERT(err == -1);
907 err = brm.lookup(0, 0, true, oid, fbo);
908 CPPUNIT_ASSERT(err == -1);
909
910 err = brm.createExtent(8000, 1, lbids, size);
911 CPPUNIT_ASSERT(err == 0);
912 CPPUNIT_ASSERT(size == brm.getExtentSize());
913 CPPUNIT_ASSERT(lbids.size() == 1);
914 // CPPUNIT_ASSERT(*(lbids.begin()) == 0);
915
916 err = brm.getExtents(1, extents);
917 CPPUNIT_ASSERT(err == 0);
918 CPPUNIT_ASSERT(extents.size() == 1);
919
920 em = *(extents.begin());
921 // CPPUNIT_ASSERT(em.range.start == 0);
922 CPPUNIT_ASSERT(em.range.size * 1024 == static_cast<uint32_t>(brm.getExtentSize()));
923 CPPUNIT_ASSERT(em.HWM == 0);
924 CPPUNIT_ASSERT(em.blockOffset == 0);
925
926 for (i = 0; i < 50; i++)
927 {
928 range.start = i * 100;
929 range.size = 100;
930 ranges.push_back(range);
931 }
932
933 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
934
935 err = brm.beginVBCopy(1, ranges, vbRanges);
936 CPPUNIT_ASSERT(err == 0);
937
938 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
939
940 cl.lock(CopyLocks::READ);
941
942 for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
943 lbidRangeIT++)
944 CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT));
945
946 cl.release(CopyLocks::READ);
947
948 err = brm.beginVBCopy(1, ranges, vbRanges2);
949 CPPUNIT_ASSERT(err == -1);
950
951 cl.lock(CopyLocks::READ);
952
953 for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
954 lbidRangeIT++)
955 CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT));
956
957 cl.release(CopyLocks::READ);
958
959 for (i = 0; i < 5000; i++)
960 {
961 verID = MAXINT;
962 err = brm.vssLookup(i, verID, 1, vbFlag);
963 CPPUNIT_ASSERT(err == -1);
964 }
965
966 vbRange = *(vbRanges.begin());
967
968 // CPPUNIT_ASSERT(vbRange.vbFBO == 0);
969 for (i = 0; i < (int)vbRange.size; i++)
970 {
971 err = brm.writeVBEntry(1, i, vbRange.vbOID, vbRange.vbFBO + i);
972 CPPUNIT_ASSERT(err == 0);
973 }
974
975 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
976
977 for (i = 0; i < (int)vbRange.size; i++)
978 {
979 verID = MAXINT;
980 err = brm.vssLookup(i, verID, 1, vbFlag);
981 CPPUNIT_ASSERT(err == 0);
982 CPPUNIT_ASSERT(verID == 1);
983 CPPUNIT_ASSERT(vbFlag == false);
984 verID = MAXINT;
985 err = brm.vssLookup(i, verID, 0, vbFlag);
986 CPPUNIT_ASSERT(err == 0);
987 CPPUNIT_ASSERT(verID == 0);
988 CPPUNIT_ASSERT(vbFlag == true);
989 }
990
991 for (; i < 5000; i++)
992 {
993 verID = MAXINT;
994 err = brm.vssLookup(i, verID, 1, vbFlag);
995 CPPUNIT_ASSERT(err == -1);
996 }
997
998 err = brm.endVBCopy(0, ranges);
999
1000 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1001
1002 cl.lock(CopyLocks::READ);
1003
1004 for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
1005 lbidRangeIT++)
1006 CPPUNIT_ASSERT(!cl.isLocked(*lbidRangeIT));
1007
1008 cl.release(CopyLocks::READ);
1009
1010 brm.saveState("TestImage");
1011 brm.loadState("TestImage");
1012
1013 brm.vbCommit(1);
1014
1015 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1016
1017 for (i = 0; i < (int)vbRange.size; i++)
1018 {
1019 verID = MAXINT;
1020 err = brm.vssLookup(i, verID, 0, vbFlag);
1021 CPPUNIT_ASSERT(err == 0);
1022 CPPUNIT_ASSERT(verID == 1);
1023 CPPUNIT_ASSERT(vbFlag == false);
1024
1025 verID = 0;
1026 err = brm.vssLookup(i, verID, 0, vbFlag);
1027 CPPUNIT_ASSERT(err == 0);
1028 CPPUNIT_ASSERT(verID == 0);
1029 CPPUNIT_ASSERT(vbFlag == true);
1030
1031 err = brm.lookup(i, verID, vbFlag, oid, fbo);
1032 CPPUNIT_ASSERT(err == 0);
1033 CPPUNIT_ASSERT(oid == vbRange.vbOID);
1034 CPPUNIT_ASSERT(fbo == static_cast<uint32_t>(i + vbRange.vbFBO));
1035
1036 vbbm.lock(VBBM::WRITE);
1037 vss.lock(VSS::WRITE);
1038 vbbm.removeEntry(i, verID);
1039 // vss.removeEntry(i, 1);
1040 vss.removeEntry(i, verID);
1041 vbbm.confirmChanges();
1042 vss.confirmChanges();
1043 vss.release(VSS::WRITE);
1044 vbbm.release(VBBM::WRITE);
1045 }
1046
1047 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1048
1049 brm.deleteOID(1);
1050
1051 vss.lock(VSS::READ);
1052 vbbm.lock(VBBM::READ);
1053 CPPUNIT_ASSERT(vbbm.size() == 0);
1054 CPPUNIT_ASSERT(vbbm.hashEmpty());
1055 CPPUNIT_ASSERT(vss.size() == 0);
1056 CPPUNIT_ASSERT(vss.hashEmpty());
1057 vss.release(VSS::READ);
1058 vbbm.release(VBBM::READ);
1059
1060 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1061 Config::deleteInstanceMap();
1062 }
1063
1064 // cut & pasted from brm_good_2(), but with rollback instead of commit.
brm_good_3()1065 void brm_good_3()
1066 {
1067 BlockResolutionManager brm;
1068 VBBM vbbm;
1069 VSS vss;
1070 CopyLocks cl;
1071 int i, err, size;
1072 vector<LBID_t> lbids;
1073 vector<LBID_t>::iterator lbid;
1074 vector<EMEntry> extents;
1075 LBIDRange_v ranges;
1076 LBIDRange_v::iterator lbidRangeIT;
1077 VBRange_v vbRanges, vbRanges2;
1078 VBRange_v::iterator vbRangesIT;
1079 LBIDRange_v tmp;
1080 EMEntry em;
1081 OID_t oid;
1082 uint32_t fbo;
1083 LBIDRange range;
1084 VBRange vbRange;
1085 VER_t verID;
1086 bool vbFlag;
1087 bool caughtException;
1088
1089 // Buildbot times out on the getBlocks() call during leakcheck b/c it takes
1090 // > 5 mins for some reason. Have to ping it before 300 seconds go by.
1091 void (*oldsig)(int);
1092
1093 // cerr << "brm_good_3" << endl;
1094
1095 oldsig = signal(SIGALRM, keepalive);
1096 alarm(290);
1097
1098 err = brm.lookup(0, 0, false, oid, fbo);
1099 CPPUNIT_ASSERT(err == -1);
1100 err = brm.lookup(0, 0, true, oid, fbo);
1101 CPPUNIT_ASSERT(err == -1);
1102
1103 err = brm.createExtent(8000, 1, lbids, size);
1104 CPPUNIT_ASSERT(err == 0);
1105 CPPUNIT_ASSERT(size == brm.getExtentSize());
1106 CPPUNIT_ASSERT(lbids.size() == 1);
1107 CPPUNIT_ASSERT(*(lbids.begin()) == 0);
1108
1109 err = brm.getExtents(1, extents);
1110 CPPUNIT_ASSERT(err == 0);
1111 CPPUNIT_ASSERT(extents.size() == 1);
1112
1113 em = *(extents.begin());
1114 CPPUNIT_ASSERT(em.range.start == 0);
1115 CPPUNIT_ASSERT(em.range.size * 1024 == static_cast<uint32_t>(brm.getExtentSize()));
1116 CPPUNIT_ASSERT(em.HWM == 0);
1117 CPPUNIT_ASSERT(em.blockOffset == 0);
1118
1119 for (i = 0; i < 50; i++)
1120 {
1121 range.start = i * 100;
1122 range.size = 100;
1123 ranges.push_back(range);
1124 }
1125
1126 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1127
1128 err = brm.beginVBCopy(1, ranges, vbRanges);
1129 CPPUNIT_ASSERT(err == 0);
1130
1131 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1132
1133 cl.lock(CopyLocks::READ);
1134
1135 for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
1136 lbidRangeIT++)
1137 CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT));
1138
1139 cl.release(CopyLocks::READ);
1140
1141 err = brm.beginVBCopy(1, ranges, vbRanges2);
1142 CPPUNIT_ASSERT(err == -1);
1143
1144 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1145
1146 cl.lock(CopyLocks::READ);
1147
1148 for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
1149 lbidRangeIT++)
1150 CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT));
1151
1152 cl.release(CopyLocks::READ);
1153
1154 for (i = 0; i < 5000; i++)
1155 {
1156 verID = MAXINT;
1157 err = brm.vssLookup(i, verID, 1, vbFlag);
1158 CPPUNIT_ASSERT(err == -1);
1159 }
1160
1161 vbRange = *(vbRanges.begin());
1162
1163 // CPPUNIT_ASSERT(vbRange.vbFBO == 0);
1164 for (i = 0; i < (int)vbRange.size; i++)
1165 {
1166 err = brm.writeVBEntry(1, i, vbRange.vbOID, vbRange.vbFBO + i);
1167 CPPUNIT_ASSERT(err == 0);
1168 }
1169
1170 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1171
1172 for (i = 0; i < (int)vbRange.size; i++)
1173 {
1174 verID = MAXINT;
1175 err = brm.vssLookup(i, verID, 1, vbFlag);
1176 CPPUNIT_ASSERT(err == 0);
1177 CPPUNIT_ASSERT(verID == 1);
1178 CPPUNIT_ASSERT(vbFlag == false);
1179 verID = MAXINT;
1180 err = brm.vssLookup(i, verID, 0, vbFlag);
1181 CPPUNIT_ASSERT(err == 0);
1182 CPPUNIT_ASSERT(verID == 0);
1183 CPPUNIT_ASSERT(vbFlag == true);
1184 }
1185
1186 for (; i < 5000; i++)
1187 {
1188 verID = MAXINT;
1189 err = brm.vssLookup(i, verID, 1, vbFlag);
1190 CPPUNIT_ASSERT(err == -1);
1191 }
1192
1193 err = brm.endVBCopy(0, ranges);
1194
1195 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1196
1197 cl.lock(CopyLocks::READ);
1198
1199 for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end();
1200 lbidRangeIT++)
1201 CPPUNIT_ASSERT(!cl.isLocked(*lbidRangeIT));
1202
1203 cl.release(CopyLocks::READ);
1204
1205 err = brm.getUncommittedLBIDs(1, lbids);
1206 CPPUNIT_ASSERT(err == 0);
1207 CPPUNIT_ASSERT(lbids.size() == vbRange.size);
1208 sort<vector<LBID_t>::iterator>(lbids.begin(), lbids.end());
1209 lbid = lbids.begin();
1210
1211 for (i = 0; i < static_cast<int>(lbids.size()); i++, lbid++)
1212 CPPUNIT_ASSERT((*lbid) == static_cast<LBID_t>(i));
1213
1214 range.start = 0;
1215 range.size = i;
1216 tmp.push_back(range);
1217 err = brm.vbRollback(1, tmp);
1218 CPPUNIT_ASSERT(err == 0);
1219
1220 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1221
1222 for (i = 0; i < (int)vbRange.size; i++)
1223 {
1224 verID = MAXINT;
1225
1226 err = brm.vssLookup(i, verID, 0, vbFlag);
1227 CPPUNIT_ASSERT(err == 0);
1228 CPPUNIT_ASSERT(verID == 0);
1229 CPPUNIT_ASSERT(vbFlag == false);
1230
1231 err = brm.lookup(i, verID, vbFlag, oid, fbo);
1232 CPPUNIT_ASSERT(err == 0);
1233 CPPUNIT_ASSERT(oid == 1);
1234 CPPUNIT_ASSERT(fbo == static_cast<uint32_t>(i));
1235
1236 vbbm.lock(VBBM::WRITE);
1237 vss.lock(VSS::WRITE);
1238
1239 #ifdef BRM_DEBUG
1240 caughtException = false;
1241
1242 try
1243 {
1244 vbbm.removeEntry(i, verID);
1245 vbbm.confirmChanges();
1246 }
1247 catch (logic_error& e)
1248 {
1249 vbbm.undoChanges();
1250 caughtException = true;
1251 }
1252
1253 CPPUNIT_ASSERT(caughtException);
1254 caughtException = false;
1255
1256 try
1257 {
1258 vss.removeEntry(i, 1);
1259 vss.confirmChanges();
1260 }
1261 catch (logic_error& e)
1262 {
1263 vss.undoChanges();
1264 caughtException = true;
1265 }
1266
1267 CPPUNIT_ASSERT(caughtException);
1268 #endif
1269
1270 vss.removeEntry(i, verID);
1271 vss.confirmChanges();
1272 vss.release(VSS::WRITE);
1273 vbbm.release(VBBM::WRITE);
1274 }
1275
1276 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1277
1278 brm.deleteOID(1);
1279
1280 vbbm.lock(VBBM::READ);
1281 vss.lock(VSS::READ);
1282 CPPUNIT_ASSERT(vbbm.size() == 0);
1283 CPPUNIT_ASSERT(vbbm.hashEmpty());
1284 CPPUNIT_ASSERT(vss.size() == 0);
1285 CPPUNIT_ASSERT(vss.hashEmpty());
1286 vss.release(VSS::READ);
1287 vbbm.release(VBBM::READ);
1288
1289 CPPUNIT_ASSERT(brm.checkConsistency() == 0);
1290 Config::deleteInstanceMap();
1291 }
1292
1293 /* This test verifies that deleteOID returns an error for
1294 non-existant OIDs (bug #105) */
brm_deleteOID()1295 void brm_deleteOID()
1296 {
1297 BlockResolutionManager brm;
1298 int err;
1299 vector<EMEntry> extents;
1300
1301 // cerr << "brm_deleteOID" << endl;
1302
1303 err = brm.getExtents(1, extents);
1304 #ifdef BRM_DEBUG
1305
1306 if (err != -1)
1307 cerr << "Make sure OID 1 isn't allocated in the extent map" << endl;
1308
1309 CPPUNIT_ASSERT(err == -1);
1310 #else
1311 CPPUNIT_ASSERT(err == 0);
1312 CPPUNIT_ASSERT(extents.empty());
1313 #endif
1314 err = brm.deleteOID(1);
1315 CPPUNIT_ASSERT(err == -1);
1316 Config::deleteInstanceMap();
1317 }
1318
1319 /* This test verifies that setHWM and getHWM return an error for
1320 nonexistant OIDs (bugs #106, 107) */
1321
brm_HWM()1322 void brm_HWM()
1323 {
1324 BlockResolutionManager brm;
1325 int err;
1326 HWM_t hwm;
1327 vector<EMEntry> extents;
1328
1329 // cerr << "brm_HWM" << endl;
1330
1331 err = brm.getExtents(1, extents);
1332 #ifdef BRM_DEBUG
1333
1334 if (err != -1)
1335 cerr << "Make sure OID 1 isn't allocated in the extent map" << endl;
1336
1337 CPPUNIT_ASSERT(err == -1);
1338 #else
1339 CPPUNIT_ASSERT(err == 0);
1340 #endif
1341 CPPUNIT_ASSERT(extents.size() == 0);
1342 err = brm.setHWM(1, 10);
1343 CPPUNIT_ASSERT(err == -1);
1344 err = brm.getHWM(1, hwm);
1345 CPPUNIT_ASSERT(err == -1);
1346 Config::deleteInstanceMap();
1347 }
1348
vbbm_good_1()1349 void vbbm_good_1()
1350 {
1351
1352 // add some VBBM entries
1353 // do some lookups
1354 // manipulate them
1355 // do more lookups
1356
1357 VBBM vbbm;
1358 VSS vss;
1359 vector<VBRange> ranges;
1360 vector<VBRange>::iterator it;
1361 int i, iterations = 100010, err;
1362 OID_t oid;
1363 uint32_t fbo, fbo2;
1364
1365 // Buildbot times out on the getBlocks() call during leakcheck b/c it takes
1366 // > 5 mins for some reason. Have to ping it before 300 seconds go by.
1367 void (*oldsig)(int);
1368
1369 // cerr << "vbbm_good_1" << endl;
1370
1371 oldsig = signal(SIGALRM, keepalive);
1372 alarm(290);
1373
1374 // cerr << "\nVBBM test (this can take awhile)\n";
1375 vbbm.lock(VBBM::READ);
1376 vbbm.release(VBBM::READ);
1377 vbbm.lock(VBBM::WRITE);
1378 vbbm.release(VBBM::WRITE);
1379
1380 vbbm.lock(VBBM::WRITE);
1381
1382 err = vbbm.lookup(0, 0, oid, fbo);
1383 CPPUNIT_ASSERT(err == -1);
1384
1385 // cerr << "step 1/4: get some VB blocks" << endl;
1386
1387 vss.lock(VSS::WRITE);
1388 vbbm.getBlocks(iterations, ranges, vss);
1389 vbbm.confirmChanges();
1390 vss.confirmChanges();
1391 vss.release(VSS::WRITE);
1392 CPPUNIT_ASSERT(!ranges.empty());
1393
1394 // cerr << "step 2/4: inserts & lookups" << endl;
1395 for (it = ranges.begin(), i = 0; it != ranges.end(); it++)
1396 {
1397 for (fbo = (*it).vbFBO; fbo < (*it).vbFBO + (*it).size; fbo++, i++)
1398 {
1399 vbbm.insert(i, i + 1, (*it).vbOID, fbo);
1400 vbbm.confirmChanges();
1401 err = vbbm.lookup(i, i + 1, oid, fbo2);
1402 CPPUNIT_ASSERT(err == 0);
1403 CPPUNIT_ASSERT(oid == (*it).vbOID);
1404 CPPUNIT_ASSERT(fbo2 == fbo);
1405 }
1406 }
1407
1408 /*
1409 for (i = 0; i < iterations; i++) {
1410
1411 vbbm.insert(i, i+1, i+2, i+3);
1412 err = vbbm.lookup(i, i+1, oid, fbo);
1413 CPPUNIT_ASSERT(err == 0);
1414 CPPUNIT_ASSERT(oid == i + 2);
1415 CPPUNIT_ASSERT(fbo == static_cast<uint32_t>(i + 3));
1416 }
1417 */
1418
1419 vbbm.save(string("VBBMImage"));
1420 vbbm.load(string("VBBMImage"));
1421
1422 // cerr << "step 3/4: lookups" << endl;
1423 for (it = ranges.begin(), i = 0; it != ranges.end(); it++)
1424 {
1425 for (fbo = (*it).vbFBO; fbo < (*it).vbFBO + (*it).size; fbo++, i++)
1426 {
1427 err = vbbm.lookup(i, i + 1, oid, fbo2);
1428 CPPUNIT_ASSERT(err == 0);
1429 CPPUNIT_ASSERT(oid == (*it).vbOID);
1430 CPPUNIT_ASSERT(fbo2 == fbo);
1431 }
1432 }
1433
1434 /*
1435 for (i = 0; i < iterations; i++) {
1436 err = vbbm.lookup(i, i+1, oid, fbo);
1437 CPPUNIT_ASSERT(err == 0);
1438 CPPUNIT_ASSERT(oid == i + 2);
1439 CPPUNIT_ASSERT(fbo == static_cast<uint32_t>(i + 3));
1440 } */
1441
1442 // cerr << "step 4/4: remove all entries" << endl;
1443 for (i = 0; i < iterations; i++)
1444 {
1445 vbbm.removeEntry(i, i + 1);
1446 vbbm.confirmChanges();
1447 }
1448
1449 CPPUNIT_ASSERT(vbbm.size() == 0);
1450 CPPUNIT_ASSERT(vbbm.hashEmpty());
1451
1452 vbbm.release(VBBM::WRITE);
1453 Config::deleteInstanceMap();
1454 }
1455
vss_good_1()1456 void vss_good_1()
1457 {
1458 VSS vss;
1459 VBBM vbbm;
1460 ExtentMap em;
1461 int i, err, iterations = 100010;
1462 VER_t verID;
1463 bool vbFlag;
1464 vector<LBID_t> lbids;
1465 LBIDRange range;
1466
1467 // Buildbot times out on the getBlocks() call during leakcheck b/c it takes
1468 // > 5 mins for some reason. Have to ping it before 300 seconds go by.
1469 void (*oldsig)(int);
1470
1471 // cerr << "vss_good_1" << endl;
1472
1473 oldsig = signal(SIGALRM, keepalive);
1474 alarm(290);
1475
1476 cerr << endl << "VSS test (this can take awhile)" << endl;
1477
1478 vss.lock(VSS::READ);
1479 vss.release(VSS::READ);
1480
1481 vss.lock(VSS::WRITE);
1482
1483 cerr << "step 1/5: insert 2 entries for 100010 LBIDs & test lookup logic" << endl;
1484
1485 range.start = 0;
1486 range.size = 200000;
1487
1488 CPPUNIT_ASSERT(!vss.isLocked(range));
1489
1490 for (i = 0; i < iterations; i++)
1491 {
1492 vss.insert(i, i + 1, (i % 2 ? true : false), (i % 2 ? false : true));
1493 vss.insert(i, i, true, false);
1494 vss.confirmChanges();
1495
1496 if (i == 0)
1497 {
1498 range.start = 0;
1499 range.size = 1;
1500 CPPUNIT_ASSERT(vss.isLocked(range));
1501 }
1502 else if (i == 1)
1503 {
1504 range.start = 1;
1505 CPPUNIT_ASSERT(!vss.isLocked(range));
1506 }
1507
1508 verID = i + 10;
1509 err = vss.lookup(i, verID, i + 1, vbFlag);
1510 CPPUNIT_ASSERT(err == 0);
1511 CPPUNIT_ASSERT(verID == i + 1);
1512 CPPUNIT_ASSERT((vbFlag && (i % 2)) || (!vbFlag && !(i % 2)));
1513 verID = i + 10;
1514 err = vss.lookup(i, verID, 0, vbFlag);
1515 CPPUNIT_ASSERT(err == 0);
1516 CPPUNIT_ASSERT(verID == (i % 2 ? i + 1 : i));
1517 CPPUNIT_ASSERT(vbFlag == true);
1518
1519 if (i > 0)
1520 {
1521 verID = i - 1;
1522 err = vss.lookup(i, verID, 0, vbFlag);
1523 CPPUNIT_ASSERT(err == -1);
1524 }
1525
1526 }
1527
1528 range.start = 0;
1529 range.size = 200000;
1530 CPPUNIT_ASSERT(vss.isLocked(range));
1531 vss.save(string("VSSImage"));
1532 vss.load(string("VSSImage"));
1533
1534 // this loop actually breaks the locked -> !vbFlag invariant
1535 // switch it back afterward
1536 cerr << "step 2/5: flip the vbFlag on half of the entries & test lookup logic" << endl;
1537
1538 for (i = 0; i < iterations; i++)
1539 {
1540 vss.setVBFlag(i, i + 1, (i % 2 ? false : true));
1541 vss.confirmChanges();
1542 }
1543
1544 for (i = 0; i < iterations; i++)
1545 {
1546 verID = i + 10;
1547 err = vss.lookup(i, verID, i + 1, vbFlag);
1548 CPPUNIT_ASSERT(err == 0);
1549 CPPUNIT_ASSERT(verID == i + 1);
1550 CPPUNIT_ASSERT((!vbFlag && (i % 2)) || (vbFlag && !(i % 2)));
1551 }
1552
1553 cerr << "step 3/5: some clean up" << endl;
1554
1555 for (i = 0; i < iterations; i++)
1556 {
1557 vss.setVBFlag(i, i + 1, (i % 2 ? true : false));
1558 vss.confirmChanges();
1559 }
1560
1561
1562 // there are 2 entries for every txnid at this point, one
1563 // which is locked, one which isn't. That's technically a violation,
1564 // so we have to get rid of the unlocked ones for the next test.
1565 for (i = 0; i < iterations; i++)
1566 {
1567 vss.removeEntry(i, i);
1568 vss.confirmChanges();
1569 }
1570
1571 //speed up the next step!
1572 for (i = iterations / 50; i < iterations; i++)
1573 {
1574 vss.removeEntry(i, i + 1);
1575 vss.confirmChanges();
1576 }
1577
1578 cerr << "step 4/5: get \'uncommitted\' LBIDs, commit, and test lookup logic" << endl;
1579
1580 for (i = 1; i < iterations / 50; i++)
1581 {
1582 bool ex = false;
1583
1584 if (i % 2 == 0)
1585 {
1586 #ifdef BRM_DEBUG
1587
1588 try
1589 {
1590 vss.getUncommittedLBIDs(i, lbids);
1591 }
1592 catch (logic_error& e)
1593 {
1594 ex = true;
1595 }
1596
1597 CPPUNIT_ASSERT(ex == true);
1598 #endif
1599 }
1600 else
1601 {
1602 LBID_t lbid;
1603
1604 vss.getUncommittedLBIDs(i, lbids);
1605 CPPUNIT_ASSERT(lbids.size() == 1);
1606 lbid = *(lbids.begin());
1607 CPPUNIT_ASSERT(lbid == i - 1);
1608 verID = i + 10;
1609 err = vss.lookup(i - 1, verID, i, vbFlag);
1610 CPPUNIT_ASSERT(err == 0);
1611 CPPUNIT_ASSERT(verID == i);
1612 CPPUNIT_ASSERT(vbFlag == false);
1613
1614 err = vss.lookup(i - 1, verID, 0, vbFlag);
1615 CPPUNIT_ASSERT(err == -1);
1616
1617 vss.commit(i);
1618 vss.confirmChanges();
1619 verID = i + 10;
1620 err = vss.lookup(i - 1, verID, 0, vbFlag);
1621 CPPUNIT_ASSERT(err == 0);
1622 CPPUNIT_ASSERT(verID == i);
1623 CPPUNIT_ASSERT(vbFlag == false);
1624
1625 }
1626 }
1627
1628 cerr << "step 5/5: final clean up" << endl;
1629
1630 CPPUNIT_ASSERT(vss.size() == iterations / 50);
1631 range.start = 0;
1632 range.size = iterations / 50;
1633 vss.removeEntriesFromDB(range, vbbm, false);
1634 vbbm.confirmChanges();
1635 vss.confirmChanges();
1636
1637 // the new logic for removeEntriesFromDB deletes all entries in the range,
1638 // locked or not, in the VB or not
1639
1640 // CPPUNIT_ASSERT(vss.size() == iterations/100);
1641
1642 // for (i = 1; i < iterations/50; i+=2)
1643 // vss.removeEntry(i, i+1);
1644
1645 CPPUNIT_ASSERT(vss.size() == 0);
1646 CPPUNIT_ASSERT(vss.hashEmpty());
1647 vss.release(VSS::WRITE);
1648
1649 alarm(0);
1650 signal(SIGALRM, oldsig);
1651 Config::deleteInstanceMap();
1652 }
1653
1654 /* This test was suggested by Jean, who observed some odd behavior at around
1655 1032 EM instances in her code. This test creates 2000 instances and uses 1400 of them
1656 to do the extentmap_freelist_1 test above. */
many_ExtentMap_instances()1657 void many_ExtentMap_instances()
1658 {
1659 ExtentMap** ems;
1660 int i, allocdSize, iterations = 1400; // (EM_INITIAL_SIZE + 4*EM_INCREMENT)
1661 vector<LBID_t> lbids;
1662 uint32_t extentSize;
1663
1664 // cerr << endl << "Extent Map instance test" << endl;
1665
1666 ems = new ExtentMap*[2000];
1667
1668 for (i = 0; i < 2000; i++)
1669 ems[i] = new ExtentMap();
1670
1671 extentSize = ems[0]->getExtentSize();
1672
1673 // cerr << " - Successfully created 2000 instances, starting the freelist test"
1674 // << endl;
1675 for (i = 1; i < iterations; i++)
1676 {
1677 ems[i]->createExtent(extentSize, i, lbids, allocdSize);
1678 ems[i]->confirmChanges();
1679 CPPUNIT_ASSERT(lbids.back() == static_cast<LBID_t>((i - 1)*extentSize));
1680 }
1681
1682 //frag the lbid space to blow up the free list
1683 for (i = 1; i < iterations; i += 2)
1684 {
1685 ems[i]->deleteOID(i);
1686 ems[i]->confirmChanges();
1687 }
1688
1689 //fill in the holes
1690 for (i = 1; i < iterations; i += 2)
1691 {
1692 ems[i]->createExtent(extentSize, i, lbids, allocdSize);
1693 ems[i]->confirmChanges();
1694 }
1695
1696 for (i = 1; i < iterations; i += 2)
1697 {
1698 ems[i]->deleteOID(i);
1699 ems[i]->confirmChanges();
1700 }
1701
1702 for (i = 2; i < iterations; i += 2)
1703 {
1704 ems[i]->deleteOID(i);
1705 ems[i]->confirmChanges();
1706 }
1707
1708 // cerr << "done. sleeping for 30 seconds." << endl;
1709 // sleep(30);
1710
1711 for (i = 0; i < 2000; i++)
1712 delete ems[i];
1713
1714 delete [] ems;
1715 Config::deleteInstanceMap();
1716
1717 }
1718
resource_graph_1()1719 void resource_graph_1()
1720 {
1721 LBIDResourceGraph rg;
1722 pthread_t t;
1723 VER_t txn = 1;
1724 int err;
1725
1726 pthread_mutex_init(&mutex, NULL);
1727 pthread_mutex_lock(&mutex);
1728
1729 err = rg.reserveRange(1001, 2000, txn, mutex);
1730 CPPUNIT_ASSERT(err == 0);
1731 err = rg.reserveRange(2001, 2000, txn, mutex);
1732 CPPUNIT_ASSERT(err == 0);
1733 err = rg.reserveRange(0, 1000, txn, mutex);
1734 CPPUNIT_ASSERT(err == 0);
1735 err = rg.reserveRange(3001, 2000, txn, mutex);
1736 CPPUNIT_ASSERT(err == 0);
1737 pthread_create(&t, NULL, dummy_1, &rg);
1738 pthread_mutex_unlock(&mutex);
1739 sleep(5);
1740
1741 // thread should sleep here
1742
1743 pthread_mutex_lock(&mutex);
1744 rg.releaseResources(txn);
1745 pthread_mutex_unlock(&mutex);
1746
1747 // thread should be unblocked and finish here
1748
1749 pthread_join(t, NULL);
1750 pthread_mutex_lock(&mutex);
1751 err = rg.reserveRange(0, 1000, txn, mutex);
1752 CPPUNIT_ASSERT(err == 0);
1753 rg.releaseResources(txn);
1754 pthread_mutex_unlock(&mutex);
1755 pthread_mutex_destroy(&mutex);
1756 Config::deleteInstanceMap();
1757 }
1758
resource_graph_deadlock()1759 void resource_graph_deadlock()
1760 {
1761 LBIDResourceGraph rg;
1762 pthread_t t;
1763 VER_t txn = 1;
1764 int err;
1765
1766 pthread_mutex_init(&mutex, NULL);
1767 pthread_mutex_lock(&mutex);
1768 err = rg.reserveRange(0, 1000, txn, mutex);
1769 CPPUNIT_ASSERT(err == 0);
1770 pthread_create(&t, NULL, dummy_deadlock, &rg);
1771 pthread_mutex_unlock(&mutex);
1772 sleep(1);
1773
1774 // thread grabs 1001-2000, then 0-1000 and blocks
1775
1776 pthread_mutex_lock(&mutex);
1777 err = rg.reserveRange(1001, 2000, txn, mutex); // deadlock
1778 CPPUNIT_ASSERT(err == ERR_DEADLOCK);
1779 rg.releaseResources(txn);
1780
1781 pthread_mutex_unlock(&mutex); // should wake the thread
1782 pthread_join(t, NULL); // wait for it to finish
1783
1784 pthread_mutex_lock(&mutex);
1785 err = rg.reserveRange(0, 2000, txn, mutex); //verify we can now grab both ranges
1786 CPPUNIT_ASSERT(err == ERR_OK);
1787 pthread_mutex_unlock(&mutex);
1788 pthread_mutex_destroy(&mutex);
1789 Config::deleteInstanceMap();
1790 }
1791
resource_graph_fragd_range()1792 void resource_graph_fragd_range()
1793 {
1794 LBIDResourceGraph rg;
1795 set<ResourceNode*, RNLess<ResourceNode*> >* resources;
1796 map<VER_t, TransactionNode*>* txns;
1797 pthread_t t;
1798 VER_t txn = 1;
1799 int err;
1800
1801 pthread_mutex_init(&mutex, NULL);
1802 pthread_mutex_lock(&mutex);
1803
1804 err = rg.reserveRange(1001, 2000, txn, mutex);
1805 CPPUNIT_ASSERT(err == ERR_OK);
1806 err = rg.reserveRange(3001, 4000, txn, mutex);
1807 CPPUNIT_ASSERT(err == ERR_OK);
1808 pthread_create(&t, NULL, fragd_range_helper, &rg);
1809 pthread_mutex_unlock(&mutex);
1810 sleep(1);
1811
1812 // thread wakes, tries to grab 0-5000
1813 // check that there are 5 resource nodes
1814
1815 pthread_mutex_lock(&mutex);
1816 resources = rg.getResources();
1817 txns = rg.getTxns();
1818 CPPUNIT_ASSERT(resources->size() == 5);
1819 CPPUNIT_ASSERT(txns->size() == 2);
1820 rg.releaseResources(txn);
1821 CPPUNIT_ASSERT(resources->size() == 3);
1822 CPPUNIT_ASSERT(txns->size() == 1);
1823 pthread_mutex_unlock(&mutex);
1824
1825 // thread releases, exits
1826
1827 pthread_join(t, NULL);
1828 CPPUNIT_ASSERT(resources->size() == 0);
1829 CPPUNIT_ASSERT(txns->size() == 0);
1830
1831 pthread_mutex_destroy(&mutex);
1832 Config::deleteInstanceMap();
1833 }
1834
resource_graph_overlapping_ranges()1835 void resource_graph_overlapping_ranges()
1836 {
1837 LBIDResourceGraph rg;
1838 set<ResourceNode*, RNLess<ResourceNode*> >* resources;
1839 set<ResourceNode*, RNLess<ResourceNode*> >::const_iterator it;
1840 map<VER_t, TransactionNode*>* txns;
1841 pthread_t t;
1842 VER_t txn = 1;
1843 int err;
1844
1845 // make a fragmented range, then request a range that overlaps existing
1846 // ranges on both ends
1847
1848 pthread_mutex_init(&mutex, NULL);
1849 pthread_mutex_lock(&mutex);
1850
1851 err = rg.reserveRange(1001, 2000, txn, mutex);
1852 CPPUNIT_ASSERT(err == ERR_OK);
1853 err = rg.reserveRange(3001, 4000, txn, mutex);
1854 CPPUNIT_ASSERT(err == ERR_OK);
1855 pthread_create(&t, NULL, overlapping_range_helper, &rg);
1856 pthread_mutex_unlock(&mutex);
1857 sleep(1);
1858
1859 // thread executes, tries to grab 1100-3900
1860
1861 pthread_mutex_lock(&mutex);
1862 resources = rg.getResources();
1863 txns = rg.getTxns();
1864
1865 #ifdef BRM_VERBOSE
1866 cerr << " resources->size = " << resources->size() << endl;
1867
1868 for (it = resources->begin(); it != resources->end(); it++)
1869 cerr << " " << (*it)->start() << "-" << (*it)->end() << endl;
1870
1871 #endif
1872
1873 it = resources->begin();
1874 CPPUNIT_ASSERT(resources->size() == 3);
1875 CPPUNIT_ASSERT((*it)->start() == 1001);
1876 CPPUNIT_ASSERT((*it)->end() == 2000);
1877 it++;
1878 CPPUNIT_ASSERT((*it)->start() == 2001);
1879 CPPUNIT_ASSERT((*it)->end() == 3000);
1880 it++;
1881 CPPUNIT_ASSERT((*it)->start() == 3001);
1882 CPPUNIT_ASSERT((*it)->end() == 4000);
1883
1884 CPPUNIT_ASSERT(txns->size() == 2);
1885 rg.releaseResources(txn);
1886 CPPUNIT_ASSERT(txns->size() == 1);
1887 pthread_mutex_unlock(&mutex);
1888
1889 pthread_join(t, NULL);
1890 CPPUNIT_ASSERT(resources->size() == 0);
1891 CPPUNIT_ASSERT(txns->size() == 0);
1892
1893 pthread_mutex_destroy(&mutex);
1894 Config::deleteInstanceMap();
1895 }
1896
1897 };
1898
1899
1900
1901 CPPUNIT_TEST_SUITE_REGISTRATION( BRMTest );
1902
1903 #include <cppunit/extensions/TestFactoryRegistry.h>
1904 #include <cppunit/ui/text/TestRunner.h>
1905
main(int argc,char ** argv)1906 int main( int argc, char** argv)
1907 {
1908 CppUnit::TextUi::TestRunner runner;
1909 CppUnit::TestFactoryRegistry& registry = CppUnit::TestFactoryRegistry::getRegistry();
1910 runner.addTest( registry.makeTest() );
1911 bool wasSuccessful = runner.run( "", false );
1912 return (wasSuccessful ? 0 : 1);
1913 }
1914
1915
1916