private SecondaryDatabase openSecondaryDb(
      TupleSerialFactory factory,
      String keyName,
      Database primary,
      String file,
      Database foreignStore)
      throws Exception {

    TupleSerialMarshalledKeyCreator keyCreator =
        factory.getKeyCreator(MarshalledObject.class, keyName);

    SecondaryConfig secConfig = new SecondaryConfig();
    DbCompat.setTypeBtree(secConfig);
    secConfig.setTransactional(testEnv.isTxnMode());
    secConfig.setAllowCreate(true);
    secConfig.setKeyCreator(keyCreator);
    if (foreignStore != null) {
      secConfig.setForeignKeyDatabase(foreignStore);
      secConfig.setForeignKeyDeleteAction(onDelete);
      if (onDelete == ForeignKeyDeleteAction.NULLIFY) {
        secConfig.setForeignKeyNullifier(keyCreator);
      }
    }

    return DbCompat.testOpenSecondaryDatabase(env, null, file, null, primary, secConfig);
  }
  /** Open all storage containers, indices, and catalogs. */
  public SampleDatabase(String homeDirectory) throws DatabaseException, FileNotFoundException {

    // Open the Berkeley DB environment in transactional mode.
    //
    System.out.println("Opening environment in: " + homeDirectory);
    EnvironmentConfig envConfig = new EnvironmentConfig();
    envConfig.setTransactional(true);
    envConfig.setAllowCreate(true);
    envConfig.setInitializeCache(true);
    envConfig.setInitializeLocking(true);
    env = new Environment(new File(homeDirectory), envConfig);

    // Set the Berkeley DB config for opening all stores.
    //
    DatabaseConfig dbConfig = new DatabaseConfig();
    dbConfig.setTransactional(true);
    dbConfig.setAllowCreate(true);
    dbConfig.setType(DatabaseType.BTREE);

    // Create the Serial class catalog.  This holds the serialized class
    // format for all database records of serial format.
    //
    Database catalogDb = env.openDatabase(null, CLASS_CATALOG, null, dbConfig);
    javaCatalog = new StoredClassCatalog(catalogDb);

    // Open the Berkeley DB database for the part, supplier and shipment
    // stores.  The stores are opened with no duplicate keys allowed.
    //
    partDb = env.openDatabase(null, PART_STORE, null, dbConfig);

    supplierDb = env.openDatabase(null, SUPPLIER_STORE, null, dbConfig);

    shipmentDb = env.openDatabase(null, SHIPMENT_STORE, null, dbConfig);

    // Open the SecondaryDatabase for the city index of the supplier store,
    // and for the part and supplier indices of the shipment store.
    // Duplicate keys are allowed since more than one supplier may be in
    // the same city, and more than one shipment may exist for the same
    // supplier or part.  A foreign key constraint is defined for the
    // supplier and part indices to ensure that a shipment only refers to
    // existing part and supplier keys.  The CASCADE delete action means
    // that shipments will be deleted if their associated part or supplier
    // is deleted.
    //
    SecondaryConfig secConfig = new SecondaryConfig();
    secConfig.setTransactional(true);
    secConfig.setAllowCreate(true);
    secConfig.setType(DatabaseType.BTREE);
    secConfig.setSortedDuplicates(true);

    secConfig.setKeyCreator(
        new SupplierByCityKeyCreator(
            javaCatalog, SupplierKey.class, SupplierData.class, String.class));
    supplierByCityDb =
        env.openSecondaryDatabase(null, SUPPLIER_CITY_INDEX, null, supplierDb, secConfig);

    secConfig.setForeignKeyDatabase(partDb);
    secConfig.setForeignKeyDeleteAction(ForeignKeyDeleteAction.CASCADE);
    secConfig.setKeyCreator(
        new ShipmentByPartKeyCreator(
            javaCatalog, ShipmentKey.class, ShipmentData.class, PartKey.class));
    shipmentByPartDb =
        env.openSecondaryDatabase(null, SHIPMENT_PART_INDEX, null, shipmentDb, secConfig);

    secConfig.setForeignKeyDatabase(supplierDb);
    secConfig.setForeignKeyDeleteAction(ForeignKeyDeleteAction.CASCADE);
    secConfig.setKeyCreator(
        new ShipmentBySupplierKeyCreator(
            javaCatalog, ShipmentKey.class, ShipmentData.class, SupplierKey.class));
    shipmentBySupplierDb =
        env.openSecondaryDatabase(null, SHIPMENT_SUPPLIER_INDEX, null, shipmentDb, secConfig);
  }