@Test
  public void getSliceRespectsAllBoundsInclusionArguments() throws Exception {
    // Test case where endColumn=startColumn+1
    ByteBuffer key = KeyColumnValueStoreUtil.longToByteBuffer(0);
    ByteBuffer columnBeforeStart = KeyColumnValueStoreUtil.longToByteBuffer(776);
    ByteBuffer columnStart = KeyColumnValueStoreUtil.longToByteBuffer(777);
    ByteBuffer columnEnd = KeyColumnValueStoreUtil.longToByteBuffer(778);
    ByteBuffer columnAfterEnd = KeyColumnValueStoreUtil.longToByteBuffer(779);

    // First insert four test Entries
    TransactionHandle txn = manager.beginTransaction();
    List<Entry> entries =
        Arrays.asList(
            new Entry(columnBeforeStart, columnBeforeStart),
            new Entry(columnStart, columnStart),
            new Entry(columnEnd, columnEnd),
            new Entry(columnAfterEnd, columnAfterEnd));
    store.mutate(key, entries, null, txn);
    txn.commit();

    // getSlice() with only start inclusive
    txn = manager.beginTransaction();
    List<Entry> result = store.getSlice(key, columnStart, columnEnd, txn);
    assertEquals(1, result.size());
    assertEquals(777, result.get(0).getColumn().getLong());
    txn.commit();
  }
  // Inherit interface docs.
  @Override
  public void closeTable(TableInfo tableInfo) throws IOException {
    // Remove this table from the cache since it's about to be closed.
    openTables.remove(tableInfo.getTableName());

    DBFile dbFile = tableInfo.getTupleFile().getDBFile();

    // Flush all open pages for the table.
    storageManager.getBufferManager().flushDBFile(dbFile);
    storageManager.getFileManager().closeDBFile(dbFile);
  }
  @Test
  public void containsKeyColumnReturnsTrueOnExtantInput() throws Exception {
    TransactionHandle txn = manager.beginTransaction();
    KeyColumnValueStoreUtil.insert(store, txn, 1, "c", "v");
    txn.commit();

    txn = manager.beginTransaction();
    ByteBuffer key1 = KeyColumnValueStoreUtil.longToByteBuffer(1);
    ByteBuffer c = KeyColumnValueStoreUtil.stringToByteBuffer("c");
    assertTrue(store.containsKeyColumn(key1.duplicate(), c.duplicate(), txn));
    txn.commit();
  }
 @Test
 public void containsKeyReturnsFalseOnNonexistentKey() throws Exception {
   TransactionHandle txn = manager.beginTransaction();
   ByteBuffer key1 = KeyColumnValueStoreUtil.longToByteBuffer(1);
   assertFalse(store.containsKey(key1.duplicate(), txn));
   txn.commit();
 }
  // Inherit interface docs.
  @Override
  public boolean tableExists(String tableName) throws IOException {
    String tblFileName = getTableFileName(tableName);
    FileManager fileManager = storageManager.getFileManager();

    return fileManager.fileExists(tblFileName);
  }
 @Test
 public void getNonExistentKeyReturnsNull() throws Exception {
   TransactionHandle txn = manager.beginTransaction();
   assertEquals(null, KeyColumnValueStoreUtil.get(store, txn, 0, "col0"));
   assertEquals(null, KeyColumnValueStoreUtil.get(store, txn, 0, "col1"));
   txn.commit();
 }
 @Override
 public InternalTitanTransaction startTransaction(TransactionConfig configuration) {
   try {
     return new StandardPersistTitanTx(this, etManager, configuration, storage.beginTransaction());
   } catch (StorageException e) {
     throw new TitanException("Could not start new transaction", e);
   }
 }
  @Test
  public void insertingGettingAndDeletingSimpleDataWorks() throws Exception {
    TransactionHandle txn = manager.beginTransaction();
    KeyColumnValueStoreUtil.insert(store, txn, 0, "col0", "val0");
    KeyColumnValueStoreUtil.insert(store, txn, 0, "col1", "val1");
    txn.commit();

    txn = manager.beginTransaction();
    assertEquals("val0", KeyColumnValueStoreUtil.get(store, txn, 0, "col0"));
    assertEquals("val1", KeyColumnValueStoreUtil.get(store, txn, 0, "col1"));
    KeyColumnValueStoreUtil.delete(store, txn, 0, "col0");
    KeyColumnValueStoreUtil.delete(store, txn, 0, "col1");
    txn.commit();

    txn = manager.beginTransaction();
    assertEquals(null, KeyColumnValueStoreUtil.get(store, txn, 0, "col0"));
    assertEquals(null, KeyColumnValueStoreUtil.get(store, txn, 0, "col1"));
    txn.commit();
  }
  @Test
  public void getSliceRespectsColumnLimit() throws Exception {
    TransactionHandle txn = manager.beginTransaction();
    ByteBuffer key = KeyColumnValueStoreUtil.longToByteBuffer(0);

    final int cols = 1024;

    List<Entry> entries = new LinkedList<Entry>();
    for (int i = 0; i < cols; i++) {
      ByteBuffer col = KeyColumnValueStoreUtil.longToByteBuffer(i);
      entries.add(new Entry(col, col));
    }
    store.mutate(key, entries, null, txn);
    txn.commit();

    txn = manager.beginTransaction();
    ByteBuffer columnStart = KeyColumnValueStoreUtil.longToByteBuffer(0);
    ByteBuffer columnEnd = KeyColumnValueStoreUtil.longToByteBuffer(cols);
    /*
     * When limit is greater than or equal to the matching column count,
     * all matching columns must be returned.
     */
    List<Entry> result = store.getSlice(key, columnStart, columnEnd, cols, txn);
    assertEquals(cols, result.size());
    assertEquals(entries, result);
    result = store.getSlice(key, columnStart, columnEnd, cols + 10, txn);
    assertEquals(cols, result.size());
    assertEquals(entries, result);

    /*
     * When limit is less the matching column count, the columns up to the
     * limit (ordered bytewise) must be returned.
     */
    result = store.getSlice(key, columnStart, columnEnd, cols - 1, txn);
    assertEquals(cols - 1, result.size());
    entries.remove(entries.size() - 1);
    assertEquals(entries, result);
    result = store.getSlice(key, columnStart, columnEnd, 1, txn);
    assertEquals(1, result.size());
    List<Entry> firstEntrySingleton = Arrays.asList(entries.get(0));
    assertEquals(firstEntrySingleton, result);
    txn.commit();
  }
  // Inherit interface docs.
  @Override
  public void dropTable(String tableName) throws IOException {
    TableInfo tableInfo = openTable(tableName);

    if (StorageManager.ENABLE_INDEXES) dropTableIndexes(tableInfo);

    // Close the table.  This will purge out all dirty pages for the table
    // as well.
    closeTable(tableInfo);

    String tblFileName = getTableFileName(tableName);
    storageManager.getFileManager().deleteDBFile(tblFileName);
  }
  @Override
  public synchronized void shutdown() throws TitanException {
    if (!isOpen) return;
    super.shutdown();
    etManager.close();
    idAssigner.close();

    try {
      edgeStore.close();
      propertyIndex.close();
      storage.close();
    } catch (StorageException e) {
      throw new TitanException("Could not close storage backend", e);
    }
    isOpen = false;
  }
  // Inherit interface docs.
  @Override
  public TableInfo openTable(String tableName) throws IOException {
    TableInfo tableInfo;

    // If the table is already open, just return the cached information.
    tableInfo = openTables.get(tableName);
    if (tableInfo != null) return tableInfo;

    // Open the data file for the table; read out its type and page-size.

    String tblFileName = getTableFileName(tableName);
    TupleFile tupleFile = storageManager.openTupleFile(tblFileName);
    tableInfo = new TableInfo(tableName, tupleFile);

    // Cache this table since it's now considered "open".
    openTables.put(tableName, tableInfo);

    return tableInfo;
  }
  // Inherit interface docs.
  @Override
  public TableInfo createTable(String tableName, TableSchema schema, CommandProperties properties)
      throws IOException {

    int pageSize = StorageManager.getCurrentPageSize();
    String storageType = "heap";
    ArrayList<Integer> hashColumns = new ArrayList<Integer>();

    if (properties != null) {
      logger.info("Using command properties " + properties);

      pageSize = properties.getInt("pagesize", pageSize);
      storageType = properties.getString("storage", storageType);

      String hashString = properties.getString("hashkey", null);
      if (hashString != null) {
        List<String> hashList = Arrays.asList(hashString.split("\\s*,\\s*"));
        for (String s : hashList) {
          hashColumns.add(Integer.valueOf(s));
        }
      }

      HashSet<String> names = new HashSet<String>(properties.getNames());
      names.remove("pagesize");
      names.remove("storage");
      names.remove("hashkey");
      if (!names.isEmpty()) {
        throw new IllegalArgumentException(
            "Unrecognized property " + "name(s) specified:  " + names);
      }
    }

    String tblFileName = getTableFileName(tableName);

    DBFileType type;
    if ("heap".equals(storageType)) {
      type = DBFileType.HEAP_TUPLE_FILE;
    } else if ("btree".equals(storageType)) {
      type = DBFileType.BTREE_TUPLE_FILE;
    } else if ("lin-hash".equals(storageType)) {
      type = DBFileType.LINEAR_HASH_FILE;
      if (hashColumns.isEmpty()) {
        throw new IllegalArgumentException("Hash storage must specify a key!");
      }
    } else {
      throw new IllegalArgumentException("Unrecognized table file " + "type:  " + storageType);
    }
    TupleFileManager tupleFileManager = storageManager.getTupleFileManager(type);

    // First, create a new DBFile that the tuple file will go into.
    FileManager fileManager = storageManager.getFileManager();
    DBFile dbFile = fileManager.createDBFile(tblFileName, type, pageSize);
    logger.debug("Created new DBFile for table " + tableName + " at path " + dbFile.getDataFile());

    // Now, initialize it to be a tuple file with the specified type and
    // schema.
    TupleFile tupleFile;

    if (type == DBFileType.LINEAR_HASH_FILE) {
      DBFile overflow =
          fileManager.createDBFile("ovflw_" + tblFileName, DBFileType.OVERFLOW_FILE, pageSize);

      HashTupleFileManager hashManager = (HashTupleFileManager) tupleFileManager;
      tupleFile = hashManager.createTupleFile(dbFile, schema, hashColumns, overflow);
    } else {
      tupleFile = tupleFileManager.createTupleFile(dbFile, schema);
    }

    // Cache this table since it's now considered "open".
    TableInfo tableInfo = new TableInfo(tableName, tupleFile);
    openTables.put(tableName, tableInfo);

    return tableInfo;
  }
 public void open() {
   manager = openStorageManager();
   tx = manager.beginTransaction();
   store = manager.openDatabase(storeName);
 }
  private void dropTableIndexes(TableInfo tableInfo) throws IOException {
    String tableName = tableInfo.getTableName();

    // We need to open the table so that we can drop all related objects,
    // such as indexes on the table, etc.
    TableSchema schema = tableInfo.getTupleFile().getSchema();

    // Check whether this table is referenced by any other tables via
    // foreign keys.  Need to check the primary key and candidate keys.

    KeyColumnRefs pk = schema.getPrimaryKey();
    if (pk != null && !pk.getReferencingIndexes().isEmpty()) {
      throw new IOException(
          "Drop table failed due to the table" + " having foreign key dependencies:  " + tableName);
    }

    List<KeyColumnRefs> candKeyList = schema.getCandidateKeys();
    for (KeyColumnRefs candKey : candKeyList) {
      if (!candKey.getReferencingIndexes().isEmpty()) {
        throw new IOException(
            "Drop table failed due to the table"
                + " having foreign key dependencies:  "
                + tableName);
      }
    }

    // If we got here, the table being dropped is not a referenced table.
    // Start cleaning up various schema objects for the table.

    List<KeyColumnRefs> parentCandKeyList;
    TableInfo parentTableInfo;
    // Now drop the foreign key constraint fields that this table
    // may have on other parent tables. Scan through this table's
    // Foreign key indexes to see which tables need maintenance
    List<ForeignKeyColumnRefs> forKeyList = schema.getForeignKeys();
    for (ForeignKeyColumnRefs forKey : forKeyList) {
      // Open the parent table, and iterate through all of its primary
      // and candidate keys, dropping any foreign key constraints that
      // refer to the child table with tableName
      String parentTableName = forKey.getRefTable();
      try {
        parentTableInfo = openTable(parentTableName);
      } catch (Exception e) {
        throw new IOException(
            "The referenced table, "
                + parentTableName
                + ", which is referenced by "
                + tableName
                + ", does not exist.");
      }

      TableSchema parentSchema = parentTableInfo.getTupleFile().getSchema();
      KeyColumnRefs parentPK = parentSchema.getPrimaryKey();

      if (parentPK != null) {
        parentPK.dropRefToTable(tableName);
      }

      parentCandKeyList = parentSchema.getCandidateKeys();
      for (KeyColumnRefs parentCandKey : parentCandKeyList) {
        parentCandKey.dropRefToTable(tableName);
      }

      // Persist the changes we made to the schema
      saveTableInfo(parentTableInfo);
    }

    // Then drop the indexes since we've checked the constraints

    IndexManager indexManager = storageManager.getIndexManager();
    for (String indexName : schema.getIndexes().keySet())
      indexManager.dropIndex(tableInfo, indexName);
  }
 public void close() {
   if (tx != null) tx.commit();
   store.close();
   manager.close();
 }
 @Override
 public Features getFeatures() {
   return TitanFeatures.getFeatures(getConfiguration(), storage.getFeatures());
 }