You've already forked mariadb-columnstore-engine
							
							
				mirror of
				https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
				synced 2025-11-03 17:13:17 +03:00 
			
		
		
		
	* Fix clang warnings * Remove vim tab guides * initialize variables * 'strncpy' output truncated before terminating nul copying as many bytes from a string as its length * Fix ISO C++17 does not allow 'register' storage class specifier for outdated bison * chars are unsigned on ARM, having if (ival < 0) always false * chars are unsigned by default on ARM and comparison with -1 if always true
		
			
				
	
	
		
			1133 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1133 lines
		
	
	
		
			40 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2014 InfiniDB, Inc.
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or
 | 
						|
   modify it under the terms of the GNU General Public License
 | 
						|
   as published by the Free Software Foundation; version 2 of
 | 
						|
   the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 | 
						|
   MA 02110-1301, USA. */
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
 * $Id: index.cpp 2035 2013-01-21 14:12:19Z rdempsey $
 | 
						|
 *
 | 
						|
 ****************************************************************************/
 | 
						|
 | 
						|
#include <iostream>
 | 
						|
using namespace std;
 | 
						|
 | 
						|
#include "primitiveprocessor.h"
 | 
						|
#include "we_index.h"
 | 
						|
#include "messagelog.h"
 | 
						|
#include "messageobj.h"
 | 
						|
 | 
						|
/** @file
 | 
						|
 * Brief description of the file contents
 | 
						|
 *
 | 
						|
 * More detailed description
 | 
						|
 */
 | 
						|
 | 
						|
using namespace logging;
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
#define GET_BITTEST(test, string, x)                                                               \
 | 
						|
  if (in->Shift + x >= in->SSlen)                                                                  \
 | 
						|
  {                                                                                                \
 | 
						|
    test = (string & masks[in->SSlen - in->Shift]);                                                \
 | 
						|
    lastStage = true;                                                                              \
 | 
						|
    cerr << "  bittest is 0x" << hex << (int)test << dec << " this is the last iteration" << endl; \
 | 
						|
  }                                                                                                \
 | 
						|
  else                                                                                             \
 | 
						|
  {                                                                                                \
 | 
						|
    test = (string >> (in->SSlen - in->Shift - x)) & masks[x];                                     \
 | 
						|
    lastStage = false;                                                                             \
 | 
						|
    cerr << "  bittest is 0x" << hex << (int)test << dec << endl;                                  \
 | 
						|
  }
 | 
						|
#else
 | 
						|
#define GET_BITTEST(test, string, x)                           \
 | 
						|
  if (in->Shift + x >= in->SSlen)                              \
 | 
						|
  {                                                            \
 | 
						|
    test = (string & masks[in->SSlen - in->Shift]);            \
 | 
						|
    lastStage = true;                                          \
 | 
						|
  }                                                            \
 | 
						|
  else                                                         \
 | 
						|
  {                                                            \
 | 
						|
    test = (string >> (in->SSlen - in->Shift - x)) & masks[x]; \
 | 
						|
    lastStage = false;                                         \
 | 
						|
  }
 | 
						|
#endif
 | 
						|
 | 
						|
#define IDXWALK_INIT()                                                                  \
 | 
						|
  niceBlock = reinterpret_cast<uint8_t*>(block);                                        \
 | 
						|
  blockOffset = (in->SubBlock * WriteEngine::SUBBLOCK_TOTAL_BYTES) + (in->SBEntry * 8); \
 | 
						|
  treePtr = reinterpret_cast<WriteEngine::IdxBitTestEntry*>(&niceBlock[blockOffset]);
 | 
						|
 | 
						|
#define GET_GROUP_SIZE()                                                                                     \
 | 
						|
  switch (treePtr->group)                                                                                    \
 | 
						|
  {                                                                                                          \
 | 
						|
    case 0: bitTestGroupSize = 1; break;                                                                     \
 | 
						|
    case 1: bitTestGroupSize = 2; break;                                                                     \
 | 
						|
    case 2: bitTestGroupSize = 4; break;                                                                     \
 | 
						|
    case 3: bitTestGroupSize = 8; break;                                                                     \
 | 
						|
    case 4: bitTestGroupSize = 16; break;                                                                    \
 | 
						|
    case 5: bitTestGroupSize = 32; break;                                                                    \
 | 
						|
    default: cerr << "PrimitiveProcessor::IndexWalk*(): bad group field " << treePtr->group << endl; return; \
 | 
						|
  }
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
#define ADD_ELEMENT(index, shift, state)                                                        \
 | 
						|
  element = new IndexWalkHeader();                                                              \
 | 
						|
  memcpy(element, in, sizeof(IndexWalkHeader));                                                 \
 | 
						|
  element->ism.Command = INDEX_WALK_RESULTS;                                                    \
 | 
						|
  element->Shift += shift;                                                                      \
 | 
						|
  element->LBID = treePtr[index].fbo;                                                           \
 | 
						|
  element->SubBlock = treePtr[index].sbid;                                                      \
 | 
						|
  element->SBEntry = treePtr[index].entry;                                                      \
 | 
						|
  element->State = state;                                                                       \
 | 
						|
  cerr << "  (no convert) creating a result from subblock entry " << (int)index                 \
 | 
						|
       << " with Shift=" << (int)element->Shift << " LBID=" << element->LBID                    \
 | 
						|
       << " Subblock=" << (int)element->SubBlock << " Subblock entry=" << (int)element->SBEntry \
 | 
						|
       << " State=" << (int)state;                                                              \
 | 
						|
  if (element->LBID == in->LBID && element->Shift < element->SSlen)                             \
 | 
						|
  {                                                                                             \
 | 
						|
    cerr << "  recursing..." << endl;                                                           \
 | 
						|
    p_IdxWalk(element, out);                                                                    \
 | 
						|
    delete element;                                                                             \
 | 
						|
  }                                                                                             \
 | 
						|
  else                                                                                          \
 | 
						|
  {                                                                                             \
 | 
						|
    cerr << "  adding this to the result set" << endl;                                          \
 | 
						|
    out->push_back(element);                                                                    \
 | 
						|
  }
 | 
						|
#else
 | 
						|
