public void remove(Session session) {
   if (trace.isDebugEnabled()) {
     trace.debug("{0} remove", this);
   }
   removeAllRows();
   store.free(rootPageId);
   store.removeMeta(this, session);
 }
 private void removeAllRows() {
   try {
     PageData root = getPage(rootPageId, 0);
     root.freeRecursive();
     root = PageDataLeaf.create(this, rootPageId, PageData.ROOT);
     store.removeRecord(rootPageId);
     store.update(root);
     rowCount = 0;
     lastKey = 0;
   } finally {
     store.incrementChangeCount();
   }
 }
 /**
  * Read an overflow page page.
  *
  * @param id the page id
  * @return the page
  */
 PageDataOverflow getPageOverflow(int id) {
   Page p = store.getPage(id);
   if (p instanceof PageDataOverflow) {
     return (PageDataOverflow) p;
   }
   throw DbException.get(ErrorCode.FILE_CORRUPTED_1, p == null ? "null" : p.toString());
 }
 /**
  * Read the given page.
  *
  * @param id the page id
  * @param parent the parent, or -1 if unknown
  * @return the page
  */
 PageData getPage(int id, int parent) {
   Page pd = store.getPage(id);
   if (pd == null) {
     PageDataLeaf empty = PageDataLeaf.create(this, id, parent);
     // could have been created before, but never committed
     store.logUndo(empty, null);
     store.update(empty);
     return empty;
   } else if (!(pd instanceof PageData)) {
     throw DbException.get(ErrorCode.FILE_CORRUPTED_1, "" + pd);
   }
   PageData p = (PageData) pd;
   if (parent != -1) {
     if (p.getParentPageId() != parent) {
       throw DbException.throwInternalError(
           p + " parent " + p.getParentPageId() + " expected " + parent);
     }
   }
   return p;
 }
 public void writeRowCount() {
   if (SysProperties.MODIFY_ON_WRITE && rootPageId == 0) {
     // currently creating the index
     return;
   }
   try {
     PageData root = getPage(rootPageId, 0);
     root.setRowCountStored(MathUtils.convertLongToInt(rowCount));
   } finally {
     store.incrementChangeCount();
   }
 }
 public void add(Session session, Row row) {
   boolean retry = false;
   if (mainIndexColumn != -1) {
     row.setKey(row.getValue(mainIndexColumn).getLong());
   } else {
     if (row.getKey() == 0) {
       row.setKey((int) ++lastKey);
       retry = true;
     }
   }
   if (tableData.getContainsLargeObject()) {
     for (int i = 0, len = row.getColumnCount(); i < len; i++) {
       Value v = row.getValue(i);
       Value v2 = v.link(database, getId());
       if (v2.isLinked()) {
         session.unlinkAtCommitStop(v2);
       }
       if (v != v2) {
         row.setValue(i, v2);
       }
     }
   }
   // when using auto-generated values, it's possible that multiple
   // tries are required (specially if there was originally a primary key)
   if (trace.isDebugEnabled()) {
     trace.debug("{0} add {1}", getName(), row);
   }
   long add = 0;
   while (true) {
     try {
       addTry(session, row);
       break;
     } catch (DbException e) {
       if (e != fastDuplicateKeyException) {
         throw e;
       }
       if (!retry) {
         throw getNewDuplicateKeyException();
       }
       if (add == 0) {
         // in the first re-try add a small random number,
         // to avoid collisions after a re-start
         row.setKey((long) (row.getKey() + Math.random() * 10000));
       } else {
         row.setKey(row.getKey() + add);
       }
       add++;
     } finally {
       store.incrementChangeCount();
     }
   }
   lastKey = Math.max(lastKey, row.getKey());
 }
 public void remove(Session session, Row row) {
   if (tableData.getContainsLargeObject()) {
     for (int i = 0, len = row.getColumnCount(); i < len; i++) {
       Value v = row.getValue(i);
       if (v.isLinked()) {
         session.unlinkAtCommit(v);
       }
     }
   }
   if (trace.isDebugEnabled()) {
     trace.debug("{0} remove {1}", getName(), row);
   }
   if (rowCount == 1) {
     removeAllRows();
   } else {
     try {
       long key = row.getKey();
       PageData root = getPage(rootPageId, 0);
       root.remove(key);
       invalidateRowCount();
       rowCount--;
     } finally {
       store.incrementChangeCount();
     }
   }
   if (multiVersion) {
     // if storage is null, the delete flag is not yet set
     row.setDeleted(true);
     if (delta == null) {
       delta = New.hashSet();
     }
     boolean wasAdded = delta.remove(row);
     if (!wasAdded) {
       delta.add(row);
     }
     incrementRowCount(session.getId(), -1);
   }
   store.logAddOrRemoveRow(session, tableData.getId(), row, false);
 }
 private void addTry(Session session, Row row) {
   while (true) {
     PageData root = getPage(rootPageId, 0);
     int splitPoint = root.addRowTry(row);
     if (splitPoint == -1) {
       break;
     }
     if (trace.isDebugEnabled()) {
       trace.debug("{0} split", this);
     }
     long pivot = splitPoint == 0 ? row.getKey() : root.getKey(splitPoint - 1);
     PageData page1 = root;
     PageData page2 = root.split(splitPoint);
     int id = store.allocatePage();
     page1.setPageId(id);
     page1.setParentPageId(rootPageId);
     page2.setParentPageId(rootPageId);
     PageDataNode newRoot = PageDataNode.create(this, rootPageId, PageData.ROOT);
     newRoot.init(page1, pivot, page2);
     store.update(page1);
     store.update(page2);
     store.update(newRoot);
     root = newRoot;
   }
   row.setDeleted(false);
   if (multiVersion) {
     if (delta == null) {
       delta = New.hashSet();
     }
     boolean wasDeleted = delta.remove(row);
     if (!wasDeleted) {
       delta.add(row);
     }
     incrementRowCount(session.getId(), 1);
   }
   invalidateRowCount();
   rowCount++;
   store.logAddOrRemoveRow(session, tableData.getId(), row, true);
 }
 public void truncate(Session session) {
   if (trace.isDebugEnabled()) {
     trace.debug("{0} truncate", this);
   }
   store.logTruncate(session, tableData.getId());
   removeAllRows();
   if (tableData.getContainsLargeObject() && tableData.isPersistData()) {
     // unfortunately, the data is gone on rollback
     session.commit(false);
     database.getLobStorage().removeAllForTable(table.getId());
   }
   if (multiVersion) {
     sessionRowCount.clear();
   }
   tableData.setRowCount(0);
 }
  public PageDataIndex(
      RegularTable table,
      int id,
      IndexColumn[] columns,
      IndexType indexType,
      boolean create,
      Session session) {
    initBaseIndex(table, id, table.getName() + "_DATA", columns, indexType);
    RegularDatabase database = (RegularDatabase) this.database;
    this.multiVersion = database.isMultiVersion();

    // trace = database.getTrace(Trace.PAGE_STORE + "_di");
    // trace.setLevel(TraceSystem.DEBUG);
    if (multiVersion) {
      sessionRowCount = New.hashMap();
      isMultiVersion = true;
    } else {
      sessionRowCount = null;
    }
    tableData = table;
    this.store = database.getPageStore();
    store.addIndex(this);
    if (!database.isPersistent()) {
      throw DbException.throwInternalError(table.getName());
    }
    if (create) {
      rootPageId = store.allocatePage();
      store.addMeta(this, session);
      PageDataLeaf root = PageDataLeaf.create(this, rootPageId, PageData.ROOT);
      store.update(root);
    } else {
      rootPageId = store.getRootPageId(id);
      PageData root = getPage(rootPageId, 0);
      lastKey = root.getLastKey();
      rowCount = root.getRowCount();
    }
    if (trace.isDebugEnabled()) {
      trace.debug("{0} opened rows: {1}", this, rowCount);
    }
    table.setRowCount(rowCount);
    memoryPerPage = (Constants.MEMORY_PAGE_DATA + store.getPageSize()) >> 2;
  }
 /**
  * The root page has changed.
  *
  * @param session the session
  * @param newPos the new position
  */
 void setRootPageId(Session session, int newPos) {
   store.removeMeta(this, session);
   this.rootPageId = newPos;
   store.addMeta(this, session);
   store.addIndex(this);
 }