Example #1
0
  public Backend(Configuration storageConfig) {
    this.storageConfig = storageConfig;

    storeManager = getStorageManager(storageConfig);
    indexes = getIndexes(storageConfig);
    storeFeatures = storeManager.getFeatures();

    basicMetrics = storageConfig.getBoolean(BASIC_METRICS, BASIC_METRICS_DEFAULT);
    mergeBasicMetrics =
        storageConfig.getBoolean(MERGE_BASIC_METRICS_KEY, MERGE_BASIC_METRICS_DEFAULT);

    int bufferSizeTmp = storageConfig.getInt(BUFFER_SIZE_KEY, BUFFER_SIZE_DEFAULT);
    Preconditions.checkArgument(
        bufferSizeTmp >= 0, "Buffer size must be non-negative (use 0 to disable)");
    if (!storeFeatures.supportsBatchMutation()) {
      bufferSize = 0;
      log.debug("Buffering disabled because backend does not support batch mutations");
    } else bufferSize = bufferSizeTmp;

    writeAttempts = storageConfig.getInt(WRITE_ATTEMPTS_KEY, WRITE_ATTEMPTS_DEFAULT);
    Preconditions.checkArgument(writeAttempts > 0, "Write attempts must be positive");
    readAttempts = storageConfig.getInt(READ_ATTEMPTS_KEY, READ_ATTEMPTS_DEFAULT);
    Preconditions.checkArgument(readAttempts > 0, "Read attempts must be positive");
    persistAttemptWaittime =
        storageConfig.getInt(STORAGE_ATTEMPT_WAITTIME_KEY, STORAGE_ATTEMPT_WAITTIME_DEFAULT);
    Preconditions.checkArgument(
        persistAttemptWaittime > 0, "Persistence attempt retry wait time must be non-negative");

    // If lock prefix is unspecified, specify it now
    storageConfig.setProperty(
        ExpectedValueCheckingStore.LOCAL_LOCK_MEDIATOR_PREFIX_KEY,
        storageConfig.getString(
            ExpectedValueCheckingStore.LOCAL_LOCK_MEDIATOR_PREFIX_KEY, storeManager.getName()));

    final String lockBackendName =
        storageConfig.getString(
            GraphDatabaseConfiguration.LOCK_BACKEND,
            GraphDatabaseConfiguration.LOCK_BACKEND_DEFAULT);
    if (REGISTERED_LOCKERS.containsKey(lockBackendName)) {
      lockerCreator = REGISTERED_LOCKERS.get(lockBackendName);
    } else {
      throw new TitanConfigurationException(
          "Unknown lock backend \""
              + lockBackendName
              + "\".  Known lock backends: "
              + Joiner.on(", ").join(REGISTERED_LOCKERS.keySet())
              + ".");
    }
    // Never used for backends that have innate transaction support, but we
    // want to maintain the non-null invariant regardless; it will default
    // to connsistentkey impl if none is specified
    Preconditions.checkNotNull(lockerCreator);

    if (storeFeatures.isDistributed() && storeFeatures.isKeyOrdered()) {
      log.debug("Wrapping index store with HashPrefix");
      hashPrefixIndex = true;
    } else {
      hashPrefixIndex = false;
    }
  }
 private Log openLog(String logManagerName, String logName) {
   try {
     ModifiableConfiguration configuration =
         new ModifiableConfiguration(
             GraphDatabaseConfiguration.ROOT_NS,
             config.copy(),
             BasicConfiguration.Restriction.NONE);
     configuration.set(GraphDatabaseConfiguration.UNIQUE_INSTANCE_ID, "reader");
     configuration.set(
         GraphDatabaseConfiguration.LOG_READ_INTERVAL, Duration.ofMillis(500L), logManagerName);
     if (logStoreManager == null) {
       logStoreManager = Backend.getStorageManager(configuration);
     }
     StoreFeatures f = logStoreManager.getFeatures();
     boolean part = f.isDistributed() && f.isKeyOrdered();
     if (part) {
       for (String logname : new String[] {USER_LOG, TRANSACTION_LOG, MANAGEMENT_LOG})
         configuration.set(KCVSLogManager.LOG_MAX_PARTITIONS, 8, logname);
     }
     assert logStoreManager != null;
     if (!logManagers.containsKey(logManagerName)) {
       // Open log manager - only supports KCVSLog
       Configuration logConfig = configuration.restrictTo(logManagerName);
       Preconditions.checkArgument(
           logConfig.get(LOG_BACKEND).equals(LOG_BACKEND.getDefaultValue()));
       logManagers.put(logManagerName, new KCVSLogManager(logStoreManager, logConfig));
     }
     assert logManagers.containsKey(logManagerName);
     return logManagers.get(logManagerName).openLog(logName);
   } catch (BackendException e) {
     throw new TitanException("Could not open log: " + logName, e);
   }
 }
