Mercurial > hg > blitz_stable
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}; + } + } +}