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:
hns 2005-03-18 02:05:24 +00:00
parent d8dc1fc61e
commit 9ef4316dd6
4 changed files with 136 additions and 139 deletions

View file

@ -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;

View file

@ -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"));
}
}
/**

View file

@ -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();

View file

@ -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