/*
   * Check that the notReplicate attribute is properly immutable and
   * persistent.
   */
  private void validate(DatabaseConfig config, boolean replicated) throws DatabaseException {

    /* Create the database -- is its config what we expect? */
    db = env.openDatabase(null, TEST_DB, config);
    DatabaseConfig inUseConfig = db.getConfig();
    assertEquals(replicated, DbInternal.getReplicated(inUseConfig));

    /* Close, re-open. */
    db.close();
    db = null;
    db = env.openDatabase(null, TEST_DB, inUseConfig);
    assertEquals(replicated, DbInternal.getReplicated(db.getConfig()));

    /*
     * Close, re-open w/inappropriate value for the replicated bit. This is
     * only checked for replicated environments.
     */
    db.close();
    db = null;
    if (DbInternal.getEnvironmentImpl(env).isReplicated()) {
      DbInternal.setReplicated(inUseConfig, !replicated);
      try {
        db = env.openDatabase(null, TEST_DB, inUseConfig);
        fail("Should have caught config mismatch");
      } catch (IllegalArgumentException expected) {
      }
    }
  }
Пример #2
0
  BasicIndex(Database db, Class<K> keyClass, EntryBinding keyBinding, ValueAdapter<E> entityAdapter)
      throws DatabaseException {

    this.db = db;
    DatabaseConfig config = db.getConfig();
    transactional = config.getTransactional();

    this.keyClass = keyClass;
    this.keyBinding = keyBinding;
    this.entityAdapter = entityAdapter;

    emptyRange = new KeyRange(config.getBtreeComparator());
    keyAdapter = new KeyValueAdapter(keyClass, keyBinding);
  }
  /**
   * Test that we can retrieve a database configuration and that it clones its configuration
   * appropriately.
   */
  @Test
  public void testConfig() throws Throwable {

    try {
      EnvironmentConfig envConfig = TestUtils.initEnvConfig();
      envConfig.setAllowCreate(true);
      env = create(envHome, envConfig);

      /*
       * Make sure that the database keeps its own copy of the
       * configuration object.
       */
      DatabaseConfig dbConfigA = new DatabaseConfig();
      dbConfigA.setAllowCreate(true);
      Database dbA = env.openDatabase(null, "foo", dbConfigA);

      /* Change the original dbConfig */
      dbConfigA.setAllowCreate(false);
      DatabaseConfig getConfig1 = dbA.getConfig();
      assertEquals(true, getConfig1.getAllowCreate());
      assertEquals(false, getConfig1.getSortedDuplicates());

      /*
       * Change the retrieved config, ought to have no effect on what the
       * Database is storing.
       */
      getConfig1.setSortedDuplicates(true);
      DatabaseConfig getConfig2 = dbA.getConfig();
      assertEquals(false, getConfig2.getSortedDuplicates());

      dbA.close();
      close(env);
    } catch (Throwable t) {
      t.printStackTrace();
      throw t;
    }
  }
  public BerkeleyStorage(File file, boolean readonly, boolean async) {
    if (file == null) {
      int pid = 0;
      try {
        pid = Integer.parseInt((new File("/proc/self")).getCanonicalFile().getName());
      } catch (NumberFormatException | IOException e) {
      }
      String path = "/tmp";
      String db_path = System.getenv("DB");
      if (db_path != null) {
        path = db_path;
      }
      file = new File(path + "/ringpaxos-db/" + pid);
      file.mkdirs();
    }
    EnvironmentConfig envConfig = new EnvironmentConfig();
    DatabaseConfig dbConfig = new DatabaseConfig();
    envConfig.setReadOnly(readonly);
    dbConfig.setReadOnly(readonly);
    envConfig.setAllowCreate(!readonly);
    dbConfig.setAllowCreate(!readonly);

    // performance settings
    envConfig.setTransactional(true);
    envConfig.setCacheMode(CacheMode.DEFAULT);
    // envConfig.setCacheSize(1000000*800); // 800M
    if (async) {
      dbConfig.setTransactional(false);
      envConfig.setDurability(Durability.COMMIT_NO_SYNC);
      dbConfig.setDeferredWrite(true);
    } else {
      dbConfig.setTransactional(true);
      envConfig.setDurability(Durability.COMMIT_SYNC);
      dbConfig.setDeferredWrite(false);
    }

    env = new Environment(file, envConfig);
    db = env.openDatabase(null, "paxosDB", dbConfig);
    classCatalogDb = env.openDatabase(null, "ClassCatalogDB", dbConfig);
    classCatalog = new StoredClassCatalog(classCatalogDb);
    keyBinding = TupleBinding.getPrimitiveBinding(Long.class);
    dataBinding = new SerialBinding<Decision>(classCatalog, Decision.class);
    ballotBinding = TupleBinding.getPrimitiveBinding(Integer.class);

    logger.info("BerkeleyStorage cache size: " + env.getMutableConfig().getCacheSize());
    logger.info(
        "BerkeleyStorage durability: " + env.getMutableConfig().getDurability().getLocalSync());
    logger.info("BerkeleyStorage deferred write: " + db.getConfig().getDeferredWrite());
  }
  /*
   * This method will:
   * 1. apply the modified DatabaseConfig to the database.
   * 2. close the database and do a sync to make sure the new configuration
   *    is written to the log.
   * 3. open the database with a useExisting config and return the current
   *    DatabaseConfig.
   */
  private DatabaseConfig setAndGetDbConfig(Environment env, DatabaseConfig dbConfig, String dbName)
      throws Exception {

    Database db = env.openDatabase(null, "foo", dbConfig);
    db.close();

    env.sync();

    /*
     * Open with the useExisting config to see what attributes have been
     * persisted.
     */
    DatabaseConfig newConfig = new DatabaseConfig();
    newConfig.setReadOnly(true);
    newConfig.setTransactional(true);
    newConfig.setUseExistingConfig(true);

    db = env.openDatabase(null, dbName, newConfig);
    newConfig = db.getConfig();
    db.close();

    return newConfig;
  }
 @Override
 public synchronized boolean trim(Long instance) {
   if (instance == 0) {
     return true;
   } // fast track
   Transaction t = null;
   if (db.getConfig().getTransactional()) {
     t = env.beginTransaction(null, null);
   }
   Cursor cursor = db.openCursor(t, null);
   boolean dirty = false;
   try {
     while (cursor.getNext(key, data, LockMode.READ_UNCOMMITTED) == OperationStatus.SUCCESS) {
       Long i = keyBinding.entryToObject(key);
       if (i < instance && cursor.delete() != OperationStatus.SUCCESS) {
         logger.error("Error deleting instance " + i + " from DB!");
         dirty = true;
       }
     }
   } finally {
     cursor.close();
     if (!dirty) {
       if (t != null) {
         t.commit();
       }
     } else {
       if (t != null) {
         t.abort();
       }
       return false;
     }
   }
   putDecision(-1L, new Decision(0, instance, 0, null));
   logger.debug("DB deltete up to instance " + instance);
   return true;
 }
  /*
   * Test that changing the Btree comparator really writes it to disk.
   */
  @Test
  public void testConfigOverrideUpdateSR15743() throws Throwable {

    try {
      EnvironmentConfig envConfig = TestUtils.initEnvConfig();
      envConfig.setAllowCreate(true);
      env = create(envHome, envConfig);

      /*
       * Make sure that the database keeps its own copy of the
       * configuration object.
       */
      DatabaseConfig dbConfigA = new DatabaseConfig();
      dbConfigA.setOverrideBtreeComparator(false);
      dbConfigA.setBtreeComparator(TestComparator.class);
      dbConfigA.setAllowCreate(true);
      Database dbA = env.openDatabase(null, "foo", dbConfigA);

      /* Change the original dbConfig */
      dbConfigA.setBtreeComparator(TestComparator2.class);
      DatabaseConfig getConfig1 = dbA.getConfig();
      assertEquals(TestComparator.class, getConfig1.getBtreeComparator().getClass());

      /*
       * Change the retrieved config, ought to have no effect on what the
       * Database is storing.
       */
      getConfig1.setBtreeComparator(TestComparator2.class);
      DatabaseConfig getConfig2 = dbA.getConfig();
      assertEquals(TestComparator.class, getConfig2.getBtreeComparator().getClass());

      dbA.close();
      close(env);

      /* Ensure new comparator is written to disk. */
      envConfig = TestUtils.initEnvConfig();
      env = create(envHome, envConfig);

      dbConfigA = new DatabaseConfig();
      /* Change the comparator. */
      dbConfigA.setOverrideBtreeComparator(true);
      dbConfigA.setBtreeComparator(TestComparator2.class);
      dbA = env.openDatabase(null, "foo", dbConfigA);

      getConfig2 = dbA.getConfig();
      assertEquals(TestComparator2.class, getConfig2.getBtreeComparator().getClass());

      dbA.close();
      close(env);

      /* Read it back during recovery to ensure it was written. */
      envConfig = TestUtils.initEnvConfig();
      env = create(envHome, envConfig);

      dbConfigA = new DatabaseConfig();
      dbA = env.openDatabase(null, "foo", dbConfigA);
      getConfig2 = dbA.getConfig();
      assertEquals(TestComparator2.class, getConfig2.getBtreeComparator().getClass());

      /* Create a root for the tree. */
      dbA.put(null, new DatabaseEntry(new byte[1]), new DatabaseEntry(new byte[1]));

      dbA.close();
      close(env);

      /* Change it to a third one when there is a root present. */
      envConfig = TestUtils.initEnvConfig();
      env = create(envHome, envConfig);

      dbConfigA = new DatabaseConfig();
      /* Change the comparator. */
      dbConfigA.setOverrideBtreeComparator(true);
      dbConfigA.setBtreeComparator(TestComparator3.class);
      dbA = env.openDatabase(null, "foo", dbConfigA);
      getConfig2 = dbA.getConfig();
      assertEquals(TestComparator3.class, getConfig2.getBtreeComparator().getClass());
      dbA.close();
      close(env);

      /* Read it back during recovery to ensure it was written. */
      envConfig = TestUtils.initEnvConfig();
      env = create(envHome, envConfig);

      dbConfigA = new DatabaseConfig();
      dbA = env.openDatabase(null, "foo", dbConfigA);
      getConfig2 = dbA.getConfig();
      assertEquals(TestComparator3.class, getConfig2.getBtreeComparator().getClass());
      dbA.close();
      close(env);

    } catch (Throwable t) {
      t.printStackTrace();
      throw t;
    }
  }
  @Test
  public void testOpenReadOnly() throws Throwable {

    try {
      EnvironmentConfig envConfig = TestUtils.initEnvConfig();
      envConfig.setTransactional(true);
      envConfig.setAllowCreate(true);
      env = create(envHome, envConfig);

      DatabaseEntry key = new DatabaseEntry();
      DatabaseEntry data = new DatabaseEntry();

      Transaction txn = env.beginTransaction(null, null);
      DatabaseConfig dbConfig = new DatabaseConfig();
      dbConfig.setTransactional(true);
      dbConfig.setAllowCreate(true);
      Database myDb = env.openDatabase(txn, "testDB2", dbConfig);

      key.setData(TestUtils.getTestArray(0));
      data.setData(TestUtils.getTestArray(0));
      try {
        myDb.put(txn, key, data);
      } catch (DatabaseException DBE) {
        fail("unexpected DatabaseException during put");
      }

      txn.commit();
      myDb.close();

      dbConfig = new DatabaseConfig();
      dbConfig.setTransactional(true);
      dbConfig.setReadOnly(true);
      txn = env.beginTransaction(null, null);
      myDb = env.openDatabase(txn, "testDB2", dbConfig);
      assertTrue(myDb.isTransactional());
      assertTrue(myDb.getConfig().getTransactional());

      key.setData(TestUtils.getTestArray(0));
      data.setData(TestUtils.getTestArray(0));
      try {
        myDb.put(txn, key, data);
        fail("expected UnsupportedOperationException " + "because open RDONLY");
      } catch (UnsupportedOperationException expected) {
      }

      key.setData(TestUtils.getTestArray(0));
      data.setData(TestUtils.getTestArray(0));
      assertEquals(OperationStatus.SUCCESS, myDb.get(txn, key, data, LockMode.DEFAULT));

      Cursor cursor = myDb.openCursor(txn, null);

      assertEquals(OperationStatus.SUCCESS, cursor.getFirst(key, data, LockMode.DEFAULT));

      try {
        cursor.delete();
        fail("expected Exception from delete on RD_ONLY db");
      } catch (UnsupportedOperationException e) {
      }

      key.setData(TestUtils.getTestArray(1));
      data.setData(TestUtils.getTestArray(1));
      try {
        myDb.put(txn, key, data);
        fail("expected UnsupportedOperationException because open RDONLY");
      } catch (UnsupportedOperationException expected) {
      }

      cursor.close();
      txn.commit();
      myDb.close();

      close(env);
    } catch (Throwable t) {
      t.printStackTrace();
      throw t;
    }
  }
  @Test
  public void testIsTransactional() throws Throwable {

    try {
      /* Open environment in transactional mode.*/
      EnvironmentConfig envConfig = TestUtils.initEnvConfig();
      envConfig.setTransactional(true);
      envConfig.setAllowCreate(true);
      env = create(envHome, envConfig);

      /* Create a db, open transactionally with implied auto-commit. */
      DatabaseConfig dbConfig = new DatabaseConfig();
      dbConfig.setAllowCreate(true);
      dbConfig.setTransactional(true);
      Database myDb = env.openDatabase(null, "testDB", dbConfig);
      assertTrue(myDb.isTransactional());
      assertTrue(myDb.getConfig().getTransactional());
      myDb.close();

      /* Open an existing db, can open it non-transactionally. */
      dbConfig.setTransactional(false);
      myDb = env.openDatabase(null, "testDB", null);
      assertFalse(myDb.isTransactional());
      assertFalse(myDb.getConfig().getTransactional());
      myDb.close();

      /* Open another db, pass an explicit transaction. */
      dbConfig.setTransactional(true);
      Transaction txn = env.beginTransaction(null, null);
      myDb = env.openDatabase(txn, "testDB2", dbConfig);
      assertTrue(myDb.isTransactional());
      assertTrue(myDb.getConfig().getTransactional());

      DatabaseEntry key = new DatabaseEntry();
      DatabaseEntry data = new DatabaseEntry();
      key.setData(TestUtils.getTestArray(0));
      data.setData(TestUtils.getTestArray(0));
      try {
        myDb.put(null, key, data);
      } catch (DatabaseException DBE) {
        fail("didn't expect DatabaseException, implied autocommit");
      }

      key.setData(TestUtils.getTestArray(1));
      data.setData(TestUtils.getTestArray(1));
      try {
        myDb.put(txn, key, data);
      } catch (DatabaseException DBE) {
        fail("didn't expect DatabaseException with txn passed");
      }

      try {
        myDb.get(txn, key, data, LockMode.DEFAULT);
      } catch (DatabaseException DBE) {
        fail("didn't expect DatabaseException with txn passed");
      }

      txn.commit();

      try {
        myDb.get(null, key, data, LockMode.DEFAULT);
      } catch (DatabaseException DBE) {
        fail("didn't expect DatabaseException because no txn passed");
      }

      myDb.close();

      close(env);
    } catch (Throwable t) {
      t.printStackTrace();
      throw t;
    }
  }
  /**
   * Test that any conflicts between configuration object settings and the underlying impl object
   * are detected.
   */
  @Test
  public void testConfigConflict() throws Throwable {

    try {
      EnvironmentConfig envConfig = TestUtils.initEnvConfig();
      envConfig.setAllowCreate(true);
      env = create(envHome, envConfig);

      /*
       * Test conflicts of duplicate allowed configuration.
       */

      /* 1a. Create allowing duplicates. */
      DatabaseConfig firstConfig = new DatabaseConfig();
      firstConfig.setAllowCreate(true);
      firstConfig.setSortedDuplicates(true);
      Database firstHandle = env.openDatabase(null, "fooDups", firstConfig);
      /* 1b. Try to open w/no duplicates. */
      DatabaseConfig secondConfig = new DatabaseConfig();
      secondConfig.setSortedDuplicates(false);
      try {
        env.openDatabase(null, "fooDups", secondConfig);
        fail("Conflict in duplicates allowed should be detected.");
      } catch (IllegalArgumentException expected) {
      }

      firstHandle.close();
      env.removeDatabase(null, "fooDups");

      /* 2a. Create dis-allowing duplicates. */
      firstConfig.setSortedDuplicates(false);
      firstConfig.setKeyPrefixing(false);
      firstHandle = env.openDatabase(null, "fooDups", firstConfig);
      /* 2b. Try to open w/duplicates. */
      secondConfig.setSortedDuplicates(true);
      try {
        env.openDatabase(null, "fooDups", secondConfig);
        fail("Conflict in duplicates allowed should be detected.");
      } catch (IllegalArgumentException expected) {
      }
      firstHandle.close();

      /*
       * Test conflicts of read only. If the environment is read/write
       * we should be able to open handles in read only or read/write
       * mode. If the environment is readonly, the database handles
       * must also be read only.
       */
      DatabaseConfig readOnlyConfig = new DatabaseConfig();
      readOnlyConfig.setReadOnly(true);
      Database roHandle = env.openDatabase(null, "fooDups", readOnlyConfig);
      roHandle.close();

      /* Open the environment in read only mode. */
      close(env);
      envConfig = TestUtils.initEnvConfig();
      envConfig.setReadOnly(true);
      env = create(envHome, envConfig);

      /* Open a readOnly database handle, should succeed */
      roHandle = env.openDatabase(null, "fooDups", readOnlyConfig);
      roHandle.close();

      /* Open a read/write database handle, should not succeed. */
      try {
        env.openDatabase(null, "fooDups", null);
        fail("Should not be able to open read/write");
      } catch (IllegalArgumentException expected) {
      }
      close(env);

      /*
       * Check comparator changes.
       */
      /* 1a. Open w/a null comparator */
      env = create(envHome, null);
      firstConfig = new DatabaseConfig();
      firstConfig.setAllowCreate(true);
      firstHandle = env.openDatabase(null, "fooComparator", firstConfig);
      DatabaseConfig firstRetrievedConfig = firstHandle.getConfig();
      assertEquals(null, firstRetrievedConfig.getBtreeComparator());
      assertEquals(null, firstRetrievedConfig.getDuplicateComparator());

      /*
       * 1b. Open a db w/a different comparator, shouldn't take effect
       * because override is not set.
       */
      secondConfig = new DatabaseConfig();
      Comparator btreeComparator = new TestComparator();
      Comparator dupComparator = new TestComparator();
      secondConfig.setBtreeComparator((Class<Comparator<byte[]>>) btreeComparator.getClass());
      secondConfig.setDuplicateComparator((Class<Comparator<byte[]>>) dupComparator.getClass());
      Database secondHandle = env.openDatabase(null, "fooComparator", secondConfig);
      DatabaseConfig retrievedConfig = secondHandle.getConfig();
      assertEquals(null, retrievedConfig.getBtreeComparator());
      assertEquals(null, retrievedConfig.getDuplicateComparator());
      secondHandle.close();

      /* Same as above but with a serialized comparator. */
      secondConfig = new DatabaseConfig();
      btreeComparator = new TestSerialComparator();
      dupComparator = new TestSerialComparator();
      secondConfig.setBtreeComparator(btreeComparator);
      secondConfig.setDuplicateComparator(dupComparator);
      secondHandle = env.openDatabase(null, "fooComparator", secondConfig);
      retrievedConfig = secondHandle.getConfig();
      assertEquals(null, retrievedConfig.getBtreeComparator());
      assertEquals(null, retrievedConfig.getDuplicateComparator());
      secondHandle.close();

      /*
       * Test that update DatabaseConfig while there are open handles
       * should throw exceptions.
       */
      secondConfig.setOverrideBtreeComparator(true);
      secondConfig.setOverrideDuplicateComparator(true);
      btreeComparator = new TestComparator();
      dupComparator = new TestComparator();
      secondConfig.setBtreeComparator((Class<Comparator<byte[]>>) btreeComparator.getClass());
      secondConfig.setDuplicateComparator((Class<Comparator<byte[]>>) dupComparator.getClass());
      try {
        secondHandle = env.openDatabase(null, "fooComparator", secondConfig);
        fail("Expect exceptions here");
      } catch (IllegalStateException e) {
        /* Expected exception. */
      } catch (Exception e) {
        fail("Unexpected exception: " + e.getMessage());
      }
      secondHandle.close();

      /*
       * Open a new database handle without DatabaseConfig changes should
       * be valid.
       */
      try {
        secondHandle = env.openDatabase(null, "fooComparator", firstConfig);
      } catch (Exception e) {
        fail("Unexpected exception: " + e.getMessage());
      }

      secondHandle.close();
      firstHandle.close();
      close(env);
    } catch (Throwable t) {
      t.printStackTrace();
      close(env);
      throw t;
    }
  }
