void extentMap_freelist() { ExtentMap em; int i, allocdSize, iterations = 1400; // (EM_INITIAL_SIZE + 4*EM_INCREMENT) vector<LBID_t> lbids; const int extentSize = em.getExtentSize(); for (i = 0; i < iterations; i++) { em.createExtent(extentSize, i, lbids, allocdSize); em.confirmChanges(); CPPUNIT_ASSERT(lbids.back() == static_cast<LBID_t>(i * extentSize)); } em.checkConsistency(); //frag the lbid space to blow up the free list for (i = 0; i < iterations; i += 2) { em.deleteOID(i); em.confirmChanges(); } em.checkConsistency(); //fill in the holes for (i = 0; i < iterations; i += 2) { em.createExtent(extentSize, i, lbids, allocdSize); em.confirmChanges(); } for (i = 0; i < iterations; i += 2) { em.deleteOID(i); em.confirmChanges(); } for (i = 1; i < iterations; i += 2) { em.deleteOID(i); em.confirmChanges(); } em.checkConsistency(); }
static void* EMRunner(void *arg) { // keep track of LBID ranges allocated here and // randomly allocate, lookup, delete, get/set HWM, and // destroy the EM object. struct EMEntries { u_int64_t LBIDstart; u_int32_t size; int OID; u_int32_t FBO; u_int32_t HWM; u_int32_t secondHWM; u_int32_t txnID; struct EMEntries *next; EMEntries() { next = NULL; HWM = 0; secondHWM = 0; txnID = 0; } }; #ifdef BRM_VERBOSE int threadNum = reinterpret_cast<int>(arg); #endif int op, listSize = 0, i; uint randstate; struct EMEntries *head = NULL, *tmp; struct timeval tv; ExtentMap *em; vector<LBID_t> lbids; #ifdef BRM_VERBOSE cerr << "thread number " << threadNum << " started." << endl; #endif gettimeofday(&tv, NULL); randstate = static_cast<uint>(tv.tv_usec); em = new ExtentMap(); while (!threadStop) { op = rand_r(&randstate) % 10; #ifdef BRM_VERBOSE cerr << "next op is " << op << endl; #endif switch (op) { case 0: //allocate space for a new file { struct EMEntries *newEm; int size = rand_r(&randstate) % 102399 + 1; int entries, OID, allocdSize; pthread_mutex_lock(&mutex); OID = oid++; pthread_mutex_unlock(&mutex); em->createExtent(size, OID, lbids, allocdSize); em->confirmChanges(); entries = size/em->getExtentSize(); if ((size % em->getExtentSize()) != 0) entries++; CPPUNIT_ASSERT((uint)entries == lbids.size()); for (i = 0 ; i < entries; i++) { newEm = new EMEntries(); newEm->size = em->getExtentSize(); newEm->OID = OID; newEm->FBO = i * em->getExtentSize(); newEm->LBIDstart = lbids[i]; newEm->next = head; head = newEm; listSize++; } #ifdef BRM_VERBOSE cerr << "created new space for OID " << newEm->OID << endl; #endif em->checkConsistency(); break; } case 1: //allocate space for an existing file { if (listSize == 0) break; struct EMEntries *newEm, *tmp; int size = rand_r(&randstate) % 102399 + 1; int fileRand = rand_r(&randstate) % listSize; int i, lastExtent, blockEnd, oid; int tmpHWM, entries, allocdSize; vector<LBID_t> lbids; for (i = 0, tmp = head; i < fileRand; i++) tmp = tmp->next; oid = tmp->OID; for (lastExtent = 0, tmp = head; tmp != NULL; tmp = tmp->next) { if (tmp->OID != oid) continue; tmpHWM = tmp->HWM; blockEnd = tmp->FBO + tmp->size; if (lastExtent < blockEnd) lastExtent = blockEnd; } em->createExtent(size, oid, lbids, allocdSize); em->confirmChanges(); entries = size/em->getExtentSize(); if ((size % em->getExtentSize()) != 0) entries++; CPPUNIT_ASSERT((uint)entries == lbids.size()); for (i = 0; i < entries; i++) { newEm = new EMEntries(); if (i != entries) newEm->size = em->getExtentSize(); else newEm->size = size % em->getExtentSize(); newEm->OID = oid; newEm->FBO = lastExtent + (i*em->getExtentSize()); newEm->LBIDstart = lbids[i]; newEm->HWM = tmpHWM; newEm->next = head; head = newEm; listSize++; } #ifdef BRM_VERBOSE cerr << "created another extent for OID " << newEm->OID << endl; #endif em->checkConsistency(); break; } case 2: //delete an OID { if (listSize == 0) break; struct EMEntries *tmp, *prev; int fileRand = rand_r(&randstate) % listSize; int i, oid; for (i = 0, tmp = head; i < fileRand; i++) tmp = tmp->next; oid = tmp->OID; em->deleteOID(oid); em->confirmChanges(); for (tmp = head; tmp != NULL;) { if (tmp->OID == oid) { if (tmp == head) { head = head->next; delete tmp; tmp = head; } else { prev->next = tmp->next; delete tmp; tmp = prev->next; } listSize--; } else { prev = tmp; tmp = tmp->next; } } #ifdef BRM_VERBOSE cerr << "deleted OID " << oid << endl; #endif em->checkConsistency(); break; } case 3: //lookup by LBID { if (listSize == 0) break; int entryRand = rand_r(&randstate) % listSize; int i, err, offset, oid; struct EMEntries *tmp; LBID_t target; u_int32_t fbo; for (i = 0, tmp = head; i < entryRand; i++) tmp = tmp->next; offset = rand_r(&randstate) % tmp->size; target = tmp->LBIDstart + offset; err = em->lookup(target, oid, fbo); #ifdef BRM_VERBOSE cerr << "looked up LBID " << target << " got oid " << oid << " fbo " << fbo << endl; cerr << " oid should be " << tmp->OID << " fbo should be " << offset+tmp->FBO << endl; #endif CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(oid == tmp->OID); CPPUNIT_ASSERT(fbo == offset + tmp->FBO); em->checkConsistency(); break; } case 4: //lookup by OID, FBO { if (listSize == 0) break; int entryRand = rand_r(&randstate) % listSize; int i, oid, err, offset; struct EMEntries *tmp; LBID_t lbid; for (i = 0, tmp = head; i < entryRand; i++) tmp = tmp->next; offset = rand_r(&randstate) % tmp->size; oid = tmp->OID; err = em->lookup(oid, offset + tmp->FBO, lbid); #ifdef BRM_VERBOSE cerr << "looked up OID " << oid << " fbo " << offset + tmp->FBO << " got lbid " << lbid << endl; cerr << " lbid should be " << tmp->LBIDstart + offset << endl; #endif CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(lbid == tmp->LBIDstart + offset); em->checkConsistency(); break; } case 5: //getHWM { if (listSize == 0) break; int entryRand = rand_r(&randstate) % listSize; int i; struct EMEntries *tmp; u_int32_t hwm; for (i = 0, tmp = head; i < entryRand; i++) tmp = tmp->next; hwm = em->getHWM(tmp->OID); #ifdef BRM_VERBOSE cerr << "stored HWM for OID " << tmp->OID << " is " << tmp->HWM << " BRM says it's " << hwm << endl; #endif CPPUNIT_ASSERT(hwm == tmp->HWM); em->checkConsistency(); break; } case 6: //setHWM { if (listSize == 0) break; int entryRand = rand_r(&randstate) % listSize; int i, hwm, oid; struct EMEntries *tmp; for (i = 0, tmp = head; i < entryRand; i++) tmp = tmp->next; oid = tmp->OID; hwm = rand_r(&randstate) % (tmp->FBO + em->getExtentSize()); em->setHWM(oid, hwm); em->confirmChanges(); for (tmp = head; tmp != NULL; tmp = tmp->next) if (tmp->OID == oid) tmp->HWM = hwm; #ifdef BRM_VERBOSE cerr << "setHWM of OID " << oid << " to " << hwm << endl; #endif em->checkConsistency(); break; } case 7: // renew this EM object { delete em; em = new ExtentMap(); #ifdef BRM_VERBOSE cerr << "got a new EM instance" << endl; #endif em->checkConsistency(); break; } case 8: //getBulkInsertVars { if (listSize == 0) break; HWM_t hwm; VER_t txnID; int entryRand = rand_r(&randstate) % listSize; int i, err, offset; EMEntries *tmp; LBID_t lbid; for (i = 0, tmp = head; i < entryRand; i++) tmp = tmp->next; offset = rand_r(&randstate) % tmp->size; lbid = tmp->LBIDstart + offset; err = em->getBulkInsertVars(lbid, hwm, txnID); CPPUNIT_ASSERT(err == 0); CPPUNIT_ASSERT(hwm == tmp->secondHWM); CPPUNIT_ASSERT(txnID == tmp->txnID); break; } case 9: //setBulkInsertVars { if (listSize == 0) break; int entryRand = rand_r(&randstate) % listSize; int i, err, offset; EMEntries *tmp; for (i = 0, tmp = head; i < entryRand; i++) tmp = tmp->next; offset = rand_r(&randstate) % tmp->size; tmp->secondHWM = rand_r(&randstate) % MAXINT; tmp->txnID = rand_r(&randstate) % MAXINT; err = em->setBulkInsertVars(tmp->LBIDstart + offset, tmp->secondHWM, tmp->txnID); em->confirmChanges(); CPPUNIT_ASSERT(err == 0); break; } default: break; } } delete em; while (head != NULL) { tmp = head->next; delete head; head = tmp; } #ifdef BRM_VERBOSE cerr << "thread " << threadNum << " exiting" << endl; #endif return NULL; }