📄 externaldatabase.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: 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 + -