Ejemplo n.º 1
0
  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);
  }
Ejemplo n.º 2
0
  /**
   * Insert a new row into the heap.
   *
   * <p>Overflow policy: The current heap access method implements an algorithm that optimizes for
   * fetch efficiency vs. space efficiency. A row will not be over flowed unless it is bigger than a
   * page. If it is bigger than a page then it's initial part will be placed on a page and then
   * subsequent parts will be overflowed to other pages.
   *
   * <p>
   *
   * @return The record handle of the inserted row.
   * @param row The row to insert.
   * @exception StandardException Standard exception policy.
   */
  private RecordHandle doInsert(DataValueDescriptor[] row) throws StandardException {
    Page page = null;
    byte insert_mode;

    RecordHandle rh;

    if (SanityManager.DEBUG) {
      Heap heap = (Heap) open_conglom.getConglomerate();
      // 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, null, heap.format_ids.length);

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

    // Get the last page that was returned for insert or the last page
    // that was allocated.
    page = open_conglom.getContainer().getPageForInsert(0);

    if (page != null) {

      // if there are 0 rows on the page allow the insert to overflow.
      insert_mode = (page.recordCount() == 0) ? Page.INSERT_OVERFLOW : Page.INSERT_DEFAULT;

      // Check to see if there is enough space on the page
      // for the row.
      rh = page.insert(row, null, insert_mode, AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);
      page.unlatch();
      page = null;

      // If we have found a page with enough space for the row,
      // insert it and release exclusive access to the page.
      if (rh != null) {
        return rh;
      }
    }

    // If the last inserted page is now full, or RawStore have
    // forgotten what it was, or the row cannot fit on the last
    // inserted page, try to have rawStore get a relatively unfilled
    // page.

    page = open_conglom.getContainer().getPageForInsert(ContainerHandle.GET_PAGE_UNFILLED);

    if (page != null) {
      // Do the insert all over again hoping that it will fit into
      // this page, and if not, allocate a new page.

      // if there are 0 rows on the page allow the insert to overflow.
      insert_mode = (page.recordCount() == 0) ? Page.INSERT_OVERFLOW : Page.INSERT_DEFAULT;

      rh = page.insert(row, null, insert_mode, AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);

      page.unlatch();
      page = null;

      // If we have found a page with enough space for the row,
      // insert it and release exclusive access to the page.
      if (rh != null) {
        return rh;
      }
    }

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

    // At this point with long rows the raw store will guarantee
    // that any size row will fit on an empty page.

    rh = page.insert(row, null, Page.INSERT_OVERFLOW, AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);
    page.unlatch();
    page = null;

    if (SanityManager.DEBUG) {
      // a null will only be returned if this page is not empty
      SanityManager.ASSERT(rh != null);
    }

    return rh;
  }