You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xindice-dev@xml.apache.org by by...@apache.org on 2006/05/17 21:16:29 UTC
svn commit: r407356 - in
/xml/xindice/trunk/java/src/org/apache/xindice/core: Database.java
DatabaseChangeObserver.java DatabaseShutdownHandler.java
Author: byrne
Date: Wed May 17 12:16:29 2006
New Revision: 407356
URL: http://svn.apache.org/viewvc?rev=407356&view=rev
Log:
Changes to include and automatic flush collections that have had document changes. Its currently set to run every minute but can be adjusted or
later a configure parameter can be set to override the default.
Also added a shutdown hook to help catch unclean Java shutdowns. This hook just insure that open databases that haven't been closed get properly
closed.
Todd Byrne
Added:
xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseChangeObserver.java (with props)
xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseShutdownHandler.java (with props)
Modified:
xml/xindice/trunk/java/src/org/apache/xindice/core/Database.java
Modified: xml/xindice/trunk/java/src/org/apache/xindice/core/Database.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/Database.java?rev=407356&r1=407355&r2=407356&view=diff
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/Database.java (original)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/Database.java Wed May 17 12:16:29 2006
@@ -60,7 +60,12 @@
public static final String DBROOT_DEFAULT = "./db/";
private static final Map databases = new HashMap(); // String to Database
-
+ private static final DatabaseShutdownHandler shutdownHandler = new DatabaseShutdownHandler();
+ static {
+ // sets up our golbal observer. will automatically flush document
+ // changes to disk.
+ DBObserver.setInstance(new DatabaseChangeObserver());
+ }
/**
* This will return an instance of a Database for the given
* name if one has already been loaded, otherwise it will
@@ -142,38 +147,59 @@
private boolean sysInit;
private SystemCollection systemCollection;
private FileOutputStream lock;
-
+ private boolean closed;
public Database() {
super();
this.docCache = new DocumentCache();
this.engine = new QueryEngine(this);
+ shutdownHandler.registerDatabase(this);
+ closed = false;
}
-
/**
- * @see org.apache.xindice.core.DBObject#close()
+ * Checks to see if it has been closed to insure that it doesn't try to do it
+ * twice.
+ *
+ * @param removeFromShutdown If true removes its self from the shutdown hook
*/
- public boolean close() throws DBException {
- if (log.isDebugEnabled()) {
- log.debug("Shutting down database: '" + getName() + "'");
- }
+ protected synchronized boolean close(boolean removeFromShutdown) throws DBException {
- flushConfig();
- super.close();
+ if(removeFromShutdown) {
+ // we have already been closed so no need to do this again.
+ shutdownHandler.removeDatabase(this);
+ }
+ // check to see if we have already been closed.
+ if(!closed)
+ {
+ if(log.isDebugEnabled()) {
+ log.debug("Shutting down database: '" + getName() + "'");
+ }
- // Release database lock
- try {
- this.lock.close();
- } catch (IOException e) {
- // Ignore IO exception
- }
- this.lock = null;
+ flushConfig();
+ super.close();
- synchronized (databases) {
- databases.remove(getName());
- }
+ // Release database lock
+ try {
+ this.lock.close();
+ }
+ catch(IOException e) {
+ // Ignore IO exception
+ }
+ this.lock=null;
+ synchronized(databases) {
+ databases.remove(getName());
+ }
+ closed = true;
+ }
return true;
+ }
+ /**
+ * @see org.apache.xindice.core.DBObject#close()
+ * @see org.apache.xindice.core.Database#close(boolean removeFromShutdown)
+ */
+ public boolean close() throws DBException {
+ return close(true);
}
/**
Added: xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseChangeObserver.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseChangeObserver.java?rev=407356&view=auto
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseChangeObserver.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseChangeObserver.java Wed May 17 12:16:29 2006
@@ -0,0 +1,160 @@
+/*
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
+ * 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.apache.xindice.core;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xindice.core.data.Key;
+import org.apache.xindice.core.data.Record;
+import org.apache.xindice.util.Configuration;
+import org.w3c.dom.Document;
+
+/**
+ * DatabaseChangeObserver is going to handle changes to collections by
+ * flushing the apporate collection Filer.
+ *
+ * This current version we are only going to worry about document changes and
+ * their Filer storage are kept updated.
+ *
+ * <a href="mailto:toddbyrne@gmail.com">Todd Byrne</a>
+ */
+public class DatabaseChangeObserver extends DBObserver {
+ private static final Log log = LogFactory.getLog(DatabaseChangeObserver.class);
+ // by using a hashtable instead of a queue collections only get added once.
+ private Hashtable collectionDirtyFlags;
+ private Timer flushTimer;
+ /** One minute flush period **/
+ private long FLUSH_PERIOD = 1000 * 60;
+ public DatabaseChangeObserver() {
+ collectionDirtyFlags = new Hashtable();
+ flushTimer = new Timer(true);
+ flushTimer.schedule(new FlushTask(),FLUSH_PERIOD,FLUSH_PERIOD);
+ }
+ /**
+ * Queues the collection to be flushed by the FlushTask synchronized
+ * by the hashtable
+ * @param col Collection
+ * @param key Key
+ * @throws DBException
+ */
+ public void dropDocument(Collection col, Key key) throws DBException {
+ collectionDirtyFlags.put(col,Boolean.TRUE);
+ }
+ /**
+ *
+ * @param col Collection
+ * @param key Key
+ * @param document Document
+ * @param create boolean
+ * @throws DBException
+ */
+ public void putDocument(Collection col, Key key, Document document, boolean create) throws DBException {
+ collectionDirtyFlags.put(col,Boolean.TRUE);
+ }
+
+ /**
+ *
+ * @param col Collection
+ * @throws DBException
+ */
+ public void createCollection(Collection col) throws DBException {
+ }
+
+ /**
+ *
+ * @param col Collection
+ * @param record Record
+ * @param document Document
+ * @throws DBException
+ */
+ public void loadDocument(Collection col, Record record, Document document) throws DBException {
+ }
+ /**
+ *
+ * @param col Collection
+ * @throws DBException
+ */
+ public void dropCollection(Collection col) throws DBException {
+ }
+
+ /**
+ *
+ * @param db Database
+ * @param cfg Configuration
+ */
+ public void flushDatabaseConfig(Database db, Configuration cfg) {
+ }
+
+ /**
+ *
+ * @param col Collection
+ * @param cfg Configuration
+ */
+ public void setCollectionConfig(Collection col, Configuration cfg) {
+ }
+
+ /**
+ *
+ * @param db Database
+ * @param collections Map
+ * @param cfg Configuration
+ */
+ public void setDatabaseConfig(Database db, Map collections, Configuration cfg) {
+ }
+ /**
+ * FlushTask handles the work of
+ */
+ private class FlushTask extends TimerTask{
+ public FlushTask(){
+ }
+ public void run(){
+
+ synchronized(collectionDirtyFlags) {
+
+ Iterator collections = collectionDirtyFlags.entrySet().iterator();
+ int flushCount = 0;
+ while(collections.hasNext())
+ {
+ Map.Entry e = (Map.Entry)collections.next();
+ Collection c = (Collection)e.getKey();
+ try
+ {
+ // don't need to flush indexes because everytime a document
+ // gets added the indexes get flushed.
+ c.getFiler().flush();
+ flushCount ++;
+ }
+ catch(DBException ex) {
+ log.error("Couldn't flush collection: " + c.getName() , ex);
+ }
+ }
+ log.info("Successfully flushed " + flushCount + " collections out of " +
+ collectionDirtyFlags.size());
+ collectionDirtyFlags.clear();
+ }
+ }
+ }
+
+}
Propchange: xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseChangeObserver.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseShutdownHandler.java
URL: http://svn.apache.org/viewvc/xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseShutdownHandler.java?rev=407356&view=auto
==============================================================================
--- xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseShutdownHandler.java (added)
+++ xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseShutdownHandler.java Wed May 17 12:16:29 2006
@@ -0,0 +1,75 @@
+/*
+ * Copyright 1999-2006 The Apache Software Foundation.
+ *
+ * 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.apache.xindice.core;
+
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Going to handle the JVM Shutdown hook and insuring clean shutdown
+ * of all registered Database Intances.
+ *
+ * <a href="mailto:toddbyrne@gmail.com">Todd Byrne</a>
+ */
+public class DatabaseShutdownHandler implements Runnable{
+
+ private Hashtable databases;
+
+ public DatabaseShutdownHandler() {
+ databases = new Hashtable();
+ Runtime.getRuntime().addShutdownHook(new Thread(this));
+ }
+ /**
+ * @param db database to register
+ */
+ public void registerDatabase(Database db) {
+ databases.put(db, Boolean.TRUE);
+ }
+ /**
+ * @param db removed the database from the hashtable
+ */
+ public void removeDatabase(Database db) {
+ databases.remove(db);
+ }
+ /**
+ * Cleans up any unclosed databases before the JVM exits.
+ */
+ public void run() {
+ synchronized(databases) {
+ Iterator dbs = databases.entrySet().iterator();
+ while(dbs.hasNext())
+ {
+ Database db = (Database)((Map.Entry)dbs.next()).getKey();
+
+ // synch again on the db object just incase a close operation
+ // is happening on a different thread
+ synchronized(db) {
+ // call close but don't bother removing the db from the database
+ // table
+ try {
+ db.close(false);
+ System.out.println("Dirty close on: " + db.getName());
+ }
+ catch(DBException ex) {
+ }
+ }
+ }
+ databases.clear();
+ }
+ }
+}
Propchange: xml/xindice/trunk/java/src/org/apache/xindice/core/DatabaseShutdownHandler.java
------------------------------------------------------------------------------
svn:eol-style = native