Commit f4ce3ec1 authored by unknown's avatar unknown
Browse files

Merge joreland@bk-internal.mysql.com:/home/bk/mysql-4.1-ndb

into mysql.com:/home/jonas/src/mysql-4.1-ndb

parents 11e5f207 0fbbaf9e
Loading
Loading
Loading
Loading
+15 −10
Original line number Diff line number Diff line
@@ -7,10 +7,12 @@

use strict;
use integer;
use Getopt::Long;

my $all = shift;
!defined($all) || ($all eq '--all' && !defined(shift))
  or die "only available option is --all";
my $opt_all = 0;
my $opt_cnt = 5;
GetOptions("all" => \$opt_all, "cnt=i" => \$opt_cnt)
  or die "options are:  --all --cnt=N";

my $table = 't';

@@ -67,15 +69,18 @@ sub mkall ($$$\@) {
  my($col, $key1, $key2, $val) = @_;
  my @a = ();
  my $p = mkdummy(@$val);
  push(@a, $p) if $all;
  my @ops1 = $all ? qw(< <= = >= >) : qw(= >= >);
  my @ops2 = $all ? qw(< <= = >= >) : qw(< <=);
  push(@a, $p) if $opt_all;
  my @ops = qw(< <= = >= >);
  for my $op (@ops) {
    my $p = mkone($col, $op, $key1, @$val);
    push(@a, $p) if $opt_all || $p->{cnt} != 0;
  }
  my @ops1 = $opt_all ? @ops : qw(= >= >);
  my @ops2 = $opt_all ? @ops : qw(<= <);
  for my $op1 (@ops1) {
    my $p = mkone($col, $op1, $key1, @$val);
    push(@a, $p) if $all || $p->{cnt} != 0;
    for my $op2 (@ops2) {
      my $p = mktwo($col, $op1, $key1, $op2, $key2, @$val);
      push(@a, $p) if $all || $p->{cnt} != 0;
      push(@a, $p) if $opt_all || $p->{cnt} != 0;
    }
  }
  return \@a;
@@ -95,7 +100,7 @@ create table $table (
  index (b, c, d)
) engine=ndb;
EOF
  my @val = (0..4);
  my @val = (0..($opt_cnt-1));
  my $v0 = 0;
  for my $v1 (@val) {
    for my $v2 (@val) {
+15 −24
Original line number Diff line number Diff line
@@ -250,8 +250,8 @@ private:
  static const unsigned NodeHeadSize = sizeof(TreeNode) >> 2;

  /*
   * Tree nodes are not always accessed fully, for cache reasons.  There
   * are 3 access sizes.
   * Tree node "access size" was for an early version with signal
   * interface to TUP.  It is now used only to compute sizes.
   */
  enum AccSize {
    AccNone = 0,
@@ -284,7 +284,7 @@ private:
   * m_occup), and whether the position is at an existing entry or
   * before one (if any).  Position m_occup points past the node and is
   * also represented by position 0 of next node.  Includes direction
   * and copy of entry used by scan.
   * used by scan.
   */
  struct TreePos;
  friend struct TreePos;
@@ -292,8 +292,7 @@ private:
    TupLoc m_loc;               // physical node address
    Uint16 m_pos;               // position 0 to m_occup
    Uint8 m_match;              // at an existing entry
    Uint8 m_dir;                // from link (0-2) or within node (3)
    TreeEnt m_ent;              // copy of current entry
    Uint8 m_dir;                // see scanNext()
    TreePos();
  };

@@ -374,6 +373,10 @@ private:
   * a separate lock wait flag.  It may be for current entry or it may
   * be for an entry we were moved away from.  In any case nothing
   * happens with current entry before lock wait flag is cleared.
   *
   * An unfinished scan is always linked to some tree node, and has
   * current position and direction (see comments at scanNext).  There
   * is also a copy of latest entry found.
   */
  struct ScanOp;
  friend struct ScanOp;
@@ -412,7 +415,7 @@ private:
    ScanBound* m_bound[2];      // pointers to above 2
    Uint16 m_boundCnt[2];       // number of bounds in each
    TreePos m_scanPos;          // position
    TreeEnt m_lastEnt;          // last entry returned
    TreeEnt m_scanEnt;          // latest entry found
    Uint32 m_nodeScan;          // next scan at node (single-linked)
    union {
    Uint32 nextPool;
@@ -519,7 +522,6 @@ private:
    Frag& m_frag;               // fragment using the node
    TupLoc m_loc;               // physical node address
    TreeNode* m_node;           // pointer to node storage
    AccSize m_acc;              // accessed size
    NodeHandle(Frag& frag);
    NodeHandle(const NodeHandle& node);
    NodeHandle& operator=(const NodeHandle& node);
@@ -580,9 +582,8 @@ private:
   * DbtuxNode.cpp
   */
  int allocNode(Signal* signal, NodeHandle& node);
  void accessNode(Signal* signal, NodeHandle& node, AccSize acc);
  void selectNode(Signal* signal, NodeHandle& node, TupLoc loc, AccSize acc);
  void insertNode(Signal* signal, NodeHandle& node, AccSize acc);
  void selectNode(Signal* signal, NodeHandle& node, TupLoc loc);
  void insertNode(Signal* signal, NodeHandle& node);
  void deleteNode(Signal* signal, NodeHandle& node);
  void setNodePref(Signal* signal, NodeHandle& node);
  // node operations
@@ -968,8 +969,7 @@ Dbtux::TreePos::TreePos() :
  m_loc(),
  m_pos(ZNIL),
  m_match(false),
  m_dir(255),
  m_ent()
  m_dir(255)
{
}

@@ -1010,7 +1010,7 @@ Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
  m_boundMin(scanBoundPool),
  m_boundMax(scanBoundPool),
  m_scanPos(),
  m_lastEnt(),
  m_scanEnt(),
  m_nodeScan(RNIL)
{
  m_bound[0] = &m_boundMin;
@@ -1084,8 +1084,7 @@ inline
Dbtux::NodeHandle::NodeHandle(Frag& frag) :
  m_frag(frag),
  m_loc(),
  m_node(0),
  m_acc(AccNone)
  m_node(0)
{
}

@@ -1093,8 +1092,7 @@ inline
Dbtux::NodeHandle::NodeHandle(const NodeHandle& node) :
  m_frag(node.m_frag),
  m_loc(node.m_loc),
  m_node(node.m_node),
  m_acc(node.m_acc)
  m_node(node.m_node)
{
}

@@ -1104,7 +1102,6 @@ Dbtux::NodeHandle::operator=(const NodeHandle& node)
  ndbassert(&m_frag == &node.m_frag);
  m_loc = node.m_loc;
  m_node = node.m_node;
  m_acc = node.m_acc;
  return *this;
}

@@ -1190,7 +1187,6 @@ inline Dbtux::Data
Dbtux::NodeHandle::getPref()
{
  TreeHead& tree = m_frag.m_tree;
  ndbrequire(m_acc >= AccPref);
  return tree.getPref(m_node);
}

@@ -1201,11 +1197,6 @@ Dbtux::NodeHandle::getEnt(unsigned pos)
  TreeEnt* entList = tree.getEntList(m_node);
  const unsigned occup = m_node->m_occup;
  ndbrequire(pos < occup);
  if (pos == 0 || pos == occup - 1) {
    ndbrequire(m_acc >= AccPref)
  } else {
    ndbrequire(m_acc == AccFull)
  }
  return entList[(1 + pos) % occup];
}

+16 −23
Original line number Diff line number Diff line
@@ -122,7 +122,7 @@ Dbtux::printNode(Signal* signal, Frag& frag, NdbOut& out, TupLoc loc, PrintPar&
  }
  TreeHead& tree = frag.m_tree;
  NodeHandle node(frag);
  selectNode(signal, node, loc, AccFull);
  selectNode(signal, node, loc);
  out << par.m_path << " " << node << endl;
  // check children
  PrintPar cpar[2];
@@ -310,7 +310,6 @@ operator<<(NdbOut& out, const Dbtux::TreePos& pos)
  out << " [pos " << dec << pos.m_pos << "]";
  out << " [match " << dec << pos.m_match << "]";
  out << " [dir " << dec << pos.m_dir << "]";
  out << " [ent " << pos.m_ent << "]";
  out << "]";
  return out;
}
@@ -347,6 +346,7 @@ operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
  out << " [lockMode " << dec << scan.m_lockMode << "]";
  out << " [keyInfo " << dec << scan.m_keyInfo << "]";
  out << " [pos " << scan.m_scanPos << "]";
  out << " [ent " << scan.m_scanEnt << "]";
  for (unsigned i = 0; i <= 1; i++) {
    out << " [bound " << dec << i;
    Dbtux::ScanBound& bound = *scan.m_bound[i];
@@ -407,9 +407,7 @@ operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
  const Dbtux::TreeHead& tree = frag.m_tree;
  out << "[NodeHandle " << hex << &node;
  out << " [loc " << node.m_loc << "]";
  out << " [acc " << dec << node.m_acc << "]";
  out << " [node " << *node.m_node << "]";
  if (node.m_acc >= Dbtux::AccPref) {
  const Uint32* data;
  out << " [pref";
  data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize;
@@ -418,17 +416,12 @@ operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
  out << "]";
  out << " [entList";
  unsigned numpos = node.m_node->m_occup;
    if (node.m_acc < Dbtux::AccFull && numpos > 2) {
      numpos = 2;
      out << "(" << dec << numpos << ")";
    }
  data = (const Uint32*)node.m_node + Dbtux::NodeHeadSize + tree.m_prefSize;
  const Dbtux::TreeEnt* entList = (const Dbtux::TreeEnt*)data;
  // print entries in logical order
  for (unsigned pos = 1; pos <= numpos; pos++)
    out << " " << entList[pos % numpos];
  out << "]";
  }
  out << "]";
  return out;
}
+3 −19
Original line number Diff line number Diff line
@@ -33,30 +33,16 @@ Dbtux::allocNode(Signal* signal, NodeHandle& node)
    jam();
    node.m_loc = TupLoc(pageId, pageOffset);
    node.m_node = reinterpret_cast<TreeNode*>(node32);
    node.m_acc = AccNone;
    ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
  }
  return errorCode;
}

