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;
  }
 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);
 }