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);
  }
  private Database openDb(String file) throws Exception {

    DatabaseConfig config = new DatabaseConfig();
    DbCompat.setTypeBtree(config);
    config.setTransactional(testEnv.isTxnMode());
    config.setAllowCreate(true);

    return DbCompat.testOpenDatabase(env, null, file, null, config);
  }
Example #3
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 #4
0
  /**
   * Opens an entity store for raw data access.
   *
   * @param env an open Berkeley DB environment.
   * @param storeName the name of the entity store within the given environment.
   * @param config the store configuration, or null to use default configuration properties.
   * @throws IllegalArgumentException if the <code>Environment</code> is read-only and the <code>
   *     config ReadOnly</code> property is false.
   */
  public RawStore(Environment env, String storeName, StoreConfig config)
      throws StoreNotFoundException, DatabaseException {

    try {
      store = new Store(env, storeName, config, true /*rawAccess*/);
    } catch (StoreExistsException e) {
      /* Should never happen, ExclusiveCreate not used. */
      throw DbCompat.unexpectedException(e);
    } catch (IncompatibleClassException e) {
      /* Should never happen, evolution is not performed. */
      throw DbCompat.unexpectedException(e);
    }
  }
Example #5
0
  /** Returns the record number for the last record read. */
  int getCurrentRecordNumber() throws DatabaseException {

    if (view.btreeRecNumDb) {
      /* BTREE-RECNO access. */
      if (otherThang == null) {
        otherThang = new DatabaseEntry();
      }
      DbCompat.getCurrentRecordNumber(cursor.getCursor(), otherThang, getLockMode(false));
      return DbCompat.getRecordNumber(otherThang);
    } else {
      /* QUEUE or RECNO database. */
      return DbCompat.getRecordNumber(keyThang);
    }
  }
Example #6
0
  /**
   * Inserts an entity and returns null, or updates it if the primary key already exists and returns
   * the existing entity.
   *
   * <p>If a {@link PrimaryKey#sequence} is used and the primary key field of the given entity is
   * null or zero, this method will assign the next value from the sequence to the primary key field
   * of the given entity.
   *
   * @param txn the transaction used to protect this operation, null to use auto-commit, or null if
   *     the store is non-transactional.
   * @param entity the entity to be inserted or updated.
   * @return the existing entity that was updated, or null if the entity was inserted.
   * @throws DatabaseException the base class for all BDB exceptions.
   */
  public E put(Transaction txn, E entity) throws DatabaseException {

    DatabaseEntry keyEntry = new DatabaseEntry();
    DatabaseEntry dataEntry = new DatabaseEntry();
    assignKey(entity, keyEntry);

    boolean autoCommit = false;
    Environment env = db.getEnvironment();
    if (transactional && txn == null && DbCompat.getThreadTransaction(env) == null) {
      txn = env.beginTransaction(null, getAutoCommitTransactionConfig());
      autoCommit = true;
    }

    CursorConfig cursorConfig = null;
    if (concurrentDB) {
      cursorConfig = new CursorConfig();
      DbCompat.setWriteCursor(cursorConfig, true);
    }
    boolean failed = true;
    Cursor cursor = db.openCursor(txn, cursorConfig);
    LockMode lockMode = locking ? LockMode.RMW : null;
    try {
      while (true) {
        OperationStatus status = cursor.getSearchKey(keyEntry, dataEntry, lockMode);
        if (status == OperationStatus.SUCCESS) {
          E existing = entityBinding.entryToObject(keyEntry, dataEntry);
          entityBinding.objectToData(entity, dataEntry);
          cursor.put(keyEntry, dataEntry);
          failed = false;
          return existing;
        } else {
          entityBinding.objectToData(entity, dataEntry);
          status = cursor.putNoOverwrite(keyEntry, dataEntry);
          if (status != OperationStatus.KEYEXIST) {
            failed = false;
            return null;
          }
        }
      }
    } finally {
      cursor.close();
      if (autoCommit) {
        if (failed) {
          txn.abort();
        } else {
          txn.commit();
        }
      }
    }
  }
Example #7
0
  public long count() throws DatabaseException {

    if (DbCompat.DATABASE_COUNT) {
      return DbCompat.getDatabaseCount(db);
    } else {
      long count = 0;
      boolean countDups = db instanceof SecondaryDatabase;
      DatabaseEntry key = NO_RETURN_ENTRY;
      DatabaseEntry data = NO_RETURN_ENTRY;
      CursorConfig cursorConfig = CursorConfig.READ_UNCOMMITTED;
      Cursor cursor = db.openCursor(null, cursorConfig);
      try {
        OperationStatus status = cursor.getFirst(key, data, null);
        while (status == OperationStatus.SUCCESS) {
          if (countDups) {
            count += cursor.count();
          } else {
            count += 1;
          }
          status = cursor.getNextNoDup(key, data, null);
        }
      } finally {
        cursor.close();
      }
      return count;
    }
  }