Example #3
0
 public BackendTransaction beginTransaction() throws StorageException {
   StoreTransaction tx = storeManager.beginTransaction(ConsistencyLevel.DEFAULT);
   if (bufferSize > 1) {
     assert storeManager.getFeatures().supportsBatchMutation();
     if (isKeyColumnValueStore) {
       assert storeManager instanceof KeyColumnValueStoreManager;
       tx =
           new BufferTransaction(
               tx,
               (KeyColumnValueStoreManager) storeManager,
               bufferSize,
               writeAttempts,
               persistAttemptWaittime);
     } else {
       assert storeManager instanceof KeyValueStoreManager;
       // TODO: support buffer mutations
     }
   }
   if (!storeFeatures.supportsLocking()) {
     if (storeFeatures.isTransactional()) {
       // No transaction wrapping needed
     } else if (storeFeatures.supportsConsistentKeyOperations()) {
       tx =
           new ConsistentKeyLockTransaction(
               tx, storeManager.beginTransaction(ConsistencyLevel.KEY_CONSISTENT));
     }
   }
   return new BackendTransaction(tx);
 }
Example #4
0
 private KeyColumnValueStore getLockStore(KeyColumnValueStore store) throws StorageException {
   if (!storeFeatures.supportsLocking()) {
     if (storeFeatures.isTransactional()) {
       store = new TransactionalLockStore(store);
     } else if (storeFeatures.supportsConsistentKeyOperations()) {
       store =
           new ConsistentKeyLockStore(
               store, getStore(store.getName() + LOCK_STORE_SUFFIX), lockConfiguration);
     } else throw new IllegalArgumentException("Store needs to support some form of locking");
   }
   return store;
 }
  public EntryMetaData[] getMetaDataSchema(String storeName) {
    List<EntryMetaData> schemaBuilder = Lists.newArrayList();
    StoreFeatures features = getFeatures();
    if (features.hasTimestamps() && storageConfig.get(STORE_META_TIMESTAMPS, storeName))
      schemaBuilder.add(EntryMetaData.TIMESTAMP);
    if (features.hasCellTTL() && storageConfig.get(STORE_META_TTL, storeName))
      schemaBuilder.add(EntryMetaData.TTL);
    if (features.hasVisibility() && storageConfig.get(STORE_META_VISIBILITY, storeName))
      schemaBuilder.add(EntryMetaData.VISIBILITY);

    if (schemaBuilder.isEmpty()) return StaticArrayEntry.EMPTY_SCHEMA;
    return schemaBuilder.toArray(new EntryMetaData[schemaBuilder.size()]);
  }
