Cleaned up embedded database code:
Cleaned up IDatabase interface, moved code into XmlDatabase, removed IDGenerator code from NodeManager and Transactor.
This commit is contained in:
parent
d8dc1fc61e
commit
9ef4316dd6
4 changed files with 136 additions and 139 deletions
|
@ -16,89 +16,91 @@
|
|||
|
||||
package helma.objectmodel;
|
||||
|
||||
import helma.objectmodel.INode;
|
||||
import helma.objectmodel.db.IDGenerator;
|
||||
import helma.framework.core.Application;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Interface that is implemented by Database wrappers
|
||||
*/
|
||||
public interface IDatabase {
|
||||
// db-related
|
||||
|
||||
/**
|
||||
* Initialize the database with the given db directory and application.
|
||||
*
|
||||
* @param dbHome
|
||||
* @param app
|
||||
*/
|
||||
public void init(File dbHome, Application app);
|
||||
|
||||
/**
|
||||
* Let the database know we're shutting down.
|
||||
*/
|
||||
public void shutdown();
|
||||
|
||||
// id-related
|
||||
/**
|
||||
* Get the next ID from the db's ID generator
|
||||
* @return a unique id
|
||||
* @throws ObjectNotFoundException
|
||||
*/
|
||||
public String nextID() throws ObjectNotFoundException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param transaction ...
|
||||
*
|
||||
* @return ...
|
||||
*
|
||||
* @throws IOException ...
|
||||
*/
|
||||
public IDGenerator getIDGenerator(ITransaction transaction)
|
||||
throws IOException, ObjectNotFoundException;
|
||||
|
||||
/**
|
||||
* Get the node from the database specified by the given key.
|
||||
*
|
||||
*
|
||||
* @param transaction ...
|
||||
* @param idgen ...
|
||||
*
|
||||
* @throws IOException ...
|
||||
* @param transaction
|
||||
* @param key
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ObjectNotFoundException if no object exists for the key.
|
||||
*/
|
||||
public void saveIDGenerator(ITransaction transaction, IDGenerator idgen)
|
||||
throws IOException;
|
||||
|
||||
// node-related
|
||||
public INode getNode(ITransaction transaction, String key)
|
||||
throws IOException, ObjectNotFoundException;
|
||||
|
||||
/**
|
||||
* Save a node with the given key
|
||||
*
|
||||
*
|
||||
* @param transaction ...
|
||||
* @param key ...
|
||||
* @param node ...
|
||||
*
|
||||
* @throws IOException ...
|
||||
* @param transaction
|
||||
* @param key
|
||||
* @param node
|
||||
* @throws IOException
|
||||
*/
|
||||
public void saveNode(ITransaction transaction, String key, INode node)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Delete the node specified by the given key.
|
||||
*
|
||||
* @param transaction ...
|
||||
* @param key ...
|
||||
*
|
||||
* @throws IOException ...
|
||||
*/
|
||||
public void deleteNode(ITransaction transaction, String key)
|
||||
throws IOException;
|
||||
|
||||
// transaction-related
|
||||
/**
|
||||
* Begin a new transaction.
|
||||
*
|
||||
* @return the transaction
|
||||
*/
|
||||
public ITransaction beginTransaction();
|
||||
|
||||
/**
|
||||
* Commit a transaction, making all changes persistent
|
||||
*
|
||||
*
|
||||
* @param transaction ...
|
||||
*
|
||||
* @throws DatabaseException ...
|
||||
* @param transaction
|
||||
* @throws DatabaseException
|
||||
*/
|
||||
public void commitTransaction(ITransaction transaction)
|
||||
throws DatabaseException;
|
||||
|
||||
/**
|
||||
* Abort a transaction, rolling back all changes.
|
||||
*
|
||||
*
|
||||
* @param transaction ...
|
||||
*
|
||||
* @throws DatabaseException ...
|
||||
* @param transaction
|
||||
* @throws DatabaseException
|
||||
*/
|
||||
public void abortTransaction(ITransaction transaction)
|
||||
throws DatabaseException;
|
||||
|
|
|
@ -22,6 +22,7 @@ import helma.objectmodel.*;
|
|||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
|
@ -39,8 +40,6 @@ public final class NodeManager {
|
|||
protected Application app;
|
||||
private ObjectCache cache;
|
||||
protected IDatabase db;
|
||||
protected IDGenerator idgen;
|
||||
private long idBaseValue = 1L;
|
||||
private boolean logSql;
|
||||
private Log sqlLog = null;
|
||||
protected boolean logReplication;
|
||||
|
@ -62,7 +61,7 @@ public final class NodeManager {
|
|||
* application properties. An embedded database will be
|
||||
* created in dbHome if one doesn't already exist.
|
||||
*/
|
||||
public void init(String dbHome, Properties props)
|
||||
public void init(File dbHome, Properties props)
|
||||
throws DatabaseException, ClassNotFoundException,
|
||||
IllegalAccessException, InstantiationException {
|
||||
String cacheImpl = props.getProperty("cacheimpl", "helma.util.CacheMap");
|
||||
|
@ -85,19 +84,8 @@ public final class NodeManager {
|
|||
addNodeChangeListener(replicator);
|
||||
}
|
||||
|
||||
// get the initial id generator value
|
||||
String idb = props.getProperty("idBaseValue");
|
||||
|
||||
if (idb != null) {
|
||||
try {
|
||||
idBaseValue = Long.parseLong(idb);
|
||||
idBaseValue = Math.max(1L, idBaseValue); // 0 and 1 are reserved for root nodes
|
||||
} catch (NumberFormatException ignore) {
|
||||
}
|
||||
}
|
||||
|
||||
db = new XmlDatabase(dbHome, this);
|
||||
initDb();
|
||||
db = new XmlDatabase();
|
||||
db.init(dbHome, app);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -114,59 +102,6 @@ public final class NodeManager {
|
|||
* Method used to create the root node and id-generator, if they don't exist already.
|
||||
*/
|
||||
public void initDb() throws DatabaseException {
|
||||
ITransaction txn = null;
|
||||
|
||||
try {
|
||||
txn = db.beginTransaction();
|
||||
|
||||
try {
|
||||
idgen = db.getIDGenerator(txn);
|
||||
|
||||
if (idgen.getValue() < idBaseValue) {
|
||||
idgen.setValue(idBaseValue);
|
||||
db.saveIDGenerator(txn, idgen);
|
||||
}
|
||||
} catch (ObjectNotFoundException notfound) {
|
||||
// will start with idBaseValue+1
|
||||
idgen = new IDGenerator(idBaseValue);
|
||||
db.saveIDGenerator(txn, idgen);
|
||||
}
|
||||
|
||||
// check if we need to set the id generator to a base value
|
||||
Node node = null;
|
||||
|
||||
try {
|
||||
node = (Node) db.getNode(txn, "0");
|
||||
node.nmgr = safe;
|
||||
} catch (ObjectNotFoundException notfound) {
|
||||
node = new Node("root", "0", "Root", safe);
|
||||
node.setDbMapping(app.getDbMapping("root"));
|
||||
db.saveNode(txn, node.getID(), node);
|
||||
registerNode(node); // register node with nodemanager cache
|
||||
}
|
||||
|
||||
try {
|
||||
node = (Node) db.getNode(txn, "1");
|
||||
node.nmgr = safe;
|
||||
} catch (ObjectNotFoundException notfound) {
|
||||
node = new Node("users", "1", null, safe);
|
||||
node.setDbMapping(app.getDbMapping("__userroot__"));
|
||||
db.saveNode(txn, node.getID(), node);
|
||||
registerNode(node); // register node with nodemanager cache
|
||||
}
|
||||
|
||||
db.commitTransaction(txn);
|
||||
} catch (Exception x) {
|
||||
System.err.println(x);
|
||||
x.printStackTrace();
|
||||
|
||||
try {
|
||||
db.abortTransaction(txn);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
throw (new DatabaseException("Error initializing db"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -309,13 +309,6 @@ public class Transactor extends Thread {
|
|||
dbm.setLastDataChange(now);
|
||||
}
|
||||
}
|
||||
|
||||
// save the id-generator for the embedded db, if necessary
|
||||
if (nmgr.idgen.dirty) {
|
||||
nmgr.db.saveIDGenerator(txn, nmgr.idgen);
|
||||
nmgr.idgen.dirty = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
|
|
|
@ -20,6 +20,7 @@ import helma.objectmodel.*;
|
|||
import helma.objectmodel.dom.IDGenParser;
|
||||
import helma.objectmodel.dom.XmlDatabaseReader;
|
||||
import helma.objectmodel.dom.XmlWriter;
|
||||
import helma.framework.core.Application;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
@ -32,27 +33,24 @@ import java.util.ArrayList;
|
|||
*/
|
||||
public final class XmlDatabase implements IDatabase {
|
||||
|
||||
private File dbHomeDir;
|
||||
private NodeManager nmgr;
|
||||
private IDGenerator idgen;
|
||||
protected File dbHomeDir;
|
||||
protected Application app;
|
||||
protected NodeManager nmgr;
|
||||
protected IDGenerator idgen;
|
||||
|
||||
// character encoding to use when writing files.
|
||||
// use standard encoding by default.
|
||||
private String encoding = null;
|
||||
protected String encoding = null;
|
||||
|
||||
/**
|
||||
* Creates a new XmlDatabase object.
|
||||
*
|
||||
* @param dbHome ...
|
||||
* @param nmgr ...
|
||||
*
|
||||
* @throws DatabaseException ...
|
||||
* @throws RuntimeException ...
|
||||
* Initializes the database from an application.
|
||||
* @param app
|
||||
* @throws DatabaseException
|
||||
*/
|
||||
public XmlDatabase(String dbHome, NodeManager nmgr)
|
||||
throws DatabaseException {
|
||||
this.nmgr = nmgr;
|
||||
dbHomeDir = new File(dbHome);
|
||||
public void init(File dbHome, Application app) throws DatabaseException {
|
||||
this.app = app;
|
||||
nmgr = app.getNodeManager();
|
||||
dbHomeDir = dbHome;
|
||||
|
||||
if (!dbHomeDir.exists() && !dbHomeDir.mkdirs()) {
|
||||
throw new DatabaseException("Can't create database directory "+dbHomeDir);
|
||||
|
@ -68,7 +66,70 @@ public final class XmlDatabase implements IDatabase {
|
|||
copyStylesheet(stylesheet);
|
||||
}
|
||||
|
||||
this.encoding = nmgr.app.getCharset();
|
||||
this.encoding = app.getCharset();
|
||||
|
||||
// get the initial id generator value
|
||||
long idBaseValue;
|
||||
try {
|
||||
idBaseValue = Long.parseLong(app.getProperty("idBaseValue", "1"));
|
||||
// 0 and 1 are reserved for root nodes
|
||||
idBaseValue = Math.max(1L, idBaseValue);
|
||||
} catch (NumberFormatException ignore) {
|
||||
idBaseValue = 1L;
|
||||
}
|
||||
|
||||
ITransaction txn = null;
|
||||
|
||||
try {
|
||||
txn = beginTransaction();
|
||||
|
||||
try {
|
||||
idgen = getIDGenerator(txn);
|
||||
|
||||
if (idgen.getValue() < idBaseValue) {
|
||||
idgen.setValue(idBaseValue);
|
||||
}
|
||||
} catch (ObjectNotFoundException notfound) {
|
||||
// will start with idBaseValue+1
|
||||
idgen = new IDGenerator(idBaseValue);
|
||||
}
|
||||
|
||||
// check if we need to set the id generator to a base value
|
||||
Node node = null;
|
||||
|
||||
try {
|
||||
node = (Node) getNode(txn, "0");
|
||||
node.nmgr = nmgr.safe;
|
||||
} catch (ObjectNotFoundException notfound) {
|
||||
node = new Node("root", "0", "Root", nmgr.safe);
|
||||
node.setDbMapping(app.getDbMapping("root"));
|
||||
saveNode(txn, node.getID(), node);
|
||||
// register node with nodemanager cache
|
||||
nmgr.registerNode(node);
|
||||
}
|
||||
|
||||
try {
|
||||
node = (Node) getNode(txn, "1");
|
||||
node.nmgr = nmgr.safe;
|
||||
} catch (ObjectNotFoundException notfound) {
|
||||
node = new Node("users", "1", null, nmgr.safe);
|
||||
node.setDbMapping(app.getDbMapping("__userroot__"));
|
||||
saveNode(txn, node.getID(), node);
|
||||
// register node with nodemanager cache
|
||||
nmgr.registerNode(node);
|
||||
}
|
||||
|
||||
commitTransaction(txn);
|
||||
} catch (Exception x) {
|
||||
x.printStackTrace();
|
||||
|
||||
try {
|
||||
abortTransaction(txn);
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
|
||||
throw (new DatabaseException("Error initializing db"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,6 +184,14 @@ public final class XmlDatabase implements IDatabase {
|
|||
* @throws DatabaseException
|
||||
*/
|
||||
public void commitTransaction(ITransaction txn) throws DatabaseException {
|
||||
if (idgen.dirty) {
|
||||
try {
|
||||
saveIDGenerator(txn);
|
||||
idgen.dirty = false;
|
||||
} catch (IOException x) {
|
||||
throw new DatabaseException(x.toString());
|
||||
}
|
||||
}
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
|
@ -170,15 +239,13 @@ public final class XmlDatabase implements IDatabase {
|
|||
* Write the id-generator to file.
|
||||
*
|
||||
* @param txn
|
||||
* @param idgen
|
||||
* @throws IOException
|
||||
*/
|
||||
public void saveIDGenerator(ITransaction txn, IDGenerator idgen)
|
||||
public void saveIDGenerator(ITransaction txn)
|
||||
throws IOException {
|
||||
File tmp = File.createTempFile("idgen.xml.", ".tmp", dbHomeDir);
|
||||
|
||||
IDGenParser.saveIDGenerator(idgen, tmp);
|
||||
this.idgen = idgen;
|
||||
|
||||
File file = new File(dbHomeDir, "idgen.xml");
|
||||
if (file.exists() && !file.canWrite()) {
|
||||
|
@ -211,7 +278,7 @@ public final class XmlDatabase implements IDatabase {
|
|||
|
||||
return node;
|
||||
} catch (Exception x) {
|
||||
nmgr.app.logError("Error reading " +f, x);
|
||||
app.logError("Error reading " +f, x);
|
||||
throw new IOException(x.toString());
|
||||
}
|
||||
}
|
||||
|
@ -303,8 +370,8 @@ public final class XmlDatabase implements IDatabase {
|
|||
res.tmpfile.delete();
|
||||
} else {
|
||||
// error - leave tmp file and print a message
|
||||
nmgr.app.logError("*** Error committing "+res.file);
|
||||
nmgr.app.logError("*** Committed version is in "+res.tmpfile);
|
||||
app.logError("*** Error committing "+res.file);
|
||||
app.logError("*** Committed version is in "+res.tmpfile);
|
||||
}
|
||||
} catch (SecurityException ignore) {
|
||||
// shouldn't happen
|
||||
|
|
Loading…
Add table
Reference in a new issue