Example #8
0
  private static EnvironmentConfig newEnvConfig() {

    EnvironmentConfig config = new EnvironmentConfig();
    if (DbCompat.MEMORY_SUBSYSTEM) {
      DbCompat.setInitializeCache(config, true);
    }
    return config;
  }
Example #9
0
  public Environment open(String testName, boolean create) throws IOException, DatabaseException {

    config.setAllowCreate(create);
    /* OLDEST deadlock detection on DB matches the use of timeouts on JE.*/
    DbCompat.setLockDetectModeOldest(config);
    File dir = getDirectory(testName, create);
    return newEnvironment(dir, config);
  }
Example #10
0
  private static EnvironmentConfig newEnvConfig() {

    EnvironmentConfig config = new EnvironmentConfig();
    config.setTxnNoSync(Boolean.getBoolean(SharedTestUtils.NO_SYNC));
    if (DbCompat.MEMORY_SUBSYSTEM) {
      DbCompat.setInitializeCache(config, true);
    }
    return config;
  }
Example #11
0
  /**
   * Opens a cursor for a given database, dup'ing an existing CDB cursor if one is open for the
   * current thread.
   */
  Cursor openCursor(Database db, CursorConfig cursorConfig, boolean writeCursor, Transaction txn)
      throws DatabaseException {

    if (cdbMode) {
      CdbCursors cdbCursors = null;
      WeakHashMap cdbCursorsMap = (WeakHashMap) localCdbCursors.get();
      if (cdbCursorsMap == null) {
        cdbCursorsMap = new WeakHashMap();
        localCdbCursors.set(cdbCursorsMap);
      } else {
        cdbCursors = (CdbCursors) cdbCursorsMap.get(db);
      }
      if (cdbCursors == null) {
        cdbCursors = new CdbCursors();
        cdbCursorsMap.put(db, cdbCursors);
      }

      /*
       * In CDB mode the cursorConfig specified by the user is ignored
       * and only the writeCursor parameter is honored.  This is the only
       * meaningful cursor attribute for CDB, and here we count on
       * writeCursor flag being set correctly by the caller.
       */
      List cursors;
      CursorConfig cdbConfig;
      if (writeCursor) {
        if (cdbCursors.readCursors.size() > 0) {

          /*
           * Although CDB allows opening a write cursor when a read
           * cursor is open, a self-deadlock will occur if a write is
           * attempted for a record that is read-locked; we should
           * avoid self-deadlocks at all costs
           */
          throw new IllegalStateException("cannot open CDB write cursor when read cursor is open");
        }
        cursors = cdbCursors.writeCursors;
        cdbConfig = new CursorConfig();
        DbCompat.setWriteCursor(cdbConfig, true);
      } else {
        cursors = cdbCursors.readCursors;
        cdbConfig = null;
      }
      Cursor cursor;
      if (cursors.size() > 0) {
        Cursor other = ((Cursor) cursors.get(0));
        cursor = other.dup(false);
      } else {
        cursor = db.openCursor(null, cdbConfig);
      }
      cursors.add(cursor);
      return cursor;
    } else {
      return db.openCursor(txn, cursorConfig);
    }
  }
Example #12
0
  static {
    EnvironmentConfig config;

    config = newEnvConfig();
    BDB = new TestEnv("bdb", config);

    if (DbCompat.CDB) {
      config = newEnvConfig();
      DbCompat.setInitializeCDB(config, true);
      CDB = new TestEnv("cdb", config);
    } else {
      CDB = null;
    }

    config = newEnvConfig();
    config.setTransactional(true);
    DbCompat.setInitializeLocking(config, true);
    TXN = new TestEnv("txn", config);
  }
