All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.atomikos.persistence.imp.StateRecoveryManagerImp Maven / Gradle / Ivy

There is a newer version: 6.0.0
Show newest version
/**
 * Copyright (C) 2000-2010 Atomikos 
 *
 * This code ("Atomikos TransactionsEssentials"), by itself,
 * is being distributed under the
 * Apache License, Version 2.0 ("License"), a copy of which may be found at
 * http://www.atomikos.com/licenses/apache-license-2.0.txt .
 * You may not use this file except in compliance with the License.
 *
 * While the License grants certain patent license rights,
 * those patent license rights only extend to the use of
 * Atomikos TransactionsEssentials by itself.
 *
 * This code (Atomikos TransactionsEssentials) contains certain interfaces
 * in package (namespace) com.atomikos.icatch
 * (including com.atomikos.icatch.Participant) which, if implemented, may
 * infringe one or more patents held by Atomikos.
 * It should be appreciated that you may NOT implement such interfaces;
 * licensing to implement these interfaces must be obtained separately from Atomikos.
 *
 * 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.
 */

package com.atomikos.persistence.imp;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

import com.atomikos.finitestates.FSMEnterEvent;
import com.atomikos.finitestates.FSMPreEnterListener;
import com.atomikos.icatch.TxState;
import com.atomikos.icatch.provider.ConfigProperties;
import com.atomikos.logging.Logger;
import com.atomikos.logging.LoggerFactory;
import com.atomikos.persistence.LogException;
import com.atomikos.persistence.LogStream;
import com.atomikos.persistence.ObjectImage;
import com.atomikos.persistence.ObjectLog;
import com.atomikos.persistence.StateRecoverable;
import com.atomikos.persistence.StateRecoveryManager;
import com.atomikos.util.Assert;
import com.atomikos.util.ClassLoadingHelper;

/**
 * Default implementation of a state recovery manager.
 */

public class StateRecoveryManagerImp  implements StateRecoveryManager, FSMPreEnterListener
{

	private static final String WRITE_AHEAD_OBJECT_LOG_CLASSNAME = "com.atomikos.persistence.imp.WriteAheadObjectLog";
	private static final Logger LOGGER = LoggerFactory.createLogger(StateRecoveryManagerImp.class);
	private static final String CHECKPOINT_INTERVAL_PROPERTY_NAME = "com.atomikos.icatch.checkpoint_interval";
	private static final String LOG_BASE_DIR_PROPERTY_NAME = "com.atomikos.icatch.log_base_dir";
	private static final String LOG_BASE_NAME_PROPERTY_NAME = "com.atomikos.icatch.log_base_name";
	private static final String SERIALIZABLE_LOGGING_PROPERTY_NAME = "com.atomikos.icatch.serializable_logging";
	
	private ObjectLog objectlog_;
	private LogFileLock lock_;


	/**
	 * @see StateRecoveryManager
	 */
	public void register(StateRecoverable staterecoverable) {
		Assert.notNull("illegal attempt to register null staterecoverable", staterecoverable);
		TxState[] states = staterecoverable.getRecoverableStates();
		if (states != null) {
			for (int i = 0; i < states.length; i++) {
				staterecoverable.addFSMPreEnterListener(this, states[i]);
			}
			states = staterecoverable.getFinalStates();
			for (int i = 0; i < states.length; i++) {
				staterecoverable.addFSMPreEnterListener(this, states[i]);
			}
		}
	}

	/**
	 * @see FSMPreEnterListener
	 */
	public void preEnter(FSMEnterEvent event) throws IllegalStateException {
		TxState state = event.getState();
		StateRecoverable source = (StateRecoverable) event.getSource();
		ObjectImage img = source.getObjectImage(state);
		if (img != null) {
			// null images are not logged as per the Recoverable contract
			StateObjectImage simg = new StateObjectImage(img);
			Object[] finalstates = source.getFinalStates();
			boolean delete = false;

			for (int i = 0; i < finalstates.length; i++) {
				if (state.equals(finalstates[i]))
					delete = true;
			}

			try {
				if (!delete)
					objectlog_.flush(simg);
				else
					objectlog_.delete(simg.getId());
			} catch (LogException le) {
				le.printStackTrace();
				throw new IllegalStateException("could not flush state image " + le.getMessage() + " " + le.getClass().getName());
			}
		}

	}

	/**
	 * @see StateRecoveryManager
	 */
	public void close() throws LogException {
		objectlog_.close();
		lock_.releaseLock();
	}

	/**
	 * @see StateRecoveryManager
	 */
	public StateRecoverable recover(Object id) throws LogException {
		StateRecoverable srec = (StateRecoverable) objectlog_.recover(id);
		if (srec != null) {// null if not found!
			register(srec);
		} 
		return srec;
	}

	/**
	 * @see StateRecoveryManager
	 */
	public Vector> recover() throws LogException {
		Vector> ret = objectlog_.recover();
		Enumeration> enumm = ret.elements();
		while (enumm.hasMoreElements()) {
			StateRecoverable srec = (StateRecoverable) enumm.nextElement();
			register(srec);
		}
		return ret;
	}

	/**
	 * @see StateRecoveryManager
	 */
	public void delete(Object id) throws LogException {
		objectlog_.delete(id);
	}

	
	
	public void init(Properties p) throws LogException {
		ConfigProperties configProperties = new ConfigProperties(p);
		long chckpt = configProperties.getAsLong(CHECKPOINT_INTERVAL_PROPERTY_NAME);

        String logdir = configProperties.getProperty(LOG_BASE_DIR_PROPERTY_NAME);
        String logname = configProperties.getProperty(LOG_BASE_NAME_PROPERTY_NAME);
        logdir = Utils.findOrCreateFolder ( logdir );
        
        lock_ = new LogFileLock(logdir, logname);
        lock_.acquireLock();
        
        boolean serializableLogging = configProperties.getAsBoolean(SERIALIZABLE_LOGGING_PROPERTY_NAME);
        
        LogStream logstream=null;	
		try {
			if (serializableLogging) {
				  logstream = new FileLogStream ( logdir, logname );
			} else {
				  logstream = new com.atomikos.persistence.dataserializable.FileLogStream ( logdir, logname );
		    }
			
			objectlog_ = new StreamObjectLog ( logstream, chckpt );
			
			try {
				ObjectLog objectLog = createWriteAheadObjectLogIfAvailableOnClasspath(objectlog_);
			
				objectlog_ = objectLog;
			} catch (Exception writeAheadObjectLogInstantiationFailed) {
				LOGGER.logInfo(WRITE_AHEAD_OBJECT_LOG_CLASSNAME+" instantiation failed - falling back to default");
			}
			
			objectlog_.init();
		} catch (IOException e) {
			throw new LogException(e.getMessage(), e);
		}
		
	}
	private ObjectLog createWriteAheadObjectLogIfAvailableOnClasspath(ObjectLog normalObjectLog)
			throws ClassNotFoundException, InstantiationException,
			IllegalAccessException, NoSuchMethodException,
			InvocationTargetException {
		Class  theClass =  ClassLoadingHelper.loadClass(WRITE_AHEAD_OBJECT_LOG_CLASSNAME);
		ObjectLog objectLog = theClass.newInstance();
		Method delegateMethod = theClass.getMethod("setDelegate", AbstractObjectLog.class);
		delegateMethod.invoke(objectLog, normalObjectLog);
		LOGGER.logInfo("Instantiated write-ahead logging - this constitutes a license violation if you are not a paying customer!");
		return objectLog;
	}

	

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy