📄 clientcachedatabase.java
字号:
// You can redistribute this software and/or modify it under the terms of
// the Ozone Library License version 1 published by ozone-db.org.
//
// The original code and portions created by SMB are
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
//
// $Id: ClientCacheDatabase.java,v 1.8 2003/01/23 18:07:00 per_nyfelt Exp $
package org.ozoneDB;
import org.ozoneDB.DxLib.*;
import org.ozoneDB.core.DbRemote.*;
import org.ozoneDB.core.*;
import java.io.*;
import java.util.Hashtable;
/**
* This is an {@link ExternalDatabase} that implements a client side cache on
* top of another {@link ExternalDatabase}.<p>
*
* <i> In contrast to {@link LocalDatabase} and {@link RemoteDatabase} which
* produce the exactly same results for the same code, this implementation of
* {@link ExternalDatabase} is not guaranteed to do so.</i><p>
*
* Note: The method parameters of type {@link OzoneRemote} are supposed to by
* proxy objects (of type {@link OzoneProxy}). However, it's possible to pass
* a database objects (of type {@link OzoneCompatible}). In this case the
* parameter should be substituted. Currently this is done by the invoke()
* method only.<p>
*
* Impl. Note: All interface methods are synchronized because they have to be
* executed as an atomar operation.
*
*
* @author <a href="http://www.softwarebuero.de/">SMB</a>
* @version $Revision: 1.8 $Date: 2003/01/23 18:07:00 $
* @see OzoneInterface
*/
public class ClientCacheDatabase extends ExternalDatabase {
/**
* Holds all currently cached target objects. Maps ObjectID into
* CacheObjectContainer.
*/
private DxMap idTable;
/**
* Holds the names that are known to this database instance. Maps String
* into ObjectID.
*/
private DxMap nameTable;
private long totalMemory;
private ExternalDatabase delegate;
private long idCount;
private long idBorder;
private long idRange = 1000;
private boolean debug;
/**
* Constructs a new ClientCacheDatabase with the given delegate as
* back-end.<p>
*
* Note: The size of the client side cache can be adjusted via the heap
* size of the VM (parameter -Xmx). The cache uses all available heap in
* its VM.
*
*
* @param _delegate The back-end database.
*/
public ClientCacheDatabase( ExternalDatabase _delegate ) {
this( _delegate, false );
}
/**
* Constructs a new ClientCacheDatabase with the given delegate as
* back-end and the given debug option.<p>
*
* Note: The size of the client side cache can be adjusted via the heap
* size of the VM (parameter -Xmx). The cache uses all available heap in
* its VM.
*
*
* @param _delegate The back-end database.
* @param _debug
*/
public ClientCacheDatabase( ExternalDatabase _delegate, boolean _debug ) {
delegate = _delegate;
delegate.setWrapper( this );
debug = _debug;
idTable = new DxHashMap( 1000 );
nameTable = new DxHashMap( 100 );
calcMemory();
}
protected void open( Hashtable _props ) throws Exception {
throw new RuntimeException( "Method open() must not be called for this class." );
}
protected synchronized ObjectID nextID() throws Exception {
if (idCount >= idBorder) {
ObjectID id = (ObjectID)delegate.sendCommand( new DbNextID( idRange ), true );
idCount = id.value();
idBorder = idCount + idRange;
}
return new ObjectID( ++idCount );
}
public ExternalDatabase delegate() {
return delegate;
}
protected Object sendCommand( DbCommand command, boolean waitForResult, DbClient connection ) throws Exception {
throw new RuntimeException( "ClientCacheDatabase must access the actual database through its delegate only." );
}
protected DbClient newConnection() throws Exception {
return delegate.newConnection();
}
public boolean isOpen() throws Exception {
return delegate.isOpen();
}
public void close() throws Exception {
delegate.close();
}
protected void finalize() throws Throwable {
close();
}
public ExternalTransaction newTransaction() {
return new ExternalTransaction( this );
}
public void beginTX( AbstractTransaction tx ) throws TransactionException, IOException {
if (debug) {
System.out.println( "[debug] beginTX()" );
}
delegate.beginTX( tx );
}
public void joinTX( AbstractTransaction tx ) throws TransactionException {
if (debug) {
System.out.println( "[debug] joinTX()" );
}
delegate.joinTX( tx );
}
public boolean leaveTX( AbstractTransaction tx ) {
if (debug) {
System.out.println( "[debug] leaveTX()" );
}
return delegate.leaveTX( tx );
}
public void checkpointTX( AbstractTransaction tx ) throws TransactionException, IOException {
if (debug) {
System.out.println( "[debug] checkpointTX()" );
}
throw new RuntimeException( "Not yet implemented." );
}
public synchronized void prepareTX( AbstractTransaction tx ) throws TransactionException, IOException {
if (debug) {
System.out.println( "[debug] prepareTX()" );
}
try {
syncCache();
delegate.prepareTX( tx );
updateModTimes();
} catch (TransactionException e) {
abortCache();
throw e;
} catch (Exception e) {
throw new UnexpectedException( e.toString() );
}
}
public synchronized void commitTX( AbstractTransaction tx, boolean onePhase ) throws TransactionException, IOException {
if (debug) {
System.out.println( "[debug] commitTX(): onePhase:" + onePhase );
}
if (onePhase) {
prepareTX( tx );
}
try {
delegate.commitTX( tx, false );
} catch (TransactionException e) {
throw e;
} catch (Exception e) {
throw new UnexpectedException( e.toString() );
}
// reset container states; handle exceptions in a special way
try {
DxIterator it = idTable.iterator();
while (it.next() != null) {
// clearing the states of all containers without checking should
// be the fastest way here
CacheObjectContainer container = (CacheObjectContainer)it.object();
container.clearState();
}
} catch (Exception e) {
// if someting failes after the server transaction is commited we
// have to signal a strong error
throw new UnexpectedException( e.toString() );
}
}
public synchronized void rollbackTX( AbstractTransaction tx ) throws TransactionException, IOException {
if (debug) {
System.out.println( "[debug] rollbackTX()" );
}
delegate.rollbackTX( tx );
abortCache();
}
// OzoneInterface methods *****************************
/**
* Force the database server to reload all classes which extend
* OzoneObject. This is useful while testing new classes.
*/
public void reloadClasses() throws Exception {
delegate.reloadClasses();
}
public synchronized OzoneProxy createObject( String className, int access, String name, String sig, Object[] args )
throws RuntimeException {
try {
AbstractTransaction tx = delegate.txForThread( Thread.currentThread() );
if (tx == null) {
throw new TransactionException( "Thread has not yet joined a transaction.", TransactionException.STATE );
}
// todo: uncommented until verified that it works
//OzoneCompatible target = (OzoneCompatible)Class.forName( className ).newInstance();
OzoneCompatible target = (OzoneCompatible)Env.currentEnv().classManager.classForName( className ).newInstance();
CacheObjectContainer container = new CacheObjectContainer( target, nextID(), name, access );
container.setDatabase( this );
container.raiseState( ObjectContainer.STATE_CREATED );
container.setDirty( true );
container.tx = tx;
idTable.addForKey( container, container.id() );
return container.ozoneProxy();
} catch (Exception e) {
// only supported from JDK1.4 on
// throw new RuntimeException("Caught during createObject()",e);
throw new RuntimeException("Caught during createObject(): "+e);
}
}
public synchronized void deleteObject( OzoneRemote obj ) throws RuntimeException {
try {
OzoneProxy proxy = (OzoneProxy)obj;
CacheObjectContainer container = fetch0( proxy.remoteID(), Lock.LEVEL_WRITE );
container.raiseState( ObjectContainer.STATE_DELETED );
} catch (Exception e) {
// only supported from JDK1.4 on
// throw new RuntimeException("Caught during createObject()",e);
throw new RuntimeException("Caught during createObject(): "+e);
}
}
public synchronized OzoneProxy copyObject( OzoneRemote obj ) throws Exception {
throw new RuntimeException( "copyObject(): Method not implemented." );
}
public synchronized void nameObject( OzoneRemote obj, String name ) throws Exception {
ObjectID id = (ObjectID)nameTable.elementForKey( name );
if (id != null) {
throw new PermissionDeniedException( "Root object name '" + name + "' already exists." );
}
OzoneProxy proxy = (OzoneProxy)obj;
CacheObjectContainer container = fetch0( proxy.remoteID(), Lock.LEVEL_WRITE );
container.setName( name );
nameTable.addForKey( container.id(), name );
}
public synchronized OzoneProxy objectForName( String name ) throws Exception {
if (debug) {
System.out.println( "[debug] objectForName(): name:" + name );
}
ObjectID id = (ObjectID)nameTable.elementForKey( name );
if (id != null) {
CacheObjectContainer container = (CacheObjectContainer)idTable.elementForKey( id );
if (container != null) {
return container.ozoneProxy();
} else {
container = fetch0( id, Lock.LEVEL_READ );
if (container != null) {
return container.ozoneProxy();
} else {
nameTable.removeForKey( name );
return null;
}
}
} else {
OzoneProxy proxy = delegate.objectForName( name );
if (proxy != null) {
id = proxy.remoteID();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -