diff --git a/src/dynamo-framework/com/silverwrist/dynamo/iface/IndexManagerConfig.java b/src/dynamo-framework/com/silverwrist/dynamo/iface/IndexManagerConfig.java index 2c02d87..920ea95 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/iface/IndexManagerConfig.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/iface/IndexManagerConfig.java @@ -17,8 +17,15 @@ */ package com.silverwrist.dynamo.iface; +import com.silverwrist.dynamo.except.DatabaseException; +import com.silverwrist.dynamo.except.IndexException; + public interface IndexManagerConfig { public ComponentShutdown registerResolver(String namespace, String name, IndexedObjectResolver res); + public void createIndex(String namespace, String name, String analyzer) throws DatabaseException, IndexException; + + public void deleteIndex(String namespace, String name) throws DatabaseException, IndexException; + } // end interface IndexManagerConfig diff --git a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexDirectoryImpl.java b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexDirectoryImpl.java index 5b06e1f..7417d4e 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexDirectoryImpl.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexDirectoryImpl.java @@ -428,4 +428,17 @@ class IndexDirectoryImpl extends Directory } // end detach + void abandon() + { + LinkedList files = new LinkedList(m_current.values()); + m_current.clear(); + while (!(files.isEmpty())) + { // get each file in turn and release it till it dies + CurrentFile cf = (CurrentFile)(files.removeFirst()); + cf.abandon(); + + } // end while + + } // end abandon + } // end class IndexDirectoryImpl diff --git a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerObject.java b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerObject.java index 4f70a47..7b67d2b 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerObject.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerObject.java @@ -74,6 +74,8 @@ public class IndexManagerObject private static Logger logger = Logger.getLogger(IndexManagerObject.class); + private static final String DEFAULT_ANALYZER = "org.apache.lucene.analysis.standard.StandardAnalyzer"; + /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- @@ -225,7 +227,8 @@ public class IndexManagerObject } // end if - rc = new IndexServiceImpl(this,new QualifiedNameKey(namespace,name),ndx,m_ops.getIndexOps(),m_cleanupqueue); + rc = new IndexServiceImpl(this,new QualifiedNameKey(namespace,name),ndx,m_ops.getIndexOps(), + m_cleanupqueue,false); m_indexcache.put(key,rc); } // end if @@ -247,6 +250,64 @@ public class IndexManagerObject } // end registerResolver + public void createIndex(String namespace, String name, String analyzer) throws DatabaseException, IndexException + { + if (analyzer==null) + analyzer = DEFAULT_ANALYZER; + IndexServiceImpl.createAnalyzer(analyzer); + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (this) + { // call down to database to create index + int ndx = m_ops.createIndexID(key.getNamespaceID(),key.getName(),analyzer); + if (ndx==-1) + { // this index already exists + IndexException ie = new IndexException(IndexManagerObject.class,"IndexMessages","index.exists"); + ie.setParameter(0,namespace); + ie.setParameter(1,name); + throw ie; + + } // end if + + // now create the index service object and put it in the cache + IndexServiceImpl tmp = new IndexServiceImpl(this,new QualifiedNameKey(namespace,name),ndx,m_ops.getIndexOps(), + m_cleanupqueue,true); + m_indexcache.put(key,tmp); + + } // end synchronized block + + } // end createIndex + + public void deleteIndex(String namespace, String name) throws DatabaseException, IndexException + { + PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + synchronized (this) + { // see what the index ID is first + int ndx = m_ops.getIndexID(key.getNamespaceID(),key.getName()); + if (ndx==-1) + { // the index is not present - bail out + IndexException ie = new IndexException(IndexManagerObject.class,"IndexMessages","no.such.index"); + ie.setParameter(0,namespace); + ie.setParameter(1,name); + throw ie; + + } // end if + + // is there an IndexServiceImpl for this index? if so, take it down + IndexServiceImpl tmp = (IndexServiceImpl)(m_indexcache.get(key)); + if (tmp!=null) + { // abandon this index + m_indexcache.remove(key); + tmp.abandon(); + + } // end if + + // now blow away the database data + m_ops.deleteIndex(ndx); + + } // end synchronized block + + } // end deleteIndex + /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- @@ -270,3 +331,4 @@ public class IndexManagerObject } // end getResolver } // end class IndexManagerObject + diff --git a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerOps.java b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerOps.java index b78331d..4751d1f 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerOps.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerOps.java @@ -64,6 +64,10 @@ abstract class IndexManagerOps extends OpsBase abstract int getIndexID(int nsid, String name) throws DatabaseException; + abstract int createIndexID(int nsid, String name, String analyzer) throws DatabaseException; + + abstract void deleteIndex(int ndx) throws DatabaseException; + /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- diff --git a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerOps_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerOps_mysql.java index af2df76..7526548 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerOps_mysql.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexManagerOps_mysql.java @@ -81,4 +81,98 @@ public class IndexManagerOps_mysql extends IndexManagerOps } // end getIndexID + int createIndexID(int nsid, String name, String analyzer) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the tables + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES ndx_main WRITE;"); + + // look to see if it's already in the list + stmt = conn.prepareStatement("SELECT ndxid FROM ndx_main WHERE nsid = ? AND name = ?;"); + stmt.setInt(1,nsid); + stmt.setString(2,name); + rs = stmt.executeQuery(); + if (rs.next()) + return -1; // already present + rs.close(); + rs = null; + stmt.close(); + + // Now insert it! + stmt = conn.prepareStatement("INSERT INTO ndx_main (nsid, name, analyzer) VALUES (?, ?, ?);"); + stmt.setInt(1,nsid); + stmt.setString(2,name); + stmt.setString(3,analyzer); + stmt.executeUpdate(); + return MySQLUtils.getLastInsertInt(conn); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end createIndexID + + void deleteIndex(int ndx) throws DatabaseException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + try + { // get a connection + conn = getConnection(); + + // lock the tables + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES ndx_main WRITE, ndx_files WRITE, ndx_locks WRITE;"); + + // Do the deletes. + stmt = conn.prepareStatement("DELETE FROM ndx_main WHERE ndxid = ?;"); + stmt.setInt(1,ndx); + stmt.executeUpdate(); + stmt.close(); + stmt = conn.prepareStatement("DELETE FROM ndx_files WHERE ndxid = ?;"); + stmt.setInt(1,ndx); + stmt.executeUpdate(); + stmt.close(); + stmt = conn.prepareStatement("DELETE FROM ndx_locks WHERE ndxid = ?;"); + stmt.setInt(1,ndx); + stmt.executeUpdate(); + + } // end try + catch (SQLException e) + { // translate to a general DatabaseException + throw generalException(e); + + } // end catch + finally + { // shut everything down + MySQLUtils.unlockTables(conn); + SQLUtils.shutdown(stmt); + SQLUtils.shutdown(stmt2); + SQLUtils.shutdown(conn); + + } // end finally + + } // end deleteIndex + } // end class IndexManagerOps_mysql diff --git a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexMessages.properties b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexMessages.properties index 13016c2..4050fbc 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexMessages.properties +++ b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexMessages.properties @@ -24,3 +24,5 @@ addItem.fail=Unable to add a new item (namespace {0}, name {1}) to index {2}. deleteItem.fail=Unable to remove an item (namespace {0}, name {1}) from index {2}. query.syntax=Parse error in query string: {0} query.fail=Unable to execute search query. +indexCreate.fail=Unable to create the index {0}. +index.exists=The index with namespace {0} and name {1} already exists. diff --git a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexServiceImpl.java b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexServiceImpl.java index b108c3b..32e0170 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/index/IndexServiceImpl.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/index/IndexServiceImpl.java @@ -185,49 +185,31 @@ class IndexServiceImpl implements IndexService *-------------------------------------------------------------------------------- */ - IndexServiceImpl(IndexManagerObject base, QualifiedNameKey identity, int ndx, IndexOps ops, ReferenceQueue rq) - throws DatabaseException, IndexException + IndexServiceImpl(IndexManagerObject base, QualifiedNameKey identity, int ndx, IndexOps ops, ReferenceQueue rq, + boolean create) throws DatabaseException, IndexException { - String ana_klass = null; - try - { // Create the analyzer class. - ana_klass = ops.getAnalyzerClassName(ndx); - m_analyzer = (Analyzer)(Class.forName(ana_klass).newInstance()); - - } // end try - catch (ClassNotFoundException e) - { // unable to find the Analyzer class - IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","analyzer.class.notfound",e); - ie.setParameter(0,ana_klass); - throw ie; - - } // end catch - catch (IllegalAccessException e) - { // problem creating the analyzer class - IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","analyzer.noCreate",e); - ie.setParameter(0,ana_klass); - throw ie; - - } // end catch - catch (InstantiationException e) - { // unable to instantiate the class - IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","analyzer.noCreate",e); - ie.setParameter(0,ana_klass); - throw ie; - - } // end catch - catch (ClassCastException e) - { // bad class specified - IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","analyzer.badType",e); - ie.setParameter(0,ana_klass); - throw ie; - - } // end catch - + m_analyzer = createAnalyzer(ops.getAnalyzerClassName(ndx)); m_base = base; m_identity = identity; m_directory = new IndexDirectoryImpl(ndx,ops); m_cleanup = new DirectoryAutoCleanup(this,m_directory,rq); + if (create) + { // create the new index + try + { // Use an IndexWriter to create the index for the first time. + IndexWriter iwr = new IndexWriter(m_directory,m_analyzer,true); + iwr.close(); + + } // end try + catch (IOException e) + { // translate Lucene's IOException here + IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","indexCreate.fail",e); + ie.setParameter(0,m_identity.toString()); + throw ie; + + } // end catch + + } // end if } // end constructor @@ -492,4 +474,59 @@ class IndexServiceImpl implements IndexService } // end queryCount + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + void abandon() + { + m_cleanup.clear(); + m_directory.abandon(); + + } // end abandon + + /*-------------------------------------------------------------------------------- + * External static operations + *-------------------------------------------------------------------------------- + */ + + static Analyzer createAnalyzer(String classname) throws IndexException + { + try + { // Create the analyzer class. + return (Analyzer)(Class.forName(classname).newInstance()); + + } // end try + catch (ClassNotFoundException e) + { // unable to find the Analyzer class + IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","analyzer.class.notfound",e); + ie.setParameter(0,classname); + throw ie; + + } // end catch + catch (IllegalAccessException e) + { // problem creating the analyzer class + IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","analyzer.noCreate",e); + ie.setParameter(0,classname); + throw ie; + + } // end catch + catch (InstantiationException e) + { // unable to instantiate the class + IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","analyzer.noCreate",e); + ie.setParameter(0,classname); + throw ie; + + } // end catch + catch (ClassCastException e) + { // bad class specified + IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","analyzer.badType",e); + ie.setParameter(0,classname); + throw ie; + + } // end catch + + } // end createAnalyzer + } // end class IndexServiceImpl