Example #1
0
  public void compressConglomerate(TransactionManager xact_manager, Transaction rawtran)
      throws StandardException {
    B2IController b2ic = new B2IController();

    try {
      int open_mode = TransactionController.OPENMODE_FORUPDATE;

      // Do the actual open of the container in the super class.
      b2ic.init(
          xact_manager, // current transaction
          xact_manager.getRawStoreXact(), // current raw store xact
          false, // Not holdable
          open_mode,
          TransactionController.MODE_TABLE,
          xact_manager
              .getRawStoreXact()
              .newLockingPolicy(
                  LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true),
          true,
          this,
          new B2IUndo(),
          (B2IStaticCompiledInfo) null,
          (DynamicCompiledOpenConglomInfo) null);

      b2ic.getContainer().compressContainer();

    } finally {
      b2ic.close();
    }

    return;
  }
  protected void queueDeletePostCommitWork(RowPosition pos) throws StandardException {
    TransactionManager xact_mgr = open_conglom.getXactMgr();

    xact_mgr.addPostCommitWork(
        new HeapPostCommit(
            xact_mgr.getAccessManager(),
            (Heap) open_conglom.getConglomerate(),
            pos.current_page.getPageNumber()));
  }
Example #3
0
  /**
   * Lock the base table.
   *
   * <p>Assumes that segment of the base container is the same as the segment of the btree segment.
   *
   * <p>RESOLVE - we really want to get the lock without opening the container. raw store will be
   * providing this.
   *
   * @param xact_manager Transaction to associate the lock with.
   * @exception StandardException Standard exception policy.
   */
  public final ConglomerateController lockTable(
      TransactionManager xact_manager, int open_mode, int lock_level, int isolation_level)
      throws StandardException {
    open_mode |= TransactionController.OPENMODE_FOR_LOCK_ONLY;

    // open the base conglomerate - just to get the table lock.
    ConglomerateController cc =
        xact_manager.openConglomerate(
            this.baseConglomerateId, false, open_mode, lock_level, isolation_level);

    return (cc);
  }
Example #4
0
  /**
   * Bulk Load a B-tree secondary index.
   *
   * @see Conglomerate#load
   * @exception StandardException Standard Derby Error policy. raise
   *     SQLState.STORE_CONGLOMERATE_DUPLICATE_KEY_EXCEPTION if a duplicate key is detected in the
   *     load.
   */
  public long load(
      TransactionManager xact_manager, boolean createConglom, RowLocationRetRowSource rowSource)
      throws StandardException {
    long num_rows_loaded = 0;
    B2IController b2ic = new B2IController();

    try {
      int open_mode = TransactionController.OPENMODE_FORUPDATE;

      if (createConglom) {
        open_mode |= (ContainerHandle.MODE_UNLOGGED | ContainerHandle.MODE_CREATE_UNLOGGED);
      }

      // Do the actual open of the container in the super class.
      b2ic.init(
          xact_manager, // current transaction
          xact_manager.getRawStoreXact(), // current raw store xact
          false, // Not holdable
          open_mode,
          TransactionController.MODE_TABLE,
          xact_manager
              .getRawStoreXact()
              .newLockingPolicy(
                  LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true),
          true,
          this,
          new B2IUndo(),
          (B2IStaticCompiledInfo) null,
          (DynamicCompiledOpenConglomInfo) null);

      num_rows_loaded = b2ic.load(xact_manager, createConglom, rowSource);

    } finally {
      b2ic.close();
    }

    return (num_rows_loaded);
  }
