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

📄 externaldatabase.java

📁 Java的面向对象数据库系统的源代码
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
// 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: ExternalDatabase.java,v 1.21 2003/11/07 21:34:21 per_nyfelt Exp $

package org.ozoneDB;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.UnknownHostException;
import java.net.URISyntaxException;
import java.net.URI;
import java.util.Hashtable;
import java.util.StringTokenizer;
import javax.transaction.xa.XAResource;

import org.ozoneDB.DxLib.*;
import org.ozoneDB.core.DbRemote.*;
import org.ozoneDB.core.Transaction;
import org.ozoneDB.core.TransactionID;
import org.ozoneDB.core.admin.Admin;
import org.ozoneDB.core.admin.AdminImpl;
import org.ozoneDB.xa.OzoneXAResource;
import org.ozoneDB.xml.util.SAXChunkConsumer;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;


/**
 * Base class for implementations of the OzoneInterface which are used from
 * a client application to access an ozone.<p>
 *
 * Each thread is associated with a server connection. This connection is used
 * if the thread is not associated with a transaction. Otherwise the connection
 * of the transaction is used. So in case the thread has *joined* a transaction
 * it does not use its own connection but the connection of the transaction.
 * The prepare/commit/abort methods don't need to be called from the thread that
 * is joined to the transaction.<p>
 *
 * Impl. note: The OzoneInterface methods don't need to be synchronized any
 * longer because each threads has its own connection.<p>
 *
 * @author <a href="http://www.softwarebuero.de/">SMB</a>
 * @author <a href="http://www.medium.net/">Medium.net</a>
 * @version $Revision: 1.21 $Date: 2003/11/07 21:34:21 $
 * @see OzoneInterface
 */
public abstract class ExternalDatabase extends AbstractDatabase {

    // Constants

    public final static String PROP_HOST = "host";

    public final static String PROP_PORT = "port";

    public final static String PROP_DIR = "dir";

    public final static String PROP_USER = "user";

    public final static String PROP_PASSWD = "passwd";

    public final static String PROP_DEBUG = "debug";

    // Data

    /**
     * The wrapper that uses this as its delegate or null if there is no such
     * wrapper. Especially the linkForProxy() calls are redirected to the
     * wrapper to have the proxies link to the wrapper instead of this database.
     */
    private ExternalDatabase wrapper;

    /**
     * Table of all current external transactions (thread -> transaction).
     */
    private DxMap txTable;

    /**
     * Pool of currently available database connections.
     */
    private DxDeque apool;

    /**
     * Pool of currently used database connections.
     */
    private DxSet upool;

    /**
     * The XAResource of this database connection.
     */
    private XAResource xares;

    /**
     * If this is non-null it is used by all threads as the current transaction.
     */
    // private AbstractTransaction	globalTX;

    /**
     * All ExternalDatabase objects that have been created in the current VM.
     * This is used by the forThread() method.
     */
    private static DxBag databases = new DxArrayBag();


    /**
     * Static method to find a database connection that has an associated
     * transaction that has been joined by the given thread. Used by proxy
     * constructors to determine its database. This method returns the first
     * database that was found.
     *
     *
     * @param _thread The thread for which to find the corresponding database.
     * @return The database for the given thread.
     */
    public static ExternalDatabase forThread(Thread _thread) {
        DxIterator it = databases.iterator();
        ExternalDatabase db;
        while ((db = (ExternalDatabase) it.next()) != null) {
            DxSet threads = db.txTable.keySet();
            if (threads.contains(_thread)) {
                return db;
            }
        }
        return null;
    }


    // Constructors ***************************************

    public ExternalDatabase() {
    }


    // XAResource factory *********************************

    /**
     * Return a new XAResource for this database connection.
     * @return new XAResource.
     */
    public final XAResource getXAResource() {
        if (xares == null) {
            synchronized (this) {
                if (xares == null) {
                    xares = new OzoneXAResource(this);
                }
            }
        }
        return xares;
    }


    // external transaction handling **********************

    protected final AbstractTransaction txForThread(Thread thread) {
        return (AbstractTransaction) txTable.elementForKey(thread);
    }