#define ADD_ELEMENT(index, shift, state)                            \
 | 
						|
  element = new IndexWalkHeader();                                  \
 | 
						|
  memcpy(element, in, sizeof(IndexWalkHeader));                     \
 | 
						|
  element->ism.Command = INDEX_WALK_RESULTS;                        \
 | 
						|
  element->Shift += shift;                                          \
 | 
						|
  element->LBID = treePtr[index].fbo;                               \
 | 
						|
  element->SubBlock = treePtr[index].sbid;                          \
 | 
						|
  element->SBEntry = treePtr[index].entry;                          \
 | 
						|
  element->State = state;                                           \
 | 
						|
  if (element->LBID == in->LBID && element->Shift < element->SSlen) \
 | 
						|
  {                                                                 \
 | 
						|
    p_IdxWalk(element, out);                                        \
 | 
						|
    delete element;                                                 \
 | 
						|
  }                                                                 \
 | 
						|
  else                                                              \
 | 
						|
    out->push_back(element);
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
#define ADD_ELEMENT_WITH_CONVERT(index, shift, state)                                           \
 | 
						|
  element = new IndexWalkHeader();                                                              \
 | 
						|
  memcpy(element, in, sizeof(IndexWalkHeader));                                                 \
 | 
						|
  element->ism.Command = INDEX_WALK_RESULTS;                                                    \
 | 
						|
  element->Shift += shift;                                                                      \
 | 
						|
  element->LBID = treePtr[index].fbo;                                                           \
 | 
						|
  element->SubBlock = treePtr[index].sbid;                                                      \
 | 
						|
  element->SBEntry = treePtr[index].entry;                                                      \
 | 
						|
  element->State = state;                                                                       \
 | 
						|
  cerr << "  (convert) creating a result from subblock entry " << (int)index                    \
 | 
						|
       << " with Shift=" << (int)element->Shift << " LBID=" << element->LBID                    \
 | 
						|
       << " Subblock=" << (int)element->SubBlock << " Subblock entry=" << (int)element->SBEntry \
 | 
						|
       << " State=" << (int)state << endl;                                                      \
 | 
						|
  if (convertToSingleOp != -1)                                                                  \
 | 
						|
  {                                                                                             \
 | 
						|
    cerr << "  converting it to a single COP filter" << endl;                                   \
 | 
						|
    element->NVALS = 1;                                                                         \
 | 
						|
    if (convertToSingleOp == 1)                                                                 \
 | 
						|
    {                                                                                           \
 | 
						|
      element->COP1 = element->COP2;                                                            \
 | 
						|
      element->SearchString[0] = element->SearchString[1];                                      \
 | 
						|
    }                                                                                           \
 | 
						|
  }                                                                                             \
 | 
						|
  if (element->LBID == in->LBID && element->Shift < element->SSlen)                             \
 | 
						|
  {                                                                                             \
 | 
						|
    cerr << "  recursing..." << endl;                                                           \
 | 
						|
    p_IdxWalk(element, out);                                                                    \
 | 
						|
    delete element;                                                                             \
 | 
						|
  }                                                                                             \
 | 
						|
  else                                                                                          \
 | 
						|
  {                                                                                             \
 | 
						|
    cerr << "  adding it to the result set" << endl;                                            \
 | 
						|
    out->push_back(element);                                                                    \
 | 
						|
  }
 | 
						|
#else
 | 
						|
#define ADD_ELEMENT_WITH_CONVERT(index, shift, state)               \
 | 
						|
  element = new IndexWalkHeader();                                  \
 | 
						|
  memcpy(element, in, sizeof(IndexWalkHeader));                     \
 | 
						|
  element->ism.Command = INDEX_WALK_RESULTS;                        \
 | 
						|
  element->Shift += shift;                                          \
 | 
						|
  element->LBID = treePtr[index].fbo;                               \
 | 
						|
  element->SubBlock = treePtr[index].sbid;                          \
 | 
						|
  element->SBEntry = treePtr[index].entry;                          \
 | 
						|
  element->State = state;                                           \
 | 
						|
  if (convertToSingleOp != -1)                                      \
 | 
						|
  {                                                                 \
 | 
						|
    element->NVALS = 1;                                             \
 | 
						|
    if (convertToSingleOp == 1)                                     \
 | 
						|
    {                                                               \
 | 
						|
      element->COP1 = element->COP2;                                \
 | 
						|
      element->SearchString[0] = element->SearchString[1];          \
 | 
						|
    }                                                               \
 | 
						|
  }                                                                 \
 | 
						|
  if (element->LBID == in->LBID && element->Shift < element->SSlen) \
 | 
						|
  {                                                                 \
 | 
						|
    p_IdxWalk(element, out);                                        \
 | 
						|
    delete element;                                                 \
 | 
						|
  }                                                                 \
 | 
						|
  else                                                              \
 | 
						|
    out->push_back(element);
 | 
						|
#endif
 | 
						|
 | 
						|
