/* * Copyright 2011 Future Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.confdb.file; import java.io.File; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.krakenapps.confdb.CollectionEntry; import org.krakenapps.confdb.CommitOp; import org.krakenapps.confdb.ConfigChange; import org.krakenapps.confdb.ConfigDatabase; import org.krakenapps.confdb.ConfigEntry; import org.krakenapps.confdb.ConfigTransaction; import org.krakenapps.confdb.ConfigTransactionCache; import org.krakenapps.confdb.Manifest; public class FileConfigTransaction implements ConfigTransaction { private FileConfigDatabase db; private Manifest manifest; private List<ConfigChange> changeSet; private File changeLogFile; private File changeDatFile; private File manifestLogFile; private File manifestDatFile; private Map<File, RevLogWriter> writers; private ConfigTransactionCache cache; public FileConfigTransaction(FileConfigDatabase db) { this.db = db; this.cache = new FileConfigTransactionCache(); File dbDir = db.getDbDirectory(); // TODO: apply changeset rev manifest = ((FileManifest) db.getManifest(null)).duplicate(); changeSet = new ArrayList<ConfigChange>(); changeLogFile = new File(dbDir, "changeset.log"); changeDatFile = new File(dbDir, "changeset.dat"); manifestLogFile = new File(dbDir, "manifest.log"); manifestDatFile = new File(dbDir, "manifest.dat"); writers = new HashMap<File, RevLogWriter>(); } public Map<File, RevLogWriter> getWriters() { return writers; } @Override public Manifest getManifest() { return manifest; } @Override public ConfigDatabase getDatabase() { return db; } @Override public void begin() { db.lock(); } @Override public void begin(int timeout) { db.lock(timeout); } /** * log all transaction */ @Override public void log(CommitOp op, String colName, int docId, long rev, int index) { CollectionEntry col = null; if (op == CommitOp.CreateCol) { col = new CollectionEntry(db.nextCollectionId(), colName); } else col = manifest.getCollectionEntry(colName); ConfigEntry entry = new ConfigEntry(col.getId(), docId, rev, index); if (op == CommitOp.CreateDoc || op == CommitOp.UpdateDoc) manifest.add(entry); else if (op == CommitOp.DeleteDoc) manifest.remove(entry); else if (op == CommitOp.CreateCol) manifest.add(col); else if (op == CommitOp.DropCol) manifest.remove(col); changeSet.add(new ConfigChange(op, col.getName(), col.getId(), docId)); } @Override public void commit(String committer, String log) { try { Manifest manifest = FileManifest.writeManifest(this.manifest, manifestLogFile, manifestDatFile); ChangeSetWriter.log(changeLogFile, changeDatFile, changeSet, manifest.getId(), committer, log); // do not move this code to finally block. rollback should be called // after exception throwing closeWriters(); db.unlock(); } catch (Exception e) { throw new IllegalStateException(e); } } @Override public void rollback() { closeWriters(); db.unlock(); } @Override public ConfigTransactionCache getCache() { return cache; } private void closeWriters() { for (RevLogWriter writer : writers.values()) { writer.close(); } writers.clear(); } }