/*
 * Access more of the node.
 */
void
Dbtux::accessNode(Signal* signal, NodeHandle& node, AccSize acc)
{
  ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
  if (node.m_acc >= acc)
    return;
  // XXX could do prefetch
  node.m_acc = acc;
}

/*
 * Set handle to point to existing node.
 */
void
Dbtux::selectNode(Signal* signal, NodeHandle& node, TupLoc loc, AccSize acc)
Dbtux::selectNode(Signal* signal, NodeHandle& node, TupLoc loc)
{
  Frag& frag = node.m_frag;
  ndbrequire(loc != NullTupLoc);
@@ -67,21 +53,19 @@ Dbtux::selectNode(Signal* signal, NodeHandle& node, TupLoc loc, AccSize acc)
  jamEntry();
  node.m_loc = loc;
  node.m_node = reinterpret_cast<TreeNode*>(node32);
  node.m_acc = AccNone;
  ndbrequire(node.m_loc != NullTupLoc && node.m_node != 0);
  accessNode(signal, node, acc);
}

/*
 * Set handle to point to new node.  Uses the pre-allocated node.
 */
void
Dbtux::insertNode(Signal* signal, NodeHandle& node, AccSize acc)
Dbtux::insertNode(Signal* signal, NodeHandle& node)
{
  Frag& frag = node.m_frag;
  TupLoc loc = frag.m_freeLoc;
  frag.m_freeLoc = NullTupLoc;
  selectNode(signal, node, loc, acc);
  selectNode(signal, node, loc);
  new (node.m_node) TreeNode();
#ifdef VM_TRACE
  TreeHead& tree = frag.m_tree;
+26 −25
Original line number Diff line number Diff line
@@ -275,7 +275,7 @@ Dbtux::execNEXT_SCANREQ(Signal* signal)
      jam();
      const TupLoc loc = scan.m_scanPos.m_loc;
      NodeHandle node(frag);
      selectNode(signal, node, loc, AccHead);
      selectNode(signal, node, loc);
      unlinkScan(node, scanPtr);
      scan.m_scanPos.m_loc = NullTupLoc;
    }