Example #13
0
 private CurrentTransaction(Environment env) {
   this.env = env;
   try {
     EnvironmentConfig config = env.getConfig();
     txnMode = config.getTransactional();
     lockingMode = DbCompat.getInitializeLocking(config);
     if (txnMode || lockingMode) {
       writeLockMode = LockMode.RMW;
     } else {
       writeLockMode = LockMode.DEFAULT;
     }
     cdbMode = DbCompat.getInitializeCDB(config);
     if (cdbMode) {
       localCdbCursors = new ThreadLocal();
     }
   } catch (DatabaseException e) {
     throw new RuntimeExceptionWrapper(e);
   }
 }
 public void objectToKey(final Object entity, final DatabaseEntry key) {
   try {
     objectToKeyInternal(entity, key);
   } catch (RefreshException e) {
     e.refresh();
     try {
       objectToKeyInternal(entity, key);
     } catch (RefreshException e2) {
       throw DbCompat.unexpectedException(e2);
     }
   }
 }
 public Object entryToObject(final DatabaseEntry key, final DatabaseEntry data) {
   try {
     return entryToObjectInternal(key, null, data);
   } catch (RefreshException e) {
     e.refresh();
     try {
       return entryToObjectInternal(key, null, data);
     } catch (RefreshException e2) {
       throw DbCompat.unexpectedException(e2);
     }
   }
 }
  public boolean assignPrimaryKey(Object entity, DatabaseEntry key) throws DatabaseException {

    try {
      return assignPrimaryKeyInternal(entity, key);
    } catch (RefreshException e) {
      e.refresh();
      try {
        return assignPrimaryKeyInternal(entity, key);
      } catch (RefreshException e2) {
        throw DbCompat.unexpectedException(e2);
      }
    }
  }
Example #17
0
 private synchronized DatabaseConfig getPrimaryConfig(EntityMetadata meta) {
   String clsName = meta.getClassName();
   DatabaseConfig config = priConfigMap.get(clsName);
   if (config == null) {
     config = new DatabaseConfig();
     config.setTransactional(storeConfig.getTransactional());
     config.setAllowCreate(!storeConfig.getReadOnly());
     config.setReadOnly(storeConfig.getReadOnly());
     DbCompat.setDeferredWrite(config, storeConfig.getDeferredWrite());
     setBtreeComparator(config, meta.getPrimaryKey().getClassName());
     priConfigMap.put(clsName, config);
   }
   return config;
 }
  public void testReadOnlyEmptyCatalog() throws Exception {

    String file = "catalog.db";

    /* Create an empty database. */
    DatabaseConfig config = new DatabaseConfig();
    config.setAllowCreate(true);
    DbCompat.setTypeBtree(config);
    Database db = DbCompat.testOpenDatabase(env, null, file, null, config);
    db.close();

    /* Open the empty database read-only. */
    config.setAllowCreate(false);
    config.setReadOnly(true);
    db = DbCompat.testOpenDatabase(env, null, file, null, config);

    /* Expect exception when creating the catalog. */
    try {
      new StoredClassCatalog(db);
      fail();
    } catch (IllegalStateException e) {
    }
    db.close();
  }
 /**
  * This method will be used in PrimaryIndex.get, where the primary key is known to DPL. This
  * method will force to call readEntityWithPriKey to directly assign primary key to the
  * de-serialized object.
  */
 public Object entryToObjectWithPriKey(final Object priKey, final DatabaseEntry data) {
   try {
     if (priKey == null) {
       throw new IllegalArgumentException("Primary key cannot be null.");
     }
     return entryToObjectInternal(null, priKey, data);
   } catch (RefreshException e) {
     e.refresh();
     try {
       return entryToObjectInternal(null, priKey, data);
     } catch (RefreshException e2) {
       throw DbCompat.unexpectedException(e2);
     }
   }
 }
  @Override
  void copySecMultiKey(RecordInput input, Format keyFormat, Set results) throws RefreshException {

    int len = input.readPackedInt();
    for (int i = 0; i < len; i += 1) {
      KeyLocation loc = input.getKeyLocation(useComponentFormat);
      if (loc == null) {
        throw new IllegalArgumentException("Secondary key values in array may not be null");
      }
      if (loc.format != useComponentFormat) {
        throw DbCompat.unexpectedState(useComponentFormat.getClassName());
      }
      int off1 = loc.input.getBufferOffset();
      useComponentFormat.skipContents(loc.input);
      int off2 = loc.input.getBufferOffset();
      DatabaseEntry entry = new DatabaseEntry(loc.input.getBufferBytes(), off1, off2 - off1);
      results.add(entry);
    }
  }
