Example #1
0
  /**
   * Opens any secondary indexes defined in the given entity metadata that are not already open.
   * This method is called when a new entity subclass is encountered when an instance of that class
   * is stored, and the EntityStore.getSubclassIndex has not been previously called for that class.
   * [#15247]
   */
  synchronized void openSecondaryIndexes(
      Transaction txn, EntityMetadata entityMeta, PrimaryOpenState priOpenState)
      throws DatabaseException {

    String entityClassName = entityMeta.getClassName();
    PrimaryIndex<Object, Object> priIndex = priIndexMap.get(entityClassName);
    assert priIndex != null;
    Class<Object> entityClass = priIndex.getEntityClass();

    for (SecondaryKeyMetadata secKeyMeta : entityMeta.getSecondaryKeys().values()) {
      String keyName = secKeyMeta.getKeyName();
      String secName = makeSecName(entityClassName, keyName);
      SecondaryIndex<Object, Object, Object> secIndex = secIndexMap.get(secName);
      if (secIndex == null) {
        String keyClassName = getSecKeyClass(secKeyMeta);
        /* RawMode: should not require class. */
        Class keyClass = SimpleCatalog.keyClassForName(keyClassName);
        openSecondaryIndex(
            txn,
            priIndex,
            entityClass,
            entityMeta,
            keyClass,
            keyClassName,
            secKeyMeta,
            makeSecName(entityClassName, secKeyMeta.getKeyName()),
            storeConfig.getSecondaryBulkLoad() /*doNotCreate*/,
            priOpenState);
      }
    }
  }
Example #2
0
  /**
   * Creates a secondary index without using an <code>EntityStore</code>. When using an {@link
   * EntityStore}, call {@link EntityStore#getSecondaryIndex getSecondaryIndex} instead.
   *
   * <p>This constructor is not normally needed and is provided for applications that wish to use
   * custom bindings along with the Direct Persistence Layer. Normally, {@link
   * EntityStore#getSecondaryIndex getSecondaryIndex} is used instead.
   *
   * @param database the secondary database used for all access other than via a {@link #keysIndex}.
   * @param keysDatabase another handle on the secondary database, opened without association to the
   *     primary, and used only for access via a {@link #keysIndex}. If this argument is null and
   *     the {@link #keysIndex} method is called, then the keys database will be opened
   *     automatically; however, the user is then responsible for closing the keys database. To get
   *     the keys database in order to close it, call {@link #getKeysDatabase}.
   * @param primaryIndex the primary index associated with this secondary index.
   * @param secondaryKeyClass the class of the secondary key.
   * @param secondaryKeyBinding the binding to be used for secondary keys.
   */
  public SecondaryIndex(
      SecondaryDatabase database,
      Database keysDatabase,
      PrimaryIndex<PK, E> primaryIndex,
      Class<SK> secondaryKeyClass,
      EntryBinding secondaryKeyBinding)
      throws DatabaseException {

    super(
        database,
        secondaryKeyClass,
        secondaryKeyBinding,
        new EntityValueAdapter(
            primaryIndex.getEntityClass(), primaryIndex.getEntityBinding(), true));
    secDb = database;
    keysDb = keysDatabase;
    priIndex = primaryIndex;
    entityBinding = primaryIndex.getEntityBinding();
  }
Example #3
0
  /**
   * A getSecondaryIndex with extra parameters for opening a raw store. keyClassName is used for
   * consistency checking and should be null for a raw store only.
   */
  public synchronized <SK, PK, E1, E2 extends E1> SecondaryIndex<SK, PK, E2> getSecondaryIndex(
      PrimaryIndex<PK, E1> primaryIndex,
      Class<E2> entityClass,
      String entityClassName,
      Class<SK> keyClass,
      String keyClassName,
      String keyName)
      throws DatabaseException {

    assert (rawAccess && keyClassName == null) || (!rawAccess && keyClassName != null);

    checkOpen();

    EntityMetadata entityMeta = null;
    SecondaryKeyMetadata secKeyMeta = null;

    /* Validate the subclass for a subclass index. */
    if (entityClass != primaryIndex.getEntityClass()) {
      entityMeta = model.getEntityMetadata(entityClassName);
      assert entityMeta != null;
      secKeyMeta = checkSecKey(entityMeta, keyName);
      String subclassName = entityClass.getName();
      String declaringClassName = secKeyMeta.getDeclaringClassName();
      if (!subclassName.equals(declaringClassName)) {
        throw new IllegalArgumentException(
            "Key for subclass "
                + subclassName
                + " is declared in a different class: "
                + makeSecName(declaringClassName, keyName));
      }
    }

    /*
     * Even though the primary is already open, we can't assume the
     * secondary is open because we don't automatically open all
     * secondaries when the primary is read-only.  Use auto-commit (a null
     * transaction) since we're opening only one database.
     */
    String secName = makeSecName(entityClassName, keyName);
    SecondaryIndex<SK, PK, E2> secIndex = secIndexMap.get(secName);
    if (secIndex == null) {
      if (entityMeta == null) {
        entityMeta = model.getEntityMetadata(entityClassName);
        assert entityMeta != null;
      }
      if (secKeyMeta == null) {
        secKeyMeta = checkSecKey(entityMeta, keyName);
      }

      /* Check metadata. */
      if (keyClassName == null) {
        keyClassName = getSecKeyClass(secKeyMeta);
      } else {
        String expectClsName = getSecKeyClass(secKeyMeta);
        if (!keyClassName.equals(expectClsName)) {
          throw new IllegalArgumentException(
              "Wrong secondary key class: " + keyClassName + " Correct class is: " + expectClsName);
        }
      }

      secIndex =
          openSecondaryIndex(
              null,
              primaryIndex,
              entityClass,
              entityMeta,
              keyClass,
              keyClassName,
              secKeyMeta,
              secName,
              false /*doNotCreate*/,
              null /*priOpenState*/);
    }
    return secIndex;
  }