added the start of the Index Manager, which integrates Lucene indexing into

the base Dynamo framework
This commit is contained in:
Eric J. Bowersox 2003-06-12 19:07:01 +00:00
parent 172ec3b314
commit 60f24d8412
19 changed files with 2302 additions and 0 deletions

View File

@ -59,5 +59,10 @@ velocity.base=/usr/local/jakarta/velocity-1.3.1
# velocity.lib=${velocity.base}
velocity.jarfile=velocity-1.3.1.jar
# [Location of Lucene 1.3RC1]
lucene.base=/usr/local/jakarta/lucene-1.3-rc1
# lucene.lib=${lucene.base}
lucene.jarfile=lucene-1.3-rc1.jar
# [Location of SourceID SSO 1.0b7/1.0 (optional)]
# sourceid.base=${user.home}/sso

View File

@ -72,6 +72,11 @@
<property name="velocity.lib" value="${velocity.base}"/>
<property name="velocity.jarfile" value="velocity.jar"/>
<!-- [Location of Lucene 1.3RC1] -->
<property name="lucene.base" value="../lucene"/>
<property name="lucene.lib" value="${lucene.base}"/>
<property name="lucene.jarfile" value="lucene.jar"/>
<!-- [Location of SourceID SSO 1.0b7/1.0 (optional)] -->
<!-- <property name="sourceid.base" value=""/> -->
@ -85,6 +90,7 @@
<fileset dir="${commlang.lib}" includes="${commlang.jarfile}"/>
<fileset dir="${log4j.lib}" includes="${log4j.jarfile}"/>
<fileset dir="${velocity.lib}" includes="${velocity.jarfile}"/>
<fileset dir="${lucene.lib}" includes="${lucene.jarfile}"/>
</path>
<!-- ============================================================================
@ -291,6 +297,7 @@
<fileset dir="${rhino.lib}" includes="${rhino.jarfile}"/>
<fileset dir="${log4j.lib}" includes="${log4j.jarfile}"/>
<fileset dir="${velocity.lib}" includes="${velocity.jarfile}"/>
<fileset dir="${lucene.lib}" includes="${lucene.jarfile}"/>
</copy>
<copy file="jars/dynamo-test-module.jar" todir="assembly/testapp/WEB-INF/modules"/>
<copy file="conf/dynamo-test.xml" tofile="assembly/testapp/WEB-INF/dynamo.xml"/>
@ -325,6 +332,7 @@
<fileset dir="${rhino.lib}" includes="${rhino.jarfile}"/>
<fileset dir="${log4j.lib}" includes="${log4j.jarfile}"/>
<fileset dir="${velocity.lib}" includes="${velocity.jarfile}"/>
<fileset dir="${lucene.lib}" includes="${lucene.jarfile}"/>
</copy>
<copy file="conf/dynamo-venice.xml" tofile="assembly/venice/WEB-INF/dynamo.xml"/>
<copy file="conf/logging-venice.xml" tofile="assembly/venice/WEB-INF/logging.xml">
@ -368,6 +376,7 @@
<fileset dir="${rhino.lib}" includes="${rhino.jarfile}"/>
<fileset dir="${log4j.lib}" includes="${log4j.jarfile}"/>
<fileset dir="${velocity.lib}" includes="${velocity.jarfile}"/>
<fileset dir="${lucene.lib}" includes="${lucene.jarfile}"/>
<fileset dir="${sourceid.base}" includes="sourceid-sso.jar"/>
<fileset dir="${sourceid.base}/webapp/WEB-INF/lib">
<include name="axis-ant.jar"/>
@ -451,6 +460,7 @@
<link href="http://jakarta.apache.org/commons/lang/api/"/>
<link href="http://jakarta.apache.org/log4j/docs/api/"/>
<link href="http://jakarta.apache.org/velocity/api/"/>
<link href="http://jakarta.apache.org/lucene/docs/api/"/>
</javadoc>
</target>

View File

@ -56,6 +56,10 @@
<database connection="data"/>
</object>
<object name="index" classname="com.silverwrist.dynamo.index.IndexManagerObject" priority="1">
<database connection="data" namespaces="nscache"/>
</object>
<object name="srm" classname="com.silverwrist.dynamo.security.SRMObject" priority="1">
<database connection="data" namespaces="nscache"/>
<user-manager cpoint="srm_proxy"/>

View File

@ -313,6 +313,32 @@ CREATE TABLE us_binary_prop (
PRIMARY KEY (msgid, part, nsid, prop_name)
);
# Listing of registered indexes.
CREATE TABLE ndx_main (
ndxid INT NOT NULL PRIMARY KEY AUTO_INCREMENT, # index ID
nsid INT NOT NULL, # namespace ID of index
name VARCHAR(255) BINARY NOT NULL, # index name
analyzer VARCHAR(255) NOT NULL, # name of analyzer class to construct
UNIQUE INDEX by_name (nsid, name)
);
# The "files" that make up an index.
CREATE TABLE ndx_files (
ndxid INT NOT NULL, # index ID
name VARCHAR(255) BINARY NOT NULL, # file name
length INT NOT NULL DEFAULT 0, # file length
mtime BIGINT NOT NULL DEFAULT 0, # modification time
data LONGBLOB, # the file data
PRIMARY KEY (ndxid, name)
);
# The locks created on an index.
CREATE TABLE ndx_locks (
ndxid INT NOT NULL, # index ID
name VARCHAR(255) BINARY NOT NULL, # lock name
PRIMARY KEY (ndxid, name)
);
############################ following this line are Venice-specific tables ############################
# The table which defines menus.