Example #21
0
  public void sync() throws DatabaseException {

    List<Database> dbs = new ArrayList<Database>();
    synchronized (this) {
      dbs.addAll(deferredWriteDatabases.keySet());
    }
    int nDbs = dbs.size();
    if (nDbs > 0) {
      for (int i = 0; i < nDbs; i += 1) {
        Database db = dbs.get(i);
        boolean flushLog = (i == nDbs - 1);
        DbCompat.syncDeferredWrite(db, flushLog);
        /* Call hook for unit testing. */
        if (syncHook != null) {
          syncHook.onSync(db, flushLog);
        }
      }
    }
  }
  /** Creates a key binding for a given entity class. */
  public PersistEntityBinding(
      final PersistCatalog catalogParam, final String entityClassName, final boolean rawAccess) {
    catalog = catalogParam;

    try {
      entityFormat = getOrCreateFormat(catalog, entityClassName, rawAccess);
    } catch (RefreshException e) {
      /* Must assign catalog field in constructor. */
      catalog = e.refresh();
      try {
        entityFormat = getOrCreateFormat(catalog, entityClassName, rawAccess);
      } catch (RefreshException e2) {
        throw DbCompat.unexpectedException(e2);
      }
    }
    if (!entityFormat.isEntity()) {
      throw new IllegalArgumentException("Not an entity class: " + entityClassName);
    }
    this.rawAccess = rawAccess;
  }
Example #23
0
  /** Returns the record number at the given slot position. */
  private int getRecordNumber(int i) {

    if (coll.view.btreeRecNumDb) {
      DataCursor cursor = null;
      try {
        cursor = new DataCursor(coll.view, false);
        if (moveCursor(i, cursor)) {
          return cursor.getCurrentRecordNumber();
        } else {
          throw new IllegalStateException();
        }
      } catch (DatabaseException e) {
        throw StoredContainer.convertException(e);
      } finally {
        closeCursor(cursor);
      }
    } else {
      DatabaseEntry entry = new DatabaseEntry(keys[i]);
      return DbCompat.getRecordNumber(entry);
    }
  }
  /**
   * Creates a mutation for converting all values of the given field in the given class version to a
   * type compatible with the current declared type of the field.
   */
  public Converter(
      String declaringClassName,
      int declaringClassVersion,
      String fieldName,
      Conversion conversion) {
    super(declaringClassName, declaringClassVersion, fieldName);
    this.conversion = conversion;

    /* Require explicit implementation of the equals method. */
    Class cls = conversion.getClass();
    try {
      Method m = cls.getMethod("equals", Object.class);
      if (m.getDeclaringClass() == Object.class) {
        throw new IllegalArgumentException(
            "Conversion class does not implement the equals method "
                + "explicitly (Object.equals is not sufficient): "
                + cls.getName());
      }
    } catch (NoSuchMethodException e) {
      throw DbCompat.unexpectedException(e);
    }
  }
Example #25
0
  /** Increments the record number key at the given slot. */
  private void bumpRecordNumber(int i) {

    DatabaseEntry entry = new DatabaseEntry(keys[i]);
    DbCompat.setRecordNumber(entry, DbCompat.getRecordNumber(entry) + 1);
    keys[i] = entry.getData();
  }
Example #26
0
  public boolean isCdbMode() {

    return DbCompat.getInitializeCDB(config);
  }
Example #27
0
 void copyConfig(EnvironmentConfig copyToConfig) {
   DbCompat.setInitializeCache(copyToConfig, DbCompat.getInitializeCache(config));
   DbCompat.setInitializeLocking(copyToConfig, DbCompat.getInitializeLocking(config));
   DbCompat.setInitializeCDB(copyToConfig, DbCompat.getInitializeCDB(config));
   copyToConfig.setTransactional(config.getTransactional());
 }
Example #28
0
  /**
   * Utility method for use by bindings to translate a entry buffer to an record number integer.
   *
   * @param entry the entry buffer.
   * @return the record number.
   */
  public static long entryToRecordNumber(DatabaseEntry entry) {

    return DbCompat.getRecordNumber(entry) & 0xFFFFFFFFL;
  }
Example #29
0
 /**
  * Utility method for use by bindings to translate a record number integer to a entry buffer.
  *
  * @param recordNumber the record number.
  * @param entry the entry buffer to hold the record number.
  */
 public static void recordNumberToEntry(long recordNumber, DatabaseEntry entry) {
   entry.setData(new byte[4], 0, 4);
   DbCompat.setRecordNumber(entry, (int) recordNumber);
 }
Example #30
0
 /**
  * Returns true if a write cursor is requested by the user via the cursor config, or if this is a
  * writable cursor and the user has not specified a cursor config. For CDB, a special cursor must
  * be created for writing. See CurrentTransaction.openCursor.
  */
 private static boolean isWriteCursor(CursorConfig config, boolean writeAllowed) {
   return DbCompat.getWriteCursor(config) || (config == CursorConfig.DEFAULT && writeAllowed);
 }