Example #1
0
  public BDBCreator(String tableName, ArrayList<Integer> keyPositions, int secondaryIndex) {
    /* Creates and loads a BDB table with a secondary index on the column defined by*/
    this.tableName = tableName.toLowerCase();
    this.keyPositions = keyPositions;
    this.secIndexPos = secondaryIndex;
    this.tMap = Main.indexTypeMaps.get(this.tableName);
    setEnvironment();

    dbConfig = new DatabaseConfig();
    dbConfig.setAllowCreate(true);
    myDB = myDbEnvironment.openDatabase(null, this.tableName, dbConfig);
    SecondaryConfig secConfig = new SecondaryConfig();
    secConfig.setAllowCreate(true);
    secConfig.setSortedDuplicates(true);

    createSecDB(secConfig);
    setConfig(dbConfig, secConfig);

    loadData();

    if (secDB != null) {
      secDB.close();
    }
    if (myDB != null) {
      myDB.close();
    }

    closeEnvironment();
  }
Example #2
0
 private SecondaryConfig getSecondaryConfig(
     String secName,
     EntityMetadata entityMeta,
     String keyClassName,
     SecondaryKeyMetadata secKeyMeta) {
   SecondaryConfig config = secConfigMap.get(secName);
   if (config == null) {
     /* Set common properties to match the primary DB. */
     DatabaseConfig priConfig = getPrimaryConfig(entityMeta);
     config = new SecondaryConfig();
     config.setTransactional(priConfig.getTransactional());
     config.setAllowCreate(!priConfig.getReadOnly());
     config.setReadOnly(priConfig.getReadOnly());
     DbCompat.setDeferredWrite(config, DbCompat.getDeferredWrite(priConfig));
     /* Set secondary properties based on metadata. */
     config.setAllowPopulate(true);
     Relationship rel = secKeyMeta.getRelationship();
     config.setSortedDuplicates(
         rel == Relationship.MANY_TO_ONE || rel == Relationship.MANY_TO_MANY);
     setBtreeComparator(config, secKeyMeta.getClassName());
     PersistKeyCreator keyCreator =
         new PersistKeyCreator(catalog, entityMeta, keyClassName, secKeyMeta);
     if (rel == Relationship.ONE_TO_MANY || rel == Relationship.MANY_TO_MANY) {
       config.setMultiKeyCreator(keyCreator);
     } else {
       config.setKeyCreator(keyCreator);
     }
     DeleteAction deleteAction = secKeyMeta.getDeleteAction();
     if (deleteAction != null) {
       ForeignKeyDeleteAction baseDeleteAction;
       switch (deleteAction) {
         case ABORT:
           baseDeleteAction = ForeignKeyDeleteAction.ABORT;
           break;
         case CASCADE:
           baseDeleteAction = ForeignKeyDeleteAction.CASCADE;
           break;
         case NULLIFY:
           baseDeleteAction = ForeignKeyDeleteAction.NULLIFY;
           break;
         default:
           throw new IllegalStateException(deleteAction.toString());
       }
       config.setForeignKeyDeleteAction(baseDeleteAction);
       if (deleteAction == DeleteAction.NULLIFY) {
         config.setForeignMultiKeyNullifier(keyCreator);
       }
     }
     secConfigMap.put(secName, config);
   }
   return config;
 }
Example #3
0
  private void createSecDB(SecondaryConfig secConfig) {
    TupleBinding<DataRow> tBinder = new GenericTupleBinder(tMap);
    SecondaryKeyCreator secKeyCreator = new GenericSecKeyCreator(tBinder, secIndexPos, tMap);

    // Get a secondary object and set the key creator on it.
    secConfig.setKeyCreator(secKeyCreator);
    String secDbName = tableName + "-secDB";
    secDB = myDbEnvironment.openSecondaryDatabase(null, secDbName, myDB, secConfig);
  }
  public static void main(String[] args) {

    Environment myEnv;
    Database myDatabase;

    try {
      EnvironmentConfig envConfig = new EnvironmentConfig();
      envConfig.setAllowCreate(true);
      myEnv = new Environment(new File("/Users/broso/testDB"), envConfig);

      // Environment open omitted for clarity
      DatabaseConfig myDbConfig = new DatabaseConfig();
      SecondaryConfig mySecConfig = new SecondaryConfig();
      myDbConfig.setAllowCreate(true);
      mySecConfig.setAllowCreate(true);
      // Duplicates are frequently required for secondary databases.
      mySecConfig.setSortedDuplicates(true);

      // Open the primary

      String dbName = "myPrimaryDatabase";
      Database myDb = myEnv.openDatabase(null, dbName, myDbConfig);

      // Open the secondary.
      // Key creators are described in the next section.
      // AKeyCreator akc = new AKeyCreator();

      // Get a secondary object and set the key creator on it.
      // mySecConfig.setKeyCreator(keyCreator);

      // Perform the actual open
      String secDbName = "mySecondaryDatabase";
      SecondaryDatabase mySecDb = myEnv.openSecondaryDatabase(null, secDbName, myDb, mySecConfig);
    } catch (DatabaseException de) {
      // Exception handling goes here
    }
  }