View File

@ -0,0 +1,58 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.except;
public class IndexException extends ExternalException
{
/*--------------------------------------------------------------------------------
* Constructors
*--------------------------------------------------------------------------------
*/
/**
* Constructs a new <CODE>IndexException</CODE> instance.
*
* @param caller The classname of the class that's creating the exception. Its class loader
* and package name will be used, together with <CODE>bundle</CODE>, to find the
* resource bundle.
* @param bundle The name of the resource bundle to be loaded.
* @param message_id The identifier of the message to be loaded from the bundle.
*/
public IndexException(Class caller, String bundle, String message_id)
{
super(caller,bundle,message_id);
} // end constructor
/**
* Constructs a new <CODE>IndexException</CODE> instance.
*
* @param caller The classname of the class that's creating the exception. Its class loader
* and package name will be used, together with <CODE>bundle</CODE>, to find the
* resource bundle.
* @param bundle The name of the resource bundle to be loaded.
* @param message_id The identifier of the message to be loaded from the bundle.
* @param inner The exception to be nested inside this one.
*/
public IndexException(Class caller, String bundle, String message_id, Throwable inner)
{
super(caller,bundle,message_id,inner);
} // end constructor
} // end class IndexException

View File

@ -0,0 +1,29 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.iface;
import com.silverwrist.dynamo.except.DatabaseException;
import com.silverwrist.dynamo.except.IndexException;
public interface IndexManager
{
public Object resolveObjectReference(String namespace, String name, String tag) throws IndexException;
public IndexService openIndex(String namespace, String name) throws DatabaseException, IndexException;
} // end interface IndexManager

View File

@ -0,0 +1,24 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.iface;
public interface IndexManagerConfig
{
public ComponentShutdown registerResolver(String namespace, String name, IndexedObjectResolver res);
} // end interface IndexManagerConfig

View File

@ -0,0 +1,29 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.iface;
import com.silverwrist.dynamo.except.IndexException;
public interface IndexService
{
public void addItem(String item_namespace, String item_name, Object item, String scope, java.util.Date date,
DynamoUser owner, String text) throws IndexException;
public boolean deleteItem(String item_namespace, String item_name, Object item) throws IndexException;
} // end interface IndexService

View File

@ -0,0 +1,28 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.iface;
import com.silverwrist.dynamo.except.IndexException;
public interface IndexedObjectResolver
{
public String getResolverTag(Object obj) throws IndexException;
public Object resolveObject(String tag) throws IndexException;
} // end interface IndexedObjectResolver

View File

