LbmEntryTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/lucidera/test/LbmEntryTest.cpp#17 $
00003 // Fennel is a library of data storage and processing components.
00004 // Copyright (C) 2006-2009 LucidEra, Inc.
00005 // Copyright (C) 2006-2009 The Eigenbase Project
00006 //
00007 // This program is free software; you can redistribute it and/or modify it
00008 // under the terms of the GNU General Public License as published by the Free
00009 // Software Foundation; either version 2 of the License, or (at your option)
00010 // any later version approved by The Eigenbase Project.
00011 //
00012 // This program is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with this program; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 */
00021 
00022 #include "fennel/common/CommonPreamble.h"
00023 #include "fennel/test/SegStorageTestBase.h"
00024 #include "fennel/tuple/StandardTypeDescriptor.h"
00025 #include "fennel/lucidera/bitmap/LbmEntry.h"
00026 #include "fennel/cache/Cache.h"
00027 #include <stdarg.h>
00028 #include <hash_set>
00029 #include <math.h>
00030 
00031 #include <boost/scoped_array.hpp>
00032 #include <boost/test/test_tools.hpp>
00033 
00034 using namespace fennel;
00035 
00036 struct LbmEntryInfo
00037 {
00038     LbmEntry entry;
00039     PBuffer pBuf;
00040     TupleData entryTuple;
00041 };
00042 
00043 typedef boost::shared_ptr<LbmEntryInfo> SharedLbmEntryInfo;
00044 
00045 enum EntryType {
00046     SBM_ADJ,            // 0 - single bitmap, adjacent to previous
00047     SGT_ADJ,            // 1 - singleton, adjacent to previous
00048     CMP_ADJ,            // 2 - compressed, adjacent to previous
00049     SBM_NADJ,           // 3 - single bitmap, non-adjacent to previous
00050     SGT_NADJ,           // 4 - singleton, non-adjacent to previous
00051     CMP_NADJ,           // 5 - compressed, non-adjacent to previous
00052     SBM_OVLP,           // 6 - single bitmap, overlaps previous
00053     SGT_OVLP,           // 7 - singleton, overlaps previous
00054     CMP_OVLP            // 8 - compressed, overlaps previous
00055 };
00056 
00060 class LbmEntryTest : virtual public SegStorageTestBase
00061 {
00062     uint bitmapColSize;
00063     StandardTypeDescriptorFactory stdTypeFactory;
00064     TupleAttributeDescriptor attrDesc_bitmap;
00065     TupleAttributeDescriptor attrDesc_int64;
00066     TupleDescriptor entryTupleDesc;
00067     uint bufSize;
00068     uint bufUsed;
00069     PBuffer pBuf;
00070     TupleData entryTuple;
00071 
00072     void testRandom(uint nUniqueKeys, uint nRows, uint scratchBufferSize);
00073 
00083     void testMergeEntry(
00084         std::vector<LcsRid> const &ridValues,
00085         VectorOfUint const &nRidsPerBitmap, uint scratchBufferSize);
00086 
00087     void newLbmEntry(
00088         std::vector<SharedLbmEntryInfo> &entryList, LcsRid startRid,
00089         SegPageLock &bufferLock);
00090 
00091     PBuffer allocateBuf(SegPageLock &bufferLock);
00092 
00093     bool compareExpected(
00094         LbmEntry &entry, std::vector<LcsRid> const &ridValues, uint &ridPos,
00095         bool testContains);
00096 
00097     void recurseCombos(uint curr, uint nEntries, VectorOfUint &eTypes);
00098 
00099     void generateBitmaps(
00100         EntryType etype, std::vector<LcsRid> &ridValues,
00101         VectorOfUint &nRidsPerBitmap);
00102 
00103     void generateSingleBitmaps(
00104         std::vector<LcsRid> &ridValues, VectorOfUint &nRidsPerBitmap,
00105         LcsRid startRid, uint nRids);
00106 
00107     void generateCompressedBitmaps(
00108         std::vector<LcsRid> &ridValues, VectorOfUint &nRidsPerBitmap,
00109         LcsRid startRid, uint nRids);
00110 
00120     void testMergeSingleton(
00121         uint scratchBufferSize, const std::vector<LcsRid> &ridValues,
00122         uint nSingletons, bool split);
00123 
00124     void testMergeSingletonRandom(uint totalRids, uint ridRange);
00125 
00126 public:
00127     explicit LbmEntryTest()
00128     {
00129         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testRandom1);
00130         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testRandom2);
00131         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testRandom3);
00132         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testRandom4);
00133         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testRandom5);
00134         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testCombos);
00135         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testldb35);
00136         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testler5920);
00137         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testZeroBytes);
00138 
00139         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonInFront1);
00140         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonInFront2);
00141         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonMidSegment1);
00142         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonMidSegment2);
00143         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonMidSegment3);
00144         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonMidSegment4);
00145         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonEndSegment);
00146         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonStartSegment1);
00147         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonStartSegment2);
00148         FENNEL_UNIT_TEST_CASE(
00149             LbmEntryTest, testMergeSingletonInBetweenSegment);
00150         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonSplitLeft1);
00151         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonSplitLeft2);
00152         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonSplitRight1);
00153         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonSplitRight2);
00154         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonSplitHalf);
00155         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonSplitLast);
00156         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonSplitMaxSegments);
00157         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonZeros1);
00158         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonZeros2);
00159         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonZeros3);
00160         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonZeros4);
00161         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonAfterSplit);
00162         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonCombine);
00163         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonMaxSeg);
00164         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonRandom1);
00165         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonRandom2);
00166         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonWithSingleton1);
00167         FENNEL_UNIT_TEST_CASE(LbmEntryTest, testMergeSingletonWithSingleton2);
00168     }
00169 
00170     virtual void testCaseSetUp();
00171     virtual void testCaseTearDown();
00172 
00173     void testRandom1();
00174     void testRandom2();
00175     void testRandom3();
00176     void testRandom4();
00177     void testRandom5();
00178     void testCombos();
00179     void testldb35();
00180     void testler5920();
00181     void testZeroBytes();
00182     void testMergeSingletonInFront1();
00183     void testMergeSingletonInFront2();
00184     void testMergeSingletonMidSegment1();
00185     void testMergeSingletonMidSegment2();
00186     void testMergeSingletonMidSegment3();
00187     void testMergeSingletonMidSegment4();
00188     void testMergeSingletonEndSegment();
00189     void testMergeSingletonStartSegment1();
00190     void testMergeSingletonStartSegment2();
00191     void testMergeSingletonInBetweenSegment();
00192     void testMergeSingletonSplitLeft1();
00193     void testMergeSingletonSplitLeft2();
00194     void testMergeSingletonSplitRight1();
00195     void testMergeSingletonSplitRight2();
00196     void testMergeSingletonSplitHalf();
00197     void testMergeSingletonSplitLast();
00198     void testMergeSingletonSplitMaxSegments();
00199     void testMergeSingletonZeros1();
00200     void testMergeSingletonZeros2();
00201     void testMergeSingletonZeros3();
00202     void testMergeSingletonZeros4();
00203     void testMergeSingletonAfterSplit();
00204     void testMergeSingletonCombine();
00205     void testMergeSingletonMaxSeg();
00206     void testMergeSingletonRandom1();
00207     void testMergeSingletonRandom2();
00208     void testMergeSingletonWithSingleton1();
00209     void testMergeSingletonWithSingleton2();
00210 };
00211 
00212 void LbmEntryTest::testRandom1()
00213 {
00214     uint nUniqueKeys = 10;
00215     uint nRows = 1000;
00216     uint scratchBufferSize = 40;
00217 
00218     testRandom(nUniqueKeys, nRows, scratchBufferSize);
00219 }
00220 
00221 void LbmEntryTest::testRandom2()
00222 {
00223     uint nUniqueKeys = 30;
00224     uint nRows = 2000;
00225     uint scratchBufferSize = 50;
00226 
00227     testRandom(nUniqueKeys, nRows, scratchBufferSize);
00228 }
00229 
00230 void LbmEntryTest::testRandom3()
00231 {
00232     uint nUniqueKeys = 25;
00233     uint nRows = 1500;
00234     uint scratchBufferSize = 30;
00235 
00236     testRandom(nUniqueKeys, nRows, scratchBufferSize);
00237 }
00238 
00239 void LbmEntryTest::testRandom4()
00240 {
00241     uint nUniqueKeys = 20;
00242     uint nRows = 2500;
00243     uint scratchBufferSize = 35;
00244 
00245     testRandom(nUniqueKeys, nRows, scratchBufferSize);
00246 }
00247 
00248 void LbmEntryTest::testRandom5()
00249 {
00250     uint nUniqueKeys = 15;
00251     uint nRows = 3000;
00252     uint scratchBufferSize = 45;
00253 
00254     testRandom(nUniqueKeys, nRows, scratchBufferSize);
00255 }
00256 
00257 void LbmEntryTest::testRandom(
00258     uint nUniqueKeys, uint nRows, uint scratchBufferSize)
00259 {
00260     std::vector<LcsRid> ridValues;
00261     VectorOfUint nRidsPerBitmap;
00262     uint totalRids = nRows / nUniqueKeys;
00263 
00264     assert(scratchBufferSize >= 8);
00265 
00266     // generate random rid values, ensuring that they are unique, then
00267     // sort them
00268     std::hash_set<uint64_t> ridsGenerated;
00269     for (uint i = 0; i < totalRids;) {
00270         uint64_t rid = rand() % nRows;
00271         if (ridsGenerated.find(rid) == ridsGenerated.end()) {
00272             ridValues.push_back(LcsRid(rid));
00273             ridsGenerated.insert(rid);
00274             i++;
00275         }
00276     }
00277     // sort the rid values
00278     std::sort(ridValues.begin(), ridValues.end());
00279 #if 0
00280     std::cout << "Rid Values After Sort" << std::endl;
00281     for (uint i = 0; i < ridValues.size(); i++) {
00282         std::cout << ridValues[i] << std::endl;
00283     }
00284 #endif
00285 
00286     // generate random values that will determine how many rids
00287     // there are per bitmap
00288     uint ridCount = 0;
00289     while (ridCount < totalRids) {
00290         // divide by 4 so we'll later merge roughly 2-4 bitmaps per
00291         // entry
00292         uint nRids = rand() % (scratchBufferSize / 4) + 1;
00293         if (nRids + ridCount < totalRids) {
00294             nRidsPerBitmap.push_back(nRids);
00295             ridCount += nRids;
00296         } else {
00297             nRidsPerBitmap.push_back(totalRids - ridCount);
00298             break;
00299         }
00300     }
00301 
00302     testMergeEntry(ridValues, nRidsPerBitmap, scratchBufferSize);
00303 }
00304 
00305 void LbmEntryTest::testMergeEntry(
00306     std::vector<LcsRid> const &ridValues,
00307     VectorOfUint const &nRidsPerBitmap, uint scratchBufferSize)
00308 {
00309     std::vector<SharedLbmEntryInfo> entryList;
00310 
00311     // bitmap entries will be created without a leading key, so the
00312     // first column is the startRid
00313     // initialize scratch accessor for scratch buffers used to
00314     // construct bitmaps
00315     SegmentAccessor scratchAccessor =
00316         pSegmentFactory->newScratchSegment(pCache, 10);
00317     bufSize = scratchAccessor.pSegment->getUsablePageSize();
00318     SegPageLock bufferLock;
00319     bufferLock.accessSegment(scratchAccessor);
00320     bufUsed = bufSize;
00321 
00322     bitmapColSize = scratchBufferSize;
00323     attrDesc_bitmap =
00324         TupleAttributeDescriptor(
00325             stdTypeFactory.newDataType(STANDARD_TYPE_VARBINARY),
00326             true, bitmapColSize);
00327     attrDesc_int64 =
00328         TupleAttributeDescriptor(
00329             stdTypeFactory.newDataType(STANDARD_TYPE_INT_64));
00330 
00331     entryTupleDesc.push_back(attrDesc_int64);
00332     entryTupleDesc.push_back(attrDesc_bitmap);
00333     entryTupleDesc.push_back(attrDesc_bitmap);
00334     entryTuple.compute(entryTupleDesc);
00335     entryTuple[1].pData = NULL;
00336     entryTuple[2].pData = NULL;
00337 
00338     // Generate bitmaps using the list of rid values. The number of rids
00339     // in each bitmap is based on the list of nRidsPerBitmap.
00340 
00341     uint totalRids = ridValues.size();
00342     uint nRidPos = 0;
00343     for (uint i = 0; i < totalRids;) {
00344         newLbmEntry(entryList, ridValues[i], bufferLock);
00345         i++;
00346 
00347         for (uint j = 1; i < totalRids && j < nRidsPerBitmap[nRidPos];
00348             i++, j++)
00349         {
00350             if (!entryList.back()->entry.setRID(ridValues[i])) {
00351                 newLbmEntry(entryList, ridValues[i], bufferLock);
00352             }
00353         }
00354         nRidPos++;
00355     }
00356 
00357     // produce the tuples corresponding to each LbmEntry
00358     for (uint i = 0; i < entryList.size(); i++) {
00359         entryList[i]->entryTuple = entryList[i]->entry.produceEntryTuple();
00360     }
00361 
00362 #if 0
00363     std::cout << "Generated Entries Before Merge" << std::endl;
00364     for (uint i = 0; i < entryList.size(); i++) {
00365         std::cout << LbmEntry::toString(entryList[i]->entryTuple, true)
00366             << std::endl;
00367     }
00368 #endif
00369 
00370     // merge the entries constructed
00371     uint ridPos = 0;
00372 
00373     PBuffer mergeBuf = allocateBuf(bufferLock);
00374     LbmEntry mEntry;
00375     mEntry.init(
00376         mergeBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00377         entryTupleDesc);
00378     mEntry.setEntryTuple(entryList[0]->entryTuple);
00379     for (uint i = 1; i < entryList.size(); i++) {
00380         if (mEntry.mergeEntry(entryList[i]->entryTuple)) {
00381             continue;
00382         }
00383         // not able to merge, so need to produce entry and compare against
00384         // expected rids before starting to merge on the next entry
00385         bool rc = compareExpected(mEntry, ridValues, ridPos, true);
00386         BOOST_REQUIRE(rc);
00387         mEntry.setEntryTuple(entryList[i]->entryTuple);
00388     }
00389     // if this is the last remaining entry, compare it against
00390     // expected rid values
00391     if (ridPos < totalRids) {
00392         bool rc = compareExpected(mEntry, ridValues, ridPos, true);
00393         BOOST_REQUIRE(rc);
00394     }
00395 
00396     BOOST_REQUIRE(ridPos == totalRids);
00397 
00398     scratchAccessor.pSegment->deallocatePageRange(NULL_PAGE_ID, NULL_PAGE_ID);
00399 }
00400 
00401 void LbmEntryTest::newLbmEntry(
00402     std::vector<SharedLbmEntryInfo> &entryList, LcsRid startRid,
00403     SegPageLock &bufferLock)
00404 {
00405     SharedLbmEntryInfo pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00406 
00407     pListElement->pBuf = allocateBuf(bufferLock);
00408     pListElement->entry.init(
00409         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00410         entryTupleDesc);
00411     entryList.push_back(pListElement);
00412     entryTuple[0].pData = (PConstBuffer) &startRid;
00413     entryList.back()->entry.setEntryTuple(entryTuple);
00414 }
00415 
00416 PBuffer LbmEntryTest::allocateBuf(SegPageLock &bufferLock)
00417 {
00418     // allocate a new scratch page if not enough space is left on
00419     // the current
00420     uint scratchBufSize = LbmEntry::getScratchBufferSize(bitmapColSize);
00421     if (bufUsed + scratchBufSize > bufSize) {
00422         bufferLock.allocatePage();
00423         pBuf = bufferLock.getPage().getWritableData();
00424         bufferLock.unlock();
00425         bufUsed = 0;
00426     }
00427     PBuffer retBuf = pBuf + bufUsed;
00428     bufUsed += scratchBufSize;
00429     return retBuf;
00430 }
00431 
00432 bool LbmEntryTest::compareExpected(
00433     LbmEntry &generatedEntry, std::vector<LcsRid> const &expectedRids,
00434     uint &ridPos, bool testContains)
00435 {
00436     TupleData const &generatedTuple = generatedEntry.produceEntryTuple();
00437     std::vector<LcsRid> actualRids;
00438     LbmEntry::generateRIDs(generatedTuple, actualRids);
00439 
00440     LcsRid endRid;
00441     uint rowCount = generatedEntry.getRowCount();
00442     if (rowCount == 1) {
00443         // singleton
00444         endRid = expectedRids[ridPos] + 1;
00445     } else {
00446         endRid =
00447             LbmSegment::roundToByteBoundary(expectedRids[ridPos]) + rowCount;
00448     }
00449 
00450     uint i;
00451     for (i = 0;
00452         ridPos < expectedRids.size() && expectedRids[ridPos] < endRid &&
00453             i < actualRids.size();
00454         i++, ridPos++)
00455     {
00456         if (expectedRids[ridPos] != actualRids[i]) {
00457             break;
00458         }
00459         // the two if blocks below are redundant but are there to test the
00460         // containsRid() method; the first tests the positive case and the
00461         // second the negative
00462         if (!generatedEntry.containsRid(expectedRids[ridPos])) {
00463             std::cout << "Positive containsRid check failed on rid = " <<
00464                 expectedRids[ridPos] << std::endl;
00465             return false;
00466         }
00467         // search for the rids in between the current and next; these should
00468         // not be set in the entry
00469         if (testContains) {
00470             if (ridPos + 1 < expectedRids.size()) {
00471                 for (LcsRid nextRid = expectedRids[ridPos] + 1;
00472                     nextRid < expectedRids[ridPos + 1]; nextRid++)
00473                 {
00474                     if (generatedEntry.containsRid(nextRid)) {
00475                         std::cout << "Negative containsRid check failed" <<
00476                            " on rid = " << nextRid << std::endl;
00477                         return false;
00478                     }
00479                 }
00480             }
00481         }
00482     }
00483 #if 0
00484     std::cout << "Generated Entry:" << LbmEntry::toString(generatedTuple, true)
00485         << std::endl;
00486 #endif
00487     if (i < actualRids.size()) {
00488         std::cout << "Mismatch in rid.  Actual = " << actualRids[i] <<
00489             ", Expected = " << expectedRids[ridPos] << std::endl;
00490         return false;
00491     }
00492     return true;
00493 }
00494 
00495 void LbmEntryTest::testldb35()
00496 {
00497     std::vector<SharedLbmEntryInfo> entryList;
00498     std::vector<LcsRid> ridValues;
00499 
00500     // bitmap entries will be created without a leading key, so the
00501     // first column is the startRid
00502     // initialize scratch accessor for scratch buffers used to
00503     // construct bitmaps
00504     SegmentAccessor scratchAccessor =
00505         pSegmentFactory->newScratchSegment(pCache, 10);
00506     bufSize = scratchAccessor.pSegment->getUsablePageSize();
00507     SegPageLock bufferLock;
00508     bufferLock.accessSegment(scratchAccessor);
00509     bufUsed = bufSize;
00510 
00511     bitmapColSize = 16;
00512     attrDesc_bitmap =
00513         TupleAttributeDescriptor(
00514             stdTypeFactory.newDataType(STANDARD_TYPE_VARBINARY),
00515             true, bitmapColSize);
00516     attrDesc_int64 =
00517         TupleAttributeDescriptor(
00518             stdTypeFactory.newDataType(STANDARD_TYPE_INT_64));
00519 
00520     entryTupleDesc.push_back(attrDesc_int64);
00521     entryTupleDesc.push_back(attrDesc_bitmap);
00522     entryTupleDesc.push_back(attrDesc_bitmap);
00523     entryTuple.compute(entryTupleDesc);
00524 
00525     SharedLbmEntryInfo pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00526 
00527     // first entry -- single bitmap with rid 98601
00528 
00529     pListElement->pBuf = allocateBuf(bufferLock);
00530     pListElement->entry.init(
00531         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00532         entryTupleDesc);
00533     entryList.push_back(pListElement);
00534     LcsRid rid = LcsRid(98061);
00535     ridValues.push_back(rid);
00536     LcsRid roundedRid = LbmSegment::roundToByteBoundary(rid);
00537     entryTuple[0].pData = (PConstBuffer) &roundedRid;
00538     entryTuple[1].pData = NULL;
00539     uint8_t byte =
00540         (uint8_t) (1 << (opaqueToInt(rid) % LbmSegment::LbmOneByteSize));
00541     entryTuple[2].pData = &byte;
00542     entryTuple[2].cbData = 1;
00543     entryList.back()->entry.setEntryTuple(entryTuple);
00544 
00545     // second entry -- compressed bitmap with only rid 98070 set
00546 
00547     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00548     pListElement->pBuf = allocateBuf(bufferLock);
00549     pListElement->entry.init(
00550         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00551         entryTupleDesc);
00552     entryList.push_back(pListElement);
00553     rid = LcsRid(98070);
00554     ridValues.push_back(rid);
00555     roundedRid = LbmSegment::roundToByteBoundary(rid);
00556     entryTuple[0].pData = (PConstBuffer) &roundedRid;
00557     uint8_t twoBytes[2];
00558     twoBytes[0] = 0xd;
00559     twoBytes[1] = 0xf0;
00560     entryTuple[1].pData = twoBytes;
00561     entryTuple[1].cbData = 2;
00562     byte = (uint8_t) (1 << (opaqueToInt(rid) % LbmSegment::LbmOneByteSize));
00563     entryTuple[2].pData = &byte;
00564     entryTuple[2].cbData = 1;
00565     entryList.back()->entry.setEntryTuple(entryTuple);
00566 
00567     // third entry -- compressed bitmap with only rid 99992 set
00568 
00569     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00570     pListElement->pBuf = allocateBuf(bufferLock);
00571     pListElement->entry.init(
00572         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00573         entryTupleDesc);
00574     entryList.push_back(pListElement);
00575     rid = LcsRid(99992);
00576     ridValues.push_back(rid);
00577     roundedRid = LbmSegment::roundToByteBoundary(rid);
00578     entryTuple[0].pData = (PConstBuffer) &roundedRid;
00579     twoBytes[0] = 0xd;
00580     twoBytes[1] = 0x10;
00581     entryTuple[1].pData = twoBytes;
00582     entryTuple[1].cbData = 2;
00583     byte = (uint8_t) (1 << (opaqueToInt(rid) % LbmSegment::LbmOneByteSize));
00584     entryTuple[2].pData = &byte;
00585     entryTuple[2].cbData = 1;
00586     entryList.back()->entry.setEntryTuple(entryTuple);
00587 
00588     // fourth entry -- singleton with rid 100133
00589 
00590     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00591     pListElement->pBuf = allocateBuf(bufferLock);
00592     pListElement->entry.init(
00593         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00594         entryTupleDesc);
00595     entryList.push_back(pListElement);
00596     rid = LcsRid(100133);
00597     ridValues.push_back(rid);
00598     entryTuple[0].pData = (PConstBuffer) &rid;
00599     entryTuple[1].pData = NULL;
00600     entryTuple[2].pData = NULL;
00601     entryList.back()->entry.setEntryTuple(entryTuple);
00602 
00603     // fifth entry -- singleton with rid 100792
00604 
00605     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00606     pListElement->pBuf = allocateBuf(bufferLock);
00607     pListElement->entry.init(
00608         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00609         entryTupleDesc);
00610     entryList.push_back(pListElement);
00611     rid = LcsRid(100792);
00612     ridValues.push_back(rid);
00613     entryTuple[0].pData = (PConstBuffer) &rid;
00614     entryTuple[1].pData = NULL;
00615     entryTuple[2].pData = NULL;
00616     entryList.back()->entry.setEntryTuple(entryTuple);
00617 
00618     // produce the tuples corresponding to each LbmEntry
00619     for (uint i = 0; i < entryList.size(); i++) {
00620         entryList[i]->entryTuple = entryList[i]->entry.produceEntryTuple();
00621     }
00622 
00623     uint ridPos = 0;
00624     PBuffer mergeBuf = allocateBuf(bufferLock);
00625     LbmEntry mEntry;
00626     mEntry.init(
00627         mergeBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00628         entryTupleDesc);
00629 
00630     mEntry.setEntryTuple(entryList[0]->entryTuple);
00631     for (uint i = 1; i < entryList.size(); i++) {
00632         if (mEntry.mergeEntry(entryList[i]->entryTuple)) {
00633             continue;
00634         }
00635         // not able to merge, so need to produce entry and compare against
00636         // expected rids before starting to merge on the next entry
00637         bool rc = compareExpected(mEntry, ridValues, ridPos, true);
00638         BOOST_REQUIRE(rc);
00639         mEntry.setEntryTuple(entryList[i]->entryTuple);
00640     }
00641     // if this is the last remaining entry, compare it against
00642     // expected rid values
00643     if (ridPos < ridValues.size()) {
00644         bool rc = compareExpected(mEntry, ridValues, ridPos, true);
00645         BOOST_REQUIRE(rc);
00646     }
00647 
00648     BOOST_REQUIRE(ridPos == ridValues.size());
00649 
00650     scratchAccessor.pSegment->deallocatePageRange(NULL_PAGE_ID, NULL_PAGE_ID);
00651 }
00652 
00653 void LbmEntryTest::testler5920()
00654 {
00655     std::vector<SharedLbmEntryInfo> entryList;
00656     std::vector<LcsRid> ridValues;
00657 
00658     // bitmap entries will be created without a leading key, so the
00659     // first column is the startRid
00660     // initialize scratch accessor for scratch buffers used to
00661     // construct bitmaps
00662     SegmentAccessor scratchAccessor =
00663         pSegmentFactory->newScratchSegment(pCache, 10);
00664     bufSize = scratchAccessor.pSegment->getUsablePageSize();
00665     SegPageLock bufferLock;
00666     bufferLock.accessSegment(scratchAccessor);
00667     bufUsed = bufSize;
00668 
00669     bitmapColSize = 16;
00670     attrDesc_bitmap =
00671         TupleAttributeDescriptor(
00672             stdTypeFactory.newDataType(STANDARD_TYPE_VARBINARY),
00673             true, bitmapColSize);
00674     attrDesc_int64 =
00675         TupleAttributeDescriptor(
00676             stdTypeFactory.newDataType(STANDARD_TYPE_INT_64));
00677 
00678     entryTupleDesc.push_back(attrDesc_int64);
00679     entryTupleDesc.push_back(attrDesc_bitmap);
00680     entryTupleDesc.push_back(attrDesc_bitmap);
00681     entryTuple.compute(entryTupleDesc);
00682 
00683     SharedLbmEntryInfo pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00684 
00685     // first entry -- full bitmap
00686 
00687     pListElement->pBuf = allocateBuf(bufferLock);
00688     pListElement->entry.init(
00689         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00690         entryTupleDesc);
00691     entryList.push_back(pListElement);
00692     LcsRid rid = LcsRid(0);
00693     ridValues.push_back(rid);
00694     entryTuple[0].pData = (PConstBuffer) &rid;
00695     entryTuple[1].cbData = 0;
00696     entryTuple[1].pData = NULL;
00697     entryTuple[2].cbData = 0;
00698     entryTuple[2].pData = NULL;
00699     entryList.back()->entry.setEntryTuple(entryTuple);
00700     for (uint i = 0; i < bitmapColSize - 2; i++) {
00701         rid = LcsRid((i + 1) * 8);
00702         entryList.back()->entry.setRID(rid);
00703         ridValues.push_back(rid);
00704     }
00705     LcsRid overlapStartRid = LcsRid((bitmapColSize - 2) * 8);
00706 
00707     // second entry -- compressed bitmap that overlaps the last byte of the
00708     // first entry
00709 
00710     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00711     pListElement->pBuf = allocateBuf(bufferLock);
00712     pListElement->entry.init(
00713         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00714         entryTupleDesc);
00715     entryList.push_back(pListElement);
00716     entryTuple[0].pData = (PConstBuffer) &overlapStartRid;
00717     entryTuple[1].pData = NULL;
00718     entryTuple[1].cbData = 0;
00719     rid = LcsRid(overlapStartRid + 4);
00720     ridValues.push_back(rid);
00721     uint8_t byte =
00722         (uint8_t) (1 << (opaqueToInt(rid) % LbmSegment::LbmOneByteSize));
00723     rid = LcsRid(overlapStartRid + 5);
00724     ridValues.push_back(rid);
00725     byte |= (uint8_t) (1 << (opaqueToInt(rid) % LbmSegment::LbmOneByteSize));
00726     entryTuple[2].pData = &byte;
00727     entryTuple[2].cbData = 1;
00728     entryList.back()->entry.setEntryTuple(entryTuple);
00729 
00730     // third entry -- singleton
00731 
00732     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00733     pListElement->pBuf = allocateBuf(bufferLock);
00734     pListElement->entry.init(
00735         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00736         entryTupleDesc);
00737     entryList.push_back(pListElement);
00738     rid = LcsRid(overlapStartRid + 8 + 2);
00739     ridValues.push_back(rid);
00740     entryTuple[0].pData = (PConstBuffer) &rid;
00741     entryTuple[1].pData = NULL;
00742     entryTuple[1].cbData = 0;
00743     entryTuple[2].pData = NULL;
00744     entryTuple[2].cbData = 0;
00745     entryList.back()->entry.setEntryTuple(entryTuple);
00746 
00747     // produce the tuples corresponding to each LbmEntry
00748     for (uint i = 0; i < entryList.size(); i++) {
00749         entryList[i]->entryTuple = entryList[i]->entry.produceEntryTuple();
00750     }
00751 
00752     uint ridPos = 0;
00753     PBuffer mergeBuf = allocateBuf(bufferLock);
00754     LbmEntry mEntry;
00755     mEntry.init(
00756         mergeBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00757         entryTupleDesc);
00758 
00759     mEntry.setEntryTuple(entryList[0]->entryTuple);
00760 
00761     // merge the the overlapping byte; mergeEntry should return true
00762     bool rc = mEntry.mergeEntry(entryList[1]->entryTuple);
00763     BOOST_REQUIRE(rc);
00764 
00765     // this merge should overflow the currentEntry
00766     rc = mEntry.mergeEntry(entryList[2]->entryTuple);
00767     BOOST_REQUIRE(!rc);
00768     rc = compareExpected(mEntry, ridValues, ridPos, true);
00769     BOOST_REQUIRE(rc);
00770 
00771     // make sure the previous merge didn't add any extra rids
00772     mEntry.setEntryTuple(entryList[2]->entryTuple);
00773     rc = compareExpected(mEntry, ridValues, ridPos, true);
00774     BOOST_REQUIRE(rc);
00775 
00776     scratchAccessor.pSegment->deallocatePageRange(NULL_PAGE_ID, NULL_PAGE_ID);
00777 }
00778 
00779 void LbmEntryTest::testZeroBytes()
00780 {
00781     // Exercise creating bitmaps that contain zero bytes requiring various
00782     // lengths to encode.
00783 
00784     std::vector<SharedLbmEntryInfo> entryList;
00785     std::vector<LcsRid> ridValues;
00786 
00787     SegmentAccessor scratchAccessor =
00788         pSegmentFactory->newScratchSegment(pCache, 10);
00789     bufSize = scratchAccessor.pSegment->getUsablePageSize();
00790     SegPageLock bufferLock;
00791     bufferLock.accessSegment(scratchAccessor);
00792     bufUsed = bufSize;
00793 
00794     bitmapColSize = 16;
00795     attrDesc_bitmap =
00796         TupleAttributeDescriptor(
00797             stdTypeFactory.newDataType(STANDARD_TYPE_VARBINARY),
00798             true, bitmapColSize);
00799     attrDesc_int64 =
00800         TupleAttributeDescriptor(
00801             stdTypeFactory.newDataType(STANDARD_TYPE_INT_64));
00802 
00803     entryTupleDesc.push_back(attrDesc_int64);
00804     entryTupleDesc.push_back(attrDesc_bitmap);
00805     entryTupleDesc.push_back(attrDesc_bitmap);
00806     entryTuple.compute(entryTupleDesc);
00807 
00808     SharedLbmEntryInfo pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00809 
00810     // 1st entry -- start with rid 1
00811 
00812     pListElement->pBuf = allocateBuf(bufferLock);
00813     pListElement->entry.init(
00814         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00815         entryTupleDesc);
00816     entryList.push_back(pListElement);
00817     LcsRid rid = LcsRid(1);
00818     ridValues.push_back(rid);
00819     LcsRid roundedRid = LbmSegment::roundToByteBoundary(rid);
00820     entryTuple[0].pData = (PConstBuffer) &roundedRid;
00821     entryTuple[1].pData = NULL;
00822     uint8_t byte =
00823         (uint8_t) (1 << (opaqueToInt(rid) % LbmSegment::LbmOneByteSize));
00824     entryTuple[2].pData = &byte;
00825     entryTuple[2].cbData = 1;
00826     entryList.back()->entry.setEntryTuple(entryTuple);
00827 
00828     // 2nd entry -- previous rid + 2^16*8.  This will require 2 bytes to store
00829     // the zero bytes in between this rid and the previous.
00830 
00831     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00832     pListElement->pBuf = allocateBuf(bufferLock);
00833     pListElement->entry.init(
00834         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00835         entryTupleDesc);
00836     entryList.push_back(pListElement);
00837     rid = LcsRid(rid + (int64_t) pow(2.0,16.0)*8);
00838     ridValues.push_back(rid);
00839     entryTuple[0].pData = (PConstBuffer) &rid;
00840     entryTuple[1].pData = NULL;
00841     entryTuple[2].pData = NULL;
00842     entryList.back()->entry.setEntryTuple(entryTuple);
00843 
00844     // 3rd entry -- previous rid + 2^24*8.  This will require 3 bytes to
00845     // store the zero bytes in between this rid and the previous.
00846 
00847     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00848     pListElement->pBuf = allocateBuf(bufferLock);
00849     pListElement->entry.init(
00850         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00851         entryTupleDesc);
00852     entryList.push_back(pListElement);
00853     rid = LcsRid(rid + (int64_t) pow(2.0,24.0)*8);
00854     ridValues.push_back(rid);
00855     entryTuple[0].pData = (PConstBuffer) &rid;
00856     entryTuple[1].pData = NULL;
00857     entryTuple[2].pData = NULL;
00858     entryList.back()->entry.setEntryTuple(entryTuple);
00859 
00860     // 4th entry -- previous rid + ((2^24)+1)*8.  The zero bytes in this case
00861     // cannot be encoded in 3 bytes, so a new bitmap entry will be created.
00862 
00863     pListElement = SharedLbmEntryInfo(new LbmEntryInfo());
00864     pListElement->pBuf = allocateBuf(bufferLock);
00865     pListElement->entry.init(
00866         pListElement->pBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00867         entryTupleDesc);
00868     entryList.push_back(pListElement);
00869     rid = LcsRid(rid + (int64_t) (pow(2.0,24.0)+1)*8);
00870     ridValues.push_back(rid);
00871     entryTuple[0].pData = (PConstBuffer) &rid;
00872     entryTuple[1].pData = NULL;
00873     entryTuple[2].pData = NULL;
00874     entryList.back()->entry.setEntryTuple(entryTuple);
00875 
00876     // produce the tuples corresponding to each LbmEntry
00877     for (uint i = 0; i < entryList.size(); i++) {
00878         entryList[i]->entryTuple = entryList[i]->entry.produceEntryTuple();
00879     }
00880 
00881     uint ridPos = 0;
00882     PBuffer mergeBuf = allocateBuf(bufferLock);
00883     LbmEntry mEntry;
00884     mEntry.init(
00885         mergeBuf, NULL, LbmEntry::getScratchBufferSize(bitmapColSize),
00886         entryTupleDesc);
00887 
00888     mEntry.setEntryTuple(entryList[0]->entryTuple);
00889     for (uint i = 1; i < entryList.size(); i++) {
00890         if (mEntry.mergeEntry(entryList[i]->entryTuple)) {
00891             continue;
00892         }
00893         // not able to merge, so need to produce entry and compare against
00894         // expected rids before starting to merge on the next entry; pass
00895         // in false for the testContains parameter to avoid excessive
00896         // containsRids() calls
00897         bool rc = compareExpected(mEntry, ridValues, ridPos, false);
00898         BOOST_REQUIRE(rc);
00899         mEntry.setEntryTuple(entryList[i]->entryTuple);
00900     }
00901     // if this is the last remaining entry, compare it against
00902     // expected rid values
00903     if (ridPos < ridValues.size()) {
00904         bool rc = compareExpected(mEntry, ridValues, ridPos, false);
00905         BOOST_REQUIRE(rc);
00906     }
00907 
00908     BOOST_REQUIRE(ridPos == ridValues.size());
00909 
00910     scratchAccessor.pSegment->deallocatePageRange(NULL_PAGE_ID, NULL_PAGE_ID);
00911 }
00912 
00913 void LbmEntryTest::testCombos()
00914 {
00915     uint nEntries = 5;
00916     VectorOfUint eTypes;
00917 
00918     for (uint i = 0; i < nEntries; i++) {
00919         eTypes.push_back(0);
00920     }
00921     recurseCombos(0, nEntries, eTypes);
00922 }
00923 
00924 void LbmEntryTest::recurseCombos(
00925     uint curr, uint nEntries, VectorOfUint &eTypes)
00926 {
00927     std::vector<LcsRid> ridValues;
00928     VectorOfUint nRidsPerBitmap;
00929 
00930     uint nETypes = (curr == 0) ? 3 : 9;
00931     for (uint i = 0; i < nETypes; i++) {
00932         eTypes[curr] = i;
00933         if (curr < nEntries - 1) {
00934             recurseCombos(curr + 1, nEntries, eTypes);
00935         } else {
00936             // generate the "nEntries" bitmaps
00937             for (uint n = 0; n < nEntries; n++) {
00938                 generateBitmaps(
00939                     EntryType(eTypes[n]), ridValues, nRidsPerBitmap);
00940             }
00941 
00942             // generate the last entry
00943             ridValues.push_back(ridValues.back() + 16);
00944             nRidsPerBitmap.push_back(1);
00945 
00946             // merge them
00947             testMergeEntry(ridValues, nRidsPerBitmap, nEntries * 24);
00948 
00949             ridValues.clear();
00950             nRidsPerBitmap.clear();
00951             entryTupleDesc.clear();
00952             entryTuple.clear();
00953         }
00954     }
00955 }
00956 
00957 void LbmEntryTest::generateBitmaps(
00958     EntryType etype, std::vector<LcsRid> &ridValues,
00959     VectorOfUint &nRidsPerBitmap)
00960 {
00961     LcsRid prev;
00962 
00963     if (ridValues.size() == 0) {
00964         prev = LcsRid(1);
00965     } else {
00966         prev = ridValues.back();
00967     }
00968 
00969     switch (etype) {
00970     case SBM_ADJ:
00971         generateSingleBitmaps(
00972             ridValues, nRidsPerBitmap, prev + LbmSegment::LbmOneByteSize, 4);
00973         break;
00974     case SBM_NADJ:
00975         generateSingleBitmaps(
00976             ridValues, nRidsPerBitmap, prev + LbmSegment::LbmOneByteSize*2, 4);
00977         break;
00978     case SBM_OVLP:
00979         generateSingleBitmaps(ridValues, nRidsPerBitmap, prev + 2, 4);
00980         break;
00981     case SGT_ADJ:
00982         generateSingleBitmaps(
00983             ridValues, nRidsPerBitmap, prev + LbmSegment::LbmOneByteSize, 1);
00984         break;
00985     case SGT_NADJ:
00986         generateSingleBitmaps(
00987             ridValues, nRidsPerBitmap, prev + LbmSegment::LbmOneByteSize*2, 1);
00988         break;
00989     case SGT_OVLP:
00990         generateSingleBitmaps(ridValues, nRidsPerBitmap, prev + 2, 1);
00991         break;
00992     case CMP_ADJ:
00993         generateCompressedBitmaps(
00994             ridValues, nRidsPerBitmap, prev + LbmSegment::LbmOneByteSize, 10);
00995         break;
00996     case CMP_NADJ:
00997         generateCompressedBitmaps(
00998             ridValues, nRidsPerBitmap, prev + LbmSegment::LbmOneByteSize*2, 10);
00999         break;
01000     case CMP_OVLP:
01001         generateCompressedBitmaps(ridValues, nRidsPerBitmap, prev + 2, 10);
01002         break;
01003     }
01004 }
01005 
01006 void LbmEntryTest::generateSingleBitmaps(
01007     std::vector<LcsRid> &ridValues, VectorOfUint &nRidsPerBitmap,
01008     LcsRid startRid, uint nRids)
01009 {
01010     for (uint i = 0;  i < nRids; i++) {
01011         ridValues.push_back(startRid);
01012         startRid += LbmSegment::LbmOneByteSize;
01013     }
01014     nRidsPerBitmap.push_back(nRids);
01015 }
01016 
01017 void LbmEntryTest::generateCompressedBitmaps(
01018     std::vector<LcsRid> &ridValues, VectorOfUint &nRidsPerBitmap,
01019     LcsRid startRid, uint nRids)
01020 {
01021     for (uint i = 0; i < nRids; i++) {
01022         ridValues.push_back(startRid);
01023         startRid += LbmSegment::LbmOneByteSize*2;
01024     }
01025     nRidsPerBitmap.push_back(nRids);
01026 }
01027 
01028 void LbmEntryTest::testMergeSingleton(
01029     uint scratchBufferSize, const std::vector<LcsRid> &ridValues,
01030     uint nSingletons, bool split)
01031 {
01032     // bitmap entries will be created without a leading key, so the
01033     // first column is the startRid
01034 
01035     bitmapColSize = scratchBufferSize;
01036     attrDesc_bitmap =
01037         TupleAttributeDescriptor(
01038             stdTypeFactory.newDataType(STANDARD_TYPE_VARBINARY),
01039             true, bitmapColSize);
01040     attrDesc_int64 =
01041         TupleAttributeDescriptor(
01042             stdTypeFactory.newDataType(STANDARD_TYPE_INT_64));
01043 
01044     entryTupleDesc.push_back(attrDesc_int64);
01045     entryTupleDesc.push_back(attrDesc_bitmap);
01046     entryTupleDesc.push_back(attrDesc_bitmap);
01047     entryTuple.compute(entryTupleDesc);
01048     entryTuple[1].pData = NULL;
01049     entryTuple[2].pData = NULL;
01050 
01051     // generate the entry that the singleton will splice into
01052     LbmEntry lbmEntry;
01053     boost::scoped_array<FixedBuffer> buf, buf2;
01054     buf.reset(new FixedBuffer[scratchBufferSize]);
01055     buf2.reset(new FixedBuffer[scratchBufferSize]);
01056     lbmEntry.init(buf.get(), buf2.get(), scratchBufferSize, entryTupleDesc);
01057     entryTuple[0].pData = (PConstBuffer) &(ridValues[0]);
01058     lbmEntry.setEntryTuple(entryTuple);
01059 
01060     uint totalRids = ridValues.size();
01061     for (uint i = 1; i < totalRids - nSingletons; i++) {
01062         bool rc = lbmEntry.setRID(ridValues[i]);
01063         // make sure there is enough space to fit the initial set of rids
01064         BOOST_REQUIRE(rc);
01065     }
01066 
01067     std::vector<LcsRid> sortedRids;
01068     sortedRids.assign(ridValues.begin(), ridValues.end());
01069     std::sort(sortedRids.begin(), sortedRids.end());
01070 #if 0
01071     std::cout << "Sorted Rid Values" << std::endl;
01072     for (uint i = 0; i < sortedRids.size(); i++) {
01073         std::cout << sortedRids[i] << std::endl;
01074     }
01075 #endif
01076 
01077     // merge in the singletons and compare against the sorted original list
01078     // as entries fill up
01079     uint ridPos = 0;
01080     bool splitOccurred = false;
01081     for (uint i = 0; i < nSingletons; i++) {
01082         entryTuple[0].pData =
01083             (PConstBuffer) &(ridValues[totalRids - nSingletons + i]);
01084         entryTuple[1].pData = NULL;
01085         entryTuple[1].cbData = 0;
01086         entryTuple[2].pData = NULL;
01087         entryTuple[1].cbData = 0;
01088         if (!lbmEntry.mergeEntry(entryTuple)) {
01089             BOOST_REQUIRE(split);
01090             bool rc = compareExpected(lbmEntry, sortedRids, ridPos, true);
01091             BOOST_REQUIRE(rc);
01092             lbmEntry.setEntryTuple(entryTuple);
01093             splitOccurred = true;
01094         }
01095     }
01096 
01097     // compare the rids in the last entry
01098     if (ridPos < totalRids) {
01099         bool rc = compareExpected(lbmEntry, sortedRids, ridPos, true);
01100         BOOST_REQUIRE(rc);
01101     }
01102 
01103     BOOST_REQUIRE(ridPos == totalRids);
01104 
01105     BOOST_REQUIRE(!(split && !splitOccurred));
01106 }
01107 
01108 void LbmEntryTest::testMergeSingletonInFront1()
01109 {
01110     std::vector<LcsRid> ridValues;
01111 
01112     ridValues.push_back(LcsRid(9));
01113     ridValues.push_back(LcsRid(18));
01114     ridValues.push_back(LcsRid(27));
01115     ridValues.push_back(LcsRid(60));
01116     ridValues.push_back(LcsRid(77));
01117 
01118     // singleton rid needs to be in a byte in front of the current entry
01119     ridValues.push_back(LcsRid(1));
01120     testMergeSingleton(24, ridValues, 1, false);
01121 }
01122 
01123 void LbmEntryTest::testMergeSingletonInFront2()
01124 {
01125     std::vector<LcsRid> ridValues;
01126 
01127     ridValues.push_back(LcsRid(20));
01128 
01129     // singleton rid needs to be in a byte in front of the current entry --
01130     // current entry is also a singleton
01131     ridValues.push_back(LcsRid(1));
01132     testMergeSingleton(24, ridValues, 1, false);
01133 }
01134 
01135 void LbmEntryTest::testMergeSingletonMidSegment1()
01136 {
01137     std::vector<LcsRid> ridValues;
01138 
01139     ridValues.push_back(LcsRid(9));
01140     ridValues.push_back(LcsRid(18));
01141     ridValues.push_back(LcsRid(27));
01142     ridValues.push_back(LcsRid(60));
01143     ridValues.push_back(LcsRid(77));
01144 
01145     // singleton rid will be set in an existing rid range -- first rid in
01146     // segment
01147     ridValues.push_back(LcsRid(8));
01148     testMergeSingleton(24, ridValues, 1, false);
01149 }
01150 
01151 void LbmEntryTest::testMergeSingletonMidSegment2()
01152 {
01153     std::vector<LcsRid> ridValues;
01154 
01155     ridValues.push_back(LcsRid(9));
01156     ridValues.push_back(LcsRid(18));
01157     ridValues.push_back(LcsRid(27));
01158     ridValues.push_back(LcsRid(60));
01159     ridValues.push_back(LcsRid(77));
01160 
01161     // singleton rid will be set in an existing rid range -- rid in the middle
01162     ridValues.push_back(LcsRid(17));
01163     testMergeSingleton(24, ridValues, 1, false);
01164 }
01165 
01166 void LbmEntryTest::testMergeSingletonMidSegment3()
01167 {
01168     std::vector<LcsRid> ridValues;
01169 
01170     ridValues.push_back(LcsRid(9));
01171     ridValues.push_back(LcsRid(18));
01172     ridValues.push_back(LcsRid(27));
01173     ridValues.push_back(LcsRid(60));
01174     ridValues.push_back(LcsRid(77));
01175 
01176     // singleton rid will be set in an existing rid range -- rid at the end
01177     ridValues.push_back(LcsRid(31));
01178     testMergeSingleton(24, ridValues, 1, false);
01179 }
01180 
01181 void LbmEntryTest::testMergeSingletonMidSegment4()
01182 {
01183     std::vector<LcsRid> ridValues;
01184 
01185     ridValues.push_back(LcsRid(9));
01186     ridValues.push_back(LcsRid(18));
01187     ridValues.push_back(LcsRid(27));
01188     ridValues.push_back(LcsRid(60));
01189     ridValues.push_back(LcsRid(77));
01190 
01191     // singleton rid will be set in an existing rid range -- rid in the 2nd
01192     // byte segment
01193     ridValues.push_back(LcsRid(56));
01194     testMergeSingleton(24, ridValues, 1, false);
01195 }
01196 
01197 void LbmEntryTest::testMergeSingletonEndSegment()
01198 {
01199     std::vector<LcsRid> ridValues;
01200 
01201     ridValues.push_back(LcsRid(9));
01202     ridValues.push_back(LcsRid(18));
01203     ridValues.push_back(LcsRid(27));
01204     ridValues.push_back(LcsRid(60));
01205     ridValues.push_back(LcsRid(77));
01206 
01207     // singleton rid is in the byte adjacent to the last byte in a segment
01208     ridValues.push_back(LcsRid(33));
01209     testMergeSingleton(24, ridValues, 1, false);
01210 }
01211 
01212 void LbmEntryTest::testMergeSingletonStartSegment1()
01213 {
01214     std::vector<LcsRid> ridValues;
01215 
01216     ridValues.push_back(LcsRid(9));
01217     ridValues.push_back(LcsRid(18));
01218     ridValues.push_back(LcsRid(27));
01219     ridValues.push_back(LcsRid(60));
01220     ridValues.push_back(LcsRid(77));
01221 
01222     // singleton rid is in the byte in front of the first byte in a segment
01223     // that's not the first byte in an entry -- last bit in new segment
01224     ridValues.push_back(LcsRid(55));
01225     testMergeSingleton(24, ridValues, 1, false);
01226 }
01227 
01228 void LbmEntryTest::testMergeSingletonStartSegment2()
01229 {
01230     std::vector<LcsRid> ridValues;
01231 
01232     ridValues.push_back(LcsRid(9));
01233     ridValues.push_back(LcsRid(18));
01234     ridValues.push_back(LcsRid(27));
01235     ridValues.push_back(LcsRid(60));
01236     ridValues.push_back(LcsRid(77));
01237 
01238     // singleton rid is in the byte in front of the first byte in a segment
01239     // that's not the first byte in an entry -- first bit in new segment
01240     ridValues.push_back(LcsRid(64));
01241     testMergeSingleton(24, ridValues, 1, false);
01242 }
01243 
01244 void LbmEntryTest::testMergeSingletonInBetweenSegment()
01245 {
01246     std::vector<LcsRid> ridValues;
01247 
01248     ridValues.push_back(LcsRid(9));
01249     ridValues.push_back(LcsRid(18));
01250     ridValues.push_back(LcsRid(27));
01251     ridValues.push_back(LcsRid(60));
01252     ridValues.push_back(LcsRid(77));
01253 
01254     // singleton rid is in a byte currently represented by trailing zeros, but
01255     // the new byte is not adjacent to an existing segment
01256     ridValues.push_back(LcsRid(40));
01257     testMergeSingleton(24, ridValues, 1, false);
01258 }
01259 
01260 void LbmEntryTest::testMergeSingletonSplitLeft1()
01261 {
01262     std::vector<LcsRid> ridValues;
01263 
01264     ridValues.push_back(LcsRid(9));
01265     ridValues.push_back(LcsRid(18));
01266     ridValues.push_back(LcsRid(27));
01267     ridValues.push_back(LcsRid(60));
01268     ridValues.push_back(LcsRid(77));
01269 
01270     // singleton rid goes to the left side of the split entry -- at the end
01271     // of the new split entry
01272     ridValues.push_back(LcsRid(39));
01273     testMergeSingleton(19, ridValues, 1, true);
01274 }
01275 
01276 void LbmEntryTest::testMergeSingletonSplitLeft2()
01277 {
01278     std::vector<LcsRid> ridValues;
01279 
01280     ridValues.push_back(LcsRid(9));
01281     ridValues.push_back(LcsRid(35));
01282     ridValues.push_back(LcsRid(60));
01283     ridValues.push_back(LcsRid(77));
01284 
01285     // singleton rid goes to the left side of the split entry -- move a
01286     // segment from the left to the right to minimize the space in the entry
01287     // that the new rid will be inserted into
01288     ridValues.push_back(LcsRid(18));
01289     testMergeSingleton(19, ridValues, 1, true);
01290 }
01291 
01292 void LbmEntryTest::testMergeSingletonSplitRight1()
01293 {
01294     std::vector<LcsRid> ridValues;
01295 
01296     ridValues.push_back(LcsRid(9));
01297     ridValues.push_back(LcsRid(18));
01298     ridValues.push_back(LcsRid(27));
01299     ridValues.push_back(LcsRid(60));
01300     ridValues.push_back(LcsRid(85));
01301 
01302     // singleton rid goes to the right side of the split entry -- in the middle
01303     // of the split entry
01304     ridValues.push_back(LcsRid(71));
01305     testMergeSingleton(19, ridValues, 1, true);
01306 }
01307 
01308 void LbmEntryTest::testMergeSingletonSplitRight2()
01309 {
01310     std::vector<LcsRid> ridValues;
01311 
01312     ridValues.push_back(LcsRid(544));
01313     ridValues.push_back(LcsRid(560));
01314     ridValues.push_back(LcsRid(576));
01315     ridValues.push_back(LcsRid(1088));
01316 
01317     // singleton rid goes to the right side of the split entry -- ensure
01318     // entry is split at the appropriate boundary; otherwise, there won't
01319     // be space in the split entry
01320     ridValues.push_back(LcsRid(832));
01321     testMergeSingleton(20, ridValues, 1, true);
01322 }
01323 
01324 void LbmEntryTest::testMergeSingletonSplitHalf()
01325 {
01326     std::vector<LcsRid> ridValues;
01327 
01328     ridValues.push_back(LcsRid(9));
01329     ridValues.push_back(LcsRid(18));
01330     ridValues.push_back(LcsRid(27));
01331     ridValues.push_back(LcsRid(539));
01332 
01333     // only 2 segments with the left segment being bigger; ensure that the new
01334     // rid fits when merged into the left entry
01335     ridValues.push_back(LcsRid(283));
01336     testMergeSingleton(18, ridValues, 1, true);
01337 }
01338 
01339 void LbmEntryTest::testMergeSingletonSplitLast()
01340 {
01341     std::vector<LcsRid> ridValues;
01342 
01343     ridValues.push_back(LcsRid(9));
01344     ridValues.push_back(LcsRid(18));
01345     ridValues.push_back(LcsRid(27));
01346     ridValues.push_back(LcsRid(48));
01347     ridValues.push_back(LcsRid(60));
01348     ridValues.push_back(LcsRid(64));
01349     ridValues.push_back(LcsRid(77));
01350     ridValues.push_back(LcsRid(87));
01351     ridValues.push_back(LcsRid(95));
01352     ridValues.push_back(LcsRid(96));
01353 
01354     // singleton rid goes to the left side of the split entry; only the last
01355     // segment in the original is split to the right
01356     ridValues.push_back(LcsRid(47));
01357     testMergeSingleton(23, ridValues, 1, true);
01358 }
01359 
01360 void LbmEntryTest::testMergeSingletonSplitMaxSegments()
01361 {
01362     std::vector<LcsRid> ridValues;
01363 
01364     ridValues.push_back(LcsRid(0));
01365     // create several segments that max out at 16 bytes
01366     for (int i = 250; i < 600; i += 8) {
01367         ridValues.push_back(LcsRid(i));
01368     }
01369     ridValues.push_back(LcsRid(617));
01370 
01371     // inserting a new rid requires spltting in between two of the 16-byte
01372     // segments
01373     ridValues.push_back(LcsRid(125));
01374     testMergeSingleton(63, ridValues, 1, true);
01375 }
01376 
01377 void LbmEntryTest::testMergeSingletonZeros1()
01378 {
01379     std::vector<LcsRid> ridValues;
01380 
01381     ridValues.push_back(LcsRid(4));
01382     // (12+2)*8 = 112
01383     ridValues.push_back(LcsRid(114));
01384     ridValues.push_back(LcsRid(123));
01385 
01386     // singleton rid replaces a trailing zero byte, which results in the
01387     // number of trailing zero bytes decreasing by 1
01388     ridValues.push_back(LcsRid(47));
01389     testMergeSingleton(24, ridValues, 1, false);
01390 }
01391 
01392 void LbmEntryTest::testMergeSingletonZeros2()
01393 {
01394     std::vector<LcsRid> ridValues;
01395 
01396     ridValues.push_back(LcsRid(4));
01397     // ((2^16)+1)*8 = 524288 (3 bytes required to encode zero length)
01398     ridValues.push_back(LcsRid(524296));
01399     ridValues.push_back(LcsRid(524305));
01400 
01401     // singleton rid replaces a trailing zero byte, which results in the
01402     // number of trailing zero bytes decreasing by 1; new byte is adjacent
01403     // to first
01404     ridValues.push_back(LcsRid(13));
01405     testMergeSingleton(24, ridValues, 1, false);
01406 }
01407 
01408 void LbmEntryTest::testMergeSingletonZeros3()
01409 {
01410     std::vector<LcsRid> ridValues;
01411 
01412     ridValues.push_back(LcsRid(4));
01413     // (12+2)*8 = 112
01414     ridValues.push_back(LcsRid(114));
01415     ridValues.push_back(LcsRid(123));
01416 
01417     // singleton rid replaces a trailing zero byte, which results in the
01418     // number of trailing zero bytes decreasing by 1 but addition of new
01419     // segment requires a split of the current entry
01420     ridValues.push_back(LcsRid(60));
01421     testMergeSingleton(17, ridValues, 1, true);
01422 }
01423 
01424 void LbmEntryTest::testMergeSingletonZeros4()
01425 {
01426     std::vector<LcsRid> ridValues;
01427 
01428     ridValues.push_back(LcsRid(4));
01429     // (12+2)*8 = 112
01430     ridValues.push_back(LcsRid(114));
01431     ridValues.push_back(LcsRid(123));
01432 
01433     // current entry is currently at max size; adding a new singleton rid
01434     // requires a new segment but doing so does not require a split because
01435     // the new segment replaces the trailing zero byte
01436     ridValues.push_back(LcsRid(13));
01437     testMergeSingleton(17, ridValues, 1, false);
01438 }
01439 
01440 void LbmEntryTest::testMergeSingletonCombine()
01441 {
01442     std::vector<LcsRid> ridValues;
01443 
01444     ridValues.push_back(LcsRid(9));
01445     ridValues.push_back(LcsRid(18));
01446     ridValues.push_back(LcsRid(27));
01447     ridValues.push_back(LcsRid(60));
01448     ridValues.push_back(LcsRid(77));
01449     ridValues.push_back(LcsRid(86));
01450     ridValues.push_back(LcsRid(111));
01451 
01452     // singleton rid goes in the middle of 2 segments, which results in the 3
01453     // segments being combined into 1
01454     ridValues.push_back(LcsRid(71));
01455     testMergeSingleton(24, ridValues, 1, false);
01456 }
01457 
01458 void LbmEntryTest::testMergeSingletonAfterSplit()
01459 {
01460     std::vector<LcsRid> ridValues;
01461 
01462     ridValues.push_back(LcsRid(9));
01463     ridValues.push_back(LcsRid(18));
01464     ridValues.push_back(LcsRid(27));
01465     ridValues.push_back(LcsRid(48));
01466     ridValues.push_back(LcsRid(60));
01467     ridValues.push_back(LcsRid(64));
01468     ridValues.push_back(LcsRid(77));
01469     ridValues.push_back(LcsRid(87));
01470     ridValues.push_back(LcsRid(95));
01471     ridValues.push_back(LcsRid(96));
01472 
01473     // singleton rid goes to the left side of the split entry; only the last
01474     // segment in the original is split to the right; add another singleton
01475     // after the split
01476     ridValues.push_back(LcsRid(33));
01477     ridValues.push_back(LcsRid(47));
01478     testMergeSingleton(23, ridValues, 2, true);
01479 }
01480 
01481 void LbmEntryTest::testMergeSingletonMaxSeg()
01482 {
01483     std::vector<LcsRid> ridValues;
01484 
01485     ridValues.push_back(LcsRid(0));
01486 
01487     ridValues.push_back(LcsRid(27));
01488     ridValues.push_back(LcsRid(36));
01489     ridValues.push_back(LcsRid(45));
01490     ridValues.push_back(LcsRid(54));
01491     ridValues.push_back(LcsRid(63));
01492     ridValues.push_back(LcsRid(64));
01493     ridValues.push_back(LcsRid(72));
01494     ridValues.push_back(LcsRid(81));
01495     ridValues.push_back(LcsRid(90));
01496     ridValues.push_back(LcsRid(99));
01497     ridValues.push_back(LcsRid(108));
01498     ridValues.push_back(LcsRid(117));
01499     ridValues.push_back(LcsRid(126));
01500     ridValues.push_back(LcsRid(135));
01501     ridValues.push_back(LcsRid(136));
01502     ridValues.push_back(LcsRid(145));
01503 
01504     // attempt to insert singleton rid in front of a segment that currently
01505     // has a segment length of 16
01506     ridValues.push_back(LcsRid(18));
01507     testMergeSingleton(32, ridValues, 1, false);
01508 }
01509 
01510 void LbmEntryTest::testMergeSingletonRandom(uint totalRids, uint ridRange)
01511 {
01512     std::vector<LcsRid> ridValues;
01513 
01514     // generate random rid values, ensuring that they are unique
01515     LcsRid rid = LcsRid(rand() % ridRange);
01516     ridValues.push_back(rid);
01517     for (uint i = 1; i < totalRids;) {
01518         rid = LcsRid(rand() % ridRange);
01519         uint j;
01520         for (j = 0; j < i; j++) {
01521             if (rid == ridValues[j]) {
01522                 break;
01523             }
01524         }
01525         if (j >= i) {
01526             ridValues.push_back(rid);
01527             i++;
01528             continue;
01529         }
01530     }
01531 
01532 #if 0
01533     std::cout << "Original Rid Values" << std::endl;
01534     for (uint i = 0; i < ridValues.size(); i++) {
01535         std::cout << ridValues[i] << std::endl;
01536     }
01537 #endif
01538 
01539     // the first rid becomes the initial entry and the rest are the singleton
01540     // rids
01541     uint scratchBufferSize = totalRids * 5 + 8;
01542     testMergeSingleton(scratchBufferSize, ridValues, totalRids - 1, false);
01543 }
01544 
01545 void LbmEntryTest::testMergeSingletonRandom1()
01546 {
01547     testMergeSingletonRandom(50, 1000);
01548 }
01549 
01550 void LbmEntryTest::testMergeSingletonRandom2()
01551 {
01552     testMergeSingletonRandom(100, 10000);
01553 }
01554 
01555 void LbmEntryTest::testMergeSingletonWithSingleton1()
01556 {
01557     std::vector<LcsRid> ridValues;
01558 
01559     ridValues.push_back(LcsRid(7));
01560 
01561     ridValues.push_back(LcsRid(1));
01562     testMergeSingleton(16, ridValues, 1, false);
01563 }
01564 
01565 void LbmEntryTest::testMergeSingletonWithSingleton2()
01566 {
01567     std::vector<LcsRid> ridValues;
01568 
01569     ridValues.push_back(LcsRid(50));
01570 
01571     ridValues.push_back(LcsRid(1));
01572     // not enough space so the entries should get split into 2
01573     testMergeSingleton(10, ridValues, 1, true);
01574 }
01575 
01576 void LbmEntryTest::testCaseSetUp()
01577 {
01578     openStorage(DeviceMode::createNew);
01579 }
01580 
01581 void LbmEntryTest::testCaseTearDown()
01582 {
01583     SegStorageTestBase::testCaseTearDown();
01584     entryTupleDesc.clear();
01585 }
01586 
01587 FENNEL_UNIT_TEST_SUITE(LbmEntryTest);
01588 
01589 
01590 // End LbmEntryTest.cpp

Generated on Mon Jun 22 04:00:19 2009 for Fennel by  doxygen 1.5.1