/* * 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) { } } }
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; } }
/** * 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); }
/** * 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; }