Example #5
0
  /**
   * Drop this b-tree secondary index.
   *
   * @see Conglomerate#drop
   * @see BTree#drop
   * @exception StandardException Standard exception policy.
   */
  public void drop(TransactionManager xact_manager) throws StandardException {
    // HACK to get around problem where index is dropped after the base
    // table.
    ConglomerateController base_cc = null;

    /* Get X table lock to make sure no thread is accessing index */
    base_cc =
        lockTable(
            xact_manager,
            TransactionController.OPENMODE_FORUPDATE,
            TransactionController.MODE_TABLE,
            TransactionController.ISOLATION_REPEATABLE_READ);

    xact_manager.getRawStoreXact().dropContainer(id);

    if (base_cc != null) base_cc.close();
  }
  /**
   * Initialize the scan for use.
   *
   * <p>Any changes to this method may have to be reflected in close as well.
   *
   * <p>The btree init opens the container (super.init), and stores away the state of the
   * qualifiers. The actual searching for the first position is delayed until the first next() call.
   *
   * @exception StandardException Standard exception policy.
   */
  public void init(
      TransactionManager xact_manager,
      Transaction rawtran,
      int open_mode,
      int lock_level,
      LockingPolicy locking_policy,
      int isolation_level,
      boolean open_for_locking,
      FormatableBitSet scanColumnList,
      B2I conglomerate,
      B2IUndo undo)
      throws StandardException {
    // open and lock the base table.

    int base_open_mode = open_mode | TransactionController.OPENMODE_FOR_LOCK_ONLY;

    // open the base conglomerate - just to get lock
    base_cc_for_locking =
        xact_manager.openConglomerate(
            conglomerate.baseConglomerateId, false, base_open_mode, lock_level, isolation_level);

    BTreeLockingPolicy b2i_locking_policy =
        conglomerate.getBtreeLockingPolicy(
            rawtran, lock_level, open_mode, isolation_level, base_cc_for_locking, this);

    super.init(
        xact_manager,
        rawtran,
        false,
        open_mode,
        lock_level,
        b2i_locking_policy,
        scanColumnList,
        (DataValueDescriptor[]) null, // no start position supported
        ScanController.NA, // no start position supported
        (Qualifier[][]) null, // no qualifier supported
        (DataValueDescriptor[]) null, // no stop position supported
        ScanController.NA, // no stop position supported
        conglomerate,
        undo,
        (StaticCompiledOpenConglomInfo) null,
        (DynamicCompiledOpenConglomInfo) null);
  }
  /** Initialize the scan, returning false if there was some error. */
  public boolean init(TransactionManager tran) throws StandardException {
    if (SanityManager.DEBUG) {
      // We really expect to have at least one
      // merge run.
      SanityManager.ASSERT(mergeRuns != null);
      SanityManager.ASSERT(mergeRuns.size() > 0);

      // This sort scan also expects that the
      // caller has ensured that the sort buffer
      // capacity will hold a row from all the
      // merge runs.
      SanityManager.ASSERT(sortBuffer.capacity() >= mergeRuns.size());
    }

    // Clear the sort buffer.
    sortBuffer.reset();

    // Create an array to hold a scan controller
    // for each merge run.
    openScans = new StreamContainerHandle[mergeRuns.size()];
    if (openScans == null) return false;

    // Open a scan on each merge run.
    int scanindex = 0;
    Enumeration e = mergeRuns.elements();
    while (e.hasMoreElements()) {
      // get the container id
      long id = ((Long) e.nextElement()).longValue();

      Transaction rawTran = tran.getRawStoreXact(); // get raw transaction
      int segmentId = StreamContainerHandle.TEMPORARY_SEGMENT;
      openScans[scanindex++] = rawTran.openStreamContainer(segmentId, id, hold);
    }

    // Load the initial rows.
    for (scanindex = 0; scanindex < openScans.length; scanindex++) mergeARow(scanindex);

    // Success!
    return true;
  }
  protected long load(
      TransactionManager xact_manager,
      Heap heap,
      boolean createConglom,
      RowLocationRetRowSource rowSource)
      throws StandardException {
    long num_rows_loaded = 0;

    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(
          open_conglom == null, "load expects container handle to be closed on entry.");
    }

    // The individual rows that are inserted are not logged.  To use a
    // logged interface, use insert.  RESOLVE: do we want to allow client
    // to use the load interface even for logged insert?
    int mode = (ContainerHandle.MODE_FORUPDATE | ContainerHandle.MODE_UNLOGGED);

    // If the container is being created in the same operation, don't log
    // page allocation.
    if (createConglom) mode |= ContainerHandle.MODE_CREATE_UNLOGGED;

    OpenConglomerate open_conglom = new OpenHeap();

    if (open_conglom.init(
            (ContainerHandle) null,
            heap,
            heap.format_ids,
            heap.collation_ids,
            xact_manager,
            xact_manager.getRawStoreXact(),
            false,
            mode,
            TransactionController.MODE_TABLE,
            xact_manager
                .getRawStoreXact()
                .newLockingPolicy(
                    LockingPolicy.MODE_CONTAINER,
                    TransactionController.ISOLATION_SERIALIZABLE,
                    true),
            (DynamicCompiledOpenConglomInfo) null)
        == null) {
      throw StandardException.newException(
          SQLState.HEAP_CONTAINER_NOT_FOUND, new Long(heap.getId().getContainerId()));
    }

    this.init(open_conglom);

    // For bulk loading, we always use only brand new page because the row
    // insertion itself is not logged.  We cannot pollute pages with
    // pre-existing data with unlogged rows because nobody is going to wipe
    // out these rows if the transaction rolls back.  We are counting on
    // the allocation page rollback to obliterate these rows if the
    // transaction fails, or, in the CREAT_UNLOGGED case, the whole
    // container to be removed.

    Page page = open_conglom.getContainer().addPage();

    boolean callbackWithRowLocation = rowSource.needsRowLocation();
    RecordHandle rh;
    HeapRowLocation rowlocation;

    if (callbackWithRowLocation) rowlocation = new HeapRowLocation();
    else rowlocation = null;

    FormatableBitSet validColumns = rowSource.getValidColumns();

    try {
      // get the next row and its valid columns from the rowSource
      DataValueDescriptor[] row;
      while ((row = rowSource.getNextRowFromRowSource()) != null) {
        num_rows_loaded++;

        if (SanityManager.DEBUG) {
          // Make sure valid columns are in the list.  The RowUtil
          // call is too expensive to make in a released system for
          // every insert.
          int invalidColumn = RowUtil.columnOutOfRange(row, validColumns, heap.format_ids.length);

          if (invalidColumn >= 0) {
            throw (StandardException.newException(
                SQLState.HEAP_TEMPLATE_MISMATCH,
                new Long(invalidColumn),
                new Long(heap.format_ids.length)));
          }
        }

        // Insert it onto this page as long as it can fit more rows.
        if ((rh =
                page.insert(
                    row,
                    validColumns,
                    Page.INSERT_DEFAULT,
                    AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD))
            == null) {
          // Insert faied, row did not fit.  Get a new page.

          page.unlatch();
          page = null;

          page = open_conglom.getContainer().addPage();

          // RESOLVE (mikem) - no long rows yet so the following code
          // will get an exception from the raw store for a row that
          // does not fit on a page.
          //
          // Multi-thread considerations aside, the raw store will
          // guarantee that any size row will fit on an empty page.
          rh =
              page.insert(
                  row,
                  validColumns,
                  Page.INSERT_OVERFLOW,
                  AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);
        }

        // Else, the row fit.  If we are expected to call back with the
        // row location, do so.  All the while keep the page latched
        // and go for the next row.
        if (callbackWithRowLocation) {
          rowlocation.setFrom(rh);
          rowSource.rowLocation(rowlocation);
        }
      }
      page.unlatch();
      page = null;

      // Done with the container, now we need to flush it to disk since
      // it is unlogged.
      if (!heap.isTemporary()) open_conglom.getContainer().flushContainer();
    } finally {
      // If an error happened here, don't bother flushing the
      // container since the changes should be rolled back anyhow.
      close();
    }
    return (num_rows_loaded);
  }
