LbmSearchTest.cpp

Go to the documentation of this file.
00001 /*
00002 // $Id: //open/dev/fennel/lucidera/test/LbmSearchTest.cpp#15 $
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/common/FemEnums.h"
00024 #include "fennel/test/ExecStreamUnitTestBase.h"
00025 #include "fennel/lucidera/colstore/LcsClusterAppendExecStream.h"
00026 #include "fennel/sorter/ExternalSortExecStream.h"
00027 #include "fennel/lucidera/bitmap/LbmGeneratorExecStream.h"
00028 #include "fennel/lucidera/bitmap/LbmSplicerExecStream.h"
00029 #include "fennel/lucidera/bitmap/LbmSearchExecStream.h"
00030 #include "fennel/lucidera/test/LbmExecStreamTestBase.h"
00031 #include "fennel/btree/BTreeBuilder.h"
00032 #include "fennel/ftrs/BTreeInsertExecStream.h"
00033 #include "fennel/ftrs/BTreeSearchExecStream.h"
00034 #include "fennel/ftrs/BTreeExecStream.h"
00035 #include "fennel/tuple/StandardTypeDescriptor.h"
00036 #include "fennel/tuple/TupleDescriptor.h"
00037 #include "fennel/exec/MockProducerExecStream.h"
00038 #include "fennel/exec/ValuesExecStream.h"
00039 #include "fennel/exec/ExecStreamGraph.h"
00040 #include "fennel/exec/ExecStreamEmbryo.h"
00041 #include "fennel/exec/SplitterExecStream.h"
00042 #include "fennel/exec/BarrierExecStream.h"
00043 #include "fennel/cache/Cache.h"
00044 #include "fennel/common/SearchEndpoint.h"
00045 #include <stdarg.h>
00046 
00047 #include <boost/test/test_tools.hpp>
00048 
00049 using namespace fennel;
00050 
00055 class LbmSearchTest : public LbmExecStreamTestBase
00056 {
00057 protected:
00058     TupleAttributeDescriptor attrDesc_char1;
00059     TupleAttributeDescriptor attrDesc_nullableInt64;
00060 
00064     vector<boost::shared_ptr<BTreeDescriptor> > bTreeClusters;
00065 
00070     vector<PageId> savedBTreeClusterRootIds;
00071 
00075     vector<boost::shared_ptr<BTreeDescriptor> > bTreeBitmaps;
00076 
00081     vector<PageId> savedBTreeBitmapRootIds;
00082 
00086     void initBTreeExecStreamParam(
00087         BTreeExecStreamParams &param, shared_ptr<BTreeDescriptor> pBTreeDesc);
00088 
00092     void initBTreeParam(
00093         BTreeParams &param, shared_ptr<BTreeDescriptor> pBTreeDesc);
00094 
00099     void initClusterScanDef(
00100         LcsRowScanBaseExecStreamParams &generatorParams,
00101         struct LcsClusterScanDef &clusterScanDef, uint bTreeIndex);
00102 
00112     void  initBTreeBitmapDesc(
00113         TupleDescriptor &tupleDesc, TupleProjection &keyProj, uint nKeys);
00114 
00122     void initBTreeTupleDesc(TupleDescriptor &tupleDesc, uint nKeys);
00123 
00143     void loadTableAndIndex(
00144         uint nRows, uint nClusters, std::vector<int> const &repeatSeqValues,
00145         bool newRoot);
00146 
00158     void testScanFullKey(
00159         uint nRows, uint nKeys, std::vector<int> const &repeatSeqValues,
00160         bool useDynamicKeys, bool includeRid);
00161 
00170     void testScanPartialKey(
00171         uint nRows, uint nKeys, std::vector<int> const &repeatSeqValues);
00172 
00200     void testScanIdx(
00201         uint totalKeys, uint nKeys, uint bufSize,
00202         boost::shared_array<FixedBuffer> inputBuffer,
00203         uint expectedNBitmaps, PBuffer expectedBitmaps,
00204         bool dynamicRootPageId,
00205         bool useDynamicKeys,
00206         bool includeRid,
00207         const boost::scoped_array<uint64_t> &vals);
00208 
00223     void initEqualSearch(
00224         uint nKeys, uint nInputTuples, boost::scoped_array<uint64_t> &vals,
00225         char &lowerDirective, char &upperDirective,
00226         TupleAccessor &inputTupleAccessor, TupleData &inputTupleData,
00227         boost::shared_array<FixedBuffer> &inputBuffer,
00228         bool useDynamicKeys);
00229 
00230     void setSearchKey(
00231         char lowerDirective, char upperDirective, uint64_t lowerVal,
00232         uint64_t upperVal, PBuffer inputBuf, uint &offset,
00233         TupleAccessor &inputTupleAccessor, TupleData &inputTupleData);
00234 
00235 public:
00236     explicit LbmSearchTest()
00237     {
00238         FENNEL_UNIT_TEST_CASE(LbmSearchTest, testScanOneLevel);
00239         FENNEL_UNIT_TEST_CASE(LbmSearchTest, testScanTwoLevel);
00240         FENNEL_UNIT_TEST_CASE(LbmSearchTest, testMultipleRanges);
00241     }
00242 
00243     void testCaseSetUp();
00244     void testCaseTearDown();
00245     void testScans(uint nRows);
00246 
00247     void testScanOneLevel();
00248     void testScanTwoLevel();
00249     void testMultipleRanges();
00250 };
00251 
00252 void LbmSearchTest::testScanOneLevel()
00253 {
00254     // single level btree
00255     testScans(100);
00256 }
00257 
00258 void LbmSearchTest::testScanTwoLevel()
00259 {
00260     // with a 3-key index, 2000 rows will generate a 2-level btree
00261     testScans(2000);
00262 }
00263 
00264 void LbmSearchTest::testScans(uint nRows)
00265 {
00266     uint nClusters = 3;
00267     std::vector<int> repeatSeqValues;
00268 
00269     // load the data
00270     repeatSeqValues.push_back(1);
00271     repeatSeqValues.push_back(5);
00272     repeatSeqValues.push_back(9);
00273     loadTableAndIndex(nRows, nClusters, repeatSeqValues, true);
00274 
00275     // Scan on all keys, passing the search keys through the input stream.
00276     // Then do the same, passing the keys via dynamic parameters.  Then,
00277     // finally, do the search, including a rid search.
00278     testScanFullKey(nRows, nClusters, repeatSeqValues, false, false);
00279     testScanFullKey(nRows, nClusters, repeatSeqValues, true, false);
00280     testScanFullKey(nRows, nClusters, repeatSeqValues, false, true);
00281 
00282     // scan on (nClusters - 1) keys
00283     testScanPartialKey(nRows, nClusters, repeatSeqValues);
00284 }
00285 
00286 void LbmSearchTest::testMultipleRanges()
00287 {
00288     uint nRows = 20000;
00289     uint nClusters = 1;
00290     std::vector<int> repeatSeqValues;
00291 
00292     // load a table with a single index on a single column
00293     repeatSeqValues.push_back(100);
00294     loadTableAndIndex(nRows, nClusters, repeatSeqValues, true);
00295 
00296     // scan on all keys, just to make sure all key values really are there
00297     testScanFullKey(nRows, nClusters, repeatSeqValues, false, false);
00298 
00299     resetExecStreamTest();
00300 
00301     // Setup the following search keys.  Note that these keys weren't randomly
00302     // selected.  Some of them correspond to boundary conditions.
00303     // 1. key < 8
00304     // 2. key > 10 && key <= 17
00305     // 3. key >= 44 and key < 60
00306     // 4. key > 71
00307 
00308     TupleDescriptor inputTupleDesc;
00309     for (uint i = 0; i < 2; i++) {
00310         inputTupleDesc.push_back(attrDesc_char1);
00311         inputTupleDesc.push_back(attrDesc_nullableInt64);
00312     }
00313     TupleData inputTupleData(inputTupleDesc);
00314     TupleAccessor inputTupleAccessor;
00315     inputTupleAccessor.compute(inputTupleDesc);
00316 
00317     uint nInputTuples = 4;
00318     boost::shared_array<FixedBuffer> inputBuffer;
00319     inputBuffer.reset(
00320         new FixedBuffer[nInputTuples * inputTupleAccessor.getMaxByteCount()]);
00321     PBuffer inputBuf = inputBuffer.get();
00322     uint offset = 0;
00323 
00324     setSearchKey(
00325         '-', ')', 0, 8, inputBuf, offset, inputTupleAccessor, inputTupleData);
00326     setSearchKey(
00327         '(', ']', 10, 17, inputBuf, offset, inputTupleAccessor,
00328         inputTupleData);
00329     setSearchKey(
00330         '[', ')', 44, 60, inputBuf, offset, inputTupleAccessor,
00331         inputTupleData);
00332     setSearchKey(
00333         '(', '+', 71, 0, inputBuf, offset, inputTupleAccessor,
00334         inputTupleData);
00335 
00336     // setup the expected bitmap result values
00337     boost::scoped_array<FixedBuffer> expectedBitmaps;
00338     uint bufferSize = ((nRows / repeatSeqValues[0] / 8 + 1) * 60) * 24;
00339     expectedBitmaps.reset(new FixedBuffer[bufferSize]);
00340     PBuffer bitmapBuf = expectedBitmaps.get();
00341     uint expectedNBitmaps = 0;
00342     uint expectedBufSize = 0;
00343     // for each range, generate the bitmap values for each key in the desired
00344     // range
00345     for (uint i = 0; i < 8; i++) {
00346         generateBitmaps(
00347             nRows, i, repeatSeqValues[0], bitmapBuf, expectedBufSize,
00348             bufferSize, expectedNBitmaps);
00349     }
00350     for (uint i = 11; i <= 17; i++) {
00351         generateBitmaps(
00352             nRows, i, repeatSeqValues[0], bitmapBuf, expectedBufSize,
00353             bufferSize, expectedNBitmaps);
00354     }
00355     for (uint i = 44; i < 60; i++) {
00356         generateBitmaps(
00357             nRows, i, repeatSeqValues[0], bitmapBuf, expectedBufSize,
00358             bufferSize, expectedNBitmaps);
00359     }
00360     for (uint i = 72; i < repeatSeqValues[0]; i++) {
00361         generateBitmaps(
00362             nRows, i, repeatSeqValues[0], bitmapBuf, expectedBufSize,
00363             bufferSize, expectedNBitmaps);
00364     }
00365 
00366     boost::scoped_array<uint64_t> vals;
00367     testScanIdx(
00368         nClusters, nClusters, offset, inputBuffer, expectedNBitmaps,
00369         bitmapBuf, true, false, false, vals);
00370 }
00371 
00372 void LbmSearchTest::setSearchKey(
00373     char lowerDirective, char upperDirective, uint64_t lowerVal,
00374     uint64_t upperVal, PBuffer inputBuf, uint &offset,
00375     TupleAccessor &inputTupleAccessor, TupleData &inputTupleData)
00376 {
00377     inputTupleData[0].pData = (PConstBuffer) &lowerDirective;
00378     inputTupleData[2].pData = (PConstBuffer) &upperDirective;
00379     if (lowerDirective != '-') {
00380         inputTupleData[1].pData = (PConstBuffer) &lowerVal;
00381     }
00382     if (upperDirective != '+') {
00383         inputTupleData[3].pData = (PConstBuffer) &upperVal;
00384     }
00385     inputTupleAccessor.marshal(inputTupleData, inputBuf + offset);
00386     offset += inputTupleAccessor.getCurrentByteCount();
00387 }
00388 
00389 void LbmSearchTest::testScanFullKey(
00390     uint nRows, uint nKeys, std::vector<int> const &repeatSeqValues,
00391     bool useDynamicKeys, bool includeRid)
00392 {
00393     // search for key0 = <val0>, key1 = <val1>, ..., key(n-1) = <val(n-1)>
00394     uint nInputTuples = 1;
00395     boost::scoped_array<uint64_t> vals;
00396     char lowerDirective;
00397     char upperDirective;
00398     TupleAccessor inputTupleAccessor;
00399     TupleData inputTupleData;
00400     boost::shared_array<FixedBuffer> inputBuffer;
00401 
00402     initEqualSearch(
00403         nKeys, nInputTuples, vals, lowerDirective, upperDirective,
00404         inputTupleAccessor, inputTupleData, inputBuffer, useDynamicKeys);
00405 
00406     // do a search on each possible key combo
00407     uint skipRows = 1;
00408     for (uint i = 0; i < nKeys; i++) {
00409         skipRows *= repeatSeqValues[i];
00410     }
00411     for (uint i = 0; i < skipRows; i++) {
00412         // generate input keys for search
00413         for (uint j = 0; j < nKeys; j++) {
00414             vals[j] = i % repeatSeqValues[j];
00415         }
00416         inputTupleAccessor.marshal(inputTupleData, inputBuffer.get());
00417 
00418         // generate expected bitmap result
00419         boost::scoped_array<FixedBuffer> expectedBitmaps;
00420         uint bufferSize = (nRows / skipRows + 1) * 16;
00421         expectedBitmaps.reset(new FixedBuffer[bufferSize]);
00422         uint expectedNBitmaps = 0;
00423         uint expectedBufSize = 0;
00424         generateBitmaps(
00425             nRows, i, skipRows, expectedBitmaps.get(), expectedBufSize,
00426             bufferSize, expectedNBitmaps);
00427 
00428         testScanIdx(
00429             nKeys, nKeys, inputTupleAccessor.getCurrentByteCount(),
00430             inputBuffer, expectedNBitmaps, expectedBitmaps.get(), false,
00431             useDynamicKeys, includeRid, vals);
00432     }
00433 }
00434 
00435 void LbmSearchTest::testScanPartialKey(
00436     uint nRows, uint nKeys, std::vector<int> const &repeatSeqValues)
00437 {
00438     // search for key0 = 0, key1 = 0, ..., key(n-2) = 0
00439     uint nInputTuples = 1;
00440     boost::scoped_array<uint64_t> vals;
00441     char lowerDirective;
00442     char upperDirective;
00443     TupleAccessor inputTupleAccessor;
00444     TupleData inputTupleData;
00445     boost::shared_array<FixedBuffer> inputBuffer;
00446 
00447     initEqualSearch(
00448         nKeys - 1, nInputTuples, vals, lowerDirective, upperDirective,
00449         inputTupleAccessor, inputTupleData, inputBuffer, false);
00450 
00451     // generate input keys for search
00452     for (uint j = 0; j < nKeys - 1; j++) {
00453         vals[j] = 0;
00454     }
00455     inputTupleAccessor.marshal(inputTupleData, inputBuffer.get());
00456 
00457     // Generate one set of bitmaps for each key combo that can be combined
00458     // with the partial key. E.g., if there are 3 keys, generate the
00459     // bitmaps that would be obtained from searching for (0, 0, 0), (0, 0, 1),
00460     // ..., (0, 0, repeatSeqValues[nKeys-1] - 1)
00461 
00462     uint skipRows = 1;
00463     for (uint i = 0; i < nKeys - 1; i++) {
00464         skipRows *= repeatSeqValues[i];
00465     }
00466     boost::scoped_array<FixedBuffer> expectedBitmaps;
00467     uint bufferSize = (nRows / skipRows / 8 + 1)
00468         * 12 * repeatSeqValues[nKeys - 1];
00469     expectedBitmaps.reset(new FixedBuffer[bufferSize]);
00470     PBuffer bitmapBuf = expectedBitmaps.get();
00471     uint expectedNBitmaps = 0;
00472     uint curBufSize = 0;
00473 
00474     for (uint i = 0; i < repeatSeqValues[nKeys - 1]; i++) {
00475         uint start;
00476         if (i == 0) {
00477             start = 0;
00478         } else {
00479             // look for the first rid where the last key is equal to "i" and
00480             // the preceeding keys are all 0
00481             for (start = i; start < nRows;
00482                  start += repeatSeqValues[nKeys - 1])
00483             {
00484                 uint j;
00485                 for (j = 0; j < nKeys - 1; j++) {
00486                     if (start % repeatSeqValues[j] != 0) {
00487                         break;
00488                     }
00489                 }
00490                 if (j == nKeys - 1) {
00491                     break;
00492                 }
00493             }
00494             if (start >= nRows) {
00495                 continue;
00496             }
00497         }
00498         generateBitmaps(
00499             nRows, start, skipRows * repeatSeqValues[nKeys - 1],
00500             bitmapBuf, curBufSize, bufferSize, expectedNBitmaps);
00501     }
00502     testScanIdx(
00503         nKeys, nKeys - 1, inputTupleAccessor.getCurrentByteCount(),
00504         inputBuffer, expectedNBitmaps, bitmapBuf, false, false, false, vals);
00505 }
00506 
00507 void LbmSearchTest::initEqualSearch(
00508     uint nKeys, uint nInputTuples, boost::scoped_array<uint64_t> &vals,
00509     char &lowerDirective, char &upperDirective,
00510     TupleAccessor &inputTupleAccessor, TupleData &inputTupleData,
00511     boost::shared_array<FixedBuffer> &inputBuffer,
00512     bool useDynamicKeys)
00513 {
00514     TupleDescriptor inputTupleDesc;
00515     for (uint i = 0; i < 2; i++) {
00516         inputTupleDesc.push_back(attrDesc_char1);
00517         for (uint j = 0; j < nKeys; j++) {
00518             inputTupleDesc.push_back(attrDesc_nullableInt64);
00519         }
00520     }
00521 
00522     inputTupleData.compute(inputTupleDesc);
00523 
00524     vals.reset(new uint64_t[nKeys]);
00525     lowerDirective = '[';
00526     inputTupleData[0].pData = (PConstBuffer) &lowerDirective;
00527     upperDirective = ']';
00528     inputTupleData[nKeys + 1].pData = (PConstBuffer) &upperDirective;
00529     for (uint i = 0; i < nKeys; i++) {
00530         // If keys are being passed through dynamic parameters, set them to
00531         // NULL in the input row
00532         if (useDynamicKeys) {
00533             inputTupleData[i + 1].pData = NULL;
00534             inputTupleData[i + 1].cbData = 0;
00535             inputTupleData[nKeys + 1 + i + 1].pData = NULL;
00536             inputTupleData[nKeys + 1 + i + 1].cbData = 0;
00537         } else {
00538             inputTupleData[i + 1].pData = (PConstBuffer) &vals[i];
00539             inputTupleData[nKeys + 1 + i + 1].pData = (PConstBuffer) &vals[i];
00540         }
00541     }
00542 
00543     inputTupleAccessor.compute(inputTupleDesc);
00544 
00545     inputBuffer.reset(
00546         new FixedBuffer[nInputTuples * inputTupleAccessor.getMaxByteCount()]);
00547 }
00548 
00549 void LbmSearchTest::loadTableAndIndex(
00550     uint nRows, uint nClusters, std::vector<int> const &repeatSeqValues,
00551     bool newRoot)
00552 {
00553     // 0. reset member fields.
00554     for (uint i = 0; i < bTreeClusters.size(); i++) {
00555         bTreeClusters[i]->segmentAccessor.reset();
00556     }
00557     for (uint i = 0; i < bTreeBitmaps.size(); i++) {
00558         bTreeBitmaps[i]->segmentAccessor.reset();
00559     }
00560     bTreeClusters.clear();
00561     bTreeBitmaps.clear();
00562 
00563     // 1. setup mock input stream
00564 
00565     MockProducerExecStreamParams mockParams;
00566     for (uint i = 0; i < nClusters; i++) {
00567         mockParams.outputTupleDesc.push_back(attrDesc_int64);
00568     }
00569     mockParams.nRows = nRows;
00570 
00571     vector<boost::shared_ptr<ColumnGenerator<int64_t> > > columnGenerators;
00572     SharedInt64ColumnGenerator col;
00573     assert(repeatSeqValues.size() == nClusters);
00574     for (uint i = 0; i < repeatSeqValues.size(); i++) {
00575         col =
00576             SharedInt64ColumnGenerator(
00577                 new RepeatingSeqColumnGenerator(repeatSeqValues[i]));
00578         columnGenerators.push_back(col);
00579     }
00580     mockParams.pGenerator.reset(
00581         new CompositeExecStreamGenerator(columnGenerators));
00582 
00583     ExecStreamEmbryo mockStreamEmbryo;
00584     mockStreamEmbryo.init(new MockProducerExecStream(), mockParams);
00585     mockStreamEmbryo.getStream()->setName("MockProducerExecStream");
00586 
00587     // 2. setup splitter stream for cluster loads
00588 
00589     SplitterExecStreamParams splitterParams;
00590     ExecStreamEmbryo splitterStreamEmbryo;
00591     splitterStreamEmbryo.init(new SplitterExecStream(), splitterParams);
00592     splitterStreamEmbryo.getStream()->setName("ClusterSplitterExecStream");
00593 
00594     // 3. setup loader streams
00595 
00596     vector<ExecStreamEmbryo> lcsAppendEmbryos;
00597     for (uint i = 0; i < nClusters; i++) {
00598         LcsClusterAppendExecStreamParams lcsAppendParams;
00599         boost::shared_ptr<BTreeDescriptor> pBTreeDesc =
00600             boost::shared_ptr<BTreeDescriptor> (new BTreeDescriptor());
00601         bTreeClusters.push_back(pBTreeDesc);
00602 
00603         // initialize the btree parameter portion of lcsAppendParams
00604         // BTree tuple desc has two columns (rid, clusterPageid)
00605         (lcsAppendParams.tupleDesc).push_back(attrDesc_int64);
00606         (lcsAppendParams.tupleDesc).push_back(attrDesc_int64);
00607 
00608         // BTree key only has one column which is the first column.
00609         (lcsAppendParams.keyProj).push_back(0);
00610 
00611         initBTreeExecStreamParam(lcsAppendParams, pBTreeDesc);
00612 
00613         // output two values (rows inserted, starting rid value)
00614         lcsAppendParams.outputTupleDesc.push_back(attrDesc_int64);
00615         lcsAppendParams.outputTupleDesc.push_back(attrDesc_int64);
00616 
00617         lcsAppendParams.inputProj.push_back(i);
00618 
00619         // create an empty page to start the btree
00620 
00621         if (newRoot) {
00622             BTreeBuilder builder(*pBTreeDesc, pRandomSegment);
00623             builder.createEmptyRoot();
00624             savedBTreeClusterRootIds.push_back(builder.getRootPageId());
00625         }
00626         lcsAppendParams.rootPageId = pBTreeDesc->rootPageId =
00627             savedBTreeClusterRootIds[i];
00628 
00629         // Now use the above initialized parameter
00630 
00631         ExecStreamEmbryo lcsAppendStreamEmbryo;
00632         lcsAppendStreamEmbryo.init(
00633             new LcsClusterAppendExecStream(), lcsAppendParams);
00634         std::ostringstream oss;
00635         oss << "LcsClusterAppendExecStream" << "#" << i;
00636         lcsAppendStreamEmbryo.getStream()->setName(oss.str());
00637         lcsAppendEmbryos.push_back(lcsAppendStreamEmbryo);
00638     }
00639 
00640     // 4. setup barrier stream for cluster loads
00641 
00642     BarrierExecStreamParams barrierParams;
00643     barrierParams.outputTupleDesc.push_back(attrDesc_int64);
00644     barrierParams.outputTupleDesc.push_back(attrDesc_int64);
00645     barrierParams.returnMode = BARRIER_RET_ANY_INPUT;
00646 
00647     ExecStreamEmbryo clusterBarrierStreamEmbryo;
00648     clusterBarrierStreamEmbryo.init(new BarrierExecStream(), barrierParams);
00649     clusterBarrierStreamEmbryo.getStream()->setName("ClusterBarrierExecStream");
00650 
00651     // create a DAG with the above, but without the final output sink
00652     prepareDAG(
00653         mockStreamEmbryo, splitterStreamEmbryo, lcsAppendEmbryos,
00654         clusterBarrierStreamEmbryo, false);
00655 
00656     // 5. setup splitter stream for create bitmaps
00657 
00658     splitterStreamEmbryo.init(
00659         new SplitterExecStream(), splitterParams);
00660     splitterStreamEmbryo.getStream()->setName("BitmapSplitterExecStream");
00661 
00662     // create streams for bitmap generator, sort, and bitmap splicer to
00663     // build an index on all columns
00664 
00665     std::vector<std::vector<ExecStreamEmbryo> > createBitmapStreamList;
00666         std::vector<ExecStreamEmbryo> createBitmapStream;
00667 
00668     // 6. setup generator
00669 
00670     LbmGeneratorExecStreamParams generatorParams;
00671     struct LcsClusterScanDef clusterScanDef;
00672     clusterScanDef.clusterTupleDesc.push_back(attrDesc_int64);
00673 
00674     for (uint j = 0; j < nClusters; j++) {
00675         initClusterScanDef(generatorParams, clusterScanDef, j);
00676     }
00677 
00678     TupleProjection proj;
00679     for (uint j = 0; j < nClusters; j++) {
00680         proj.push_back(j);
00681     }
00682     generatorParams.outputProj = proj;
00683     generatorParams.insertRowCountParamId = DynamicParamId(1);
00684     generatorParams.createIndex = false;
00685 
00686     boost::shared_ptr<BTreeDescriptor> pBTreeDesc =
00687         boost::shared_ptr<BTreeDescriptor> (new BTreeDescriptor());
00688     bTreeBitmaps.push_back(pBTreeDesc);
00689 
00690     // BTree tuple desc has the key columns + starting Rid + varbinary
00691     // field for bit segments/bit descriptors
00692     uint nKeys = nClusters;
00693     initBTreeTupleDesc(generatorParams.outputTupleDesc, nKeys);
00694 
00695     initBTreeBitmapDesc(
00696         generatorParams.tupleDesc, generatorParams.keyProj, nKeys);
00697     initBTreeExecStreamParam(generatorParams, pBTreeDesc);
00698 
00699     // create an empty page to start the btree
00700 
00701     if (newRoot) {
00702         BTreeBuilder builder(*pBTreeDesc, pRandomSegment);
00703         builder.createEmptyRoot();
00704         savedBTreeBitmapRootIds.push_back(builder.getRootPageId());
00705     }
00706     generatorParams.rootPageId = pBTreeDesc->rootPageId =
00707         savedBTreeBitmapRootIds[0];
00708 
00709     ExecStreamEmbryo generatorStreamEmbryo;
00710     generatorStreamEmbryo.init(
00711         new LbmGeneratorExecStream(), generatorParams);
00712     std::ostringstream oss;
00713     oss << "LbmGeneratorExecStream" << "#" << 0;
00714     generatorStreamEmbryo.getStream()->setName(oss.str());
00715     createBitmapStream.push_back(generatorStreamEmbryo);
00716 
00717     // 7. setup sorter
00718 
00719     ExternalSortExecStreamParams sortParams;
00720     initBTreeBitmapDesc(
00721         sortParams.outputTupleDesc, sortParams.keyProj, nKeys);
00722     sortParams.distinctness = DUP_ALLOW;
00723     sortParams.pTempSegment = pRandomSegment;
00724     sortParams.pCacheAccessor = pCache;
00725     sortParams.scratchAccessor =
00726         pSegmentFactory->newScratchSegment(pCache, 10);
00727     sortParams.storeFinalRun = false;
00728     sortParams.estimatedNumRows = MAXU;
00729     sortParams.earlyClose = false;
00730 
00731     ExecStreamEmbryo sortStreamEmbryo;
00732     sortStreamEmbryo.init(
00733         ExternalSortExecStream::newExternalSortExecStream(), sortParams);
00734     sortStreamEmbryo.getStream()->setName("ExternalSortExecStream");
00735     std::ostringstream oss2;
00736     oss2 << "ExternalSortExecStream" << "#" << 0;
00737     sortStreamEmbryo.getStream()->setName(oss2.str());
00738     createBitmapStream.push_back(sortStreamEmbryo);
00739 
00740     // 8. setup splicer
00741 
00742     LbmSplicerExecStreamParams splicerParams;
00743     splicerParams.createNewIndex = false;
00744     splicerParams.scratchAccessor =
00745         pSegmentFactory->newScratchSegment(pCache, 15);
00746     splicerParams.pCacheAccessor = pCache;
00747     BTreeParams bTreeParams;
00748     initBTreeBitmapDesc(
00749         bTreeParams.tupleDesc, bTreeParams.keyProj, nKeys);
00750     initBTreeParam(bTreeParams, pBTreeDesc);
00751     bTreeParams.rootPageId = pBTreeDesc->rootPageId;
00752     splicerParams.bTreeParams.push_back(bTreeParams);
00753     splicerParams.insertRowCountParamId = DynamicParamId(1);
00754     splicerParams.writeRowCountParamId = DynamicParamId(0);
00755     splicerParams.outputTupleDesc.push_back(attrDesc_int64);
00756 
00757     ExecStreamEmbryo splicerStreamEmbryo;
00758     splicerStreamEmbryo.init(new LbmSplicerExecStream(), splicerParams);
00759     std::ostringstream oss3;
00760     oss3 << "LbmSplicerExecStream" << "#" << 0;
00761     splicerStreamEmbryo.getStream()->setName(oss3.str());
00762     createBitmapStream.push_back(splicerStreamEmbryo);
00763 
00764     // connect the sorter and splicer to generator and then add this
00765     // newly connected stream to the list of create bitmap stream embryos
00766     createBitmapStreamList.push_back(createBitmapStream);
00767 
00768     // 9. setup barrier stream for create bitmaps
00769 
00770     barrierParams.outputTupleDesc.clear();
00771     barrierParams.outputTupleDesc.push_back(attrDesc_int64);
00772 
00773     ExecStreamEmbryo barrierStreamEmbryo;
00774     barrierStreamEmbryo.init(
00775         new BarrierExecStream(), barrierParams);
00776     barrierStreamEmbryo.getStream()->setName("BitmapBarrierExecStream");
00777 
00778     // create the bitmap stream graph, with the load stream graph from
00779     // above as the source
00780     SharedExecStream pOutputStream = prepareDAG(
00781         clusterBarrierStreamEmbryo, splitterStreamEmbryo,
00782         createBitmapStreamList, barrierStreamEmbryo, true, false);
00783 
00784     // set up a generator which can produce the expected output
00785     RampExecStreamGenerator expectedResultGenerator(mockParams.nRows);
00786 
00787     verifyOutput(*pOutputStream, 1, expectedResultGenerator);
00788 }
00789 
00790 void LbmSearchTest::initBTreeExecStreamParam(
00791     BTreeExecStreamParams &param, shared_ptr<BTreeDescriptor> pBTreeDesc)
00792 {
00793     param.scratchAccessor = pSegmentFactory->newScratchSegment(pCache, 15);
00794     param.pCacheAccessor = pCache;
00795     initBTreeParam(param, pBTreeDesc);
00796 }
00797 
00798 void LbmSearchTest::initBTreeParam(
00799     BTreeParams &param, shared_ptr<BTreeDescriptor> pBTreeDesc)
00800 {
00801     param.pSegment = pRandomSegment;
00802     param.pRootMap = 0;
00803     param.rootPageIdParamId = DynamicParamId(0);
00804 
00805     pBTreeDesc->segmentAccessor.pSegment = param.pSegment;
00806     pBTreeDesc->segmentAccessor.pCacheAccessor = pCache;
00807     pBTreeDesc->tupleDescriptor = param.tupleDesc;
00808     pBTreeDesc->keyProjection = param.keyProj;
00809     param.pageOwnerId = pBTreeDesc->pageOwnerId;
00810     param.segmentId = pBTreeDesc->segmentId;
00811 }
00812 
00813 void LbmSearchTest::initClusterScanDef(
00814     LcsRowScanBaseExecStreamParams &rowScanParams,
00815     struct LcsClusterScanDef &clusterScanDef,
00816     uint bTreeIndex)
00817 {
00818     clusterScanDef.pSegment =
00819         bTreeClusters[bTreeIndex]->segmentAccessor.pSegment;
00820     clusterScanDef.pCacheAccessor =
00821         bTreeClusters[bTreeIndex]->segmentAccessor.pCacheAccessor;
00822     clusterScanDef.tupleDesc = bTreeClusters[bTreeIndex]->tupleDescriptor;
00823     clusterScanDef.keyProj = bTreeClusters[bTreeIndex]->keyProjection;
00824     clusterScanDef.rootPageId = bTreeClusters[bTreeIndex]->rootPageId;
00825     clusterScanDef.pageOwnerId = bTreeClusters[bTreeIndex]->pageOwnerId;
00826     clusterScanDef.segmentId = bTreeClusters[bTreeIndex]->segmentId;
00827     clusterScanDef.pRootMap = 0;
00828     clusterScanDef.rootPageIdParamId = DynamicParamId(0);
00829     rowScanParams.lcsClusterScanDefs.push_back(clusterScanDef);
00830 }
00831 
00832 void LbmSearchTest::initBTreeBitmapDesc(
00833     TupleDescriptor &tupleDesc, TupleProjection &keyProj, uint nKeys)
00834 {
00835     initBTreeTupleDesc(tupleDesc, nKeys);
00836 
00837     // btree key consists of the key columns and the start rid
00838     for (uint j = 0; j < nKeys + 1; j++) {
00839         keyProj.push_back(j);
00840     }
00841 }
00842 
00843 void LbmSearchTest::initBTreeTupleDesc(
00844     TupleDescriptor &tupleDesc, uint nKeys)
00845 {
00846     for (uint i = 0; i < nKeys; i++) {
00847         tupleDesc.push_back(attrDesc_int64);
00848     }
00849     // add on the rid and bitmaps
00850     tupleDesc.push_back(bitmapTupleDesc[0]);
00851     tupleDesc.push_back(bitmapTupleDesc[1]);
00852     tupleDesc.push_back(bitmapTupleDesc[2]);
00853 }
00854 
00855 void LbmSearchTest::testCaseSetUp()
00856 {
00857     LbmExecStreamTestBase::testCaseSetUp();
00858 
00859     attrDesc_char1 = TupleAttributeDescriptor(
00860         stdTypeFactory.newDataType(STANDARD_TYPE_CHAR), false, 1);
00861     attrDesc_nullableInt64 = TupleAttributeDescriptor(
00862         stdTypeFactory.newDataType(STANDARD_TYPE_INT_64),
00863         true, sizeof(uint64_t));
00864 }
00865 
00866 void LbmSearchTest::testCaseTearDown()
00867 {
00868     for (uint i = 0; i < bTreeClusters.size(); i++) {
00869         bTreeClusters[i]->segmentAccessor.reset();
00870     }
00871     for (uint i = 0; i < bTreeBitmaps.size(); i++) {
00872         bTreeBitmaps[i]->segmentAccessor.reset();
00873     }
00874     bTreeClusters.clear();
00875     bTreeBitmaps.clear();
00876     savedBTreeClusterRootIds.clear();
00877     savedBTreeBitmapRootIds.clear();
00878 
00879     LbmExecStreamTestBase::testCaseTearDown();
00880 }
00881 
00882 void LbmSearchTest::testScanIdx(
00883     uint totalKeys, uint nKeys, uint bufSize,
00884     boost::shared_array<FixedBuffer> inputBuffer,
00885     uint expectedNBitmaps, PBuffer expectedBitmaps,
00886     bool dynamicRootPageId,
00887     bool useDynamicKeys,
00888     bool includeRid,
00889     const boost::scoped_array<uint64_t> &vals)
00890 {
00891     resetExecStreamTest();
00892 
00893     // setup input into index scan; values stream will read tuples from
00894     // inputBuffer
00895 
00896     ValuesExecStreamParams valuesParams;
00897     for (uint i = 0; i < 2; i++) {
00898         valuesParams.outputTupleDesc.push_back(attrDesc_char1);
00899         for (uint j = 0; j < nKeys; j++) {
00900             valuesParams.outputTupleDesc.push_back(attrDesc_nullableInt64);
00901         }
00902     }
00903     valuesParams.pTupleBuffer = inputBuffer;
00904     valuesParams.bufSize = bufSize;
00905 
00906     ExecStreamEmbryo valuesStreamEmbryo;
00907     valuesStreamEmbryo.init(new ValuesExecStream(), valuesParams);
00908     valuesStreamEmbryo.getStream()->setName("ValuesExecStream");
00909 
00910     // setup index scan stream
00911 
00912     LbmSearchExecStreamParams indexScanParams;
00913 
00914     // initialize parameters specific to indexScan
00915     indexScanParams.rowLimitParamId = DynamicParamId(0);
00916     if (includeRid) {
00917         indexScanParams.startRidParamId = DynamicParamId(1);
00918         SharedDynamicParamManager pDynamicParamManager =
00919             pGraph->getDynamicParamManager();
00920         pDynamicParamManager->createParam(DynamicParamId(1), attrDesc_int64);
00921         TupleDatum ridDatum;
00922         LcsRid rid = LcsRid(0);
00923         ridDatum.pData = (PConstBuffer) &rid;
00924         ridDatum.cbData = sizeof(LcsRid);
00925         pDynamicParamManager->writeParam(DynamicParamId(1), ridDatum);
00926     } else {
00927         indexScanParams.startRidParamId = DynamicParamId(0);
00928     }
00929 
00930     // initialize parameters for btree read
00931     initBTreeBitmapDesc(
00932         indexScanParams.tupleDesc, indexScanParams.keyProj, totalKeys);
00933     initBTreeExecStreamParam(indexScanParams, bTreeBitmaps[0]);
00934     bTreeBitmaps[0]->rootPageId = savedBTreeBitmapRootIds[0];
00935 
00936     if (!dynamicRootPageId) {
00937         indexScanParams.rootPageId = savedBTreeBitmapRootIds[0];
00938     } else {
00939         indexScanParams.rootPageId = NULL_PAGE_ID;
00940         indexScanParams.rootPageIdParamId = DynamicParamId(2);
00941         SharedDynamicParamManager pDynamicParamManager =
00942             pGraph->getDynamicParamManager();
00943         pDynamicParamManager->createParam(DynamicParamId(2), attrDesc_int64);
00944         TupleDatum rootPageIdDatum;
00945         rootPageIdDatum.pData = (PConstBuffer) &(savedBTreeBitmapRootIds[0]);
00946         rootPageIdDatum.cbData = sizeof(PageId);
00947         pDynamicParamManager->writeParam(DynamicParamId(2), rootPageIdDatum);
00948     }
00949 
00950     TupleProjection outputProj;
00951     for (uint i = totalKeys; i < totalKeys + 3; i++) {
00952         outputProj.push_back(i);
00953     }
00954     indexScanParams.outputProj = outputProj;
00955 
00956     // initialize parameters for btree search
00957     indexScanParams.outerJoin = false;
00958     TupleProjection inputKeyProj;
00959     for (uint i = 0; i < 2; i++) {
00960         for (uint j = 0; j < nKeys; j++) {
00961             inputKeyProj.push_back(i * (nKeys + 1) + j + 1);
00962         }
00963     }
00964     indexScanParams.inputKeyProj = inputKeyProj;
00965     indexScanParams.inputDirectiveProj.push_back(0);
00966     indexScanParams.inputDirectiveProj.push_back(nKeys + 1);
00967 
00968     // output is bitmap btree tuple without the key values, but with the rid
00969     indexScanParams.outputTupleDesc = bitmapTupleDesc;
00970 
00971     if (useDynamicKeys) {
00972         SharedDynamicParamManager pDynamicParamManager =
00973             pGraph->getDynamicParamManager();
00974         for (uint i = 3; i < nKeys * 2 + 3; i++) {
00975             indexScanParams.searchKeyParams.push_back(
00976                 BTreeSearchKeyParameter(
00977                     DynamicParamId(i),
00978                     i - 3));
00979             pDynamicParamManager->createParam(
00980                 DynamicParamId(i), attrDesc_int64);
00981             TupleDatum keyValDatum;
00982             keyValDatum.pData = (PConstBuffer) &(vals[(i - 3) % nKeys]);
00983             keyValDatum.cbData = sizeof(uint64_t);
00984             pDynamicParamManager->writeParam(DynamicParamId(i), keyValDatum);
00985         }
00986     }
00987 
00988     ExecStreamEmbryo indexScanStreamEmbryo;
00989     indexScanStreamEmbryo.init(new LbmSearchExecStream(), indexScanParams);
00990     indexScanStreamEmbryo.getStream()->setName("IndexScanStream");
00991 
00992     SharedExecStream pOutputStream = prepareTransformGraph(
00993         valuesStreamEmbryo, indexScanStreamEmbryo);
00994 
00995     bitmapTupleAccessor.setCurrentTupleBuf(expectedBitmaps);
00996     verifyBufferedOutput(
00997         *pOutputStream, bitmapTupleDesc, expectedNBitmaps, expectedBitmaps);
00998 }
00999 
01000 FENNEL_UNIT_TEST_SUITE(LbmSearchTest);
01001 
01002 // End LbmSearchTest.cpp

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