Example #6
0
 private KeyColumnValueStore getLockStore(KeyColumnValueStore store, boolean lockEnabled)
     throws StorageException {
   if (!storeFeatures.supportsLocking()) {
     if (storeFeatures.supportsTransactions()) {
       store = new TransactionalLockStore(store);
     } else if (storeFeatures.supportsConsistentKeyOperations()) {
       if (lockEnabled) {
         final String lockerName = store.getName() + LOCK_STORE_SUFFIX;
         store = new ExpectedValueCheckingStore(store, getLocker(lockerName));
       } else {
         store = new ExpectedValueCheckingStore(store, null);
       }
     } else throw new IllegalArgumentException("Store needs to support some form of locking");
   }
   return store;
 }
 public KeyValueStoreManagerAdapter(
     KeyValueStoreManager manager, Map<String, Integer> keyLengths) {
   this.manager = manager;
   ImmutableMap.Builder<String, Integer> mb = ImmutableMap.builder();
   if (keyLengths != null && !keyLengths.isEmpty()) mb.putAll(keyLengths);
   this.keyLengths = mb.build();
   features = manager.getFeatures().clone();
   features.supportsBatchMutation = false;
 }
Example #8
0
  /**
   * Opens a new transaction against all registered backend system wrapped in one {@link
   * BackendTransaction}.
   *
   * @return
   * @throws StorageException
   */
  public BackendTransaction beginTransaction(TransactionConfiguration configuration)
      throws StorageException {
    StoreTxConfig txConfig = new StoreTxConfig(configuration.getMetricsPrefix());
    if (configuration.hasTimestamp()) txConfig.setTimestamp(configuration.getTimestamp());
    StoreTransaction tx = storeManager.beginTransaction(txConfig);
    if (bufferSize > 1) {
      Preconditions.checkArgument(storeManager.getFeatures().supportsBatchMutation());
      tx =
          new BufferTransaction(
              tx, storeManager, bufferSize, writeAttempts, persistAttemptWaittime);
    }
    if (!storeFeatures.supportsLocking()) {
      if (storeFeatures.supportsTransactions()) {
        // No transaction wrapping needed
      } else if (storeFeatures.supportsConsistentKeyOperations()) {
        txConfig =
            new StoreTxConfig(ConsistencyLevel.KEY_CONSISTENT, configuration.getMetricsPrefix());
        if (configuration.hasTimestamp()) txConfig.setTimestamp(configuration.getTimestamp());
        tx =
            new ExpectedValueCheckingTransaction(
                tx, storeManager.beginTransaction(txConfig), readAttempts);
      }
    }

    // Index transactions
    Map<String, IndexTransaction> indexTx = new HashMap<String, IndexTransaction>(indexes.size());
    for (Map.Entry<String, IndexProvider> entry : indexes.entrySet()) {
      indexTx.put(entry.getKey(), new IndexTransaction(entry.getValue()));
    }

    return new BackendTransaction(
        tx,
        storeManager.getFeatures(),
        edgeStore,
        vertexIndexStore,
        edgeIndexStore,
        readAttempts,
        persistAttemptWaittime,
        indexTx);
  }
Example #9
0
  public void initialize(Configuration config) {
    try {
      // EdgeStore & VertexIndexStore
      KeyColumnValueStore idStore = getStore(ID_STORE_NAME);
      idAuthority = null;
      if (storeFeatures.isTransactional()) {
        idAuthority = new TransactionalIDManager(idStore, storeManager, config);
      } else if (storeFeatures.supportsConsistentKeyOperations()) {
        idAuthority = new ConsistentKeyIDManager(idStore, storeManager, config);
      } else {
        idAuthority = new TransactionalIDManager(idStore, storeManager, config);
        log.error(
            "Store needs to support consistent key or transactional operations for ID manager to guarantee proper id allocations");
      }
      edgeStore = getLockStore(getBufferStore(EDGESTORE_NAME));
      vertexIndexStore = getLockStore(getBufferStore(VERTEXINDEX_STORE_NAME));

      if (hashPrefixIndex)
        vertexIndexStore = new HashPrefixKeyColumnValueStore(vertexIndexStore, 4);
    } catch (StorageException e) {
      throw new TitanException("Could not initialize backend", e);
    }
  }
