Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/PrepareJob.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/PrepareJob.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/PrepareJob.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/PrepareJob.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,355 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + +import com.sun.jini.mahalo.log.ClientLog; +import com.sun.jini.thread.TaskManager; +import com.sun.jini.thread.WakeupManager; +import java.rmi.RemoteException; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.jini.core.transaction.Transaction; +import net.jini.core.transaction.TransactionException; +import net.jini.core.transaction.server.ServerTransaction; +import net.jini.core.transaction.server.TransactionConstants; +import net.jini.core.transaction.server.TransactionParticipant; + +/** + * An implementation of a <code>com.sun.jini.mahalo.Job</code> which + * interacts with a set of + * <code>net.jini.core.transaction.server.TransactionParticipant</code>s + * to inform them to vote. + * + * @author Sun Microsystems, Inc. + * @see com.sun.jini.mahalo.Job + * @see com.sun.jini.mahalo.ParticipantTask + * @see net.jini.core.transaction.Transaction + * @see net.jini.core.transaction.server.TransactionParticipant + */ +public class PrepareJob extends Job implements TransactionConstants +{ + ServerTransaction tr; + ClientLog log; + ParticipantHandle[] handles; + int maxtries = 5; + /** + * Logger for operations related messages + */ + private static final Logger operationsLogger = + TxnManagerImpl.operationsLogger; + + /** + * Logger for persistence related messages + */ + private static final Logger persistenceLogger = + TxnManagerImpl.persistenceLogger; + + /** + * Constructs an <code>PrepareJob</code> + * + * @param tr The <code>Transaction</code> whose participants + * will be instructed to vote + * @param pool The <code>TaskManager</code> which provides the + * threads used for interacting with participants. + * @param log The <code>ClientLog</code> used for recording + * recovery data. + * @param handles The array of participants which will be contacted + * and informed to vote + * @see com.sun.jini.thread.TaskManager + * @see com.sun.jini.mahalo.log.ClientLog + * @see net.jini.core.transaction.server.TransactionParticipant + */ + public PrepareJob( Transaction tr, TaskManager pool, + WakeupManager wm, ClientLog log, + ParticipantHandle[] handles ) + { + super( pool, wm ); + + if( log == null ) + { + throw new IllegalArgumentException( "PrepareJob: PrepareJob: " + + "log is null" ); + } + + this.log = log; + + if( !( tr instanceof ServerTransaction ) ) + { + throw new IllegalArgumentException( "PrepareJob: PrepareJob: " + + "must be a ServerTransaction" ); + } + + this.tr = (ServerTransaction) tr; + + if( handles == null ) + { + throw new IllegalArgumentException( "PrepareJob: PrepareJob: " + + "must have participants" ); + } + + if( handles.length == 0 ) + { + throw new IllegalArgumentException( "PrepareJob: PrepareJob: " + + "must have participants" ); + } + + this.handles = handles; + } + + + /** + * The work to be performed by each <code>TaskManager.Task</code> + * is provided by the <code>Job</code> that creates it. + * The work performed by a task belonging to the AbortJob + * contacts a participant, instructs it to vote and + * log appropriately. + * + * @param who The task performing the work + * @param param A parameter, of the task's choosing, useful + * in performing work. + * @see com.sun.jini.mahalo.Job + * @see com.sun.jini.thread.TaskManager.Task + */ + Object doWork( TaskManager.Task who, Object param ) + { + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.entering( PrepareJob.class.getName(), + "doWork", new Object[]{ who, param } ); + } + ParticipantHandle handle = (ParticipantHandle) param; + TransactionParticipant par = null; + + //check if a vote already exists because it was + //recovered from the log. In this situation, + //we do not need to log this info since it + //exists in the log which was used for recovery... + + int vote = handle.getPrepState(); + + switch( vote ) + { + case COMMITTED: + case NOTCHANGED: + case ABORTED: + case PREPARED: + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( + PrepareJob.class.getName(), + "doWork", new Integer( vote ) ); + } + return new Integer( vote ); + } + + //...otherwise, explicitly instruct the participant to + //prepare after unpacking it and checking against the + //max retry threshold + + if( par == null ) + { + par = handle.getPreParedParticipant(); + } + + //If you have exhausted the max retry threshold + //stop, so that no further attempts are made. + + try + { + if( attempt( who ) > maxtries ) + { + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( + PrepareJob.class.getName(), "doWork", + new Integer( ABORTED ) ); + } + return new Integer( ABORTED ); + } + } + catch( JobException je ) + { + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( + PrepareJob.class.getName(), "doWork", null ); + } + return null; + } + + + //At this point, if participant is null, there + //must be an error unpacking, so retry later + if( par == null ) + { + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( + PrepareJob.class.getName(), "doWork", null ); + } + return null; + } + + //Here we actually need to ask the participant to + //prepare. Note the RemoteException causes a + //retry. Here we only log info for the cases + //where a final outcome is available. + + Object response = null; + + try + { + vote = par.prepare( tr.mgr, tr.id ); + response = new Integer( vote ); + } + catch( TransactionException bte ) + { + vote = ABORTED; + response = new Integer( vote ); + } + catch( RemoteException re ) + { + } + catch( RuntimeException rte ) + { + vote = ABORTED; + response = new Integer( vote ); + } + + if( response != null ) + { + handle.setPrepState( vote ); + try + { + log.write( new PrepareRecord( handle, vote ) ); + } + catch( com.sun.jini.mahalo.log.LogException le ) + { + //the full package name used to disambiguate + //the LogException + if( persistenceLogger.isLoggable( Level.WARNING ) ) + { + persistenceLogger.log( Level.WARNING, + "Problem writing PrepareRecord.", le ); + } +//TODO - ignore? + } + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( + PrepareJob.class.getName(), "doWork", response ); + } + + return response; + } + + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( + PrepareJob.class.getName(), "doWork", null ); + } + return null; + } + + + /** + * Creates the <code>TaskManager.Task</code>s necessary to + * inform participants to vote. + */ + TaskManager.Task[] createTasks() + { + TaskManager.Task[] tmp = new TaskManager.Task[handles.length]; + + for( int i = 0; i < handles.length; i++ ) + { + tmp[ i ] = + new ParticipantTask( getPool(), getMgr(), this, handles[ i ] ); + } + + return tmp; + } + + + /** + * Gathers partial results submitted by tasks and produces + * a single outcome. + * + * @see com.sun.jini.mahalo.Job + */ + Object computeResult() throws JobException + { + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.entering( PrepareJob.class.getName(), + "computeResult" ); + } + try + { + if( !isCompleted( 0 ) ) + { + throw new ResultNotReadyException( "Cannot compute result " + + "since there are jobs pending" ); + } + } + catch( JobNotStartedException jnse ) + { + throw new ResultNotReadyException( "Cannot compute result since" + + " jobs were not created" ); + } + + int prepstate = NOTCHANGED; + int tmp = 0; + + checkresults: + for( int i = 0; i < results.length; i++ ) + { + tmp = ( (Integer) results[ i ] ).intValue(); + + switch( tmp ) + { + case NOTCHANGED: + //Does not affect the prepstate + break; + + case ABORTED: + //Causes all further checks to end + //while marking ABORTED. A single abort + //aborts the whole transaction. + + prepstate = ABORTED; + break checkresults; + + case PREPARED: + //changes the state to PREPARED only + //if currently NOTCHANGED + if( prepstate == NOTCHANGED ) + { + prepstate = PREPARED; + } + break; + } + } + Integer result = new Integer( prepstate ); + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( PrepareJob.class.getName(), + "computeResult", result ); + } + return result; + } +}
Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/PrepareRecord.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/PrepareRecord.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/PrepareRecord.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/PrepareRecord.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + +/** + * A <code>LogRecord</code> which encapsulates a participant being + * instructed to vote. + * + * @author Sun Microsystems, Inc. + */ +class PrepareRecord extends ParticipantModRecord +{ + static final long serialVersionUID = 7771643811455951474L; + + PrepareRecord( ParticipantHandle part, int result ) + { + super( part, result ); + } +} Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/ProxyVerifier.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/ProxyVerifier.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/ProxyVerifier.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/ProxyVerifier.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,160 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + +import com.sun.jini.landlord.ConstrainableLandlordLease; +import com.sun.jini.landlord.Landlord; +import com.sun.jini.landlord.LandlordProxyVerifier; +import java.io.Serializable; +import java.rmi.RemoteException; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.jini.core.constraint.MethodConstraints; +import net.jini.core.constraint.RemoteMethodControl; +import net.jini.export.proxytrust.TrustEquivalence; +import net.jini.id.ReferentUuid; +import net.jini.id.Uuid; +import net.jini.security.TrustVerifier; + +/** + * Defines a trust verifier for the smart proxies of a Mahalo server. + */ +final class ProxyVerifier implements TrustVerifier, Serializable +{ + + private static final long serialVersionUID = 1L; + + /** + * Logger for logging information about this instance + */ + private static final Logger logger = + Logger.getLogger( "net.jini.security.trust" ); + + /** + * The Mahalo server proxy. + */ + private final RemoteMethodControl serverProxy; + + /** + * The unique identifier associated with the backend server referenced + * by the <code>serverProxy</code>, used for comparison with the IDs + * extracted from the smart proxies being verified. + * + * @serial + */ + private final Uuid proxyID; + + /** + * Returns a verifier for the smart proxies of the specified Mahalo server + * proxy. + * + * @param serverProxy the Mahalo server proxy + * @throws UnsupportedOperationException if <code>serverProxy</code> does + * not implement both [EMAIL PROTECTED] RemoteMethodControl} and [EMAIL PROTECTED] + * TrustEquivalence} + */ + ProxyVerifier( TxnManager serverProxy, Uuid proxyID ) + { + if( !( serverProxy instanceof RemoteMethodControl ) ) + { + throw new UnsupportedOperationException( + "No verifier available for non-constrainable service" ); + } + else if( !( serverProxy instanceof TrustEquivalence ) ) + { + throw new UnsupportedOperationException( + "Verifier requires service proxy to implement " + + "TrustEquivalence" ); + } + else if( proxyID == null ) + { + throw new IllegalArgumentException( + "Proxy id cannot be null" ); + } + this.serverProxy = (RemoteMethodControl) serverProxy; + this.proxyID = proxyID; + } + + /** + * @throws NullPointerException [EMAIL PROTECTED] + */ + public boolean isTrustedObject( Object obj, TrustVerifier.Context ctx ) + throws RemoteException + { + if( logger.isLoggable( Level.FINER ) ) + { + logger.entering( ProxyVerifier.class.getName(), "isTrustedObject", + new Object[]{ obj, ctx } ); + } + if( obj == null || ctx == null ) + { + throw new NullPointerException( "Arguments must not be null" ); + } + RemoteMethodControl otherServerProxy; + Uuid inputProxyID = null; + if( obj instanceof TxnMgrProxy.ConstrainableTxnMgrProxy ) + { + otherServerProxy = (RemoteMethodControl) + ( (TxnMgrProxy) obj ).backend; + inputProxyID = ( (ReferentUuid) obj ).getReferentUuid(); + } + else if( obj instanceof ConstrainableLandlordLease ) + { + final LandlordProxyVerifier lpv = + new LandlordProxyVerifier( (Landlord) serverProxy, proxyID ); + return lpv.isTrustedObject( obj, ctx ); + } + else if( + obj instanceof TxnMgrAdminProxy.ConstrainableTxnMgrAdminProxy ) + { + otherServerProxy = (RemoteMethodControl) + ( (TxnMgrAdminProxy) obj ).server; + inputProxyID = ( (ReferentUuid) obj ).getReferentUuid(); + } + else if( obj instanceof TxnManager && + obj instanceof RemoteMethodControl ) + { + otherServerProxy = (RemoteMethodControl) obj; + inputProxyID = proxyID; + } + else + { + logger.log( Level.FINEST, "Object {0} is not a supported type", + obj ); + return false; + } + + // For top-level proxies, quickly verify proxy Uuid + if( ( inputProxyID != null ) && + !( proxyID.equals( inputProxyID ) ) ) + { + return false; + } + + MethodConstraints mc = otherServerProxy.getConstraints(); + TrustEquivalence trusted = + (TrustEquivalence) serverProxy.setConstraints( mc ); + boolean result = trusted.checkTrustEquivalence( otherServerProxy ); + if( logger.isLoggable( Level.FINER ) ) + { + logger.exiting( ProxyVerifier.class.getName(), "isTrustedObject", + Boolean.valueOf( result ) ); + } + return result; + } +} Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/ResultNotReadyException.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/ResultNotReadyException.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/ResultNotReadyException.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/ResultNotReadyException.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + + +/** + * @author Sun Microsystems, Inc. + */ + +public class ResultNotReadyException extends JobException +{ + static final long serialVersionUID = 5079803403238096285L; + + public ResultNotReadyException() + { + super(); + } + + public ResultNotReadyException( String msg ) + { + super( msg ); + } +} Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/SettlerTask.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/SettlerTask.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/SettlerTask.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/SettlerTask.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,181 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + +import com.sun.jini.logging.Levels; +import com.sun.jini.thread.RetryTask; +import com.sun.jini.thread.TaskManager; +import com.sun.jini.thread.WakeupManager; +import java.rmi.NoSuchObjectException; +import java.rmi.RemoteException; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; +import net.jini.core.transaction.TransactionException; +import net.jini.core.transaction.server.TransactionConstants; +import net.jini.core.transaction.server.TransactionManager; + +/** + * A <code>SettlerTask</code> is scheduled task, which + * causes an unsettled transaction to settle. + * + * @author Sun Microsystems, Inc. + */ + +public class SettlerTask extends RetryTask implements TransactionConstants +{ + private long tid; + private int attempt; + private int maxtries = Integer.MAX_VALUE; + private TransactionManager txnmgr; + + /** + * Logger for operations related messages + */ + private static final Logger operationsLogger = + TxnManagerImpl.operationsLogger; + + /** + * Logger for transactions related messages + */ + private static final Logger transactionsLogger = + TxnManagerImpl.transactionsLogger; + + /** + * Constructs a <code>SettlerTask</code>. + * + * @param manager <code>TaskManager</code> providing the threads + * of execution. + * @param txnmgr <code>TransactionManager</code> which owns the + * the transaction. + * @param tid transaction ID + */ + public SettlerTask( TaskManager manager, WakeupManager wm, + TransactionManager txnmgr, long tid ) + { + super( manager, wm ); + + if( txnmgr == null ) + { + throw new IllegalArgumentException( "SettlerTask: SettlerTask: " + + "txnmgr must be non-null" ); + } + this.txnmgr = txnmgr; + this.tid = tid; + } + + /** + * Inherit doc comment from supertype. + * + * @see com.sun.jini.thread.RetryTask + */ + public boolean runAfter( List list, int max ) + { + return false; + } + + public boolean tryOnce() + { + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.entering( SettlerTask.class.getName(), + "tryOnce" ); + } + try + { + if( attempt >= maxtries ) + { + return true; + } + + attempt++; + + if( transactionsLogger.isLoggable( Level.FINEST ) ) + { + transactionsLogger.log( Level.FINEST, + "Attempting to settle transaction id: {0}", + new Long( tid ) ); + } + + int state = txnmgr.getState( tid ); + switch( state ) + { + case VOTING: + case COMMITTED: + txnmgr.commit( tid, Long.MAX_VALUE ); + break; + + case ABORTED: + txnmgr.abort( tid, Long.MAX_VALUE ); + break; + + default: + if( transactionsLogger.isLoggable( Level.WARNING ) ) + { + transactionsLogger.log( Level.WARNING, + "Attempting to settle transaction in an invalid state: {0}", + new Integer( state ) ); + } + } + + } + catch( NoSuchObjectException nsoe ) + { + if( transactionsLogger.isLoggable( Level.WARNING ) ) + { + transactionsLogger.log( Level.WARNING, + "Unable to settle recovered transaction", nsoe ); + } +//TODO -ignore? + } + catch( TransactionException te ) + { + if( transactionsLogger.isLoggable( Levels.HANDLED ) ) + { + transactionsLogger.log( Levels.HANDLED, + "Unable to settle recovered transaction", te ); + } +//TODO -ignore? + } + catch( RemoteException re ) + { + //try again + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( SettlerTask.class.getName(), + "tryOnce", Boolean.valueOf( false ) ); + } + return false; + } + + if( transactionsLogger.isLoggable( Level.FINEST ) ) + { + transactionsLogger.log( Level.FINEST, + "Transaction id {0} was settled", + new Long( tid ) ); + } + + if( operationsLogger.isLoggable( Level.FINER ) ) + { + operationsLogger.exiting( SettlerTask.class.getName(), + "tryOnce", Boolean.valueOf( true ) ); + } + + return true; + } +} Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/StorableObject.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/StorableObject.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/StorableObject.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/StorableObject.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,143 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + +import java.io.IOException; +import java.rmi.MarshalledObject; +import java.rmi.RemoteException; + +/** + * This class holds a <code>MarshalledObject</code> that can be stored + * persistently. When you invoke <code>get</code>, the object is + * deserialized, its value cached in this object, and then returned. + * Subsequent calls to <code>get</code> return that value. This lets + * you store the object and hold it around, waiting until it is + * actually deserializable, since it may not be at any given time due + * to various factors, such as the codebase being unavailable. + * + * @author Sun Microsystems, Inc. + */ +public class StorableObject implements java.io.Serializable +{ + /** + * @serial + */ + private MarshalledObject bytes; // the serialized bytes + private transient Object obj; // the cached object reference + + private static final boolean DEBUG = false; + private static final long serialVersionUID = -3793675220968988873L; + + /** + * Create a <code>StorableObject</code> that will hold <code>obj</code> + * in a <code>MarshalledObject</code>. + */ + public StorableObject( Object obj ) throws RemoteException + { + try + { + bytes = new MarshalledObject( obj ); + this.obj = obj; + } + catch( RemoteException e ) + { + throw e; + } + catch( IOException e ) + { + fatalError( "can't encode object", e ); + } + } + + /** + * Return the <code>hashCode</code> of the <code>MarshalledObject</code>. + */ + public int hashCode() + { + return bytes.hashCode(); // value of obj.hashCode() + } + + public boolean equals( Object that ) + { + try + { + if( that instanceof StorableObject ) + { + return get().equals( ( (StorableObject) that ).get() ); + } + else + { + return get().equals( that ); + } + } + catch( RemoteException e ) + { + return false; //!! or should I just die? + } + } + + /** + * Return the Remote reference. Deserialize the object if we don't + * already have an actual reference in hand. + * + * @throws java.rmi.RemoteException Problems re-establishing connection with remote object + */ + public Object get() throws RemoteException + { + try + { + if( obj == null ) + { + obj = bytes.get(); + } + return obj; + } + catch( RemoteException e ) + { + if( DEBUG ) + { + System.out.println( "*****StorableObject:get:" + e.getMessage() ); + } + throw e; + } + catch( IOException e ) + { + fatalError( "can't decode object", e ); + } + catch( ClassNotFoundException e ) + { + fatalError( "can't decode object", e ); + } + fatalError( "how did we get here?", null ); + return null; // not reached, but compiler doesn't know + } + + /** + * Unrecoverable error happened -- show it and give up the ghost. + */ + private static void fatalError( String msg, Throwable e ) + throws RemoteException + { + System.err.println( msg ); + if( e != null ) + { + e.printStackTrace( System.err ); + } + throw new RemoteException( msg, e ); + } +} Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TransientMahaloImpl.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TransientMahaloImpl.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TransientMahaloImpl.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TransientMahaloImpl.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + +import com.sun.jini.start.LifeCycle; + +/** + * Convenience class intended for use with the + * [EMAIL PROTECTED] com.sun.jini.start.ServiceStarter} framework to start + * a <i>transient</i> (non-activatable, non-persistent) implementation + * of Mahalo. + * + * @author Sun Microsystems, Inc. + * @since 2.0 + */ +class TransientMahaloImpl extends TxnManagerImpl +{ + + /** + * Constructs a new instance of <code>TxnManagerImpl</code> that is not + * activatable, and which will not persist its state. + * + * @param configArgs <code>String</code> array whose elements are + * the arguments to use when creating the server. + * @param lifeCycle instance of <code>LifeCycle</code> that, if + * non-<code>null</code>, will cause this object's + * <code>unregister</code> method to be invoked during + * shutdown to notify the service starter framework that + * the reference to this service's implementation can be + * 'released' for garbage collection. A value of + * <code>null</code> for this argument is allowed. + * @throws Exception If there was a problem initializing the service. + */ + TransientMahaloImpl( String[] configArgs, LifeCycle lifeCycle ) + throws Exception + { + super( configArgs, lifeCycle, false );//false ==> not persistent + }//end constructor + +}//end class TransientMahaloImpl + Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TxnLogRecord.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TxnLogRecord.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TxnLogRecord.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TxnLogRecord.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + +import com.sun.jini.mahalo.log.CannotRecoverException; +import com.sun.jini.mahalo.log.LogRecord; +import net.jini.core.transaction.server.TransactionConstants; + +/** + * A <code>LogRecord</code> which encapsulates a generic + * transactional logging information. + * + * @author Sun Microsystems, Inc. + */ +interface TxnLogRecord extends TransactionConstants, LogRecord +{ + void recover( TxnManagerTransaction tmt ) throws CannotRecoverException; +} Added: incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TxnManager.java URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TxnManager.java?rev=724982&view=auto ============================================================================== --- incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TxnManager.java (added) +++ incubator/river/jtsk/skunk/niclas1/services/mahalo/src/main/java/com/sun/jini/mahalo/TxnManager.java Tue Dec 9 21:15:12 2008 @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 com.sun.jini.mahalo; + +import com.sun.jini.admin.DestroyAdmin; +import com.sun.jini.landlord.Landlord; +import com.sun.jini.start.ServiceProxyAccessor; +import java.rmi.Remote; +import java.rmi.RemoteException; +import net.jini.admin.Administrable; +import net.jini.admin.JoinAdmin; +import net.jini.core.transaction.Transaction; +import net.jini.core.transaction.UnknownTransactionException; +import net.jini.core.transaction.server.TransactionManager; + +/** + * Encapsulates the interface of an implementation of + * a <code>TransactionManager</code>. + * + * @author Sun Microsystems, Inc. + */ +public interface TxnManager extends Remote, Landlord, DestroyAdmin, + Administrable, JoinAdmin, ServiceProxyAccessor, TransactionManager +{ + /** + * Logger and configuration component name for Norm + */ + public static final String MAHALO = "com.sun.jini.mahalo"; + + /** + * Returns a reference to the <code>TransactionManager</code> + * interface. + */ + public TransactionManager manager() throws RemoteException; + + /** + * Retrieves a <code>Transaction</code> given the + * transaction's ID. + * + * @param id the id + */ + public Transaction getTransaction( long id ) + throws RemoteException, UnknownTransactionException; +}