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