/*
Copyright (C) 2007 Mobixess Inc. http://www.java-objects-database.com
This file is part of the JODB (Java Objects Database) open source project.
JODB is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation.
JODB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.mobixess.jodb.core;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URI;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Comparator;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import com.mobixess.jodb.core.index.JODBIndexingRootAgent;
import com.mobixess.jodb.core.io.IOTicket;
import com.mobixess.jodb.core.io.IRandomAccessDataBuffer;
import com.mobixess.jodb.core.io.JODBIOBase;
import com.mobixess.jodb.core.io.IOBase.ObjectIdentity;
import com.mobixess.jodb.core.io.IRandomAccessBufferFactory.BUFFER_TYPE;
import com.mobixess.jodb.core.io.rmi.IDatabaseStatisticsRemote;
import com.mobixess.jodb.core.io.rmi.IOTicketRemoteInterface;
import com.mobixess.jodb.core.io.rmi.IRemoteServer;
import com.mobixess.jodb.core.io.rmi.IRemoteTransactionContainer;
import com.mobixess.jodb.core.io.rmi.IRemoteServer.IServerQueryResult;
import com.mobixess.jodb.core.query.JODBQueryList;
import com.mobixess.jodb.core.query.NQExecutor;
import com.mobixess.jodb.core.query.QueryNode;
import com.mobixess.jodb.core.transaction.ITranslatedDataSorce;
import com.mobixess.jodb.core.transaction.JODBSession;
import com.mobixess.jodb.core.transaction.TransactionContainer;
import com.mobixess.jodb.core.transaction.TransactionUtils;
import com.mobixess.jodb.core.transaction.JODBSession.ClassDescriptor;
import com.mobixess.jodb.query.api.Predicate;
import com.mobixess.jodb.util.LongVector;
import com.mobixess.jodb.util.Utils;
import com.mobixess.jodb.util.rmi.RegistryManager;
public class JODBServer {
private JODBSessionContainer _sessionContainer;
private JODBIOBase _ioBase;
private String _serverId;
private ServerSocketAcceptor _serverSocketAcceptor;
private JODBRemoteObject _remoteObject;
//private int _rmiPort;
//private int _dataPort;
public final static String REMOTE_OBJECT_NAME = '/'+JODBRemoteObject.class.getName();
private JODBIndexingRootAgent _indexingRootAgent;
JODBServer(JODBSessionContainer sessionContainer, String serverId) throws Exception {
_sessionContainer = sessionContainer;
_ioBase = (JODBIOBase) _sessionContainer.getIoBase();
_serverId = serverId;
_serverSocketAcceptor = new ServerSocketAcceptor();
installServerObject();
reloadIndexingRootAgent();
}
private void installServerObject() throws Exception{
RegistryManager.getInstance().createRegistry();
String name = composeRemoteObjectBindName();
Naming.rebind(name, _remoteObject = new JODBRemoteObject());
}
private String composeRemoteObjectBindName(){
String name = REMOTE_OBJECT_NAME;
if(_serverId!=null && _serverId.length()>0){
name+="_"+_serverId;
}
return name;
}
public synchronized void stop() throws IOException{
_sessionContainer.close();
_serverSocketAcceptor.close();
try {
Naming.unbind(composeRemoteObjectBindName());
UnicastRemoteObject.unexportObject(_remoteObject, true);
} catch (NotBoundException e) {
throw new JodbIOException(e);
} finally{
RegistryManager.getInstance().shutdownRegistry();
}
}
private void reloadIndexingRootAgent() throws IOException{
JODBSession session = _sessionContainer.getSession();
long offset = session.getIndexingRootAgentOffset();
_indexingRootAgent = (JODBIndexingRootAgent) TransactionUtils.launchObject(session, offset, _indexingRootAgent, Integer.MAX_VALUE);
}
@SuppressWarnings("serial")
private class JODBRemoteObject extends UnicastRemoteObject implements IRemoteServer{
DatabaseStatisticsSE _databaseStatisticsSE;
protected JODBRemoteObject() throws IOException {
super();
_databaseStatisticsSE = new DatabaseStatisticsSE();
}
public void applyTransaction(TransactionContainer transactionContainer, JODBSession session, IOTicket writeTicket, JODBIndexingRootAgent indexingRootAgent) throws IOException {
}
public void close() throws IOException, RemoteException {
_sessionContainer.close();
}
public String getClassTypeForID(int id) {
return _ioBase.getClassTypeForID(id);
}
public int getClassTypeSubstitutionID(String classType) throws RemoteException {
return _ioBase.getClassTypeSubstitutionID(classType);
}
public IDatabaseStatisticsRemote getDatabaseStatistics() throws IOException {
if(!_databaseStatisticsSE.isExported()){
_databaseStatisticsSE.export();
}
_databaseStatisticsSE.setDatabaseStatistics(_ioBase.getDatabaseStatistics(true));
return _databaseStatisticsSE;
}
public URI getDbIdentificator() {
return _ioBase.getDbIdentificator();
}
public long getFirstObjectOffset() throws RemoteException {
return _ioBase.getFirstObjectOffset();
}
public long[] getForAllObjects(int ioTicket) throws IOException {
IOTicket ticket = _ioBase.findTicket(ioTicket);
return _ioBase.getForAllObjects(ticket);
}
public String getFullFieldNameForID(int id) throws RemoteException {
return _ioBase.getFullFieldNameForID(id);
}
public IOTicketRemoteInterface getIOTicket(boolean read, boolean write) throws IOException {
try {
return (IOTicketRemoteInterface) _ioBase.getIOTicket(read, write, true);
} catch (IOException e) {
e.printStackTrace();
throw e;
}
}
public int getOrSetClassTypeSubstitutionID(Class clazz) throws RemoteException {
return _ioBase.getOrSetClassTypeSubstitutionID(clazz);
}
public int getOrSetClassTypeSubstitutionID(String classType) throws RemoteException {
return _ioBase.getOrSetClassTypeSubstitutionID(classType);
}
// public int getOrSetFieldSubstitutionID(Field field) throws RemoteException {
// return _ioBase.getOrSetFieldSubstitutionID(field);
// }
public IPersistentObjectStatistics getPersistenceStatistics(long offset, JODBSession session) throws IOException {
return _ioBase.getPersistenceStatistics(offset, session);
}
public String getPrefixForID(int id) {
return _ioBase.getPrefixForID(id);
}
public String getSimpleFieldNameForID(int id) throws RemoteException {
return _ioBase.getSimpleFieldNameForID(id);
}
public boolean isClosed() throws RemoteException {
return _ioBase.isClosed();
}
public IRemoteTransactionContainer getRemoteTransactionContainer() throws RemoteException {
try {
return new RemoteTransactionContainer();
} catch (IOException e) {
throw new RemoteException("",e);
}
}
public IServerQueryResult runQuery(QueryNode query, long[] localActiveObjects) throws IOException{
LongVector remoteActiveObjects=null;
if(localActiveObjects!=null){
remoteActiveObjects = new LongVector(localActiveObjects);
}
query.setSession(_sessionContainer.getSession());
try {
LongVector additionalRejected = new LongVector();
JODBQueryList objectSet = (JODBQueryList) query.runQuery(remoteActiveObjects,additionalRejected);
long[] result = objectSet.getAllObjectIds();
long[] additionalRejectedObjects = null;
if(additionalRejected.size() > 0){
additionalRejectedObjects = additionalRejected.getDataAsArray();
}
return new ServerQueryResult(additionalRejectedObjects,result);
} catch (IllegalClassTypeException e) {
throw new JodbIOException(e);
}
}
public int getOrSetFieldSubstitutionID(int declaringClassID, int fieldTypeID, String fieldName) throws IOException {
return _ioBase.getOrSetFieldSubstitutionID(declaringClassID, fieldTypeID, fieldName);
}
public int getFieldSubstitutionID(int declaringClassID, int fieldTypeID, String fieldName) throws IOException {
return _ioBase.getFieldSubstitutionID(declaringClassID, fieldTypeID, fieldName);
}
public IPersistentObjectStatistics getPersistenceStatistics(long offset) throws IOException {
return _ioBase.getPersistenceStatistics(offset, _sessionContainer.getSession());
}
public ObjectIdentity checkObjectChanged(long objectId, int hash, byte versionCounter) throws IOException {
return _ioBase.checkObjectChanged(objectId, hash, versionCounter);
}
@SuppressWarnings("unchecked")
public boolean isOptimizedQuery( String predicateClassName, String comparatorClassName)throws IOException
{
JODBSession session = _sessionContainer.getSession();
Predicate predicate;
Comparator comparator = null;
try {
ClassDescriptor predicateClassDescriptor = session.getDescriptorForClass(predicateClassName);
predicate = (Predicate) predicateClassDescriptor.newInstance();
if (comparatorClassName != null) {
ClassDescriptor comparatorClassDescriptor = session.getDescriptorForClass(comparatorClassName);
comparator = (Comparator) comparatorClassDescriptor.newInstance();
}
} catch (Exception e) {
throw new JodbIOException(e);
}
return NQExecutor.getInstance().isOptimizedQuery(_sessionContainer.getSession(), predicate, comparator);
}
@SuppressWarnings("unchecked")
public IServerQueryResult query( String predicateClassName, String comparatorClassName)throws IOException
{
JODBSession session = _sessionContainer.getSession();
Predicate predicate;
Comparator comparator = null;
try {
ClassDescriptor predicateClassDescriptor = session.getDescriptorForClass(predicateClassName);
predicate = (Predicate) predicateClassDescriptor.newInstance();
if (comparatorClassName != null) {
ClassDescriptor comparatorClassDescriptor = session.getDescriptorForClass(comparatorClassName);
comparator = (Comparator) comparatorClassDescriptor.newInstance();
}
} catch (Exception e) {
throw new JodbIOException(e);
}
JODBQueryList objectSet = (JODBQueryList) NQExecutor.getInstance().execute(_sessionContainer.getSession(), predicate, comparator);
long[] result = objectSet.getAllObjectIds();
return new ServerQueryResult(null,result);
}
}
private static class ServerQueryResult implements IServerQueryResult, Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
long[] _excludedObjects;
long[] _searchResult;
/**
* @param excludedObjects
* @param searchResult
*/
public ServerQueryResult(long[] excludedObjects, long[] searchResult) {
super();
_excludedObjects = excludedObjects;
_searchResult = searchResult;
}
public long[] getExcludedObjects() {
return _excludedObjects;
}
public long[] getSearchResult() {
return _searchResult;
}
}
private class RemoteTransactionContainer implements IRemoteTransactionContainer, ITranslatedDataSorce{
private FileReceiver _newDataBuffer;
private FileReceiver _replacementsBuffer;
private FileReceiver _rollbackBuffer;
ReentrantReadWriteLock _lock;
long _transactionOffset;
ExecutorService _localTransactionExecutor = Executors.newSingleThreadExecutor();
Future _transactionFuture;
Exception _transactionExecutionError;
LockTransuctionRunnable _lockTransuctionRunnable = new LockTransuctionRunnable();
CompleteTransactionRunnable _completeTransactionRunnable = new CompleteTransactionRunnable();
UnlockTransactionRunnable _unlockTransactionRunnable = new UnlockTransactionRunnable();
public RemoteTransactionContainer() throws IOException {
_lock = _ioBase.getTransactionLock();
_newDataBuffer = new FileReceiver(BUFFER_TYPE.NEW_DATA);
_replacementsBuffer = new FileReceiver(BUFFER_TYPE.REPLACEMENTS);
_rollbackBuffer = new FileReceiver(BUFFER_TYPE.ROLLBACK);
UnicastRemoteObject.exportObject(this, JodbNetConstants.DEFAULT_RMI_PORT);
}
public int getNewDataBufferId() {
return _newDataBuffer.getFileId();
}
public int getReplacementsBufferId() {
return _replacementsBuffer.getFileId();
}
public long getIndexingAgentVersion() throws IOException{
return _indexingRootAgent.getVersion();
}
public int getRollbackBufferId() {
return _rollbackBuffer.getFileId();
}
public FileReceiver getReceiverForId(int id){
if(_newDataBuffer.getFileId() == id){
return _newDataBuffer;
}
if(_replacementsBuffer.getFileId() == id){
return _replacementsBuffer;
}
if(_rollbackBuffer.getFileId() == id){
return _rollbackBuffer;
}
return null;
}
boolean hasPendingFiles(){
return !_newDataBuffer._processed || !_replacementsBuffer._processed || !_rollbackBuffer._processed;
}
void ensureFileTransferComplete() throws IOException{
ensureFileTransferComplete(JodbNetConstants.FILE_TRANSFER_MAX_WAIT, _newDataBuffer);
ensureFileTransferComplete(JodbNetConstants.FILE_TRANSFER_MAX_WAIT, _replacementsBuffer);
ensureFileTransferComplete(JodbNetConstants.FILE_TRANSFER_MAX_WAIT, _rollbackBuffer);
}
void ensureFileTransferComplete(int timeout, FileReceiver fileReceiver) throws IOException{
if(fileReceiver._error!=null){
throw new JodbIOException(fileReceiver._error);
}
try {
fileReceiver.getTransferCompletionSynch(timeout).get(timeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
throw new JodbIOException(e);
}
if(fileReceiver._error!=null){
throw new JodbIOException(fileReceiver._error);
}
if(!fileReceiver._transferComplete){
throw new JodbIOException("Transfer timeout");
}
}
public IRandomAccessDataBuffer getRollbackDataFile() {
return _rollbackBuffer._file;
}
public IRandomAccessDataBuffer getTransactionNewDataFile() {
return _newDataBuffer._file;
}
public IRandomAccessDataBuffer getTransactionReplacementsDataFile() {
return _replacementsBuffer._file;
}
public void resetTransactionBufferToEnd() throws IOException {
getRollbackDataFile().resetToEnd();
getTransactionNewDataFile().resetToEnd();
getTransactionReplacementsDataFile().resetToEnd();
}
public void resetTransactionBufferToStart() throws IOException {
getRollbackDataFile().resetToStart();
getTransactionNewDataFile().resetToStart();
getTransactionReplacementsDataFile().resetToStart();
}
public void resetTranslatedObjects(JODBSession session, long transactionShift) {
_lock.writeLock().unlock();
}
public long initTransaction() throws RemoteException {
return initTransaction(JodbNetConstants.DEFAULT_TRANSACTION_LOCK_WAIT_TIMEOUT);
}
public long initTransaction(int transactioLockTimeout) throws RemoteException {
Future future = _localTransactionExecutor.submit(_lockTransuctionRunnable);
try {
future.get(transactioLockTimeout, TimeUnit.MILLISECONDS);
} catch (Exception e) {
throw new RemoteException("",e);
}
if(!_lockTransuctionRunnable._gotLock){
throw new RemoteException("Unable to obtain transaction lock");
}
_serverSocketAcceptor.addReciever(_newDataBuffer);
_serverSocketAcceptor.addReciever(_replacementsBuffer);
_serverSocketAcceptor.addReciever(_rollbackBuffer);
_transactionOffset = _ioBase.getTransactionOffset();
_transactionFuture = _localTransactionExecutor.submit(_completeTransactionRunnable);
return _transactionOffset;
}
public void setTransactionDataSizes(long newDataSize, long replacementDataSize, long rollbackDataSize) throws RemoteException {
_newDataBuffer.setTransactionDataLength(newDataSize);
_replacementsBuffer.setTransactionDataLength(replacementDataSize);
_rollbackBuffer.setTransactionDataLength(rollbackDataSize);
}
@Override
protected void finalize() throws Throwable
{
disposeRemoteContainer();
}
public void disposeRemoteContainer() throws IOException {
_newDataBuffer.close();
_replacementsBuffer.close();
_rollbackBuffer.close();
Future unlockProcess = _localTransactionExecutor.submit(_unlockTransactionRunnable);
try {
unlockProcess.get(JodbNetConstants.FILE_TRANSFER_MAX_WAIT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
throw new JodbIOException(e);//TODO should be critical error?
}
if(JODBConfig.DEBUG){
Utils.getLogger(getClass().getName()).log(Level.INFO, "Executor shutdown "+_localTransactionExecutor.toString());
}
_localTransactionExecutor.shutdownNow();
UnicastRemoteObject.unexportObject(this, false);
}
public void checkTransactionComplete() throws IOException {
try {
_transactionFuture.get(JodbNetConstants.DEFAULT_TRANSACTION_LOCK_WAIT_TIMEOUT, TimeUnit.MILLISECONDS);
} catch (Exception e) {
throw new JodbIOException(e);
}
if(_transactionExecutionError != null){
throw new JodbIOException(_transactionExecutionError);
}
}
private class CompleteTransactionRunnable implements Runnable{
public void run() {
try {
ensureFileTransferComplete();
_ioBase.applyRemoteTransaction(RemoteTransactionContainer.this,_transactionOffset);
reloadIndexingRootAgent();//TODO coditional reload (index may not change) for optimization
} catch (Exception e) {//TODO check Throwable and exit as critical error?
_transactionExecutionError = e;
} finally {
if(JODBConfig.DEBUG){
Utils.getLogger(getClass().getName()).log(Level.INFO, "Lock release "+Thread.currentThread());
}
_unlockTransactionRunnable.run();
_serverSocketAcceptor.removeReciever(_newDataBuffer);
_serverSocketAcceptor.removeReciever(_replacementsBuffer);
_serverSocketAcceptor.removeReciever(_rollbackBuffer);
}
}
}
private class UnlockTransactionRunnable implements Runnable{
public void run() {
if(_lock.isWriteLockedByCurrentThread()){
_lock.writeLock().unlock();
}
}
}
private class LockTransuctionRunnable implements Runnable{
int _transactioLockTimeout=-1;
boolean _gotLock;
void init(int transactioLockTimeout){
_transactioLockTimeout = transactioLockTimeout;
_gotLock = false;
}
public void run() {
try {
if(JODBConfig.DEBUG){
Utils.getLogger(getClass().getName()).log(Level.INFO, "Lock set "+Thread.currentThread());
}
_gotLock = _lock.writeLock().tryLock(_transactioLockTimeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
e.printStackTrace();//TODO log
}
}
}
}
private static class FileReceiver implements Runnable {
IRandomAccessDataBuffer _file;
Integer _id;
long _length=-1;
long _maxTransferTime;
ServerSocketAcceptor _container;
Socket _readSocket;
Throwable _error;
boolean _transferComplete;
boolean _processed;
Future _transferCompletionSynch;
Semaphore _transferSubmitSemaphore = new Semaphore(1);
public FileReceiver(BUFFER_TYPE bufferType) throws IOException {
_file = JODBConfig.getRandomAccessBufferFactory().createBuffer("", bufferType, true);
_id = System.identityHashCode(_file);
try {
_transferSubmitSemaphore.acquire();
} catch (InterruptedException e) {
throw new JodbIOException(e);
}
}
public Integer getFileId() {
return _id;
}
void resetId(){
_id = _id.intValue();
}
public void setContainer(ServerSocketAcceptor container) {
_container = container;
}
public void setTransactionDataLength(long length) {
_length = length;
}
public void close() throws IOException{
if(_transferSubmitSemaphore.availablePermits() == 0){
_transferSubmitSemaphore.release();
}
_file.close();
_file.delete();
}
@Override
protected void finalize() throws Throwable
{
_file.delete();
}
public void setReadSocket(Socket readSocket) {
_readSocket = readSocket;
}
public void run()
{
try {
if(_length == -1){
throw new JodbIOException("no client transaction data size available");
}
SocketChannel socketChannel = _readSocket.getChannel();
long transfered = _file.transferFrom(socketChannel, 0, _length);
if(JODBConfig.DEBUG){
Utils.getLogger(getClass().getName()).log(Level.INFO, "Transfered "+ transfered +" to file "+_file);
}
/*
InputStream input = _readSocket.getInputStream();
byte[] outBuffer = new byte[_readSocket.getReceiveBufferSize()];
int bytesReceived = 0;
while ((bytesReceived = input.read(outBuffer)) >= 0) {
_file.write(outBuffer, 0, bytesReceived);
}
input.close();
if(_file.length() != _length){
throw new JodbIOException("Incorrect transfer size "+_file.length()+"!="+_length);
}*/
} catch (Exception e) {
_error = e;
}
_transferComplete = true;
}
public void submit(ThreadPoolExecutor threadPoolExecutor) {
_transferCompletionSynch = threadPoolExecutor.submit(this);
_processed = true;
_transferSubmitSemaphore.release();
if(JODBConfig.DEBUG){
Utils.getLogger(getClass().getName()).log(Level.INFO, "Task submitted "+this);
}
//_transferCompletionSynch.get(delay, TimeUnit.MILLISECONDS);
}
public Future getTransferCompletionSynch(long waitForSynchObject) throws InterruptedException, IOException {
if(!_transferSubmitSemaphore.tryAcquire(waitForSynchObject, TimeUnit.MILLISECONDS)){
throw new JodbIOException("Transfer wait timeout");
}
_transferSubmitSemaphore.release();
return _transferCompletionSynch;
}
}
private class ServerSocketAcceptor extends Thread{
Socket _lastAcceptedSocket;
HashMap<Integer, FileReceiver> _pendingFiles = new HashMap<Integer, FileReceiver>();
ScheduledThreadPoolExecutor _threadPoolExecutor = new ScheduledThreadPoolExecutor(2);
boolean _closed = false;
public ServerSocketAcceptor() throws IOException {
setName("JodbServerSocketAcceptor");
setDaemon(true);
startDataServerSocket();
}
private ServerSocket _serverSocket;
private ServerSocketChannel _serverSocketChannel;
private void startDataServerSocket() throws IOException{
_serverSocketChannel = SelectorProvider.provider().openServerSocketChannel();
_serverSocket = _serverSocketChannel.socket();
_serverSocket.bind(new InetSocketAddress(JodbNetConstants.DEFAULT_DATA_STREAM_PORT));
//new ServerSocket(JODBConstants.DEFAULT_DATA_STREAM_PORT);
start();
}
public void addReciever(FileReceiver fileReceiver){
synchronized (_pendingFiles) {
_pendingFiles.put(fileReceiver.getFileId(), fileReceiver);
}
}
public void removeReciever(FileReceiver fileReceiver){
synchronized (_pendingFiles) {
_pendingFiles.remove(fileReceiver.getFileId());
}
}
public void close() throws IOException{
_closed = true;
_serverSocket.close();
_threadPoolExecutor.shutdown();
}
@Override
public void run()
{
while(true){
Socket socket;
try {
socket = _serverSocket.accept();
} catch (IOException e) {
if(_closed){
break;
}
Utils.fatalError(e);
continue;
}
if(_closed){
break;
}
try {
handleConnection(socket);
} catch (IOException e) {
e.printStackTrace();//TODO log
}
}
}
void handleConnection(Socket socket) throws IOException{
socket.setSoTimeout(JodbNetConstants.FILE_TRANSFER_SOCKET_TIMEOUT);
DataInputStream is = new DataInputStream(socket.getInputStream());
int id = new DataInputStream(is).readInt();
FileReceiver fileReceiver = _pendingFiles.get(id);
if(fileReceiver == null){
throw new JodbIOException("File Id is not available "+id);
}
fileReceiver.setReadSocket(socket);
fileReceiver.submit(_threadPoolExecutor);
removeReciever(fileReceiver);
if(JODBConfig.DEBUG){
Utils.getLogger(getClass().getName()).log(Level.INFO, "Task finished "+this);
}
}
}
class DatabaseStatisticsSE implements IDatabaseStatisticsRemote{
boolean _exported;
IDatabaseStatistics _databaseStatistics;
public DatabaseStatisticsSE() throws IOException {
}
public void setDatabaseStatistics(IDatabaseStatistics databaseStatistics) {
_databaseStatistics = databaseStatistics;
}
public long literalSubstFreeSize(int tableIndex) throws IOException {
return _databaseStatistics.literalSubstFreeSize(tableIndex);
}
public long literalSubstMaxSize(int tableIndex) throws IOException {
return _databaseStatistics.literalSubstMaxSize(tableIndex);
}
public int totalDataEntries() throws IOException {
return _databaseStatistics.totalDataEntries();
}
public synchronized boolean isExported() {
return _exported;
}
public synchronized void export() throws IOException {
if(_exported){
return;
}
_exported = true;
UnicastRemoteObject.exportObject(this, JodbNetConstants.DEFAULT_RMI_PORT);
}
public synchronized void unexport() throws IOException {
if(!_exported){
return;
}
_exported = false;
UnicastRemoteObject.unexportObject(this, true);
//System.gc();
}
// @Override
// protected void finalize() throws Throwable
// {
// _logger.log(Level.SEVERE,"finalize- "+this);
// }
//
// public void unreferenced() {
// _logger.log(Level.SEVERE,"unreferenced- "+this);
// }
}
}