void *DBRM_deadlock(void *arg) { DBRM dbrm; int terr; VER_t txn = 2; vector<LBIDRange> ranges; LBIDRange range; vector<VBRange> freeList; range.start = 2000; range.size = 1000; ranges.push_back(range); terr = dbrm.beginVBCopy(txn, ranges, freeList); range.start = 1000; range.size = 1000; ranges.clear(); freeList.clear(); ranges.push_back(range); terr = dbrm.beginVBCopy(txn, ranges, freeList); // block waiting on the main thread, main thread deadlocks, rolls back, // thread wakes CPPUNIT_ASSERT(terr == 0); terr = dbrm.endVBCopy(txn, ranges); CPPUNIT_ASSERT(terr == 0); terr = dbrm.vbCommit(txn); CPPUNIT_ASSERT(terr == 0); return NULL; }
void DBRM_resource_graph_1() { DBRM dbrm; pthread_t t; VER_t txn = 1; int err, allocSize; LBIDRange range; vector<LBID_t> lbids; vector<LBIDRange> ranges; vector<VBRange> freeList; err = dbrm.createExtent(8000, 1, lbids, allocSize); CPPUNIT_ASSERT(err == 0); range.start = 1000; range.size = 1000; ranges.push_back(range); err = dbrm.beginVBCopy(txn, ranges, freeList); CPPUNIT_ASSERT(err == 0); pthread_create(&t, NULL, DBRM_dummy_1, NULL); sleep(1); // thread tries to grab 500-1500, blocks err = dbrm.endVBCopy(txn, ranges); CPPUNIT_ASSERT(err == 0); err = dbrm.vbCommit(txn); CPPUNIT_ASSERT(err == 0); dbrm.deleteOID(1); //thread finishes pthread_join(t, NULL); }
void *DBRM_dummy_1(void *arg) { DBRM dbrm; int err; VER_t txn = 2; vector<LBIDRange> ranges; LBIDRange range; vector<VBRange> freeList; range.start = 500; range.size = 1000; ranges.push_back(range); err = dbrm.beginVBCopy(txn, ranges, freeList); CPPUNIT_ASSERT(err == 0); err = dbrm.endVBCopy(txn, ranges); CPPUNIT_ASSERT(err == 0); err = dbrm.vbCommit(txn); CPPUNIT_ASSERT(err == 0); return NULL; }
void dbrm_clear() { DBRM dbrm; VSS vss; VBBM vbbm; int err, vssShmid, vbbmShmid, txnID = 1, i; struct shmid_ds vssShminfo[3], vbbmShminfo[3]; LBIDRange_v ranges; LBIDRange range; VBRange_v freelist; err = dbrm.clear(); CPPUNIT_ASSERT(err == ERR_OK); // grab the size of vss and vbbm shmsegs somehow vss.lock(VSS::READ); vbbm.lock(VBBM::READ); vssShmid = vss.getShmid(); vbbmShmid = vbbm.getShmid(); err = shmctl(vssShmid, IPC_STAT, &vssShminfo[0]); CPPUNIT_ASSERT(err == 0); err = shmctl(vbbmShmid, IPC_STAT, &vbbmShminfo[0]); CPPUNIT_ASSERT(err == 0); vss.release(VSS::READ); vbbm.release(VBBM::READ); // do begin, write, end vbcopy for 150k blocks cerr << endl << "Adding 150k block entries. "; range.start = 1; range.size = 150000; ranges.push_back(range); err = dbrm.beginVBCopy(txnID, ranges, freelist); CPPUNIT_ASSERT(err == 0); for (i = range.start; (uint32_t) i < range.size; i++) { if (i % 50000 == 0) cerr << " ... " << i; err = dbrm.writeVBEntry(txnID, i, 1, i); CPPUNIT_ASSERT(err == 0); } err = dbrm.endVBCopy(txnID, ranges); CPPUNIT_ASSERT(err == 0); cerr << " done." << endl; // grab the sizes again vss.lock(VSS::READ); vbbm.lock(VBBM::READ); vssShmid = vss.getShmid(); vbbmShmid = vbbm.getShmid(); err = shmctl(vssShmid, IPC_STAT, &vssShminfo[1]); CPPUNIT_ASSERT(err == 0); err = shmctl(vbbmShmid, IPC_STAT, &vbbmShminfo[1]); CPPUNIT_ASSERT(err == 0); vss.release(VSS::READ); vbbm.release(VBBM::READ); // make sure they grew CPPUNIT_ASSERT(vssShminfo[0].shm_segsz < vssShminfo[1].shm_segsz); CPPUNIT_ASSERT(vbbmShminfo[0].shm_segsz < vbbmShminfo[1].shm_segsz); dbrm.clear(); // check that the new size is the same as the original vss.lock(VSS::READ); vbbm.lock(VBBM::READ); vssShmid = vss.getShmid(); vbbmShmid = vbbm.getShmid(); err = shmctl(vssShmid, IPC_STAT, &vssShminfo[2]); CPPUNIT_ASSERT(err == 0); err = shmctl(vbbmShmid, IPC_STAT, &vbbmShminfo[2]); CPPUNIT_ASSERT(err == 0); vss.release(VSS::READ); vbbm.release(VBBM::READ); CPPUNIT_ASSERT(vssShminfo[0].shm_segsz == vssShminfo[2].shm_segsz); CPPUNIT_ASSERT(vbbmShminfo[0].shm_segsz == vbbmShminfo[2].shm_segsz); }
void DBRM_resource_graph_deadlock() { DBRM dbrm; pthread_t t; VER_t txn = 1; int err, i; LBIDRange range; vector<LBID_t> lbids; vector<LBIDRange> ranges; vector<VBRange> freeList; range.start = 1000; range.size = 1000; ranges.push_back(range); err = dbrm.beginVBCopy(txn, ranges, freeList); CPPUNIT_ASSERT(err == 0); for (i = range.start; i < range.start + range.size; i++) { err = dbrm.writeVBEntry(txn, i, 1, i); CPPUNIT_ASSERT(err == 0); } err = dbrm.endVBCopy(txn, ranges); CPPUNIT_ASSERT(err == 0); pthread_create(&t, NULL, DBRM_deadlock, NULL); // thread grabs 2000-2999 and 1000-1999 as 2 seperate ranges sleep(1); range.start = 2000; range.size = 1000; ranges.clear(); ranges.push_back(range); err = dbrm.beginVBCopy(txn, ranges, freeList); CPPUNIT_ASSERT(err == ERR_DEADLOCK); // roll back the blocks we "wrote" range.start = 1000; range.size = 1000; ranges.clear(); ranges.push_back(range); err = dbrm.vbRollback(txn, ranges); CPPUNIT_ASSERT(err == ERR_OK); // thread finishes txn = 3; err = dbrm.beginVBCopy(txn, ranges, freeList); CPPUNIT_ASSERT(err == 0); for (i = range.start; i < range.start + range.size; i++) { err = dbrm.writeVBEntry(txn, i, 1, i); CPPUNIT_ASSERT(err == 0); } err = dbrm.endVBCopy(txn, ranges); CPPUNIT_ASSERT(err == 0); err = dbrm.vbRollback(txn, ranges); CPPUNIT_ASSERT(err == 0); pthread_join(t, NULL); }
// cut & pasted from brm_good_2(), but with rollback instead of commit. void brm_good_3() { DBRM brm; VBBM vbbm; VSS vss; CopyLocks cl; int i, err, size; vector<LBID_t> lbids; vector<LBID_t>::iterator lbid; vector<EMEntry> extents; LBIDRange_v ranges; LBIDRange_v::iterator lbidRangeIT; VBRange_v vbRanges, vbRanges2; VBRange_v::iterator vbRangesIT; LBIDRange_v tmp; EMEntry em; OID_t oid; uint32_t fbo; LBIDRange range; VBRange vbRange; VER_t verID; bool vbFlag; bool caughtException; // Buildbot times out on the getBlocks() call during leakcheck b/c it takes // > 5 mins for some reason. Have to ping it before 300 seconds go by. void (*oldsig)(int); cerr << "brm_good_3" << endl; oldsig = signal(SIGALRM, keepalive); alarm(290); err = brm.lookup(0, 0, false, oid, fbo); CPPUNIT_ASSERT(err != 0); err = brm.lookup(0, 0, true, oid, fbo); CPPUNIT_ASSERT(err != 0); err = brm.createExtent(8000, 1, lbids, size); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(size == brm.getExtentSize()); CPPUNIT_ASSERT(lbids.size() == 1); CPPUNIT_ASSERT(*(lbids.begin()) == 0); err = brm.getExtents(1, extents); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(extents.size() == 1); em = *(extents.begin()); CPPUNIT_ASSERT(em.range.start == 0); CPPUNIT_ASSERT(em.range.size*1024 == static_cast<uint32_t>(brm.getExtentSize())); CPPUNIT_ASSERT(em.HWM == 0); CPPUNIT_ASSERT(em.blockOffset == 0); for (i = 0; i < 5; i++) { range.start = i * 100; range.size = 100; ranges.push_back(range); } CPPUNIT_ASSERT(brm.checkConsistency() == 0); err = brm.beginVBCopy(1, ranges, vbRanges); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(brm.checkConsistency() == 0); cl.lock(CopyLocks::READ); for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end(); lbidRangeIT++) CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT)); cl.release(CopyLocks::READ); err = brm.beginVBCopy(1, ranges, vbRanges2); CPPUNIT_ASSERT(err != 0); CPPUNIT_ASSERT(brm.checkConsistency() == 0); cl.lock(CopyLocks::READ); for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end(); lbidRangeIT++) CPPUNIT_ASSERT(cl.isLocked(*lbidRangeIT)); cl.release(CopyLocks::READ); for (i = 0; i < 500; i++) { verID = MAXINT; err = brm.vssLookup(i, verID, 1, vbFlag); CPPUNIT_ASSERT(err != 0); } vbRange = *(vbRanges.begin()); // CPPUNIT_ASSERT(vbRange.vbFBO == 0); for (i = 0; i < (int)vbRange.size; i++) { err = brm.writeVBEntry(1, i, vbRange.vbOID, vbRange.vbFBO + i); CPPUNIT_ASSERT(err == 0); } CPPUNIT_ASSERT(brm.checkConsistency() == 0); for (i = 0; i < (int)vbRange.size; i++) { verID = MAXINT; err = brm.vssLookup(i, verID, 1, vbFlag); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(verID == 1); CPPUNIT_ASSERT(vbFlag == false); verID = MAXINT; err = brm.vssLookup(i, verID, 0, vbFlag); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(verID == 0); CPPUNIT_ASSERT(vbFlag == true); } for (; i < 500; i++) { verID = MAXINT; err = brm.vssLookup(i, verID, 1, vbFlag); CPPUNIT_ASSERT(err != 0); } err = brm.endVBCopy(0, ranges); CPPUNIT_ASSERT(brm.checkConsistency() == 0); cl.lock(CopyLocks::READ); for (lbidRangeIT = ranges.begin(); lbidRangeIT != ranges.end(); lbidRangeIT++) CPPUNIT_ASSERT(!cl.isLocked(*lbidRangeIT)); cl.release(CopyLocks::READ); err = brm.getUncommittedLBIDs(1, lbids); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(lbids.size() == vbRange.size); sort<vector<LBID_t>::iterator>(lbids.begin(), lbids.end()); lbid = lbids.begin(); for (i = 0; i < static_cast<int>(lbids.size()); i++, lbid++) CPPUNIT_ASSERT((*lbid) == static_cast<LBID_t>(i)); range.start = 0; range.size = i; tmp.push_back(range); err = brm.vbRollback(1, tmp); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(brm.checkConsistency() == 0); for (i = 0; i < (int)vbRange.size; i++) { verID = MAXINT; err = brm.vssLookup(i, verID, 0, vbFlag); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(verID == 0); CPPUNIT_ASSERT(vbFlag == false); err = brm.lookup(i, verID, vbFlag, oid, fbo); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(oid == 1); CPPUNIT_ASSERT(fbo == static_cast<uint32_t>(i)); vbbm.lock(VBBM::WRITE); vss.lock(VSS::WRITE); #ifdef BRM_DEBUG caughtException = false; try { vbbm.removeEntry(i, verID); vbbm.confirmChanges(); } catch (logic_error &e) { vbbm.undoChanges(); caughtException = true; } CPPUNIT_ASSERT(caughtException); caughtException = false; try { vss.removeEntry(i, 1); vss.confirmChanges(); } catch (logic_error &e) { vss.undoChanges(); caughtException = true; } CPPUNIT_ASSERT(caughtException); #endif vss.removeEntry(i, verID); vss.confirmChanges(); vss.release(VSS::WRITE); vbbm.release(VBBM::WRITE); } CPPUNIT_ASSERT(brm.checkConsistency() == 0); brm.deleteOID(1); vbbm.lock(VBBM::READ); vss.lock(VSS::READ); CPPUNIT_ASSERT(vbbm.size() == 0); CPPUNIT_ASSERT(vbbm.hashEmpty()); CPPUNIT_ASSERT(vss.size() == 0); CPPUNIT_ASSERT(vss.hashEmpty()); vss.release(VSS::READ); vbbm.release(VBBM::READ); CPPUNIT_ASSERT(brm.checkConsistency() == 0); err = brm.saveState(); CPPUNIT_ASSERT(err==0); }
static void *BRMRunner_2(void *arg) { vector<Range> copyList, copiedList, committedList; vector<Range>::iterator rit; vector<LBID_t> writtenList; vector<LBID_t>::iterator lit; pthread_mutex_t listMutex; int op; uint randstate; DBRM *brm; struct timeval tv; pthread_mutex_init(&listMutex, NULL); gettimeofday(&tv, NULL); randstate = static_cast<uint>(tv.tv_usec); brm = new DBRM(); while (!threadStop) { op = rand_r(&randstate) % 9; switch(op) { case 0: // beginVBCopy { int blockCount, size, err; Range newEntry; VBRange_v vbRanges; VBRange_v::iterator vit; LBIDRange_v ranges; LBIDRange range; VER_t txnID; size = rand_r(&randstate) % 10000; pthread_mutex_lock(&mutex); newEntry.start = lbidCounter; lbidCounter += size; txnID = nextTxnID++; pthread_mutex_unlock(&mutex); newEntry.nextBlock = newEntry.start; newEntry.end = newEntry.start + size; range.start = newEntry.start; range.size = size; err = brm->beginVBCopy(txnID, ranges, vbRanges); CPPUNIT_ASSERT(err == 0); for (blockCount = 0, vit = vbRanges.begin(); vit != vbRanges.end(); vit++) blockCount += (*vit).size; CPPUNIT_ASSERT(blockCount == size); pthread_mutex_lock(&listMutex); copyList.push_back(newEntry); pthread_mutex_unlock(&listMutex); err = brm->beginVBCopy(txnID, ranges, vbRanges); CPPUNIT_ASSERT(err == -1); break; } case 1: // writeVBEntry { int randIndex; VER_t txnID; Range *entry; pthread_mutex_lock(&listMutex); if (copyList.size() == 0) break; randIndex = rand_r(&randstate) % copyList.size(); entry = &(copyList[randIndex]); entry->nextBlock++; txnID = entry->txnID; /********** WORKING HERE **********/ } default: cerr << "not finished yet" << endl; } } return NULL; }