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;
+}


Reply via email to