@ -0,0 +1,290 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import java.io.*;
import org.apache.log4j.Logger;
import org.apache.lucene.store.*;
class CurrentFile
{
/*--------------------------------------------------------------------------------
* Internal class implementing the random-access write capability
*--------------------------------------------------------------------------------
*/
private class MyOutput extends org.apache.lucene.store.OutputStream
{
/*====================================================================
* Attributes
*====================================================================
*/
private RandomAccessFile m_fptr;
/*====================================================================
* Constructor
*====================================================================
*/
MyOutput() throws IOException
{
super();
m_fptr = new RandomAccessFile(m_file,"rw");
addRef();
} // end constructor
/*====================================================================
* Abstract implementations from class OutputStream
*====================================================================
*/
protected void flushBuffer(byte[] b, int len) throws IOException
{
if ((len>0) && (b!=null))
{ // write data
m_fptr.write(b,0,len);
m_mtime = System.currentTimeMillis();
m_length = m_fptr.length();
m_modified = true;
} // end if
} // end flushBuffer
public long length() throws IOException
{
return m_fptr.length();
} // end length
/*====================================================================
* Overrides from class OutputStream
*====================================================================
*/
public void close() throws IOException
{
super.close();
m_fptr.close();
release();
} // end close
public void seek(long pos) throws IOException
{
super.seek(pos);
m_fptr.seek(pos);
} // end seek
} // end class MyOutput
/*--------------------------------------------------------------------------------
* Internal class implementing the random-access read capability
*--------------------------------------------------------------------------------
*/
private class MyInput extends org.apache.lucene.store.InputStream
{
/*====================================================================
* Attributes
*====================================================================
*/
private RandomAccessFile m_fptr;
/*====================================================================
* Constructor
*====================================================================
*/
MyInput() throws IOException
{
super();
m_fptr = new RandomAccessFile(m_file,"r");
addRef();
} // end constructor
/*====================================================================
* Abstract implementations from class InputStream
*====================================================================
*/
protected void readInternal(byte[] b, int offset, int length) throws IOException
{
m_fptr.readFully(b,offset,length);
} // end readInternal
public void close() throws IOException
{
m_fptr.close();
release();
} // end close
protected void seekInternal(long pos) throws IOException
{
m_fptr.seek(pos);
} // end seekInternal
/*====================================================================
* Overrides from class InputStream
*====================================================================
*/
public Object clone()
{
try
{ // return a new input object
return new MyInput();
} // end try
catch (IOException e)
{ // whoops!
logger.error("CurrentFile.MyInput.clone(): unable to clone file",e);
return null;
} // end catch
} // end clone
} // end class MyInput
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(CurrentFile.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private IndexDirectoryImpl m_base;
private File m_file;
private String m_name;
private long m_length;
private long m_mtime;
private int m_refcount = 1;
private boolean m_modified = false;
private boolean m_noupdate = true;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
CurrentFile(IndexDirectoryImpl base, File file, String name, long length, long mtime)
{
m_base = base;
m_file = file;
m_name = name;
m_length = length;
m_mtime = mtime;
} // end constructor
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
synchronized int addRef()
{
return ++m_refcount;
} // end addRef
synchronized int release() throws IOException
{
int rc = --m_refcount;
if (rc==0)
{ // dump this file back to the database
if (m_modified && !m_noupdate)
m_base.storeFile(m_name,m_mtime,m_file);
m_base.detach(m_name);
m_base = null;
m_file.delete();
m_file = null;
} // end if
return rc;
} // end release
void abandon()
{
m_base.detach(m_name);
m_base = null;
m_file.delete();
m_file = null;
} // end abandon
org.apache.lucene.store.OutputStream openOutput() throws IOException
{
return new MyOutput();
} // end openOutput
org.apache.lucene.store.InputStream openInput() throws IOException
{
return new MyInput();
} // end openInput
long getModTime()
{
return m_mtime;
} // end getModTime
void setModTime(long val)
{
m_mtime = val;
m_modified = true;
} // end setModTime
void noUpdate()
{
m_noupdate = true;
} // end noUpdate
void setName(String s)
{
m_name = s;
} // end setName
long length()
{
return m_length;
} // end length
} // end class CurrentFile

View File

@ -0,0 +1,85 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import java.io.*;
import java.lang.ref.*;
import org.apache.log4j.Logger;
class DirectoryAutoCleanup extends PhantomReference
{
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(DirectoryAutoCleanup.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private IndexDirectoryImpl m_directory;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
DirectoryAutoCleanup(IndexServiceImpl service, IndexDirectoryImpl directory, ReferenceQueue rq)
{
super(service,rq);
m_directory = directory;
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class Reference
*--------------------------------------------------------------------------------
*/
public void clear()
{
m_directory = null;
super.clear();
} // end clear
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
void cleanup()
{
try
{ // close the directory!
if (m_directory!=null)
m_directory.close();
} // end try
catch (IOException e)
{ // whoops!
logger.warn("DirectoryAutoCleanup.cleanup(): close failed",e);
} // end catch
} // end cleanup
} // end class DirectoryAutoCleanup

View File

@ -0,0 +1,431 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import java.io.*;
import java.util.*;
import org.apache.log4j.Logger;
import org.apache.lucene.store.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
class IndexDirectoryImpl extends Directory
{
/*--------------------------------------------------------------------------------
* Internal class implementing the Lock object
*--------------------------------------------------------------------------------
*/
private class MyLock extends Lock
{
/*====================================================================
* Attributes
*====================================================================
*/
private String m_name;
/*====================================================================
* Constructor
*====================================================================
*/
MyLock(String name)
{
m_name = name;
} // end constructor
/*====================================================================
* Abstract implementations from class Lock
*====================================================================
*/
public boolean obtain() throws IOException
{
try
{ // call through to the database
return m_ops.obtainLock(m_ndx,m_name);
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end obtain
public void release()
{
try
{ // call through to the database
m_ops.releaseLock(m_ndx,m_name);
} // end try
catch (DatabaseException e)
{ // just log the exception
logger.warn("IndexDirectoryImpl.MyLock.release(): failed operation",e);
} // end catch
} // end release
} // end class MyLock
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(IndexDirectoryImpl.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private IndexOps m_ops;
private int m_ndx;
private Hashtable m_current = new Hashtable();
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
IndexDirectoryImpl(int ndx, IndexOps ops)
{
super();
m_ops = ops;
m_ndx = ndx;
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
private static final IOException translateException(DatabaseException e)
{
logger.info("database operation threw exception",e);
IOException ie = new IOException("Database error on file operation");
ie.initCause(e);
return ie;
} // end translateException
/*--------------------------------------------------------------------------------
* Abstract implementations from class Directory
*--------------------------------------------------------------------------------
*/
public String[] list() throws IOException
{
try
{ // call through to the database
return m_ops.listFiles(m_ndx);
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end list
public boolean fileExists(String name) throws IOException
{
try
{ // call through to the database
CurrentFile cf = (CurrentFile)(m_current.get(name));
if (cf!=null)
return true;
return (m_ops.getModTime(m_ndx,name)>=0);
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end fileExists
public long fileModified(String name) throws IOException
{
try
{ // call through to the database
CurrentFile cf = (CurrentFile)(m_current.get(name));
if (cf!=null)
return cf.getModTime();
return m_ops.getModTime(m_ndx,name);
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end fileModified
public void touchFile(String name) throws IOException
{
try
{ // call through to the database
long mtime = System.currentTimeMillis();
CurrentFile cf = (CurrentFile)(m_current.get(name));
if (cf!=null)
cf.setModTime(mtime);
else
m_ops.setModTime(m_ndx,name,mtime);
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end touchFile
public void deleteFile(String name) throws IOException
{
try
{ // call through to the database
m_ops.deleteFile(m_ndx,name);
CurrentFile cf = (CurrentFile)(m_current.get(name));
if (cf!=null)
{ // detach file from current and make sure we don't update
m_current.remove(name);
cf.noUpdate();
} // end if
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end deleteFile
public void renameFile(String from, String to) throws IOException
{
try
{ // call through to the database
m_ops.renameFile(m_ndx,from,to);
CurrentFile cf = (CurrentFile)(m_current.get(to));
if (cf!=null)
{ // this file was deleted - detach file from current and make sure we don't update
m_current.remove(to);
cf.noUpdate();
} // end if
cf = (CurrentFile)(m_current.get(from));
if (cf!=null)
{ // reset the name and juggle things
m_current.remove(from);
cf.setName(to);
m_current.put(to,cf);
} // end if
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end renameFile
public long fileLength(String name) throws IOException
{
try
{ // call through to the database
CurrentFile cf = (CurrentFile)(m_current.get(name));
if (cf!=null)
return cf.length();
return m_ops.getLength(m_ndx,name);
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end fileLength
public org.apache.lucene.store.OutputStream createFile(String name) throws IOException
{
long mtime = -1L;
CurrentFile cf = null;
try
{ // create the file entry
mtime = m_ops.createNewEntry(m_ndx,name);
if (mtime==-1L)
throw new IOException("file " + name + " already exists");
// now create a CurrentFile object
cf = new CurrentFile(this,File.createTempFile("dynamo-index",null),name,0L,mtime);
m_current.put(name,cf);
// and open it for writing
org.apache.lucene.store.OutputStream rc = cf.openOutput();
cf.release();
cf = null;
mtime = -1L;
return rc;
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
finally
{ // if we screwed up, back out of stuff
try
{ // but do it without raising any more exceptions
if (cf!=null)
cf.abandon();
if (mtime>=0)
m_ops.deleteFile(m_ndx,name);
} // end try
catch (Exception e)
{ // just ignore exceptions here
logger.warn("IndexDirectoryImpl.createFile(): error recovery threw exception",e);
} // end catch
} // end finally
} // end try
public org.apache.lucene.store.InputStream openFile(String name) throws IOException
{
File tempfile = null;
CurrentFile cf = null;
try
{ // first see if the file's already open
CurrentFile cf2 = (CurrentFile)(m_current.get(name));
if (cf2!=null)
return cf2.openInput(); // open it again
// load the file data
tempfile = File.createTempFile("dynamo-index",null);
long mtime = m_ops.loadFile(m_ndx,name,tempfile);
if (mtime==-1)
throw new IOException("file " + name + " does not exist");
// now create a CurrentFile object
cf = new CurrentFile(this,tempfile,name,tempfile.length(),mtime);
tempfile = null; // done with tempfile
m_current.put(name,cf);
// and open it for reading
org.apache.lucene.store.InputStream rc = cf.openInput();
cf.release();
cf = null;
return rc;
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
finally
{ // if we screwed up, back out of stuff
if (cf!=null)
cf.abandon();
if (tempfile!=null)
tempfile.delete();
} // end finally
} // end openFile
public Lock makeLock(String name)
{
return new MyLock(name);
} // end makeLock
public void close() throws IOException
{
try
{ // Get all the "current" files and close them.
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());
int foo = 1;
while (foo>0)
foo = cf.release();
} // end while
// release any outstanding locks
m_ops.releaseAllLocks(m_ndx);
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end close
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
void storeFile(String name, long mtime, File data) throws IOException
{
try
{ // call through to the database
m_ops.storeFile(m_ndx,name,mtime,data);
} // end try
catch (DatabaseException e)
{ // turn it into an I/O exception
throw translateException(e);
} // end catch
} // end storeFile
void detach(String name)
{
m_current.remove(name);
} // end detach
} // end class IndexDirectoryImpl

View File

@ -0,0 +1,272 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import java.lang.ref.*;
import java.util.*;
import org.apache.commons.collections.*;
import org.apache.log4j.Logger;
import org.w3c.dom.*;
import com.silverwrist.util.xml.*;
import com.silverwrist.dynamo.db.NamespaceCache;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
public class IndexManagerObject
implements NamedObject, ComponentInitialize, ComponentShutdown, IndexManager, IndexManagerConfig
{
/*--------------------------------------------------------------------------------
* Internal class which scans the cleanup queue
*--------------------------------------------------------------------------------
*/
private class CleanupQueueTask implements BackgroundTask
{
/*====================================================================
* Constructor
*====================================================================
*/
CleanupQueueTask()
{
} // end constructor
/*====================================================================
* Implementations from itnerface BackgroundTask
*====================================================================
*/
public void run(ServiceProvider services)
{
Reference r = null;
while ((r = m_cleanupqueue.poll())!=null)
{ // do the cleanup!
DirectoryAutoCleanup dac = (DirectoryAutoCleanup)r;
dac.cleanup();
dac.clear();
} // end while
} // end run
} // end class CleanupQueueTask
/*--------------------------------------------------------------------------------
* Static data members
*--------------------------------------------------------------------------------
*/
private static Logger logger = Logger.getLogger(IndexManagerObject.class);
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private String m_name; // name of this object
private IndexManagerOps m_ops; // database operations object
private NamespaceCache m_ns_cache; // namespace cache object
private ComponentShutdown m_shut_runtime; // shutdown runtime service
private ComponentShutdown m_shut_init; // shutdown init service
private ComponentShutdown m_shut_task; // shutdown background task
private Hashtable m_resolvers; // resolvers list
private ReferenceMap m_indexcache; // index cache
private ReferenceQueue m_cleanupqueue; // cleanup object queue
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public IndexManagerObject()
{
m_resolvers = new Hashtable();
m_indexcache = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT);
m_cleanupqueue = new ReferenceQueue();
} // end constructor
/*--------------------------------------------------------------------------------
* Implementations from interface NamedObject
*--------------------------------------------------------------------------------
*/
public String getName()
{
return m_name;
} // end getName
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentInitialize
*--------------------------------------------------------------------------------
*/
/**
* Initialize the component.
*
* @param config_root Pointer to the section of the Dynamo XML configuration file that configures this
* particular component. This is to be considered "read-only" by the component.
* @param services An implementation of {@link com.silverwrist.dynamo.iface.ServiceProvider ServiceProvider}
* which provides initialization services to the component. This will include an implementation
* of {@link com.silverwrist.dynamo.iface.ObjectProvider ObjectProvider} which may be used to
* get information about other objects previously initialized by the application.
* @exception com.silverwrist.dynamo.except.ConfigException If an error is encountered in the component
* configuration.
*/
public void initialize(Element config_root, ServiceProvider services) throws ConfigException
{
logger.info("IndexManagerObject initializing");
XMLLoader loader = XMLLoader.get();
String conn_name = null;
String nscache_name = null;
try
{ // verify the right node name
loader.verifyNodeName(config_root,"object");
// get the object's name
m_name = loader.getAttribute(config_root,"name");
// get the database configuration connection
DOMElementHelper config_root_h = new DOMElementHelper(config_root);
Element elt = loader.getSubElement(config_root_h,"database");
conn_name = loader.getAttribute(elt,"connection");
nscache_name = loader.getAttribute(elt,"namespaces");
} // end try
catch (XMLLoadException e)
{ // error loading XML config data
throw new ConfigException(e);
} // end catch
// Get the database connection pool and namespace cache.
DBConnectionPool pool = GetObjectUtils.getDatabaseConnection(services,conn_name);
m_ns_cache =
(NamespaceCache)(GetObjectUtils.getDynamoComponent(services,NamespaceCache.class,nscache_name));
// Get the database access object.
m_ops = IndexManagerOps.get(pool);
// Hook up IndexManager as a runtime service.
SingletonServiceProvider ssp = new SingletonServiceProvider("IndexManagerObject",IndexManager.class,this);
HookServiceProviders hooker = (HookServiceProviders)(services.queryService(HookServiceProviders.class));
m_shut_runtime = hooker.hookRuntimeServiceProvider(ssp);
// Hook up IndexManagerConfig as an initialization service.
ssp = new SingletonServiceProvider("IndexManagerObject",IndexManagerConfig.class,this);
m_shut_init = hooker.hookInitServiceProvider(ssp);
// Set up a background task to poll the reference queue.
BackgroundScheduler sched = (BackgroundScheduler)(services.queryService(BackgroundScheduler.class));
m_shut_task = sched.runTaskPeriodic(new CleanupQueueTask(),5000,5000);
} // end initialize
/*--------------------------------------------------------------------------------
* Implementations from interface ComponentShutdown
*--------------------------------------------------------------------------------
*/
public void shutdown()
{
m_shut_task.shutdown();
m_shut_task = null;
m_shut_init.shutdown();
m_shut_init = null;
m_shut_runtime.shutdown();
m_shut_runtime = null;
m_ns_cache = null;
m_ops.dispose();
m_ops = null;
} // end shutdown
/*--------------------------------------------------------------------------------
* Implementations from interface IndexManager
*--------------------------------------------------------------------------------
*/
public Object resolveObjectReference(String namespace, String name, String tag) throws IndexException
{
return getResolver(namespace,name).resolveObject(tag);
} // end resolveObjectReference
public synchronized IndexService openIndex(String namespace, String name) throws DatabaseException, IndexException
{
PropertyKey key = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name);
IndexServiceImpl rc = (IndexServiceImpl)(m_indexcache.get(key));
if (rc==null)
{ // look up the index of the particular index service
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
rc = new IndexServiceImpl(this,new QualifiedNameKey(namespace,name),ndx,m_ops.getIndexOps(),m_cleanupqueue);
m_indexcache.put(key,rc);
} // end if
return rc;
} // end openIndex
/*--------------------------------------------------------------------------------
* Implementations from interface IndexManagerConfig
*--------------------------------------------------------------------------------
*/
public ComponentShutdown registerResolver(String namespace, String name, IndexedObjectResolver res)
{
QualifiedNameKey key = new QualifiedNameKey(namespace,name);
m_resolvers.put(key,res);
return new ShutdownHashtableRemove(m_resolvers,key);
} // end registerResolver
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
IndexedObjectResolver getResolver(String namespace, String name) throws IndexException
{
QualifiedNameKey key = new QualifiedNameKey(namespace,name);
IndexedObjectResolver res = (IndexedObjectResolver)(m_resolvers.get(key));
if (res==null)
{ // the resolver could not be found
IndexException e = new IndexException(IndexManagerObject.class,"IndexMessages","no.such.resolver");
e.setParameter(0,namespace);
e.setParameter(1,name);
throw e;
} // end if
return res;
} // end getResolver
} // end class IndexManagerObject

View File

@ -0,0 +1,92 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import com.silverwrist.dynamo.db.OpsBase;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
abstract class IndexManagerOps extends OpsBase
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private IndexOps m_indexops = null;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
protected IndexManagerOps(DBConnectionPool pool)
{
super(pool);
} // end constructor
/*--------------------------------------------------------------------------------
* Overrides from class OpsBase
*--------------------------------------------------------------------------------
*/
public void dispose()
{
if (m_indexops!=null)
m_indexops.dispose();
m_indexops = null;
super.dispose();
} // end dispose
/*--------------------------------------------------------------------------------
* Abstract operations
*--------------------------------------------------------------------------------
*/
protected abstract IndexOps createIndexOps(DBConnectionPool pool);
abstract int getIndexID(int nsid, String name) throws DatabaseException;
/*--------------------------------------------------------------------------------
* External operations
*--------------------------------------------------------------------------------
*/
synchronized IndexOps getIndexOps()
{
if (m_indexops==null)
m_indexops = createIndexOps(getPool());
return m_indexops;
} // end getIndexOps
/*--------------------------------------------------------------------------------
* External static operations
*--------------------------------------------------------------------------------
*/
static IndexManagerOps get(DBConnectionPool pool) throws ConfigException
{
return (IndexManagerOps)get(pool,IndexManagerOps.class.getClassLoader(),IndexManagerOps.class.getName() + "_",
"IndexManagerOps");
} // end get
} // end class IndexManagerOps

View File

@ -0,0 +1,84 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import java.sql.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
public class IndexManagerOps_mysql extends IndexManagerOps
{
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public IndexManagerOps_mysql(DBConnectionPool pool)
{
super(pool);
} // end constructor
/*--------------------------------------------------------------------------------
* Abstract implementations from class IndexManagerOps
*--------------------------------------------------------------------------------
*/
protected IndexOps createIndexOps(DBConnectionPool pool)
{
return new IndexOps_mysql(pool);
} // end createIndexOps
int getIndexID(int nsid, String name) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
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 rs.getInt(1);
else
return -1;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getIndexID
} // end class IndexManagerOps_mysql

View File

@ -0,0 +1,24 @@
# The contents of this file are subject to the Mozilla Public License Version 1.1
# (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.mozilla.org/MPL/>.
#
# Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
# WARRANTY OF ANY KIND, either express or implied. See the License for the specific
# language governing rights and limitations under the License.
#
# The Original Code is the Venice Web Communities System.
#
# The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
# for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
# Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
#
# Contributor(s):
# ---------------------------------------------------------------------------------
# This file has been localized for the en_US locale
no.such.resolver=No resolver has been registered for namespace {0}, name {1}.
no.such.index=No index has been defined with namespace {0} and name {1}.
analyzer.class.notfound=Unable to load the analyzer class {0}.
analyzer.noCreate=Unable to create an instance of the analyzer class {0}.
analyzer.badType=The specified analyzer class {0} is of the wrong type.
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}.

View File

@ -0,0 +1,69 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import java.io.*;
import com.silverwrist.dynamo.db.OpsBase;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
abstract class IndexOps extends OpsBase
{
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
protected IndexOps(DBConnectionPool pool)
{
super(pool);
} // end constructor
/*--------------------------------------------------------------------------------
* Abstract operations
*--------------------------------------------------------------------------------
*/
abstract String getAnalyzerClassName(int ndx) throws DatabaseException;
abstract String[] listFiles(int ndx) throws DatabaseException;
abstract long getModTime(int ndx, String file) throws DatabaseException;
abstract void setModTime(int ndx, String file, long mtime) throws DatabaseException;
abstract void deleteFile(int ndx, String file) throws DatabaseException;
abstract void renameFile(int ndx, String oldfile, String newfile) throws DatabaseException;
abstract int getLength(int ndx, String file) throws DatabaseException;
abstract long createNewEntry(int ndx, String file) throws DatabaseException;
abstract long loadFile(int ndx, String file, File output) throws DatabaseException, IOException;
abstract void storeFile(int ndx, String file, long mtime, File input) throws DatabaseException, IOException;
abstract boolean obtainLock(int ndx, String lock) throws DatabaseException;
abstract void releaseLock(int ndx, String lock) throws DatabaseException;
abstract void releaseAllLocks(int ndx) throws DatabaseException;
} // end class IndexOps

View File

@ -0,0 +1,576 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import java.io.*;
import java.sql.*;
import java.util.*;
import com.silverwrist.util.*;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
class IndexOps_mysql extends IndexOps
{
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
public IndexOps_mysql(DBConnectionPool pool)
{
super(pool);
} // end constructor
/*--------------------------------------------------------------------------------
* Abstract implementations from class IndexOps
*--------------------------------------------------------------------------------
*/
String getAnalyzerClassName(int ndx) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT analyzer FROM ndx_main WHERE ndxid = ?;");
stmt.setInt(1,ndx);
rs = stmt.executeQuery();
if (rs.next())
return rs.getString(1);
else
return null;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getAnalyzerClassName
String[] listFiles(int ndx) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// set up and execute the statement
stmt = conn.prepareStatement("SELECT name FROM ndx_files WHERE ndxid = ? ORDER BY name;");
stmt.setInt(1,ndx);
rs = stmt.executeQuery();
// create the return value
ArrayList tmp = new ArrayList();
while (rs.next())
tmp.add(rs.getString(1));
String[] rc = new String[tmp.size()];
tmp.toArray(rc);
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end listFiles
long getModTime(int ndx, String file) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT mtime FROM ndx_files WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,file);
rs = stmt.executeQuery();
if (rs.next())
return rs.getLong(1);
else
return -1;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getModTime
void setModTime(int ndx, String file, long mtime) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES ndx_files WRITE;");
// execute the update
stmt = conn.prepareStatement("UPDATE ndx_files SET mtime = ? WHERE ndxid = ? AND name = ?;");
stmt.setLong(1,mtime);
stmt.setInt(2,ndx);
stmt.setString(3,file);
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 setModTime
void deleteFile(int ndx, String file) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES ndx_files WRITE;");
// create and execute the statement
stmt = conn.prepareStatement("DELETE FROM ndx_files WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,file);
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 deleteFile
void renameFile(int ndx, String oldfile, String newfile) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES ndx_files WRITE;");
// see if the "newfile" is present
stmt = conn.prepareStatement("SELECT mtime FROM ndx_files WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,newfile);
rs = stmt.executeQuery();
boolean exists = rs.next();
rs.close();
rs = null;
stmt.close();
if (exists)
{ // delete the existing "newfile"
stmt = conn.prepareStatement("DELETE FROM ndx_files WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,newfile);
stmt.executeUpdate();
stmt.close();
} // end if
// rename the old file to the new filename
stmt = conn.prepareStatement("UPDATE ndx_files SET name = ? WHERE ndxid = ? AND name = ?;");
stmt.setString(1,newfile);
stmt.setInt(2,ndx);
stmt.setString(3,oldfile);
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(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(stmt2);
SQLUtils.shutdown(conn);
} // end finally
} // end renameFile
int getLength(int ndx, String file) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// create and execute the statement
stmt = conn.prepareStatement("SELECT length FROM ndx_files WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,file);
rs = stmt.executeQuery();
if (rs.next())
return rs.getInt(1);
else
return -1;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end getLength
long createNewEntry(int ndx, String file) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES ndx_files WRITE;");
// see if the entry exists already
stmt = conn.prepareStatement("SELECT mtime FROM ndx_files WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,file);
rs = stmt.executeQuery();
if (rs.next())
return -1L;
rs.close();
rs = null;
stmt.close();
// insert the new row
stmt = conn.prepareStatement("INSERT INTO ndx_files (ndxid, name, mtime) VALUES (?, ?, ?);");
stmt.setInt(1,ndx);
stmt.setString(2,file);
long rc = System.currentTimeMillis();
stmt.setLong(3,rc);
stmt.executeUpdate();
return rc;
} // 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 createNewEntry
long loadFile(int ndx, String file, File output) throws DatabaseException, IOException
{
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// get the modification time and data stream
stmt = conn.prepareStatement("SELECT mtime, data FROM ndx_files WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,file);
rs = stmt.executeQuery();
if (!(rs.next()))
return -1L;
long rc = rs.getLong(1); // get the mod time
// Copy the file data to the output file.
FileOutputStream fstm = new FileOutputStream(output);
IOUtils.copy(rs.getBinaryStream(2),fstm);
fstm.close();
return rc;
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end loadFile
void storeFile(int ndx, String file, long mtime, File input) throws DatabaseException, IOException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES ndx_files WRITE;");
// create and execute the statement
stmt = conn.prepareStatement("UPDATE ndx_files SET length = ?, mtime = ?, data = ? WHERE ndxid = ? "
+ "AND name = ?;");
int len = (int)(input.length());
stmt.setInt(1,len);
stmt.setLong(2,mtime);
stmt.setBinaryStream(3,new FileInputStream(input),len);
stmt.setInt(4,ndx);
stmt.setString(5,file);
stmt.executeUpdate();
} // end try
catch (SQLException e)
{ // translate to a general DatabaseException
throw generalException(e);
} // end catch
finally
{ // shut everything down
SQLUtils.shutdown(rs);
SQLUtils.shutdown(stmt);
SQLUtils.shutdown(conn);
} // end finally
} // end storeFile
boolean obtainLock(int ndx, String lock) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
ResultSet rs = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES ndx_locks WRITE;");
// see if the lock is already present
stmt = conn.prepareStatement("SELECT ndxid FROM ndx_locks WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,lock);
rs = stmt.executeQuery();
if (rs.next())
return false; // lock already present
rs.close();
rs = null;
stmt.close();
// insert the lock and return success
stmt = conn.prepareStatement("INSERT INTO ndx_locks (ndxid, name) VALUES (?, ?);");
stmt.setInt(1,ndx);
stmt.setString(2,lock);
stmt.executeUpdate();
return true;
} // 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 obtain lock
void releaseLock(int ndx, String lock) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES ndx_locks WRITE;");
// remove the lock row
stmt = conn.prepareStatement("DELETE FROM ndx_locks WHERE ndxid = ? AND name = ?;");
stmt.setInt(1,ndx);
stmt.setString(2,lock);
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 releaseLock
void releaseAllLocks(int ndx) throws DatabaseException
{
Connection conn = null;
PreparedStatement stmt = null;
Statement stmt2 = null;
try
{ // get a connection
conn = getConnection();
// lock the table
stmt2 = conn.createStatement();
stmt2.executeUpdate("LOCK TABLES ndx_locks WRITE;");
// remove the lock row
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 releaseAllLocks
} // end class IndexOps_mysql

View File

@ -0,0 +1,166 @@
/*
* The contents of this file are subject to the Mozilla Public License Version 1.1
* (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.mozilla.org/MPL/>.
*
* Software distributed under the License is distributed on an "AS IS" basis, WITHOUT
* WARRANTY OF ANY KIND, either express or implied. See the License for the specific
* language governing rights and limitations under the License.
*
* The Original Code is the Venice Web Communities System.
*
* The Initial Developer of the Original Code is Eric J. Bowersox <erbo@silcom.com>,
* for Silverwrist Design Studios. Portions created by Eric J. Bowersox are
* Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved.
*
* Contributor(s):
*/
package com.silverwrist.dynamo.index;
import java.io.*;
import java.lang.ref.*;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.*;
import org.apache.lucene.index.*;
import org.apache.lucene.store.Directory;
import com.silverwrist.dynamo.except.*;
import com.silverwrist.dynamo.iface.*;
import com.silverwrist.dynamo.util.*;
class IndexServiceImpl implements IndexService
{
/*--------------------------------------------------------------------------------
* Attributes
*--------------------------------------------------------------------------------
*/
private QualifiedNameKey m_identity;
private IndexManagerObject m_base;
private Analyzer m_analyzer;
private IndexDirectoryImpl m_directory;
private DirectoryAutoCleanup m_cleanup;
/*--------------------------------------------------------------------------------
* Constructor
*--------------------------------------------------------------------------------
*/
IndexServiceImpl(IndexManagerObject base, QualifiedNameKey identity, int ndx, IndexOps ops, ReferenceQueue rq)
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_base = base;
m_identity = identity;
m_directory = new IndexDirectoryImpl(ndx,ops);
m_cleanup = new DirectoryAutoCleanup(this,m_directory,rq);
} // end constructor
/*--------------------------------------------------------------------------------
* Internal operations
*--------------------------------------------------------------------------------
*/
private final String createTag(String namespace, String name, Object obj) throws IndexException
{
String objtag = m_base.getResolver(namespace,name).getResolverTag(obj);
return namespace + "|" + name + "|" + objtag;
} // end createTag
/*--------------------------------------------------------------------------------
* Implementations from interface IndexService
*--------------------------------------------------------------------------------
*/
public void addItem(String item_namespace, String item_name, Object item, String scope, java.util.Date date,
DynamoUser owner, String text) throws IndexException
{
// Create a new Lucene Document containing the item information.
Document doc = new Document();
doc.add(Field.Keyword("id",createTag(item_namespace,item_name,item)));
doc.add(Field.Keyword("date",date));
doc.add(Field.Keyword("owner",owner.getName()));
doc.add(Field.Keyword("scope",scope));
doc.add(Field.UnStored("text",text));
try
{ // Use an IndexWriter to write it to the index.
IndexWriter iwr = new IndexWriter(m_directory,m_analyzer,false);
iwr.addDocument(doc);
iwr.close();
} // end try
catch (IOException e)
{ // translate Lucene's IOException here
IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","addItem.fail",e);
ie.setParameter(0,item_namespace);
ie.setParameter(1,item_name);
ie.setParameter(2,m_identity.toString());
throw ie;
} // end catch
} // end addItem
public boolean deleteItem(String item_namespace, String item_name, Object item) throws IndexException
{
// Create a Lucene Term matching the given document.
Term term = new Term("id",createTag(item_namespace,item_name,item));
try
{ // Use an IndexReader to delete the appropriate document.
IndexReader irdr = IndexReader.open(m_directory);
int ndel = irdr.delete(term);
irdr.close();
return (ndel>0);
} // end try
catch (IOException e)
{ // translate Lucene's IOException here
IndexException ie = new IndexException(IndexServiceImpl.class,"IndexMessages","deleteItem.fail",e);
ie.setParameter(0,item_namespace);
ie.setParameter(1,item_name);
ie.setParameter(2,m_identity.toString());
throw ie;
} // end catch
} // end deleteItem
} // end class IndexServiceImpl