Example #10
0
  public HBaseStoreManager(org.apache.commons.configuration.Configuration config)
      throws StorageException {
    super(config, PORT_DEFAULT);

    this.tableName = config.getString(TABLE_NAME_KEY, TABLE_NAME_DEFAULT);

    this.hconf = HBaseConfiguration.create();
    for (Map.Entry<String, String> confEntry : HBASE_CONFIGURATION.entrySet()) {
      if (config.containsKey(confEntry.getKey())) {
        hconf.set(confEntry.getValue(), config.getString(confEntry.getKey()));
      }
    }

    // Copy a subset of our commons config into a Hadoop config
    org.apache.commons.configuration.Configuration hbCommons =
        config.subset(HBASE_CONFIGURATION_NAMESPACE);

    @SuppressWarnings("unchecked") // I hope commons-config eventually fixes this
    Iterator<String> keys = hbCommons.getKeys();
    int keysLoaded = 0;

    while (keys.hasNext()) {
      String key = keys.next();
      String value = hbCommons.getString(key);
      logger.debug("HBase configuration: setting {}={}", key, value);
      hconf.set(key, value);
      keysLoaded++;
    }

    logger.debug("HBase configuration: set a total of {} configuration values", keysLoaded);

    connectionPool = new HTablePool(hconf, connectionPoolSize);

    openStores = new ConcurrentHashMap<String, HBaseKeyColumnValueStore>();

    // TODO: allowing publicly mutate fields is bad, should be fixed
    features = new StoreFeatures();
    features.supportsScan = true;
    features.supportsBatchMutation = true;
    features.supportsTransactions = false;
    features.supportsConsistentKeyOperations = true;
    features.supportsLocking = false;
    features.isKeyOrdered = false;
    features.isDistributed = true;
    features.hasLocalKeyPartition = false;
  }
Example #11
0
  public Backend(Configuration storageConfig) {
    storeManager = getStorageManager(storageConfig);
    isKeyColumnValueStore = storeManager instanceof KeyColumnValueStoreManager;
    storeFeatures = storeManager.getFeatures();

    int bufferSizeTmp = storageConfig.getInt(BUFFER_SIZE_KEY, BUFFER_SIZE_DEFAULT);
    Preconditions.checkArgument(
        bufferSizeTmp >= 0, "Buffer size must be non-negative (use 0 to disable)");
    if (!storeFeatures.supportsBatchMutation()) {
      bufferSize = 0;
      log.debug("Buffering disabled because backend does not support batch mutations");
    } else bufferSize = bufferSizeTmp;

    if (!storeFeatures.supportsLocking() && storeFeatures.supportsConsistentKeyOperations()) {
      lockConfiguration =
          new ConsistentKeyLockConfiguration(storageConfig, storeManager.toString());
    } else {
      lockConfiguration = null;
    }

    writeAttempts = storageConfig.getInt(WRITE_ATTEMPTS_KEY, WRITE_ATTEMPTS_DEFAULT);
    Preconditions.checkArgument(writeAttempts > 0, "Write attempts must be positive");
    readAttempts = storageConfig.getInt(READ_ATTEMPTS_KEY, READ_ATTEMPTS_DEFAULT);
    Preconditions.checkArgument(readAttempts > 0, "Read attempts must be positive");
    persistAttemptWaittime =
        storageConfig.getInt(STORAGE_ATTEMPT_WAITTIME_KEY, STORAGE_ATTEMPT_WAITTIME_DEFAULT);
    Preconditions.checkArgument(
        persistAttemptWaittime > 0, "Persistence attempt retry wait time must be non-negative");

    if (storeFeatures.isDistributed() && storeFeatures.isKeyOrdered()) {
      log.debug("Wrapping index store with HashPrefix");
      hashPrefixIndex = true;
    } else {
      hashPrefixIndex = false;
    }
  }
 public static boolean supportsStoreTTL(StoreFeatures features) {
   return features.hasCellTTL() || features.hasStoreTTL();
 }
  @Test
  public void testFeaturesImplementation() {
    StoreFeatures features;

    features = new StandardStoreFeatures.Builder().build();

    assertFalse(features.hasMultiQuery());
    assertFalse(features.hasLocking());
    assertFalse(features.isDistributed());
    assertFalse(features.hasScan());

    features = new StandardStoreFeatures.Builder().locking(true).build();

    assertFalse(features.hasMultiQuery());
    assertTrue(features.hasLocking());
    assertFalse(features.isDistributed());

    features = new StandardStoreFeatures.Builder().multiQuery(true).unorderedScan(true).build();

    assertTrue(features.hasMultiQuery());
    assertTrue(features.hasUnorderedScan());
    assertFalse(features.hasOrderedScan());
    assertTrue(features.hasScan());
    assertFalse(features.isDistributed());
    assertFalse(features.hasLocking());
  }