Пример #11
0
  /**
   * Opens a sequence handle, adding the sequence record if appropriate.
   *
   * @throws IllegalArgumentException via Database.openSequence.
   * @throws IllegalStateException via Database.openSequence.
   */
  Sequence(Database db, Transaction txn, DatabaseEntry key, SequenceConfig config)
      throws SequenceNotFoundException, SequenceExistsException {

    if (db.getDatabaseImpl().getSortedDuplicates()) {
      throw new UnsupportedOperationException(
          "Sequences not supported in databases configured for " + "duplicates");
    }

    SequenceConfig useConfig = (config != null) ? config : SequenceConfig.DEFAULT;

    if (useConfig.getRangeMin() >= useConfig.getRangeMax()) {
      throw new IllegalArgumentException("Minimum sequence value must be less than the maximum");
    }

    if (useConfig.getInitialValue() > useConfig.getRangeMax()
        || useConfig.getInitialValue() < useConfig.getRangeMin()) {
      throw new IllegalArgumentException("Initial sequence value is out of range");
    }

    if (useConfig.getRangeMin() > useConfig.getRangeMax() - useConfig.getCacheSize()) {
      throw new IllegalArgumentException("The cache size is larger than the sequence range");
    }

    if (useConfig.getAutoCommitNoSync()) {
      autoCommitConfig = DbInternal.getDefaultTxnConfig(db.getEnvironment()).clone();
      autoCommitConfig.overrideDurability(Durability.COMMIT_NO_SYNC);
    } else {
      /* Use the environment's default transaction config. */
      autoCommitConfig = null;
    }

    this.db = db;
    this.key = copyEntry(key);
    logger = db.getEnvironment().getEnvironmentImpl().getLogger();

    /* Perform an auto-commit transaction to create the sequence. */
    Locker locker = null;
    Cursor cursor = null;
    OperationStatus status = OperationStatus.NOTFOUND;
    try {
      locker =
          LockerFactory.getReadableLocker(
              db.getEnvironment(),
              txn,
              db.isTransactional(),
              false /*retainNonTxnLocks*/,
              false /*readCommitedIsolation*/);

      cursor = new Cursor(db, locker, null);

      boolean sequenceExists = readData(cursor, null);
      boolean isWritableLocker =
          !db.getConfig().getTransactional()
              || (locker.isTransactional()
                  && !DbInternal.getEnvironmentImpl(db.getEnvironment()).isReplicated());

      if (sequenceExists) {
        if (useConfig.getAllowCreate() && useConfig.getExclusiveCreate()) {
          throw new SequenceExistsException(
              "ExclusiveCreate=true and the sequence record " + "already exists.");
        }
      } else {
        if (useConfig.getAllowCreate()) {
          if (!isWritableLocker) {
            if (cursor != null) {
              cursor.close();
            }
            locker.operationEnd(OperationStatus.SUCCESS);

            locker =
                LockerFactory.getWritableLocker(
                    db.getEnvironment(),
                    txn,
                    db.isTransactional(),
                    false,
                    db.getDatabaseImpl().isReplicated(),
                    autoCommitConfig);
            cursor = new Cursor(db, locker, null);
          }

          /* Get the persistent fields from the config. */
          rangeMin = useConfig.getRangeMin();
          rangeMax = useConfig.getRangeMax();
          increment = !useConfig.getDecrement();
          wrapAllowed = useConfig.getWrap();
          storedValue = useConfig.getInitialValue();

          /*
           * To avoid dependence on SerializableIsolation, try
           * putNoOverwrite first.  If it fails, then try to get an
           * existing record.
           */
          status = cursor.putNoOverwrite(key, makeData());

          if (!readData(cursor, null)) {
            /* A retry loop should be performed here. */
            throw new IllegalStateException("Sequence record removed during openSequence.");
          }
          status = OperationStatus.SUCCESS;
        } else {
          throw new SequenceNotFoundException(
              "AllowCreate=false and the sequence record " + "does not exist.");
        }
      }
    } finally {
      if (cursor != null) {
        cursor.close();
      }
      if (locker != null) {
        locker.operationEnd(status);
      }
    }

    /*
     * cacheLast is initialized such that the cache will be considered
     * empty the first time get() is called.
     */
    cacheSize = useConfig.getCacheSize();
    cacheValue = storedValue;
    cacheLast = increment ? (storedValue - 1) : (storedValue + 1);
  }