namespace primitives
 | 
						|
{
 | 
						|
void PrimitiveProcessor::indexWalk_1(const IndexWalkHeader* in, vector<IndexWalkHeader*>* out) throw()
 | 
						|
{
 | 
						|
  uint16_t bitTest;
 | 
						|
  uint8_t* niceBlock;
 | 
						|
  int blockOffset, bitTestGroupSize, i;
 | 
						|
  WriteEngine::IdxBitTestEntry* treePtr;
 | 
						|
  IndexWalkHeader* element;
 | 
						|
  int cmp;
 | 
						|
 | 
						|
  IDXWALK_INIT();
 | 
						|
 | 
						|
  if (in->SubBlock == 1 && in->Shift == 0)  // assume this is the first lookup step
 | 
						|
  {
 | 
						|
    // which happens in the direct pointer block
 | 
						|
    bitTest = in->SearchString[0] >> (in->SSlen - 5);
 | 
						|
#ifdef VERBOSE
 | 
						|
    cerr << "  first iteration of search for 0x" << hex << in->SearchString[0] << dec << endl;
 | 
						|
    cerr << "  bitTest is 0x" << hex << bitTest << dec << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
    switch (in->COP1)
 | 
						|
    {
 | 
						|
      case COMPARE_LT:
 | 
						|
      case COMPARE_LE:
 | 
						|
        for (i = 0; i <= bitTest; i++)
 | 
						|
        {
 | 
						|
          if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
            continue;
 | 
						|
 | 
						|
          ADD_ELEMENT(i, 5, (i < bitTest ? 1 : 0));
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case COMPARE_GT:
 | 
						|
      case COMPARE_GE:
 | 
						|
        for (i = bitTest; i < 32; i++)
 | 
						|
        {
 | 
						|
          if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
            continue;
 | 
						|
 | 
						|
          ADD_ELEMENT(i, 5, (i > bitTest ? 1 : 0));
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case COMPARE_EQ:
 | 
						|
        if (treePtr[bitTest].fbo == 0 && treePtr[bitTest].sbid == 0 && treePtr[bitTest].entry == 0)
 | 
						|
          break;
 | 
						|
 | 
						|
        ADD_ELEMENT(bitTest, 5, 0);
 | 
						|
        break;
 | 
						|
 | 
						|
      case COMPARE_NE:
 | 
						|
        for (i = 0; i < 32; i++)
 | 
						|
        {
 | 
						|
          if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
            continue;
 | 
						|
 | 
						|
          ADD_ELEMENT(i, 5, (i != bitTest ? 1 : 0));
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        MessageLog logger(LoggingID(28));
 | 
						|
        logging::Message::Args colWidth;
 | 
						|
        Message msg(34);
 | 
						|
 | 
						|
        colWidth.add(in->COP1);
 | 
						|
        colWidth.add("indexWalk_1");
 | 
						|
        msg.format(colWidth);
 | 
						|
        logger.logDebugMessage(msg);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  // This is the general case where we're working within a bit test group
 | 
						|
  else
 | 
						|
  {
 | 
						|
    GET_GROUP_SIZE();
 | 
						|
#ifdef VERBOSE
 | 
						|
    cerr << "  search string is 0x" << hex << in->SearchString[0] << dec << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
    for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
    {
 | 
						|
      bool lastStage;
 | 
						|
 | 
						|
      // skip holes
 | 
						|
      if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
        continue;
 | 
						|
 | 
						|
      if (treePtr[i].bitCompare == 0)
 | 
						|
      {
 | 
						|
        GET_BITTEST(bitTest, in->SearchString[0], 5);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        GET_BITTEST(bitTest, in->SearchString[0], 10);
 | 
						|
      }
 | 
						|
 | 
						|
      cmp = compare(treePtr[i].bitTest, bitTest, in->COP1, lastStage);
 | 
						|
 | 
						|
      if (cmp > 0)
 | 
						|
      {
 | 
						|
        ADD_ELEMENT(i, (treePtr[i].bitCompare == 0 ? 5 : 10), (cmp == 2 ? 1 : 0));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
inline int PrimitiveProcessor::compare(int val1, int val2, uint8_t COP, bool lastStage) throw()
 | 
						|
{
 | 
						|
  switch (COP)
 | 
						|
  {
 | 
						|
    case COMPARE_LT:
 | 
						|
      if (val1 < val2)
 | 
						|
        return 2;
 | 
						|
 | 
						|
      if (val1 == val2 && !lastStage)
 | 
						|
        return 1;
 | 
						|
 | 
						|
      return 0;
 | 
						|
 | 
						|
    case COMPARE_LE:
 | 
						|
      if (val1 < val2)
 | 
						|
        return 2;
 | 
						|
 | 
						|
      if (val1 == val2)
 | 
						|
        return 1;
 | 
						|
 | 
						|
      return 0;
 | 
						|
 | 
						|
    case COMPARE_GT:
 | 
						|
      if (val1 > val2)
 | 
						|
        return 2;
 | 
						|
 | 
						|
      if (val1 == val2 && !lastStage)
 | 
						|
        return 1;
 | 
						|
 | 
						|
      return 0;
 | 
						|
 | 
						|
    case COMPARE_GE:
 | 
						|
      if (val1 > val2)
 | 
						|
        return 2;
 | 
						|
 | 
						|
      if (val1 == val2)
 | 
						|
        return 1;
 | 
						|
 | 
						|
      return 0;
 | 
						|
 | 
						|
    case COMPARE_EQ:
 | 
						|
      if (val1 == val2)
 | 
						|
        return 1;
 | 
						|
 | 
						|
      return 0;
 | 
						|
 | 
						|
    case COMPARE_NE:
 | 
						|
      if (val1 != val2)
 | 
						|
        return 2;
 | 
						|
 | 
						|
      if (!lastStage)
 | 
						|
        return 1;
 | 
						|
 | 
						|
      return 0;
 | 
						|
 | 
						|
    default:
 | 
						|
      MessageLog logger(LoggingID(28));
 | 
						|
      logging::Message::Args colWidth;
 | 
						|
      Message msg(34);
 | 
						|
 | 
						|
      colWidth.add(COP);
 | 
						|
      colWidth.add("compare");
 | 
						|
      msg.format(colWidth);
 | 
						|
      logger.logDebugMessage(msg);
 | 
						|
      return false;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void PrimitiveProcessor::indexWalk_2(const IndexWalkHeader* in, vector<IndexWalkHeader*>* out) throw()
 | 
						|
{
 | 
						|
  uint16_t bitTest1, bitTest2;
 | 
						|
  uint8_t* niceBlock;
 | 
						|
  int blockOffset, bitTestGroupSize, cmp[2], i;
 | 
						|
  WriteEngine::IdxBitTestEntry* treePtr;
 | 
						|
  IndexWalkHeader* element;
 | 
						|
  int convertToSingleOp;
 | 
						|
  bool lastStage, setState;
 | 
						|
 | 
						|
  IDXWALK_INIT();
 | 
						|
 | 
						|
  if (in->SubBlock == 1 && in->Shift == 0)  // assume this is the first lookup step
 | 
						|
  {
 | 
						|
    // which happens in the direct pointer block
 | 
						|
    bitTest1 = in->SearchString[0] >> (in->SSlen - 5);
 | 
						|
    bitTest2 = in->SearchString[1] >> (in->SSlen - 5);
 | 
						|
#ifdef VERBOSE
 | 
						|
    cerr << "  first iteration.  SearchString[0]=0x" << hex << in->SearchString[0] << " bittest=0x"
 | 
						|
         << bitTest1 << " SearchString[1]=0x" << in->SearchString[1] << " bittest=0x" << bitTest2 << dec
 | 
						|
         << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
    for (i = 0; i < 32; i++)
 | 
						|
    {
 | 
						|
      if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
        continue;
 | 
						|
 | 
						|
      setState = false;
 | 
						|
      convertToSingleOp = -1;
 | 
						|
      cmp[0] = compare(i, bitTest1, in->COP1, false);
 | 
						|
      cmp[1] = compare(i, bitTest2, in->COP2, false);
 | 
						|
 | 
						|
      switch (in->BOP)
 | 
						|
      {
 | 
						|
        case BOP_OR:
 | 
						|
          if (cmp[0] == 2 || cmp[1] == 2)
 | 
						|
          {
 | 
						|
            setState = true;
 | 
						|
            goto add2;
 | 
						|
          }
 | 
						|
 | 
						|
          // 					if (cmp[0] == 1 || cmp[1] == 1)
 | 
						|
          // 						goto add2;
 | 
						|
 | 
						|
          /* XXXPAT: clean up this logic */
 | 
						|
 | 
						|
          if (cmp[0] == 1 && cmp[1] == 1)
 | 
						|
            goto add2;
 | 
						|
 | 
						|
          if (cmp[0] == 1)
 | 
						|
          {
 | 
						|
            convertToSingleOp = 0;
 | 
						|
            ADD_ELEMENT_WITH_CONVERT(i, 5, 0);
 | 
						|
            goto skip2;
 | 
						|
          }
 | 
						|
          else if (cmp[1] == 1)
 | 
						|
          {
 | 
						|
            convertToSingleOp = 1;
 | 
						|
            ADD_ELEMENT_WITH_CONVERT(i, 5, 0);
 | 
						|
            goto skip2;
 | 
						|
          }
 | 
						|
 | 
						|
          break;
 | 
						|
 | 
						|
        /* XXXPAT:  Need to verify the logic for AND.
 | 
						|
                observations: if control reaches this point, then in the previous iteration the
 | 
						|
                decision must have been 1, which implies equality for every previous comparison.
 | 
						|
 | 
						|
                If one of the comparisons returns 0, then there are no entries in this subtree
 | 
						|
                        in the result set and it can stop here.
 | 
						|
                else, if both of the comparisons return 2, then the whole subtree is in the result set.
 | 
						|
                else, if only one of the comparisons returns 2, then that comparison will be 2 for
 | 
						|
                        every comparison made down this subtree, and it is equivalent to being
 | 
						|
                        (cmp1 && true).  In this case, we repackage the query as a single argument version
 | 
						|
                        (using the comparison operator that was 1) to be processed by indexwalk_1().
 | 
						|
                else, the comparisons are both 1, meaning we have equality so far and can't decide on
 | 
						|
                        this subtree yet.
 | 
						|
        */
 | 
						|
        case BOP_AND:
 | 
						|
          if (cmp[0] == 0 || cmp[1] == 0)
 | 
						|
            break;
 | 
						|
          else if (cmp[0] == 2 && cmp[1] == 2)
 | 
						|
            setState = true;
 | 
						|
          else if (cmp[0] == 2)
 | 
						|
            convertToSingleOp = 1;
 | 
						|
          else if (cmp[1] == 2)
 | 
						|
            convertToSingleOp = 0;
 | 
						|
 | 
						|
          goto add2;
 | 
						|
 | 
						|
        default:
 | 
						|
          MessageLog logger(LoggingID(28));
 | 
						|
          logging::Message::Args colWidth;
 | 
						|
          Message msg(39);
 | 
						|
 | 
						|
          colWidth.add(in->BOP);
 | 
						|
          colWidth.add("indexwalk_2");
 | 
						|
          msg.format(colWidth);
 | 
						|
          logger.logDebugMessage(msg);
 | 
						|
          return;
 | 
						|
      }
 | 
						|
 | 
						|
      continue;
 | 
						|
    add2:
 | 
						|
      ADD_ELEMENT_WITH_CONVERT(i, 5, (setState ? 1 : 0));
 | 
						|
    skip2:;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else  // the general case
 | 
						|
  {
 | 
						|
    GET_GROUP_SIZE();
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
    cerr << "  SearchString[0]=0x" << hex << in->SearchString[0] << " SearchString[1]=0x"
 | 
						|
         << in->SearchString[1] << dec << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
    for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
    {
 | 
						|
      if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
        continue;
 | 
						|
 | 
						|
      setState = false;
 | 
						|
      lastStage = false;
 | 
						|
      convertToSingleOp = -1;
 | 
						|
 | 
						|
      if (treePtr[i].bitCompare == 0)
 | 
						|
      {
 | 
						|
        GET_BITTEST(bitTest1, in->SearchString[0], 5);
 | 
						|
        GET_BITTEST(bitTest2, in->SearchString[1], 5);
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        GET_BITTEST(bitTest1, in->SearchString[0], 10);
 | 
						|
        GET_BITTEST(bitTest2, in->SearchString[1], 10);
 | 
						|
      }
 | 
						|
 | 
						|
      cmp[0] = compare(treePtr[i].bitTest, bitTest1, in->COP1, lastStage);
 | 
						|
      cmp[1] = compare(treePtr[i].bitTest, bitTest2, in->COP2, lastStage);
 | 
						|
 | 
						|
      switch (in->BOP)
 | 
						|
      {
 | 
						|
        case BOP_OR:
 | 
						|
          if (cmp[0] == 2 || cmp[1] == 2)
 | 
						|
          {
 | 
						|
            setState = true;
 | 
						|
            goto add3;
 | 
						|
          }
 | 
						|
 | 
						|
          // 					if (cmp[0] == 1 || cmp[1] == 1)
 | 
						|
          // 						goto add3;
 | 
						|
 | 
						|
          /* XXXPAT: clean up this logic */
 | 
						|
 | 
						|
          if (cmp[0] == 1 && cmp[1] == 1)
 | 
						|
            goto add3;
 | 
						|
 | 
						|
          if (cmp[0] == 1)
 | 
						|
          {
 | 
						|
            convertToSingleOp = 0;
 | 
						|
            ADD_ELEMENT_WITH_CONVERT(i, (treePtr[i].bitCompare == 0 ? 5 : 10), 0);
 | 
						|
            goto skip3;
 | 
						|
          }
 | 
						|
          else if (cmp[1] == 1)
 | 
						|
          {
 | 
						|
            convertToSingleOp = 1;
 | 
						|
            ADD_ELEMENT_WITH_CONVERT(i, (treePtr[i].bitCompare == 0 ? 5 : 10), 0);
 | 
						|
            goto skip3;
 | 
						|
          }
 | 
						|
 | 
						|
          break;
 | 
						|
 | 
						|
        /* XXXPAT:  Need to verify the logic for AND.
 | 
						|
                        observations: if control reaches this point, then in the previous iteration the
 | 
						|
                        decision must have been 1, which implies equality for every previous comparison.
 | 
						|
 | 
						|
                        If one of the comparisons returns 0, then there are no entries in this subtree
 | 
						|
                                in the result set and it can stop here.
 | 
						|
                        else, if both of the comparisons return 2, then the whole subtree is in the result
 | 
						|
           set. else, if only one of the comparisons returns 2, then that comparison will be 2 for every
 | 
						|
           comparison made down this subtree, and it is equivalent to being (cmp1 && true).  In this case, we
 | 
						|
           repackage the query as a single argument version (using the comparison operator that was 1) to be
 | 
						|
           processed by indexwalk_1(). else, the comparisons are both 1, meaning we have equality so far and
 | 
						|
           can't decide on this subtree yet.
 | 
						|
                */
 | 
						|
        case BOP_AND:
 | 
						|
          if (cmp[0] == 0 || cmp[1] == 0)
 | 
						|
            break;
 | 
						|
          else if (cmp[0] == 2 && cmp[1] == 2)
 | 
						|
            setState = true;
 | 
						|
          else if (cmp[0] == 2)
 | 
						|
            convertToSingleOp = 1;
 | 
						|
          else if (cmp[1] == 2)
 | 
						|
            convertToSingleOp = 0;
 | 
						|
 | 
						|
          goto add3;
 | 
						|
 | 
						|
        default:
 | 
						|
          MessageLog logger(LoggingID(28));
 | 
						|
          logging::Message::Args colWidth;
 | 
						|
          Message msg(39);
 | 
						|
 | 
						|
          colWidth.add(in->BOP);
 | 
						|
          colWidth.add("indexWalk_2");
 | 
						|
          msg.format(colWidth);
 | 
						|
          logger.logDebugMessage(msg);
 | 
						|
          return;
 | 
						|
      }
 | 
						|
 | 
						|
      continue;
 | 
						|
    add3:
 | 
						|
      ADD_ELEMENT_WITH_CONVERT(i, (treePtr[i].bitCompare == 0 ? 5 : 10), (setState ? 1 : 0));
 | 
						|
    skip3:;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void PrimitiveProcessor::indexWalk_many(const IndexWalkHeader* in, vector<IndexWalkHeader*>* out) throw()
 | 
						|
{
 | 
						|
  uint16_t bitTest;
 | 
						|
  uint8_t* niceBlock;
 | 
						|
  int blockOffset, bitTestGroupSize, i;
 | 
						|
  WriteEngine::IdxBitTestEntry* treePtr;
 | 
						|
  IndexWalkHeader* element;
 | 
						|
  bool lastStage;
 | 
						|
  vector<uint64_t>::const_iterator it;
 | 
						|
  struct
 | 
						|
  {
 | 
						|
    int action;
 | 
						|
    vector<uint64_t>* searchStrings;
 | 
						|
  } nextIteration[32];
 | 
						|
 | 
						|
  IDXWALK_INIT();
 | 
						|
 | 
						|
  /*
 | 
						|
      Here's the high-level algorithm for this function:
 | 
						|
      1) Iterate over the bit test tree entries (index is i)
 | 
						|
              1a) if it is not a match, set nextIteration[i].action = 0 (searchStrings = NULL)
 | 
						|
              1b) if it is a match which determines the whole subtree goes in the result set action = 2
 | 
						|
     (searchStrings = NULL) 1c) if it's a match that determines the result is somewhere further down the tree,
 | 
						|
     set action = 1, stuff the matching search string into nextIteration[i].searchStrings. 2) Iterate over the
 | 
						|
     nextIteration structures 2a) if action == 0 do nothing 2b) if action == 1, make an intermediate
 | 
						|
     IndexWalkHeader configured s.t. it makes sense given the # of search strings that match on that subtree
 | 
						|
              2c) if action == 2,
 | 
						|
                              make an intermediate IndexWalkHeader with state = 1 so the whole subtree will be
 | 
						|
     included. 2d) if the current LBID is also the next LBID, recurse at p_IdxWalk() otherwise, add it to the
 | 
						|
     result set to return.
 | 
						|
 | 
						|
      An implementation that is definitely simpler and which may be faster
 | 
						|
      in some circumstances:
 | 
						|
      1) if BOP is OR, COP is =, so split the query into one single-op
 | 
						|
              query for each search string.
 | 
						|
      2) if BOP is AND, COP is !=, so grab every indexed value and eliminate
 | 
						|
              the entries in the argument list.  (Need to store the index values somewhere).
 | 
						|
      *** 3) Generalize the index_many case; get rid of the NVALS=[1,2] cases.
 | 
						|
                      - need to find a way to avoid dynamic mem allocation.
 | 
						|
  */
 | 
						|
 | 
						|
  if (in->SubBlock == 1 && in->Shift == 0)  // direct pointer block
 | 
						|
  {
 | 
						|
    bitTestGroupSize = 32;
 | 
						|
#ifdef VERBOSE
 | 
						|
    cerr << "  first iteration using many search strings" << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
    switch (in->BOP)
 | 
						|
    {
 | 
						|
      case BOP_OR:
 | 
						|
 | 
						|
        // according to the design doc, it's safe to assume COP1 is '='
 | 
						|
        for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
        {
 | 
						|
          nextIteration[i].action = 0;
 | 
						|
          nextIteration[i].searchStrings = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        for (it = in->SearchStrings->begin(); it != in->SearchStrings->end(); it++)
 | 
						|
        {
 | 
						|
          bitTest = *it >> (in->SSlen - 5);
 | 
						|
#ifdef VERBOSE
 | 
						|
          cerr << "  search string=0x" << hex << *it << " bittest=0x" << bitTest << dec << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
          if (treePtr[bitTest].fbo == 0 && treePtr[bitTest].sbid == 0 && treePtr[bitTest].entry == 0)
 | 
						|
            continue;
 | 
						|
 | 
						|
          if (nextIteration[bitTest].action == 0)
 | 
						|
          {
 | 
						|
            nextIteration[bitTest].searchStrings = new vector<uint64_t>();
 | 
						|
            nextIteration[bitTest].action = 1;
 | 
						|
          }
 | 
						|
 | 
						|
          nextIteration[bitTest].searchStrings->push_back(*it);
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case BOP_AND:
 | 
						|
 | 
						|
        // safe to assume COP1 is '!='
 | 
						|
        /*  Here's the logic here....
 | 
						|
                With a set of 0 search strings, the result set is the entire index.
 | 
						|
                With a set of 1 search strings, recurse the subtree containing that string, return every other
 | 
						|
           subtree. So, for every search string, we flag the respective subtree as one that has to be
 | 
						|
           recursed.
 | 
						|
        */
 | 
						|
 | 
						|
        for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
        {
 | 
						|
          if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
            nextIteration[i].action = 0;
 | 
						|
          else
 | 
						|
            nextIteration[i].action = 2;
 | 
						|
 | 
						|
          nextIteration[i].searchStrings = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        for (it = in->SearchStrings->begin(); it != in->SearchStrings->end(); it++)
 | 
						|
        {
 | 
						|
          bitTest = *it >> (in->SSlen - 5);
 | 
						|
#ifdef VERBOSE
 | 
						|
          cerr << "  search string=0x" << hex << *it << " bittest=0x" << bitTest << dec << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
          if (nextIteration[bitTest].action == 2)
 | 
						|
          {
 | 
						|
            nextIteration[bitTest].searchStrings = new vector<uint64_t>();
 | 
						|
            nextIteration[bitTest].action = 1;
 | 
						|
          }
 | 
						|
 | 
						|
          nextIteration[bitTest].searchStrings->push_back(*it);
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        MessageLog logger(LoggingID(28));
 | 
						|
        logging::Message::Args colWidth;
 | 
						|
        Message msg(39);
 | 
						|
 | 
						|
        colWidth.add(in->BOP);
 | 
						|
        msg.format(colWidth);
 | 
						|
        logger.logDebugMessage(msg);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  else  // The general case of being at a node in the middle of the tree
 | 
						|
  {
 | 
						|
    GET_GROUP_SIZE();
 | 
						|
 | 
						|
    switch (in->BOP)
 | 
						|
    {
 | 
						|
      case BOP_OR:
 | 
						|
 | 
						|
        // COP1 == '='
 | 
						|
        for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
        {
 | 
						|
          nextIteration[i].action = 0;
 | 
						|
          nextIteration[i].searchStrings = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
        {
 | 
						|
          if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
            continue;
 | 
						|
 | 
						|
          for (it = in->SearchStrings->begin(); it != in->SearchStrings->end(); it++)
 | 
						|
          {
 | 
						|
#ifdef VERBOSE
 | 
						|
            cerr << "  search string=0x" << hex << *it << dec << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
            if (treePtr[i].bitCompare == 0)
 | 
						|
            {
 | 
						|
              GET_BITTEST(bitTest, *it, 5);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
              GET_BITTEST(bitTest, *it, 10);
 | 
						|
            }
 | 
						|
 | 
						|
            if (bitTest == treePtr[i].bitTest)
 | 
						|
            {
 | 
						|
              if (nextIteration[i].action == 0)
 | 
						|
              {
 | 
						|
                nextIteration[i].searchStrings = new vector<uint64_t>();
 | 
						|
                nextIteration[i].action = 1;
 | 
						|
              }
 | 
						|
 | 
						|
              nextIteration[i].searchStrings->push_back(*it);
 | 
						|
            }
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      case BOP_AND:
 | 
						|
 | 
						|
        // COP1 == '!='
 | 
						|
        for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
        {
 | 
						|
          nextIteration[i].action = 2;
 | 
						|
          nextIteration[i].searchStrings = NULL;
 | 
						|
        }
 | 
						|
 | 
						|
        for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
        {
 | 
						|
          if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
          {
 | 
						|
            nextIteration[i].action = 0;
 | 
						|
            continue;
 | 
						|
          }
 | 
						|
 | 
						|
          for (it = in->SearchStrings->begin(); it != in->SearchStrings->end(); it++)
 | 
						|
          {
 | 
						|
#ifdef VERBOSE
 | 
						|
            cerr << "  search string=0x" << hex << *it << dec << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
            if (treePtr[i].bitCompare == 0)
 | 
						|
            {
 | 
						|
              GET_BITTEST(bitTest, *it, 5);
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
              GET_BITTEST(bitTest, *it, 10);
 | 
						|
            }
 | 
						|
 | 
						|
            // note: at the last stage, matches are left with action = 2 and NULL searchStrings
 | 
						|
            if (!lastStage && bitTest == treePtr[i].bitTest)
 | 
						|
            {
 | 
						|
              if (nextIteration[i].action == 2)
 | 
						|
              {
 | 
						|
                nextIteration[i].searchStrings = new vector<uint64_t>();
 | 
						|
                nextIteration[i].action = 1;
 | 
						|
              }
 | 
						|
 | 
						|
              nextIteration[i].searchStrings->push_back(*it);
 | 
						|
            }
 | 
						|
            else if (lastStage && bitTest == treePtr[i].bitTest)
 | 
						|
              nextIteration[i].action = 0;
 | 
						|
          }
 | 
						|
        }
 | 
						|
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        MessageLog logger(LoggingID(28));
 | 
						|
        logging::Message::Args colWidth;
 | 
						|
        Message msg(39);
 | 
						|
 | 
						|
        colWidth.add(in->BOP);
 | 
						|
        colWidth.add("indexWalk_many");
 | 
						|
        msg.format(colWidth);
 | 
						|
        logger.logDebugMessage(msg);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
  {
 | 
						|
    if (nextIteration[i].action > 0)
 | 
						|
    {
 | 
						|
      element = new IndexWalkHeader();
 | 
						|
      memcpy(element, in, sizeof(IndexWalkHeader));
 | 
						|
      element->ism.Command = INDEX_WALK_RESULTS;
 | 
						|
      element->Shift += (treePtr[i].bitCompare ? 10 : 5);
 | 
						|
      element->LBID = treePtr[i].fbo;
 | 
						|
      element->SubBlock = treePtr[i].sbid;
 | 
						|
      element->SBEntry = treePtr[i].entry;
 | 
						|
#ifdef VERBOSE
 | 
						|
      cerr << "  (inline _many) creating a result from subblock entry " << i
 | 
						|
           << " with Shift=" << (int)element->Shift << " LBID=" << element->LBID
 | 
						|
           << " Subblock=" << (int)element->SubBlock << " Subblock entry=" << (int)element->SBEntry
 | 
						|
           << " State=0" << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
      if (nextIteration[i].action == 1)
 | 
						|
      {
 | 
						|
        element->NVALS = nextIteration[i].searchStrings->size();
 | 
						|
 | 
						|
        if (nextIteration[i].searchStrings->size() > 2)
 | 
						|
          element->SearchStrings = nextIteration[i].searchStrings;
 | 
						|
        else if (nextIteration[i].searchStrings->size() == 2)
 | 
						|
        {
 | 
						|
          element->SearchString[0] = nextIteration[i].searchStrings->at(0);
 | 
						|
          element->SearchString[1] = nextIteration[i].searchStrings->at(1);
 | 
						|
          element->COP2 = element->COP1;
 | 
						|
          delete nextIteration[i].searchStrings;
 | 
						|
        }
 | 
						|
        else  // size == 1
 | 
						|
        {
 | 
						|
          element->SearchString[0] = nextIteration[i].searchStrings->at(0);
 | 
						|
          delete nextIteration[i].searchStrings;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else  // action == 2
 | 
						|
        element->State = 1;
 | 
						|
 | 
						|
      if (element->LBID == in->LBID && element->Shift < element->SSlen)
 | 
						|
      {
 | 
						|
#ifdef VERBOSE
 | 
						|
        cerr << "  recursing..." << endl;
 | 
						|
#endif
 | 
						|
        p_IdxWalk(element, out);
 | 
						|
 | 
						|
        if (element->State == 0 && element->NVALS > 2)
 | 
						|
          delete element->SearchStrings;
 | 
						|
 | 
						|
        delete element;
 | 
						|
      }
 | 
						|
      else
 | 
						|
        out->push_back(element);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void PrimitiveProcessor::grabSubTree(const IndexWalkHeader* in, vector<IndexWalkHeader*>* out) throw()
 | 
						|
{
 | 
						|
  uint8_t* niceBlock;
 | 
						|
  int blockOffset, bitTestGroupSize, i;
 | 
						|
  WriteEngine::IdxBitTestEntry* treePtr;
 | 
						|
  IndexWalkHeader* element;
 | 
						|
 | 
						|
  IDXWALK_INIT();
 | 
						|
  GET_GROUP_SIZE();
 | 
						|
 | 
						|
  for (i = 0; i < bitTestGroupSize; i++)
 | 
						|
  {
 | 
						|
    if (treePtr[i].fbo == 0 && treePtr[i].sbid == 0 && treePtr[i].entry == 0)
 | 
						|
      continue;
 | 
						|
 | 
						|
    ADD_ELEMENT(i, (treePtr[i].bitCompare ? 10 : 5), 1);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void PrimitiveProcessor::p_IdxWalk(const IndexWalkHeader* in, vector<IndexWalkHeader*>* out) throw()
 | 
						|
{
 | 
						|
#ifdef VERBOSE
 | 
						|
  cerr << "p_IdxWalk()" << endl;
 | 
						|
  cerr << "  COP1=" << (int)in->COP1 << endl;
 | 
						|
  cerr << "  COP2=" << (int)in->COP2 << endl;
 | 
						|
  cerr << "  BOP=" << (int)in->BOP << endl;
 | 
						|
  cerr << "  Shift=" << (int)in->Shift << endl;
 | 
						|
  cerr << "  SSlen=" << (int)in->SSlen << endl;
 | 
						|
  cerr << "  LBID=" << (int)in->LBID << endl;
 | 
						|
  cerr << "  Subblock=" << (int)in->SubBlock << endl;
 | 
						|
  cerr << "  SBEntry=" << (int)in->SBEntry << endl;
 | 
						|
  cerr << "  NVALS=" << (int)in->NVALS << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef PRIM_DEBUG
 | 
						|
 | 
						|
  if (in->Shift >= in->SSlen)
 | 
						|
    throw logic_error("p_IdxWalk: called on a completed search");
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
  if (in->State == 1)
 | 
						|
    grabSubTree(in, out);
 | 
						|
  else
 | 
						|
    switch (in->NVALS)
 | 
						|
    {
 | 
						|
      case 1: indexWalk_1(in, out); break;
 | 
						|
 | 
						|
      case 2: indexWalk_2(in, out); break;
 | 
						|
 | 
						|
      default: indexWalk_many(in, out); break;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
  cerr << "/p_IdxWalk()" << endl;
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
 * Following the headers for both the request and result will be at variable
 | 
						|
 * length list of the IndexListParam structure, where the type field is used to
 | 
						|
 * indicate whether the Index List section is a header (0), sub-block (4), or
 | 
						|
 * a block (5).
 | 
						|
 */
 | 
						|
void PrimitiveProcessor::p_IdxList(const IndexListHeader* rqst, IndexListHeader* rslt, int mode)
 | 
						|
{
 | 
						|
  uint8_t* listPtr;
 | 
						|
  IndexListParam* linkList;
 | 
						|
  IndexListEntry *listEntry, *rsltList, *sizeEntry = 0;
 | 
						|
  int listOfst, listType, ridCt, i, j, originalRidCt;
 | 
						|
  unsigned entryNumber, lastEntry = 0;
 | 
						|
  int subblk_sz = WriteEngine::SUBBLOCK_TOTAL_BYTES;
 | 
						|
  int entry_sz = WriteEngine::NEXT_PTR_BYTES;
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
  cerr << "p_IdxList()" << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
  memcpy(rslt, rqst, sizeof(IndexListHeader));
 | 
						|
  rslt->ism.Command = INDEX_LIST_RESULTS;
 | 
						|
  rslt->NVALS = 0;
 | 
						|
 | 
						|
  listPtr = (uint8_t*)block;
 | 
						|
  linkList = (IndexListParam*)(rqst + 1);
 | 
						|
  rsltList = (IndexListEntry*)(rslt + 1);
 | 
						|
 | 
						|
  for (i = 0; i < rqst->NVALS; i++)
 | 
						|
  {
 | 
						|
    j = 0;
 | 
						|
    listOfst = (linkList->sbid * subblk_sz) + (linkList->entry * entry_sz);
 | 
						|
    entryNumber = linkList->entry;
 | 
						|
    listEntry = (IndexListEntry*)(listPtr + listOfst);
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
    cerr << "  processing argument number " << i + 1 << endl;
 | 
						|
    cerr << "    type=" << linkList->type << " LBID=" << linkList->fbo << " subblock=" << linkList->sbid
 | 
						|
         << " entry=" << linkList->entry << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
    listType = linkList->type;
 | 
						|
 | 
						|
    if (listType == LIST_SIZE)
 | 
						|
    {
 | 
						|
      if (listEntry->type != LIST_SIZE)
 | 
						|
      {
 | 
						|
        MessageLog logger(LoggingID(28));
 | 
						|
        Message msg(40);
 | 
						|
        logger.logDebugMessage(msg);
 | 
						|
#ifdef VERBOSE
 | 
						|
        cerr << "PrimitiveProcessor::p_IdxList: was told to parse a header, but the given pointer does not "
 | 
						|
                "point to one.  sbid="
 | 
						|
             << linkList->sbid << " entry=" << linkList->entry << endl;
 | 
						|
#endif
 | 
						|
        throw runtime_error("p_IdxList: not a header");
 | 
						|
      }
 | 
						|
 | 
						|
      ridCt = listEntry->value;
 | 
						|
      originalRidCt = ridCt;
 | 
						|
#ifdef VERBOSE
 | 
						|
      uint64_t* tmp = (uint64_t*)&listEntry[1];
 | 
						|
      cerr << "    ridCount=" << ridCt << " key value=0x" << hex << *tmp << dec << endl;
 | 
						|
#endif
 | 
						|
      listEntry += 2;  // Skip size and key values
 | 
						|
      entryNumber += 2;
 | 
						|
      lastEntry = linkList->entry + 4;
 | 
						|
    }
 | 
						|
 | 
						|
    else
 | 
						|
    {
 | 
						|
      if (listType == LLP_SUBBLK)
 | 
						|
      {
 | 
						|
        sizeEntry = listEntry + WriteEngine::LIST_SUB_LLP_POS;
 | 
						|
        lastEntry = linkList->entry + 32;
 | 
						|
      }
 | 
						|
      else if (listType == LLP_BLK)
 | 
						|
      {
 | 
						|
        sizeEntry = listEntry + WriteEngine::LIST_BLOCK_LLP_POS;
 | 
						|
        lastEntry = linkList->entry + (mode == 0 ? 1024 : 1023);
 | 
						|
        // ignore the size entry for blocks if mode == 1
 | 
						|
      }
 | 
						|
      else
 | 
						|
        cerr << "p_IdxList: bad pointer type " << listType << endl;
 | 
						|
 | 
						|
      ridCt = sizeEntry->ridCt;  // XXXPAT: make sure these are the right bits
 | 
						|
      originalRidCt = ridCt;
 | 
						|
#ifdef VERBOSE
 | 
						|
      cerr << "    ridCount for this " << (listType == LLP_SUBBLK ? "subblock: " : "block: ") << ridCt
 | 
						|
           << endl;
 | 
						|
#endif
 | 
						|
    }
 | 
						|
 | 
						|
    // 		while (ridCt > 0 && entryNumber < lastEntry) {
 | 
						|
    while (entryNumber < lastEntry)
 | 
						|
    {
 | 
						|
      switch (listEntry->type)
 | 
						|
      {
 | 
						|
        case LLP_SUBBLK:
 | 
						|
        case LLP_BLK:
 | 
						|
 | 
						|
          /* the second to last entry of a subblock
 | 
						|
          can now be a HWM disguised as a continuation ptr. */
 | 
						|
          if (mode && entryNumber == static_cast<unsigned>(linkList->entry + 30) && listType == LLP_SUBBLK)
 | 
						|
            break;
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
          ilptmp = reinterpret_cast<IndexListParam*>(listEntry);
 | 
						|
 | 
						|
          cerr << "   found a continuation pointer: LBID=" << ilptmp->fbo << " subblock=" << ilptmp->sbid
 | 
						|
               << " subblock entry=" << ilptmp->entry << endl;
 | 
						|
#endif
 | 
						|
          *rsltList = *listEntry;
 | 
						|
          rslt->NVALS++;
 | 
						|
          rsltList++;
 | 
						|
          break;
 | 
						|
 | 
						|
        /*
 | 
						|
        #ifdef VERBOSE
 | 
						|
                                                cerr << "   reached the end of the list" << endl;
 | 
						|
                                                if (listEntry != sizeEntry && listType != LIST_SIZE)
 | 
						|
                                                        cerr << "   ERROR: there's a list pointer in the
 | 
						|
        middle of the list" << endl; else if (listType != LIST_SIZE) cerr << "   Possible error: the pointer
 | 
						|
        clause executed for a subblock or block" << endl; #endif endOfList = true; break;
 | 
						|
        */
 | 
						|
        case RID:
 | 
						|
#ifdef VERBOSE
 | 
						|
// 					cerr << "    returning rid " << listEntry->value << endl;
 | 
						|
#endif
 | 
						|
          *rsltList = *listEntry;
 | 
						|
          rslt->NVALS++;
 | 
						|
          rsltList++;
 | 
						|
          ridCt--;
 | 
						|
          j++;
 | 
						|
          break;
 | 
						|
 | 
						|
        case LIST_SIZE:
 | 
						|
        case NOT_IN_USE:
 | 
						|
        case EMPTY_LIST_PTR:
 | 
						|
        case EMPTY_PTR:
 | 
						|
        case PARENT: break;
 | 
						|
 | 
						|
        default:
 | 
						|
#ifdef VERBOSE
 | 
						|
          IndexListParam* tmp = reinterpret_cast<IndexListParam*>(listEntry);
 | 
						|
          cerr << "PrimitiveProcessor::p_IdxList: invalid list entry type" << endl;
 | 
						|
          cerr << "   Entry contents: type=" << listEntry->type << " value/RID=" << listEntry->value << endl;
 | 
						|
          cerr << "   (if a pointer, fbo=" << tmp->fbo << " subblock=" << tmp->sbid << " entry=" << tmp->entry
 | 
						|
               << ")" << endl;
 | 
						|
          cerr << "   Location of the entry: lbid=" << linkList->fbo
 | 
						|
               << " subblock=" << linkList->sbid + entryNumber / 32 << " entry=" << entryNumber % 32 << endl;
 | 
						|
          cerr << "   Input parameter indicates the start of the list is sbid=" << linkList->sbid
 | 
						|
               << " entry=" << linkList->entry << endl;
 | 
						|
          cerr << "   Type of search: "
 | 
						|
               << (linkList->type == LIST_SIZE ? "header"
 | 
						|
                                               : (linkList->type == LLP_SUBBLK
 | 
						|
                                                      ? "subblock"
 | 
						|
                                                      : (linkList->type == LLP_BLK ? "block" : "unknown..?")))
 | 
						|
               << endl;
 | 
						|
          cerr << "   Processed " << entryNumber - linkList->entry << " entries for this request so far."
 | 
						|
               << endl;
 | 
						|
          cerr << "   Rid count read from the list is " << originalRidCt << endl;
 | 
						|
#endif
 | 
						|
          MessageLog logger(LoggingID(28));
 | 
						|
          Message msg(40);
 | 
						|
          logger.logDebugMessage(msg);
 | 
						|
          throw runtime_error("Bad index list entry, see stderr");
 | 
						|
          return;
 | 
						|
      }
 | 
						|
 | 
						|
      listEntry++;
 | 
						|
      entryNumber++;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef VERBOSE
 | 
						|
    cerr << "  RIDs in result generated from input arg #" << i + 1 << ": " << j << endl;
 | 
						|
#endif
 | 
						|
 | 
						|
    linkList++;
 | 
						|
  }
 | 
						|
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace primitives
 |