diff src/org/dancres/blitz/remote/BlitzProxy.java @ 0:3dc0c5604566

Initial checkin of blitz 2.0 fcs - no installer yet.
author Dan Creswell <dan.creswell@gmail.com>
date Sat, 21 Mar 2009 11:00:06 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/dancres/blitz/remote/BlitzProxy.java	Sat Mar 21 11:00:06 2009 +0000
@@ -0,0 +1,372 @@
+package org.dancres.blitz.remote;
+
+import java.io.Serializable;
+import java.io.ObjectInputStream;
+import java.io.IOException;
+
+import java.rmi.RemoteException;
+import java.rmi.MarshalledObject;
+
+import java.util.Collections;
+import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import net.jini.space.JavaSpace;
+import net.jini.space.JavaSpace05;
+
+import net.jini.core.entry.Entry;
+import net.jini.core.entry.UnusableEntryException;
+
+import net.jini.core.transaction.Transaction;
+import net.jini.core.transaction.TransactionException;
+
+import net.jini.core.event.EventRegistration;
+import net.jini.core.event.RemoteEventListener;
+
+import net.jini.core.lease.Lease;
+
+import net.jini.entry.UnusableEntriesException;
+
+import net.jini.lookup.entry.ServiceInfo;
+import net.jini.lookup.entry.Name;
+
+import com.sun.jini.lookup.entry.BasicServiceType;
+
+import net.jini.admin.Administrable;
+
+import net.jini.id.Uuid;
+import net.jini.id.ReferentUuid;
+import net.jini.id.ReferentUuids;
+
+import org.dancres.blitz.mangler.EntryMangler;
+import org.dancres.blitz.mangler.MangledEntry;
+
+import org.dancres.blitz.VersionInfo;
+import org.dancres.blitz.remote.nio.FastSpace;
+
+/**
+   The Blitz front-end proxy responsible for implementing the JavaSpace
+   interface.
+ */
+class BlitzProxy implements Serializable, JavaSpace, JavaSpace05,
+                            Administrable, ReferentUuid {
+
+    FastSpace theFast;
+    BlitzServer theStub;
+    Uuid theUuid;
+
+    BlitzProxy(BlitzServer aServer, Uuid aUuid) {
+        theStub = aServer;
+        theUuid = aUuid;
+    }
+
+    void enableFastIO(FastSpace aSpace) {
+        theFast = aSpace;
+    }
+
+    synchronized FastSpace getFastChannel() {
+        if (theFast != null) {
+            if (! theFast.isInited()) {
+                try {
+                    theFast.init();
+                } catch (IOException anIOE) {
+                    throw new Error("Panic: fast io didn't init", anIOE);
+                }
+            }
+        }
+
+        return theFast;
+    }
+
+    public Uuid getReferentUuid() {
+        return theUuid;
+    }
+
+    private EntryMangler getMangler() {
+        return EntryMangler.getMangler();
+    }
+
+    private MangledEntry packEntry(Entry anEntry, boolean isWrite) {
+        if ((isWrite) && (anEntry == null))
+            throw new IllegalArgumentException("You cannot write a null Entry");
+
+        if (anEntry == null)
+            return MangledEntry.NULL_TEMPLATE;
+        // Is it a snapshot?
+        else if (anEntry instanceof MangledEntry)
+            return (MangledEntry) anEntry;
+        else
+            return getMangler().mangle(anEntry, false);
+    }
+
+    public Lease write(Entry entry, Transaction txn, long lease)
+        throws TransactionException, RemoteException {
+
+        LeaseImpl myLease;
+
+        if (getFastChannel() != null)
+            myLease = getFastChannel().write(packEntry(entry, true), txn, lease);
+        else
+            myLease = theStub.write(packEntry(entry, true), txn, lease);
+
+        myLease.setLandlord(theStub, theUuid);
+        return myLease;
+    }
+
+    public Entry read(Entry tmpl, Transaction txn, long timeout)
+        throws UnusableEntryException, TransactionException,
+               InterruptedException, RemoteException {
+
+        MangledEntry myResult;
+
+        if (getFastChannel() != null)
+            myResult = getFastChannel().read(packEntry(tmpl, false), txn, timeout);
+        else
+            myResult = theStub.read(packEntry(tmpl, false), txn, timeout);
+
+        return (myResult != null) ?
+            getMangler().unMangle(myResult) : null;
+    }
+
+    public Entry readIfExists(Entry tmpl, Transaction txn, long timeout)
+        throws UnusableEntryException, TransactionException,
+               InterruptedException, RemoteException {
+
+        MangledEntry myResult;
+
+        if (getFastChannel() != null)
+            myResult = getFastChannel().readIfExists(packEntry(tmpl, false), txn, timeout);
+        else
+            myResult = theStub.readIfExists(packEntry(tmpl, false), txn, timeout);
+
+        return (myResult != null) ?
+            getMangler().unMangle(myResult) : null;
+    }
+
+    public Entry take(Entry tmpl, Transaction txn, long timeout)
+        throws UnusableEntryException, TransactionException,
+               InterruptedException, RemoteException {
+
+        MangledEntry myResult;
+
+        if (getFastChannel() != null)
+            myResult = getFastChannel().take(packEntry(tmpl, false), txn, timeout);
+        else
+            myResult = theStub.take(packEntry(tmpl, false), txn, timeout);
+
+        return (myResult != null) ?
+            getMangler().unMangle(myResult) : null;
+    }
+
+    public Entry takeIfExists(Entry tmpl, Transaction txn, long timeout)
+        throws UnusableEntryException, TransactionException,
+               InterruptedException, RemoteException {
+
+        MangledEntry myResult;
+
+        if (getFastChannel() != null)
+            myResult = getFastChannel().takeIfExists(packEntry(tmpl, false), txn, timeout);
+        else
+            myResult = theStub.takeIfExists(packEntry(tmpl, false), txn, timeout);
+
+        return (myResult != null) ?
+            getMangler().unMangle(myResult) : null;
+    }
+
+    public EventRegistration
+        notify(Entry tmpl, Transaction txn, RemoteEventListener listener,
+               long lease, MarshalledObject handback)
+        throws TransactionException, RemoteException {
+
+        return theStub.notify(packEntry(tmpl, false), txn, listener, lease,
+                                handback);
+    }
+
+    public Entry snapshot(Entry e) throws RemoteException {
+        if (e instanceof MangledEntry)
+            return e;
+        else
+            return getMangler().mangle(e, true);
+    }
+
+    public Object getAdmin() throws RemoteException {
+        return theStub.getAdmin();
+    }
+
+    /* *******************************************************************
+     * JavaSpace05
+     * *******************************************************************/
+
+    public List write(List anEntries, Transaction aTxn, List aLeaseTimes)
+        throws RemoteException, TransactionException {
+
+        if ((anEntries.size() == 0) || (aLeaseTimes.size() == 0))
+            throw new IllegalArgumentException("Empty lists are not allowed!");
+
+        if (anEntries.size() != aLeaseTimes.size())
+            throw new IllegalArgumentException("Entry list different size from lease list");
+
+        ArrayList myMangledEntries = new ArrayList();
+
+        for (int i = 0; i < anEntries.size(); i++) {
+            Entry myEntry = (Entry) anEntries.get(i);
+            Long myLeaseTime = (Long) aLeaseTimes.get(i);
+
+            if (myEntry == null)
+                throw new NullPointerException("Whoops, null Entry in list");
+            if (myLeaseTime.longValue() <= 0)
+                throw new IllegalArgumentException("Non-positive lease times are not allowed");
+
+            myMangledEntries.add(packEntry(myEntry, true));
+        }
+
+        List myLeases = theStub.write(myMangledEntries, aTxn, aLeaseTimes);
+
+        Iterator myFixups = myLeases.iterator();
+
+        while (myFixups.hasNext()) {
+            LeaseImpl myLease = (LeaseImpl) myFixups.next();
+            myLease.setLandlord(theStub, theUuid);
+        }
+
+        return Collections.unmodifiableList(myLeases);
+    }
+
+    public Collection take(Collection aTemplates, Transaction aTxn,
+                           long aWaitTime, long aLimit)
+        throws RemoteException, TransactionException, UnusableEntriesException {
+
+        if (aLimit <= 0)
+            throw new IllegalArgumentException("Limit needs to be a positive number");
+
+        if (aTemplates.size() == 0)
+            throw new IllegalArgumentException("Templates must be non-zero length");
+
+        MangledEntry[] myPackedTemplates = new MangledEntry[aTemplates.size()];
+        Iterator myTemplates = aTemplates.iterator();
+
+        int myIndex = 0;
+
+        while(myTemplates.hasNext()) {
+            Entry myEntry = (Entry) myTemplates.next();
+            myPackedTemplates[myIndex++] = packEntry(myEntry, false);
+        }
+
+        List myMatches = theStub.take(myPackedTemplates, aTxn, aWaitTime,
+                                      aLimit);
+
+
+        Iterator myMangledEntrys = myMatches.iterator();
+
+        List myExceptions = new ArrayList();
+        List myEntrys = new ArrayList();
+
+        while (myMangledEntrys.hasNext()) {
+            MangledEntry myEntry = (MangledEntry) myMangledEntrys.next();
+
+            try {
+                Entry myUnpacked = getMangler().unMangle(myEntry);
+                myEntrys.add(myUnpacked);
+            } catch (Exception anE) {
+                myExceptions.add(anE);
+            }
+        }
+
+        if (myExceptions.size() == 0)
+            return Collections.unmodifiableList(myEntrys);
+        else
+            throw new UnusableEntriesException("Couldn't unpack all Entrys",
+                                               myEntrys, myExceptions);
+    }
+
+    public EventRegistration
+        registerForAvailabilityEvent(Collection aTemplates, Transaction aTxn,
+                                     boolean visibilityOnly,
+                                     RemoteEventListener aListener,
+                                     long aLeaseTime,
+                                     MarshalledObject aHandback)
+        throws RemoteException, TransactionException {
+
+        MangledEntry[] myPackedTemplates = new MangledEntry[aTemplates.size()];
+        Iterator myTemplates = aTemplates.iterator();
+
+        int myIndex = 0;
+
+        while(myTemplates.hasNext()) {
+            Entry myEntry = (Entry) myTemplates.next();
+            myPackedTemplates[myIndex++] = packEntry(myEntry, false);
+        }
+
+        return theStub.registerForVisibility(myPackedTemplates, aTxn,
+                                             aListener, aLeaseTime, aHandback,
+                                             visibilityOnly);
+    }
+
+    public net.jini.space.MatchSet contents(Collection aTemplates,
+                                            Transaction aTxn,
+                                            long aLeaseTime,
+                                            long aLimit)
+        throws RemoteException, TransactionException {
+
+        if (aTemplates.size() == 0)
+            throw new IllegalArgumentException("No template entry's");
+
+        if (aLeaseTime == 0)
+            throw new IllegalArgumentException("Single bulk read via zero length lease time is no longer spec'd");
+
+        MangledEntry[] myMangledTemplates = new MangledEntry[aTemplates.size()];
+
+        Iterator myTemplates = aTemplates.iterator();
+
+        int myIndex = 0;
+
+        while (myTemplates.hasNext()) {
+            myMangledTemplates[myIndex++] =
+                packEntry((Entry) myTemplates.next(), false);
+        }
+
+        ViewResult myResult = theStub.newView(myMangledTemplates, aTxn,
+                                             aLeaseTime, true, aLimit, MatchSetImpl.CHUNK_SIZE);
+
+        return new MatchSetImpl(theStub, myResult.getLease(), aLimit,
+                myResult.getInitialBatch());
+    }
+
+    /* *******************************************************************
+     * End of JavaSpace05
+     * ******************************************************************/
+
+    public boolean equals(Object anObject) {
+        return ReferentUuids.compare(this, anObject);
+    }
+
+    public int hashCode() {
+        return theUuid.hashCode();
+    }
+
+    /**
+       As we put these default attributes on the proxy when we register it
+       and we need to include them in the dependencies, it makes sense to
+       have a method on this class to return those attributes.  Thus, we
+       ensure the dependencies are accounted for and they're in the place
+       that is most closely related to them (the proxy to which they'll
+       be attached).
+     */
+    static Entry[] getDefaultAttrs(String aName) {
+        Entry myInfo =
+            new ServiceInfo(VersionInfo.PRODUCT_NAME,
+                            VersionInfo.EMAIL_CONTACT,
+                            VersionInfo.SUPPLIER_NAME,
+                            VersionInfo.VERSION, "", "");
+
+        Entry myType = new BasicServiceType("JavaSpace/JavaSpace05");
+
+        if (aName != null) {
+            return new Entry[]{myInfo, myType, new Name(aName)};
+        } else {
+            return new Entry[]{myInfo, myType};
+        }
+    }
+}