Пример #12
0
  /**
   * Opens a secondary index with a given transaction and adds it to the secIndexMap. We assume that
   * the index is not already open.
   */
  private <SK, PK, E1, E2 extends E1> SecondaryIndex<SK, PK, E2> openSecondaryIndex(
      Transaction txn,
      PrimaryIndex<PK, E1> primaryIndex,
      Class<E2> entityClass,
      EntityMetadata entityMeta,
      Class<SK> keyClass,
      String keyClassName,
      SecondaryKeyMetadata secKeyMeta,
      String secName,
      boolean doNotCreate,
      PrimaryOpenState priOpenState)
      throws DatabaseException {

    assert !secIndexMap.containsKey(secName);
    String dbName = storePrefix + secName;
    SecondaryConfig config = getSecondaryConfig(secName, entityMeta, keyClassName, secKeyMeta);
    Database priDb = primaryIndex.getDatabase();
    DatabaseConfig priConfig = priDb.getConfig();

    String relatedClsName = secKeyMeta.getRelatedEntity();
    if (relatedClsName != null) {
      PrimaryIndex relatedIndex = getRelatedIndex(relatedClsName);
      config.setForeignKeyDatabase(relatedIndex.getDatabase());
    }

    if (config.getTransactional() != priConfig.getTransactional()
        || DbCompat.getDeferredWrite(config) != DbCompat.getDeferredWrite(priConfig)
        || config.getReadOnly() != priConfig.getReadOnly()) {
      throw new IllegalArgumentException(
          "One of these properties was changed to be inconsistent"
              + " with the associated primary database: "
              + " Transactional, DeferredWrite, ReadOnly");
    }

    PersistKeyBinding keyBinding = getKeyBinding(keyClassName);

    /*
     * doNotCreate is true when StoreConfig.getSecondaryBulkLoad is true
     * and we are opening a secondary as a side effect of opening a
     * primary, i.e., getSecondaryIndex is not being called.  If
     * doNotCreate is true and the database does not exist, we silently
     * ignore the DatabaseNotFoundException and return null.  When
     * getSecondaryIndex is subsequently called, the secondary database
     * will be created and populated from the primary -- a bulk load.
     */
    SecondaryDatabase db;
    boolean saveAllowCreate = config.getAllowCreate();
    try {
      if (doNotCreate) {
        config.setAllowCreate(false);
      }
      db = env.openSecondaryDatabase(txn, dbName, priDb, config);
    } catch (DatabaseNotFoundException e) {
      if (doNotCreate) {
        return null;
      } else {
        throw e;
      }
    } finally {
      if (doNotCreate) {
        config.setAllowCreate(saveAllowCreate);
      }
    }
    SecondaryIndex<SK, PK, E2> secIndex =
        new SecondaryIndex(db, null, primaryIndex, keyClass, keyBinding);

    /* Update index and database maps. */
    secIndexMap.put(secName, secIndex);
    if (DbCompat.getDeferredWrite(config)) {
      deferredWriteDatabases.put(db, null);
    }
    if (priOpenState != null) {
      priOpenState.addDatabase(db);
      priOpenState.addSecondaryName(secName);
    }
    return secIndex;
  }