private void open(Class clsToRegister) throws DatabaseException { StoreConfig config = new StoreConfig(); config.setAllowCreate(envConfig.getAllowCreate()); if (clsToRegister != null) { com.sleepycat.persist.model.EntityModel model = new com.sleepycat.persist.model.AnnotationModel(); model.registerClass(clsToRegister); config.setModel(model); } open(config); }
/** Checks that an entity class exists or does not exist. */ void checkEntity( boolean exists, EntityModel model, Environment env, String className, int version, String secKeyName) { if (exists) { TestCase.assertNotNull(model.getEntityMetadata(className)); ClassMetadata meta = model.getClassMetadata(className); TestCase.assertNotNull(meta); TestCase.assertEquals(version, meta.getVersion()); TestCase.assertTrue(meta.isEntityClass()); RawType raw = model.getRawType(className); TestCase.assertNotNull(raw); TestCase.assertEquals(version, raw.getVersion()); RawType rawVersion = model.getRawTypeVersion(className, version); TestCase.assertNotNull(rawVersion); TestCase.assertTrue(!rawVersion.isDeleted()); } else { TestCase.assertNull(model.getEntityMetadata(className)); TestCase.assertNull(model.getClassMetadata(className)); TestCase.assertNull(model.getRawType(className)); RawType rawVersion = model.getRawTypeVersion(className, version); TestCase.assertTrue(rawVersion == null || rawVersion.isDeleted()); } assertDbExists(exists, env, className); if (secKeyName != null) { assertDbExists(exists, env, className, secKeyName); } }
/** * Opens a primary index related via a foreign key (relatedEntity). Related indexes are not opened * in the same transaction used by the caller to open a primary or secondary. It is OK to leave * the related index open when the caller's transaction aborts. It is only important to open a * primary and its secondaries atomically. */ private PrimaryIndex getRelatedIndex(String relatedClsName) throws DatabaseException { PrimaryIndex relatedIndex = priIndexMap.get(relatedClsName); if (relatedIndex == null) { EntityMetadata relatedEntityMeta = checkEntityClass(relatedClsName); Class relatedKeyCls; String relatedKeyClsName; Class relatedCls; if (rawAccess) { relatedCls = RawObject.class; relatedKeyCls = Object.class; relatedKeyClsName = null; } else { try { relatedCls = EntityModel.classForName(relatedClsName); } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Related entity class not found: " + relatedClsName); } relatedKeyClsName = SimpleCatalog.keyClassName(relatedEntityMeta.getPrimaryKey().getClassName()); relatedKeyCls = SimpleCatalog.keyClassForName(relatedKeyClsName); } /* * Cycles are prevented here by adding primary indexes to the * priIndexMap as soon as they are created, before opening related * indexes. */ relatedIndex = getPrimaryIndex( relatedKeyCls, relatedKeyClsName, relatedCls, relatedClsName); } return relatedIndex; }
private EntityMetadata checkEntityClass(String clsName) { EntityMetadata meta = model.getEntityMetadata(clsName); if (meta == null) { throw new IllegalArgumentException( "Class could not be loaded or is not an entity class: " + clsName); } return meta; }
private static void checkVersions(EntityModel model, String[] names, int[] versions) { List<RawType> all = model.getAllRawTypeVersions(names[0]); TestCase.assertNotNull(all); assert names.length == versions.length; TestCase.assertEquals(all.toString(), names.length, all.size()); Iterator<RawType> iter = all.iterator(); for (int i = 0; i < names.length; i += 1) { RawType type = iter.next(); TestCase.assertEquals(versions[i], type.getVersion()); TestCase.assertEquals(names[i], type.getClassName()); } }
private void setBtreeComparator(DatabaseConfig config, String clsName) { if (!rawAccess) { ClassMetadata meta = model.getClassMetadata(clsName); if (meta != null) { List<FieldMetadata> compositeKeyFields = meta.getCompositeKeyFields(); if (compositeKeyFields != null) { Class keyClass = SimpleCatalog.keyClassForName(clsName); if (Comparable.class.isAssignableFrom(keyClass)) { Comparator<Object> cmp = new PersistComparator(clsName, compositeKeyFields, getKeyBinding(clsName)); config.setBtreeComparator(cmp); } } } } }
/** * 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; }
private void evolveIndex(Format format, EvolveEvent event, EvolveListener listener) throws DatabaseException { Class entityClass = format.getType(); String entityClassName = format.getClassName(); EntityMetadata meta = model.getEntityMetadata(entityClassName); String keyClassName = meta.getPrimaryKey().getClassName(); keyClassName = SimpleCatalog.keyClassName(keyClassName); DatabaseConfig dbConfig = getPrimaryConfig(meta); PrimaryIndex<Object, Object> index = getPrimaryIndex(Object.class, keyClassName, entityClass, entityClassName); Database db = index.getDatabase(); EntityBinding binding = index.getEntityBinding(); DatabaseEntry key = new DatabaseEntry(); DatabaseEntry data = new DatabaseEntry(); Cursor readCursor = db.openCursor(null, CursorConfig.READ_UNCOMMITTED); try { while (readCursor.getNext(key, data, null) == OperationStatus.SUCCESS) { if (evolveNeeded(key, data, binding)) { Transaction txn = null; if (dbConfig.getTransactional()) { boolean success = false; txn = env.beginTransaction(null, null); } boolean doCommit = false; Cursor writeCursor = null; try { writeCursor = db.openCursor(txn, null); if (writeCursor.getSearchKey(key, data, LockMode.RMW) == OperationStatus.SUCCESS) { boolean written = false; if (evolveNeeded(key, data, binding)) { writeCursor.putCurrent(data); written = true; } if (listener != null) { EvolveInternal.updateEvent(event, entityClassName, 1, written ? 1 : 0); if (!listener.evolveProgress(event)) { break; } } } } finally { if (writeCursor != null) { writeCursor.close(); } if (txn != null) { if (doCommit) { txn.commit(); } else { txn.abort(); } } } } } } finally { readCursor.close(); } }