@Override
  public long[] indexRetrieval(Object key, TitanKey pt, InternalTitanTransaction tx) {
    Preconditions.checkArgument(
        pt.isSimple(), "Currently, only simple properties are supported for index retrieval");
    Preconditions.checkArgument(
        pt.hasIndex(), "Cannot retrieve for given property key - it does not have an index");

    long[] vertices = null;

    Preconditions.checkArgument(
        pt.getDataType().isInstance(key),
        "Specified object is incompatible with property data type [" + pt.getName() + "]");

    for (int readAttempt = 0; readAttempt < maxReadRetryAttempts; readAttempt++) {
      try {
        if (pt.isUnique()) {
          ByteBuffer value =
              propertyIndex.get(getIndexKey(key), getKeyedIndexColumn(pt), tx.getTxHandle());
          if (value != null) {
            vertices = new long[1];
            vertices[0] = VariableLong.readPositive(value);
          }
        } else {
          ByteBuffer startColumn = VariableLong.positiveByteBuffer(pt.getID());
          List<Entry> entries =
              propertyIndex.getSlice(
                  getIndexKey(key),
                  startColumn,
                  ByteBufferUtil.nextBiggerBuffer(startColumn),
                  tx.getTxHandle());
          vertices = new long[entries.size()];
          int i = 0;
          for (Entry ent : entries) {
            vertices[i++] = VariableLong.readPositive(ent.getValue());
          }
        }

        break;
      } catch (StorageException e) {
        if (e instanceof TemporaryStorageException) {
          if (readAttempt < maxReadRetryAttempts - 1) temporaryStorageException(e);
          else throw readException(e, maxReadRetryAttempts);
        } else throw readException(e);
      }
    }

    if (vertices == null) return new long[0];
    else return vertices;
  }
  private List<Entry> appendResults(
      ByteBuffer key,
      ByteBuffer columnStart,
      ByteBuffer columnEnd,
      List<Entry> entries,
      LimitTracker limit,
      TransactionHandle txh) {
    if (limit.limitExhausted()) return null;
    List<Entry> results = null;

    for (int readAttempt = 0; readAttempt < maxReadRetryAttempts; readAttempt++) {
      try {
        results = edgeStore.getSlice(key, columnStart, columnEnd, limit.getLimit(), txh);
        break;
      } catch (StorageException e) {
        if (e instanceof TemporaryStorageException) {
          if (readAttempt < maxReadRetryAttempts - 1) temporaryStorageException(e);
          else throw readException(e, maxReadRetryAttempts);
        } else throw readException(e);
      }
    }

    limit.retrieved(results.size());

    if (entries == null) return results;
    else {
      entries.addAll(results);
      return entries;
    }
  }
  @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;
  }
  @Override
  public boolean containsVertexID(long id, InternalTitanTransaction tx) {
    log.trace("Checking node existence for {}", id);

    for (int readAttempt = 0; readAttempt < maxReadRetryAttempts; readAttempt++) {
      try {
        return edgeStore.containsKey(IDHandler.getKey(id), tx.getTxHandle());
      } catch (StorageException e) {
        if (e instanceof TemporaryStorageException) {
          if (readAttempt < maxReadRetryAttempts - 1) temporaryStorageException(e);
          else throw readException(e, maxReadRetryAttempts);
        } else throw readException(e);
      }
    }
    throw new AssertionError("Illegal program state");
  }