    /**
     * Create a new transaction. Before using this transaction it must be started.
     *
     * @return The newly created transaction.
     */
    public ExternalTransaction newTransaction() {
        return new ExternalTransaction(this);
    }


    /**
     * Obtain the {@link ExternalTransaction} that is assocaited to the
     * caller's thread or null, if there is no such transaction. This does not
     * necessarily mean that there is no transaction associated to this
     * thread at all. For example there might be an XA transaction.
     *
     * @return The transaction that is associated to the caller's thread.
     * @see #currentTransaction()
     */
    public ExternalTransaction currentExternalTransaction() {
        AbstractTransaction atx = txForThread(Thread.currentThread());

        if (atx instanceof ExternalTransaction) {
            return (ExternalTransaction) atx;
        } else {
            return null;
        }
    }


    /**
     * Obtain the transaction that is assocaited to the caller's thread or null,
     * if there is no such transaction. The transaction might be an instance
     * of any subclass of AbstractTransaction, which includes also non-user
     * transactions like org.ozoneDB.xa.XATransaction.
     *
     * @return The transaction that is associated to the caller's thread.
     * @see #currentExternalTransaction()
     */
    public AbstractTransaction currentTransaction() {
        return txForThread(Thread.currentThread());
    }


    /**
     * This method is never directly called from the client code.
     */
    public void beginTX(AbstractTransaction tx) throws TransactionException, IOException {

        // check if the transaction is already started
        if (tx.connection != null) {
            throw new TransactionException("Transaction already started.", TransactionException.STATE);
        }

        synchronized (tx) {
            try {
                tx.connection = acquirePooledConnection();
                joinTX(tx);

                // exceptions are catched and re-thrown be sendCommand()
                TransactionID taID = (TransactionID) sendCommand(new DbTransaction(DbTransaction.MODE_BEGIN), true, tx.connection);
            } catch (IOException e) {
                throw e;
            } catch (Exception e) {
                throw new TransactionException(e.toString(), TransactionException.UNEXPECTED);
            }
        }
    }


    /**
     * This method is never directly called from the client code.
     */
    public void joinTX(AbstractTransaction tx) throws TransactionException {
        Thread thread = Thread.currentThread();

        synchronized (txTable) {
            // check if the current thread is already joined to a transaction
            AbstractTransaction txOfThread = (AbstractTransaction) txTable.elementForKey(thread);
            if (txOfThread != null && txOfThread != tx) {
                throw new TransactionException("Thread is already joined to a transaction.", TransactionException.STATE);
            }
            txTable.addForKey(tx, thread);
        }
    }


    /**
     * This method is never directly called from the client code.
     */
    public boolean leaveTX(AbstractTransaction tx) {
        return txTable.removeForKey(Thread.currentThread()) != null;
    }


    /**
     * This method is never directly called from the client code.
     */
    public void checkpointTX(AbstractTransaction tx) throws TransactionException, IOException {
        commandTX(tx, new DbTransaction(DbTransaction.MODE_CHECKPOINT));
    }


    /**
     * This method is never directly called from the client code.
     */
    public void prepareTX(AbstractTransaction tx) throws TransactionException, IOException {
        if (tx.connection == null) {
            throw new TransactionException("Illegal state.", TransactionException.STATE);
        }
        commandTX(tx, new DbTransaction(DbTransaction.MODE_PREPARE));
    }


    /**
     * This method is never directly called from the client code.
     */
    public void commitTX(AbstractTransaction tx, boolean onePhase) throws TransactionException, IOException {
        synchronized (tx) {
            if (tx.connection == null) {
                throw new TransactionException("Illegal state.", TransactionException.STATE);
            }

            if (onePhase) {
                commandTX(tx, new DbTransaction(DbTransaction.MODE_COMMIT_ONEPHASE));
            } else {
                commandTX(tx, new DbTransaction(DbTransaction.MODE_COMMIT_TWOPHASE));
            }
            releasePooledConnection(tx.connection);
            tx.connection = null;
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -