/*
* $Header: /home/cvs/jakarta-slide/src/stores/org/apache/slide/store/txfile/FileSequenceStore.java,v 1.4 2004/07/28 09:33:58 ib Exp $
* $Revision: 1.4 $
* $Date: 2004/07/28 09:33:58 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.slide.store.txfile;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import org.apache.commons.transaction.file.FileSequence;
import org.apache.commons.transaction.file.ResourceManagerException;
import org.apache.slide.common.ServiceAccessException;
import org.apache.slide.common.ServiceConnectionFailedException;
import org.apache.slide.common.ServiceDisconnectionFailedException;
import org.apache.slide.common.ServiceParameterErrorException;
import org.apache.slide.common.ServiceParameterMissingException;
import org.apache.slide.common.ServiceResetFailedException;
import org.apache.slide.common.AbstractServiceBase;
import org.apache.slide.store.SequenceStore;
import org.apache.slide.util.logger.Logger;
import org.apache.slide.util.logger.TxLogger;
/**
* Sequence store using the file system.
*
*/
public class FileSequenceStore extends AbstractServiceBase implements SequenceStore {
protected static final String LOG_CHANNEL = FileSequenceStore.class.getName();
protected static final String STORE_DIR_PARAMETER = "rootpath";
protected FileSequence fileSequence;
protected String storeDir = null;
protected Map sequenceHash = new HashMap();
protected int sequenceIncrement = 100;
protected long sequenceStartValue = 1;
public void setParameters(Hashtable parameters)
throws ServiceParameterErrorException, ServiceParameterMissingException {
storeDir = (String) parameters.get(STORE_DIR_PARAMETER);
if (storeDir == null) {
throw new ServiceParameterMissingException(this, STORE_DIR_PARAMETER);
}
try {
fileSequence = new FileSequence(storeDir, new TxLogger(getLogger(), LOG_CHANNEL));
getLogger().log("File Sequence Store configured to " + storeDir, LOG_CHANNEL, Logger.INFO);
} catch (ResourceManagerException e) {
getLogger().log("Can not initialize File Sequence Store", e, LOG_CHANNEL, Logger.CRITICAL);
throw new ServiceParameterErrorException(this, STORE_DIR_PARAMETER);
}
}
public String toString() {
return "FileSequenceStore at " + storeDir;
}
/**
* @see org.apache.slide.common.AbstractServiceBase#connect()
*/
public void connect() throws ServiceConnectionFailedException {
}
/**
* @see org.apache.slide.common.AbstractServiceBase#disconnect()
*/
public void disconnect() throws ServiceDisconnectionFailedException {
}
/**
* @see org.apache.slide.common.AbstractServiceBase#reset()
*/
public void reset() throws ServiceResetFailedException {
}
/**
* @see org.apache.slide.common.AbstractServiceBase#isConnected()
*/
public boolean isConnected() throws ServiceAccessException {
return true;
}
/**
* @see org.apache.slide.store.SequenceStore#isSequenceSupported()
*/
public boolean isSequenceSupported() {
return true;
}
/**
* @see org.apache.slide.store.SequenceStore#sequenceExists(java.lang.String)
*/
public boolean sequenceExists(String sequenceName) throws ServiceAccessException {
SeqContext seq = (SeqContext) sequenceHash.get(sequenceName);
if (seq != null) {
return true;
} else {
return fileSequence.exists(sequenceName);
}
}
/**
* @see org.apache.slide.store.SequenceStore#createSequence(java.lang.String)
*/
public synchronized boolean createSequence(String sequenceName) throws ServiceAccessException {
try {
if (fileSequence.create(sequenceName, sequenceStartValue)) {
sequenceHash.put(sequenceName, new SeqContext(sequenceName, sequenceStartValue, sequenceStartValue));
return true;
} else {
return false;
}
} catch (ResourceManagerException e) {
throw new ServiceAccessException(this, e);
}
}
/**
* @see org.apache.slide.store.SequenceStore#nextSequenceValue(java.lang.String)
*/
public synchronized long nextSequenceValue(String sequenceName) throws ServiceAccessException {
// get chunks of values to save disk access
SeqContext seq = (SeqContext) sequenceHash.get(sequenceName);
if (seq != null && seq.pos < seq.end - 1) {
seq.pos++;
return seq.pos;
} else {
try {
if (seq == null) {
seq = new SeqContext(sequenceName);
sequenceHash.put(sequenceName, seq);
}
long pos = fileSequence.nextSequenceValueBottom(sequenceName, sequenceIncrement);
seq.pos = pos;
seq.end = seq.pos + sequenceIncrement;
return seq.pos;
} catch (ResourceManagerException e) {
throw new ServiceAccessException(this, e);
}
}
}
/**
* @see javax.transaction.xa.XAResource#commit(javax.transaction.xa.Xid, boolean)
*/
public void commit(Xid xid, boolean onePhase) throws XAException {
// XXX we are not transactional, this is our trick
}
/**
* @see javax.transaction.xa.XAResource#end(javax.transaction.xa.Xid, int)
*/
public void end(Xid xid, int flags) throws XAException {
// XXX we are not transactional, this is our trick
}
/**
* @see javax.transaction.xa.XAResource#forget(javax.transaction.xa.Xid)
*/
public void forget(Xid xid) throws XAException {
// XXX we are not transactional, this is our trick
}
/**
* @see javax.transaction.xa.XAResource#getTransactionTimeout()
*/
public int getTransactionTimeout() throws XAException {
// XXX we are not transactional, this is our trick
return 0;
}
/**
* @see javax.transaction.xa.XAResource#isSameRM(javax.transaction.xa.XAResource)
*/
public boolean isSameRM(XAResource xaResource) throws XAException {
return (xaResource == this);
}
/**
* @see javax.transaction.xa.XAResource#prepare(javax.transaction.xa.Xid)
*/
public int prepare(Xid xid) throws XAException {
// tell TM we do not need to commit
return XA_RDONLY;
}
/**
* @see javax.transaction.xa.XAResource#recover(int)
*/
public Xid[] recover(int flag) throws XAException {
// XXX we are not transactional, this is our trick
return null;
}
/**
* @see javax.transaction.xa.XAResource#rollback(javax.transaction.xa.Xid)
*/
public void rollback(Xid xid) throws XAException {
// XXX we are not transactional, this is our trick
}
/**
* @see javax.transaction.xa.XAResource#setTransactionTimeout(int)
*/
public boolean setTransactionTimeout(int seconds) throws XAException {
// XXX we are not transactional, this is our trick
return true;
}
/**
* @see javax.transaction.xa.XAResource#start(javax.transaction.xa.Xid, int)
*/
public void start(Xid xid, int flags) throws XAException {
// XXX we are not transactional, this is our trick
}
protected static class SeqContext {
public String name;
public long pos;
public long end;
public SeqContext(String name) {
this(name, -1, -1);
}
public SeqContext(String name, long pos, long end) {
this.name = name;
this.pos = pos;
this.end = end;
}
}
}