⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clientcachedatabase.java

📁 Java的面向对象数据库系统的源代码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
// 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 + -