@@ -350,7 +350,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
  if (scan.m_lockwait) {
    jam();
    // LQH asks if we are waiting for lock and we tell it to ask again
    const TreeEnt ent = scan.m_scanPos.m_ent;
    const TreeEnt ent = scan.m_scanEnt;
    NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
    conf->scanPtr = scan.m_userPtr;
    conf->accOperationPtr = RNIL;       // no tuple returned
@@ -385,7 +385,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
    ndbrequire(scan.m_accLockOp == RNIL);
    if (! scan.m_readCommitted) {
      jam();
      const TreeEnt ent = scan.m_scanPos.m_ent;
      const TreeEnt ent = scan.m_scanEnt;
      // read tuple key
      readTablePk(frag, ent, pkData, pkSize);
      // get read lock or exclusive lock
@@ -473,7 +473,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
    // we have lock or do not need one
    jam();
    // read keys if not already done (uses signal)
    const TreeEnt ent = scan.m_scanPos.m_ent;
    const TreeEnt ent = scan.m_scanEnt;
    if (scan.m_keyInfo) {
      jam();
      if (pkSize == 0) {
@@ -536,8 +536,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
        total += length;
      }
    }
    // remember last entry returned
    scan.m_lastEnt = ent;
    // next time look for next entry
    scan.m_state = ScanOp::Next;
    return;
@@ -712,20 +710,21 @@ Dbtux::scanFirst(Signal* signal, ScanOpPtr scanPtr)
  scan.m_state = ScanOp::Next;
  // link the scan to node found
  NodeHandle node(frag);
  selectNode(signal, node, treePos.m_loc, AccFull);
  selectNode(signal, node, treePos.m_loc);
  linkScan(node, scanPtr);
}

/*
 * Move to next entry.  The scan is already linked to some node.  When
 * we leave, if any entry was found, it will be linked to a possibly
 * different node.  The scan has a direction, one of:
 * different node.  The scan has a position, and a direction which tells
 * from where we came to this position.  This is one of:
 *
 * 0 - coming up from left child
 * 1 - coming up from right child (proceed to parent immediately)
 * 2 - coming up from root (the scan ends)
 * 3 - left to right within node
 * 4 - coming down from parent to left or right child
 * 0 - up from left child (scan this node next)
 * 1 - up from right child (proceed to parent)
 * 2 - up from root (the scan ends)
 * 3 - left to right within node (at end proceed to right child)
 * 4 - down from parent (proceed to left child)
 */
void
Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
@@ -768,10 +767,12 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
  TreePos pos = scan.m_scanPos;
  // get and remember original node
  NodeHandle origNode(frag);
  selectNode(signal, origNode, pos.m_loc, AccHead);
  selectNode(signal, origNode, pos.m_loc);
  ndbrequire(islinkScan(origNode, scanPtr));
  // current node in loop
  NodeHandle node = origNode;
  // copy of entry found
  TreeEnt ent;
  while (true) {
    jam();
    if (pos.m_dir == 2) {
@@ -783,7 +784,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
    }
    if (node.m_loc != pos.m_loc) {
      jam();
      selectNode(signal, node, pos.m_loc, AccHead);
      selectNode(signal, node, pos.m_loc);
    }
    if (pos.m_dir == 4) {
      // coming down from parent proceed to left child
@@ -799,7 +800,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
      pos.m_dir = 0;
    }
    if (pos.m_dir == 0) {
      // coming from left child scan current node
      // coming up from left child scan current node
      jam();
      pos.m_pos = 0;
      pos.m_match = false;
@@ -810,8 +811,6 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
      jam();
      unsigned occup = node.getOccup();
      ndbrequire(occup >= 1);
      // access full node
      accessNode(signal, node, AccFull);
      // advance position
      if (! pos.m_match)
        pos.m_match = true;
@@ -819,10 +818,10 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
        pos.m_pos++;
      if (pos.m_pos < occup) {
        jam();
        pos.m_ent = node.getEnt(pos.m_pos);
        ent = node.getEnt(pos.m_pos);
        pos.m_dir = 3;  // unchanged
        // read and compare all attributes
        readKeyAttrs(frag, pos.m_ent, 0, c_entryKey);
        readKeyAttrs(frag, ent, 0, c_entryKey);
        int ret = cmpScanBound(frag, 1, c_dataBuffer, scan.m_boundCnt[1], c_entryKey);
        ndbrequire(ret != NdbSqlUtil::CmpUnknown);
        if (ret < 0) {
@@ -833,7 +832,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
          break;
        }
        // can we see it
        if (! scanVisible(signal, scanPtr, pos.m_ent)) {
        if (! scanVisible(signal, scanPtr, ent)) {
          jam();
          continue;
        }
@@ -853,7 +852,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
      pos.m_dir = 1;
    }
    if (pos.m_dir == 1) {
      // coming from right child proceed to parent
      // coming up from right child proceed to parent
      jam();
      pos.m_loc = node.getLink(2);
      pos.m_dir = node.getSide();
@@ -871,6 +870,8 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
      unlinkScan(origNode, scanPtr);
      linkScan(node, scanPtr);
    }
    // copy found entry
    scan.m_scanEnt = ent;
  } else if (scan.m_state == ScanOp::Last) {
    jam();
    ndbrequire(pos.m_loc == NullTupLoc);
@@ -888,7 +889,7 @@ Dbtux::scanNext(Signal* signal, ScanOpPtr scanPtr)
/*
 * Check if an entry is visible to the scan.
 *
 * There is a special check to never return same tuple twice in a row.
 * There is a special check to never accept same tuple twice in a row.
 * This is faster than asking TUP.  It also fixes some special cases
 * which are not analyzed or handled yet.
 */
@@ -903,8 +904,8 @@ Dbtux::scanVisible(Signal* signal, ScanOpPtr scanPtr, TreeEnt ent)
  Uint32 tupAddr = getTupAddr(frag, ent);
  Uint32 tupVersion = ent.m_tupVersion;
  // check for same tuple twice in row
  if (scan.m_lastEnt.m_tupLoc == ent.m_tupLoc &&
      scan.m_lastEnt.m_fragBit == fragBit) {
  if (scan.m_scanEnt.m_tupLoc == ent.m_tupLoc &&
      scan.m_scanEnt.m_fragBit == fragBit) {
    jam();
    return false;
  }
Loading