Example #5
0
 private static SecondaryConfig set2ndDbConfig() {
   SecondaryConfig sndDatabaseConfig = null;
   if (sndDatabaseConfig == null) {
     sndDatabaseConfig = new SecondaryConfig();
     sndDatabaseConfig.setAllowCreate(true);
     sndDatabaseConfig.setTemporary(false);
     sndDatabaseConfig.setDeferredWrite(true);
     sndDatabaseConfig.setSortedDuplicates(true);
     sndDatabaseConfig.setKeyCreator(createKey());
   }
   return sndDatabaseConfig;
 }
Example #6
0
  /** @deprecated use of Database.truncate */
  public void testOperationsNotAllowed() throws DatabaseException {

    SecondaryDatabase secDb = initDb();
    Database priDb = secDb.getPrimaryDatabase();
    Transaction txn = txnBegin();

    /* Open secondary without a key creator. */
    try {
      env.openSecondaryDatabase(txn, "xxx", priDb, null);
      fail();
    } catch (NullPointerException expected) {
    }
    try {
      env.openSecondaryDatabase(txn, "xxx", priDb, new SecondaryConfig());
      fail();
    } catch (NullPointerException expected) {
    }

    /* Open secondary with both single and multi key creators. */
    SecondaryConfig config = new SecondaryConfig();
    config.setKeyCreator(new MyKeyCreator());
    config.setMultiKeyCreator(new SimpleMultiKeyCreator(new MyKeyCreator()));
    try {
      env.openSecondaryDatabase(txn, "xxx", priDb, config);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    /* Database operations. */

    DatabaseEntry key = entry(1);
    DatabaseEntry data = entry(2);

    try {
      secDb.getSearchBoth(txn, key, data, LockMode.DEFAULT);
      fail();
    } catch (UnsupportedOperationException expected) {
    }

    try {
      secDb.put(txn, key, data);
      fail();
    } catch (UnsupportedOperationException expected) {
    }

    try {
      secDb.putNoOverwrite(txn, key, data);
      fail();
    } catch (UnsupportedOperationException expected) {
    }

    try {
      secDb.putNoDupData(txn, key, data);
      fail();
    } catch (UnsupportedOperationException expected) {
    }

    try {
      secDb.truncate(txn, true);
      fail();
    } catch (UnsupportedOperationException expected) {
    }

    try {
      secDb.join(new Cursor[0], null);
      fail();
    } catch (UnsupportedOperationException expected) {
    }

    /* Cursor operations. */

    txnCommit(txn);
    txn = txnBeginCursor();

    SecondaryCursor cursor = null;
    try {
      cursor = secDb.openSecondaryCursor(txn, null);

      try {
        cursor.getSearchBoth(key, data, LockMode.DEFAULT);
        fail();
      } catch (UnsupportedOperationException expected) {
      }

      try {
        cursor.getSearchBothRange(key, data, LockMode.DEFAULT);
        fail();
      } catch (UnsupportedOperationException expected) {
      }

      try {
        cursor.putCurrent(data);
        fail();
      } catch (UnsupportedOperationException expected) {
      }

      try {
        cursor.put(key, data);
        fail();
      } catch (UnsupportedOperationException expected) {
      }

      try {
        cursor.putNoOverwrite(key, data);
        fail();
      } catch (UnsupportedOperationException expected) {
      }

      try {
        cursor.putNoDupData(key, data);
        fail();
      } catch (UnsupportedOperationException expected) {
      }
    } finally {
      if (cursor != null) {
        cursor.close();
      }
    }

    txnCommit(txn);
    secDb.close();
    priDb.close();

    /* Primary with duplicates. */
    priDb = openDatabase(true, "testDBWithDups", false);
    try {
      openSecondary(priDb, true, "testSecDB", false, false);
      fail();
    } catch (IllegalArgumentException expected) {
    }

    priDb.close();

    /* Single secondary with two primaries.*/
    Database pri1 = openDatabase(false, "pri1", false);
    Database pri2 = openDatabase(false, "pri2", false);
    Database sec1 = openSecondary(pri1, false, "sec", false, false);
    try {
      openSecondary(pri2, false, "sec", false, false);
      fail();
    } catch (IllegalArgumentException expected) {
    }
    sec1.close();
    pri1.close();
    pri2.close();
  }
Example #7
0
  private SecondaryDatabase openSecondary(
      Database priDb,
      boolean allowDuplicates,
      String dbName,
      boolean allowPopulate,
      boolean readOnly)
      throws DatabaseException {

    List secListBefore = priDb.getSecondaryDatabases();
    SecondaryConfig dbConfig = new SecondaryConfig();
    dbConfig.setTransactional(isTransactional);
    dbConfig.setAllowCreate(true);
    dbConfig.setSortedDuplicates(allowDuplicates);
    dbConfig.setReadOnly(readOnly);
    dbConfig.setAllowPopulate(allowPopulate);
    if (!readOnly) {
      if (useMultiKey) {
        dbConfig.setMultiKeyCreator(new SimpleMultiKeyCreator(new MyKeyCreator()));
      } else {
        dbConfig.setKeyCreator(new MyKeyCreator());
      }
    }
    Transaction txn = txnBegin();
    SecondaryDatabase secDb;
    try {
      secDb = env.openSecondaryDatabase(txn, dbName, priDb, dbConfig);
    } finally {
      txnCommit(txn);
    }
    assertNotNull(secDb);

    /* Check configuration. */
    assertSame(priDb, secDb.getPrimaryDatabase());
    SecondaryConfig config2 = secDb.getSecondaryConfig();
    assertEquals(allowPopulate, config2.getAllowPopulate());
    assertEquals(dbConfig.getKeyCreator(), config2.getKeyCreator());

    /* Make sure the new secondary is added to the primary's list. */
    List secListAfter = priDb.getSecondaryDatabases();
    assertTrue(secListAfter.remove(secDb));
    assertEquals(secListBefore, secListAfter);

    return secDb;
  }
  /** Insert or retrieve data. */
  public void run() throws DatabaseException {

    /* Create a new, transactional database environment. */
    EnvironmentConfig envConfig = new EnvironmentConfig();
    envConfig.setTransactional(true);
    envConfig.setAllowCreate(true);
    Environment exampleEnv = new Environment(envDir, envConfig);

    /*
     * Make a database within that environment. Because this will be used
     * as a primary database, it must not allow duplicates. The primary key
     * of a primary database must be unique.
     */
    Transaction txn = exampleEnv.beginTransaction(null, null);
    DatabaseConfig dbConfig = new DatabaseConfig();
    dbConfig.setTransactional(true);
    dbConfig.setAllowCreate(true);
    Database exampleDb = exampleEnv.openDatabase(txn, "bindingsDb", dbConfig);

    /*
     * In our example, the database record is composed of an integer key
     * and and instance of the MyData class as data.
     *
     * A class catalog database is needed for storing class descriptions
     * for the serial binding used below.  This avoids storing class
     * descriptions redundantly in each record.
     */
    DatabaseConfig catalogConfig = new DatabaseConfig();
    catalogConfig.setTransactional(true);
    catalogConfig.setAllowCreate(true);
    Database catalogDb = exampleEnv.openDatabase(txn, "catalogDb", catalogConfig);
    StoredClassCatalog catalog = new StoredClassCatalog(catalogDb);

    /*
     * Create a serial binding for MyData data objects.  Serial
     * bindings can be used to store any Serializable object.
     */
    EntryBinding<MyData> dataBinding = new SerialBinding<MyData>(catalog, MyData.class);

    /*
     * Further below we'll use a tuple binding (IntegerBinding
     * specifically) for integer keys.  Tuples, unlike serialized
     * Java objects, have a well defined sort order.
     */

    /*
     * Define a String tuple binding for a secondary key.  The
     * secondary key is the msg field of the MyData object.
     */
    EntryBinding<String> secKeyBinding = TupleBinding.getPrimitiveBinding(String.class);

    /*
     * Open a secondary database to allow accessing the primary
     * database by the secondary key value.
     */
    SecondaryConfig secConfig = new SecondaryConfig();
    secConfig.setTransactional(true);
    secConfig.setAllowCreate(true);
    secConfig.setSortedDuplicates(true);
    secConfig.setKeyCreator(new MyKeyCreator(secKeyBinding, dataBinding));
    SecondaryDatabase exampleSecDb =
        exampleEnv.openSecondaryDatabase(txn, "bindingsSecDb", exampleDb, secConfig);
    txn.commit();

    /* DatabaseEntry represents the key and data of each record. */
    DatabaseEntry keyEntry = new DatabaseEntry();
    DatabaseEntry dataEntry = new DatabaseEntry();

    if (doInsert) {

      /*
       * Put some data in.  Note that the primary database is always used
       * to add data.  Adding or changing data in the secondary database
       * is not allowed; however, deleting through the secondary database
       * is allowed.
       */
      for (int i = offset; i < numRecords + offset; i++) {
        txn = exampleEnv.beginTransaction(null, null);
        StringBuffer stars = new StringBuffer();
        for (int j = 0; j < i; j++) {
          stars.append('*');
        }
        MyData data = new MyData(i, stars.toString());

        IntegerBinding.intToEntry(i, keyEntry);
        dataBinding.objectToEntry(data, dataEntry);

        OperationStatus status = exampleDb.put(txn, keyEntry, dataEntry);

        /*
         * Note that put will throw a DatabaseException when error
         * conditions are found such as deadlock.  However, the status
         * return conveys a variety of information. For example, the
         * put might succeed, or it might not succeed if the record
         * exists and duplicates were not
         */
        if (status != OperationStatus.SUCCESS) {
          throw new RuntimeException("Data insertion got status " + status);
        }
        txn.commit();
      }
    } else {

      /*
       * Retrieve the data by secondary key by opening a cursor on the
       * secondary database.  The key parameter for a secondary cursor is
       * always the secondary key, but the data parameter is always the
       * data of the primary database.  You can cast the cursor to a
       * SecondaryCursor and use additional method signatures for
       * retrieving the primary key also.  Or you can call
       * openSecondaryCursor() to avoid casting.
       */
      txn = exampleEnv.beginTransaction(null, null);
      Cursor cursor = exampleSecDb.openCursor(txn, null);

      while (cursor.getNext(keyEntry, dataEntry, LockMode.DEFAULT) == OperationStatus.SUCCESS) {

        String key = secKeyBinding.entryToObject(keyEntry);
        MyData data = dataBinding.entryToObject(dataEntry);

        System.out.println("key=" + key + " data=" + data);
      }
      cursor.close();
      txn.commit();
    }

    /*
     * Always close secondary databases before closing their associated
     * primary database.
     */
    catalogDb.close();
    exampleSecDb.close();
    exampleDb.close();
    exampleEnv.close();
  }
Example #9
0
 private void setConfig(DatabaseConfig mydbConfig, SecondaryConfig mySecDBConfig) {
   mydbConfig.setTransactional(false);
   mySecDBConfig.setTransactional(false);
 }
Example #10
0
 public synchronized void setSecondaryConfig(
     Class entityClass, String keyName, SecondaryConfig config) {
   checkOpen();
   String entityClsName = entityClass.getName();
   EntityMetadata entityMeta = checkEntityClass(entityClsName);
   SecondaryKeyMetadata secKeyMeta = checkSecKey(entityMeta, keyName);
   String keyClassName = getSecKeyClass(secKeyMeta);
   String secName = makeSecName(entityClass.getName(), keyName);
   if (secIndexMap.containsKey(secName)) {
     throw new IllegalStateException("Cannot set config after DB is open");
   }
   SecondaryConfig dbConfig = getSecondaryConfig(secName, entityMeta, keyClassName, secKeyMeta);
   if (config.getSortedDuplicates() != dbConfig.getSortedDuplicates()
       || config.getBtreeComparator() != dbConfig.getBtreeComparator()
       || config.getDuplicateComparator() != null
       || config.getAllowPopulate() != dbConfig.getAllowPopulate()
       || config.getKeyCreator() != dbConfig.getKeyCreator()
       || config.getMultiKeyCreator() != dbConfig.getMultiKeyCreator()
       || config.getForeignKeyNullifier() != dbConfig.getForeignKeyNullifier()
       || config.getForeignMultiKeyNullifier() != dbConfig.getForeignMultiKeyNullifier()
       || config.getForeignKeyDeleteAction() != dbConfig.getForeignKeyDeleteAction()
       || config.getForeignKeyDatabase() != null) {
     throw new IllegalArgumentException(
         "One of these properties was illegally changed: "
             + " SortedDuplicates, BtreeComparator, DuplicateComparator,"
             + " AllowPopulate, KeyCreator, MultiKeyCreator,"
             + " ForeignKeyNullifer, ForeignMultiKeyNullifier,"
             + " ForeignKeyDeleteAction, ForeignKeyDatabase");
   }
   secConfigMap.put(secName, config);
 }
Example #11
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;
  }