Example #9
0
  /**
   * Create an empty secondary index b-tree, using the generic b-tree to do the generic part of the
   * creation process.
   *
   * <p>This routine opens the newly created container, adds a single page, and makes this page the
   * root by inserting a LeafControlRow onto this page at slot 0 and marking in that control row
   * that the page is a root page.
   *
   * <p>The following properties are specific to the b-tree secondary index:
   *
   * <UL>
   *   <LI>"baseConglomerateId" (integer). The conglomerate id of the base conglomerate is never
   *       actually accessed by the b-tree secondary index implementation, it only serves as a
   *       namespace for row locks. This property is required.
   *   <LI>"rowLocationColumn" (integer). The zero-based index into the row which the b-tree
   *       secondary index will assume holds a @see RowLocation of the base row in the base
   *       conglomerate. This value will be used for acquiring locks. In this implementation
   *       RowLocationColumn must be the last key column. This property is required.
   * </UL>
   *
   * A secondary index i (a, b) on table t (a, b, c) would have rows which looked like (a, b,
   * row_location). baseConglomerateId is set to the conglomerate id of t. rowLocationColumns is set
   * to 2. allowsDuplicates would be set to false, @see BTree#create. To create a unique secondary
   * index set uniquenessColumns to 2, this means that the btree code will compare the key values
   * but not the row id when determing uniqueness. To create a nonunique secondary index set
   * uniquenessColumns to 3, this would mean that the uniqueness test would include the row location
   * and since all row locations will be unique all rows inserted into the index will be
   * differentiated (at least) by row location.
   *
   * @see BTree#create
   * @exception StandardException Standard exception policy.
   */
  public void create(
      TransactionManager xact_manager,
      int segmentId,
      long input_conglomid,
      DataValueDescriptor[] template,
      ColumnOrdering[] columnOrder,
      int[] collationIds,
      Properties properties,
      int temporaryFlag)
      throws StandardException {
    String property_value = null;
    Transaction rawtran = xact_manager.getRawStoreXact();

    if (properties == null) {
      throw (StandardException.newException(
          SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
    }

    // Get baseConglomerateId //
    property_value = properties.getProperty(PROPERTY_BASECONGLOMID);
    if (property_value == null) {
      throw (StandardException.newException(
          SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
    }

    if (SanityManager.DEBUG) {
      if (property_value == null)
        SanityManager.THROWASSERT(PROPERTY_BASECONGLOMID + "property not passed to B2I.create()");
    }

    baseConglomerateId = Long.parseLong(property_value);

    // Get rowLocationColumn //
    property_value = properties.getProperty(PROPERTY_ROWLOCCOLUMN);

    if (SanityManager.DEBUG) {
      if (property_value == null)
        SanityManager.THROWASSERT(PROPERTY_ROWLOCCOLUMN + "property not passed to B2I.create()");
    }

    if (property_value == null) {
      throw (StandardException.newException(
          SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));
    }

    rowLocationColumn = Integer.parseInt(property_value);

    // Currently the row location column must be the last column (makes)
    // comparing the columns in the index easier.
    if (SanityManager.DEBUG) {
      SanityManager.ASSERT(
          rowLocationColumn == template.length - 1,
          "rowLocationColumn is not the last column in the index");
      SanityManager.ASSERT(template[rowLocationColumn] instanceof RowLocation);

      // There must be at least one key column
      if (rowLocationColumn < 1)
        SanityManager.THROWASSERT(
            "rowLocationColumn (" + rowLocationColumn + ") expected to be >= 1");
    }

    /* convert the sorting order information into a boolean array map.
     * If the sorting order for the columns is not provided, we
     * assign the default as Ascending Order.
     * array length is equal to template length, because column order
     * length changes whether it is unique or is non unique. store assumes
     * template length arrays. So, we make template length array and make
     * the last column as ascending instead of having lot of execeptions
     * code.
     */

    ascDescInfo = new boolean[template.length];
    for (int i = 0; i < ascDescInfo.length; i++) {
      if (columnOrder != null && i < columnOrder.length)
        ascDescInfo[i] = columnOrder[i].getIsAscending();
      else ascDescInfo[i] = true; // default values - ascending order
    }

    // get collation ids from input collation ids, store it in the
    // conglom state.
    collation_ids = ConglomerateUtil.createCollationIds(template.length, collationIds);
    hasCollatedTypes = hasCollatedColumns(collation_ids);

    // Do the generic part of creating the b-tree.
    super.create(
        rawtran,
        segmentId,
        input_conglomid,
        template,
        properties,
        getTypeFormatId(),
        temporaryFlag);

    // open the base conglomerate - to get the lock
    ConglomerateController base_cc =
        xact_manager.openConglomerate(
            baseConglomerateId,
            false,
            TransactionController.OPENMODE_FOR_LOCK_ONLY,
            TransactionController.MODE_TABLE,
            TransactionController.ISOLATION_SERIALIZABLE);

    OpenBTree open_btree = new OpenBTree();

    BTreeLockingPolicy b2i_locking_policy =
        new B2ITableLocking3(
            rawtran,
            TransactionController.MODE_TABLE,
            rawtran.newLockingPolicy(
                LockingPolicy.MODE_CONTAINER, TransactionController.ISOLATION_SERIALIZABLE, true),
            base_cc,
            open_btree);

    // The following call will "open" the new btree.  Create is
    // an interesting case.  What we really want is read only table lock
    // on the base conglomerate and update locks on the index.  For now
    // just get the update lock on the base table, this is done by the
    // lockTable() call made by base class.

    open_btree.init(
        (TransactionManager) xact_manager, // current user xact
        (TransactionManager) xact_manager, // current xact
        (ContainerHandle) null, // have init open the container.
        rawtran,
        false,
        (ContainerHandle.MODE_FORUPDATE),
        TransactionController.MODE_TABLE,
        b2i_locking_policy, // get table level lock.
        this,
        (LogicalUndo) null, // no logical undo necessary, as
        // initEmptyBtree()
        // work will be done single user and
        // rows will not move.
        (DynamicCompiledOpenConglomInfo) null);

    // Open the newly created container, and insert the first control row.
    LeafControlRow.initEmptyBtree(open_btree);

    open_btree.close();

    base_cc.close();
  }