public EvolveStats evolve(EvolveConfig config) throws DatabaseException { checkOpen(); List<Format> toEvolve = new ArrayList<Format>(); Set<String> configToEvolve = config.getClassesToEvolve(); if (configToEvolve.isEmpty()) { catalog.getEntityFormats(toEvolve); } else { for (String name : configToEvolve) { Format format = catalog.getFormat(name); if (format == null) { throw new IllegalArgumentException("Class to evolve is not persistent: " + name); } if (!format.isEntity()) { throw new IllegalArgumentException("Class to evolve is not an entity class: " + name); } toEvolve.add(format); } } EvolveEvent event = EvolveInternal.newEvent(); for (Format format : toEvolve) { if (format.getEvolveNeeded()) { evolveIndex(format, event, config.getEvolveListener()); format.setEvolveNeeded(false); catalog.flush(); } } return event.getStats(); }
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(); } }