Example #14
0
  /**
   * Initializes this backend with the given configuration. Must be called before this Backend can
   * be used
   *
   * @param config
   */
  public void initialize(Configuration config) {
    try {
      // EdgeStore & VertexIndexStore
      KeyColumnValueStore idStore = getStore(ID_STORE_NAME);
      if (basicMetrics) {
        idStore = new MetricInstrumentedStore(idStore, getMetricsStoreName("idStore"));
      }
      idAuthority = null;
      if (storeFeatures.supportsTransactions()) {
        idAuthority = new TransactionalIDManager(idStore, storeManager, config);
      } else if (storeFeatures.supportsConsistentKeyOperations()) {
        idAuthority = new ConsistentKeyIDManager(idStore, storeManager, config);
      } else {
        throw new IllegalStateException(
            "Store needs to support consistent key or transactional operations for ID manager to guarantee proper id allocations");
      }

      edgeStore = getLockStore(getBufferStore(EDGESTORE_NAME));
      vertexIndexStore = getLockStore(getBufferStore(VERTEXINDEX_STORE_NAME));
      edgeIndexStore = getLockStore(getBufferStore(EDGEINDEX_STORE_NAME), false);

      if (hashPrefixIndex) {
        vertexIndexStore = new HashPrefixKeyColumnValueStore(vertexIndexStore, 4);
        edgeIndexStore = new HashPrefixKeyColumnValueStore(edgeIndexStore, 4);
      }

      if (basicMetrics) {
        edgeStore = new MetricInstrumentedStore(edgeStore, getMetricsStoreName("edgeStore"));
        vertexIndexStore =
            new MetricInstrumentedStore(vertexIndexStore, getMetricsStoreName("vertexIndexStore"));
        edgeIndexStore =
            new MetricInstrumentedStore(edgeIndexStore, getMetricsStoreName("edgeIndexStore"));
      }

      String version =
          BackendOperation.execute(
              new Callable<String>() {
                @Override
                public String call() throws Exception {
                  String version = storeManager.getConfigurationProperty(TITAN_BACKEND_VERSION);
                  if (version == null) {
                    storeManager.setConfigurationProperty(
                        TITAN_BACKEND_VERSION, TitanConstants.VERSION);
                    version = TitanConstants.VERSION;
                  }
                  return version;
                }

                @Override
                public String toString() {
                  return "ConfigurationRead";
                }
              },
              config.getLong(SETUP_WAITTIME_KEY, SETUP_WAITTIME_DEFAULT));
      Preconditions.checkState(version != null, "Could not read version from storage backend");
      if (!TitanConstants.VERSION.equals(version)
          && !TitanConstants.COMPATIBLE_VERSIONS.contains(version)) {
        throw new TitanException(
            "StorageBackend version is incompatible with current Titan version: "
                + version
                + " vs. "
                + TitanConstants.VERSION);
      }
    } catch (StorageException e) {
      throw new TitanException("Could not initialize backend", e);
    }
  }