com.sun.jini.outrigger
Class EntryHandle

java.lang.Object
  extended by com.sun.jini.outrigger.FastList.Node
      extended by com.sun.jini.outrigger.BaseHandle
          extended by com.sun.jini.outrigger.EntryHandle
All Implemented Interfaces:
LeaseDesc, Transactable, TransactionConstants

 class EntryHandle
extends BaseHandle
implements LeaseDesc, Transactable

This object holds an annotated reference to an EntryRep object. Currently there is one annotation, which is a hash code for the object that can be used as a quick-reject comparison when scanning through the list. The handle holds a hash code that is based on the bytes that encode the first N fields, where N is the number of fields in the entry up to a maximum (currently this maximum is 16 (64 bits divided by 4 bits/field), so that 4 is the minimum number of bits per field in the hash).

When comparing, the template's own hash is calculated, and also a mask that masks out the hash codes of wildcard fields. A template will match an entry only if the entry's EntryHandle hash masked with the template's wildcard mask is the same as the template's hash.

Care must be taken since the template may be a supertype of the type being searched. This is why the number of fields in the static methods is passed as an argument, not simply taken from the entry in question. When a template's hash is being created, its hash value is calculated as if it were of the class being searched, with the subclass's field count. Any extra fields are assumed to be wildcards. This means that the template's hash must be recalculated for each subclass it is compared against, but this only happens once per known subclass, and so is probably not onerous.

There is a particular risk with the removal of entries outside of transactions. Ideally marking an entry as removed and making the removal durable would be atomic with respect to other operations. But this would require holding a lock across disk I/O which we try to avoid. In particular it would hold up the progress of searches that match the entry in question, even though the very next entry might be a suitable match. One alternative would be to make the removal durable, then while holding the entry's lock mark the entry as removed, but this would allow competing takes to both get the same entry (this could be corrected by making the 2nd take lose when it goes back to try and complete the removal, and then continues its query, but since logging happens up in OutriggerServerImpl restarting the query would be inconvenient, it would probably also result in a number of unnecessary log records). We could mark the entry as removed, release the entry's lock, and then make the removal durable. However, this allows for the possibility of a 2nd query that matches the entry coming in after the entry has been removed, but before the removal has been made durable, finding no matches and returning null, and then the server crashing before the removal is made durable. When the server came back up the entry would be available again, and if the 2nd query was repeated it could then return the entry that had been marked as removed. Effectively an entry would have disappeared and then reappeared.

Our solution is to introduce the removePending flag. When an entry is to be removed outside of a transaction the removePending flag is set by calling provisionallyRemove, the removal is made durable, the entry is removed internally and the removePending flag cleared (generally by calling remove on the appropriate EntryHolder or on the EntryHolderSet - either will remove the entry from all the internal tables and clear the removePending flag).

Any operation that will definitively indicate that a given entry has been removed must not only check to see if the entry has been removed but also that removePending is not set (the isProvisionallyRemoved method returns the state of the removePending flag). If removePending is set the operation must either block until removePending is cleared (this can be accomplished using the waitOnCompleteRemoval method), indicating that the removal has been made durable, or return in such a way that the entry's state is left ambiguous. Note, because any I/O failure while logging will result in the space crashing a set removePending flag will only transition to cleared after a removal has been made durable, thus an operation blocked on the removePending flag should never need to go back and see if the entry has become available.

Note some of the method of this class are synchronized internally, while other are synchronized externally. Methods which need to be synchronized externally are called out in their comments.

Author:
Sun Microsystems, Inc.

Field Summary
private  long hash
          the content hash for the rep
private  boolean removePending
          true if this entry has to been seen as removed, but the removal has not yet been committed to disk
private  TxnState txnState
          If this entry is locked by one or more transaction the info on those transactions, otherwise null.
 
Fields inherited from interface net.jini.core.transaction.server.TransactionConstants
ABORTED, ACTIVE, COMMITTED, NOTCHANGED, PREPARED, VOTING
 
Constructor Summary
EntryHandle(EntryRep rep, TransactableMgr mgr, EntryHolder holder)
          Create a new handle, calculating the hash for the object.
 
Method Summary
 void abort(TransactableMgr mgr, OutriggerServerImpl space)
          Abort this object's part of the transaction.
(package private)  void add(TransactableMgr mgr, int op, EntryHolder holder)
          Add mgr to the list of known managers, setting the the type of lock on this entry to op.
(package private)  void addTxns(Collection collection)
          Add into the collection any transactions that are known to this handle.
(package private)  boolean canPerform(TransactableMgr mgr, int op)
          Return true if the operation op under the given transaction (represented by the transaction's manager) can be performed on the object represented by this handle.
 void commit(TransactableMgr mgr, OutriggerServerImpl space)
          Commit this object's part of the transaction.
(package private) static EntryHandleTmplDesc descFor(EntryRep tmpl, int numFields)
          Return the template description -- mask and hash.
 LeasedResource getLeasedResource()
          Return the LeasedResource object for this resource.
(package private)  long hash()
          Return this handle's content hash.
(package private) static long hashFor(EntryRep rep, int numFields)
          Calculate the hash for a particular entry, assuming the given number of fields.
private static long hashFor(EntryRep rep, int numFields, EntryHandleHashDesc hashDesc)
          Calculate the hash for a particular entry, assuming the given number of fields, filling in the fields of desc with the relevant values.
(package private) static long hashForField(EntryRep rep, int field)
          Return the hash value for a given field, which is then merged in as part of the overall hash for the entry.
(package private)  boolean isProvisionallyRemoved()
          Returns true it this entry has been removed outside of a transaction, but that removal has not yet been committed to disk.The thread calling this method should own this object's lock.
(package private)  boolean knownMgr(TransactableMgr mgr)
          Return true if the given transaction is already known to the entry this handle represents.
(package private)  boolean managed()
          Return true if the entry this handle represents is being managed within any transaction.
(package private)  boolean onlyMgr(TransactableMgr mgr)
          Return true if we are being managed the given manager is the only one we know about.
 int prepare(TransactableMgr mgr, OutriggerServerImpl space)
          Methods required by the Transactable interface
(package private)  boolean promoteToTakeIfNeeded()
          It this entry is read locked promote to take locked and return true, otherwise return false.
(package private)  void provisionallyRemove()
          Marks this entry as being removed outside of a transaction but not yet committed to disk.
(package private)  void removalComplete()
          Called after the removal of a provisionally removed entry has been committed to disk and the handle has been removed from its holder.
 String toString()
           
(package private)  void waitOnCompleteRemoval()
          If this entry has been marked for removal by a non-transactional operation, but that operation has not be yet been committed to disk, block until the operation has been committed to disk, otherwise return immediately.
 
Methods inherited from class com.sun.jini.outrigger.BaseHandle
classFor, rep
 
Methods inherited from class com.sun.jini.outrigger.FastList.Node
markOnList, removed
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface com.sun.jini.outrigger.LeaseDesc
classFor
 

Field Detail

hash

private long hash
the content hash for the rep


txnState

private TxnState txnState
If this entry is locked by one or more transaction the info on those transactions, otherwise null.


removePending

private boolean removePending
true if this entry has to been seen as removed, but the removal has not yet been committed to disk

Constructor Detail

EntryHandle

EntryHandle(EntryRep rep,
            TransactableMgr mgr,
            EntryHolder holder)
Create a new handle, calculating the hash for the object. If mgr is non-null start the entry as write locked under the given transaction.

Parameters:
rep - The rep of the entry this is a handle for
mgr - If this entry is being written under a transaction the manager for that transaction, otherwise null
holder - If mgr is non-null this must be the holder holding this handle. Otherwise it may be null
Method Detail

getLeasedResource

public LeasedResource getLeasedResource()
Description copied from interface: LeaseDesc
Return the LeasedResource object for this resource.

Specified by:
getLeasedResource in interface LeaseDesc

hash

long hash()
Return this handle's content hash.


hashFor

static long hashFor(EntryRep rep,
                    int numFields)
Calculate the hash for a particular entry, assuming the given number of fields.

See Also:
hashFor(EntryRep,int,EntryHandleHashDesc)

hashFor

private static long hashFor(EntryRep rep,
                            int numFields,
                            EntryHandleHashDesc hashDesc)
Calculate the hash for a particular entry, assuming the given number of fields, filling in the fields of desc with the relevant values. desc may be null. numFields must be >= the number of fields in the rep object (this is not checked).

See Also:
hashFor(EntryRep,int), descFor(EntryRep,int), EntryHandleHashDesc

descFor

static EntryHandleTmplDesc descFor(EntryRep tmpl,
                                   int numFields)
Return the template description -- mask and hash.

See Also:
EntryHandleTmplDesc

hashForField

static long hashForField(EntryRep rep,
                         int field)
Return the hash value for a given field, which is then merged in as part of the overall hash for the entry. The last 32 bytes of the field value are used (or fewer if there are fewer).

See Also:
hashFor(EntryRep,int,EntryHandleHashDesc)

toString

public String toString()
Overrides:
toString in class Object

canPerform

boolean canPerform(TransactableMgr mgr,
                   int op)
Return true if the operation op under the given transaction (represented by the transaction's manager) can be performed on the object represented by this handle. The thread calling this method should own this object's lock.


knownMgr

boolean knownMgr(TransactableMgr mgr)
Return true if the given transaction is already known to the entry this handle represents. The thread calling this method should own this object's lock.


onlyMgr

boolean onlyMgr(TransactableMgr mgr)
Return true if we are being managed the given manager is the only one we know about. The thread calling this method should own this object's lock.


managed

boolean managed()
Return true if the entry this handle represents is being managed within any transaction. The thread calling this method should own this object's lock.


addTxns

void addTxns(Collection collection)
Add into the collection any transactions that are known to this handle. The thread calling this method should own this object's lock.


add

void add(TransactableMgr mgr,
         int op,
         EntryHolder holder)
Add mgr to the list of known managers, setting the the type of lock on this entry to op. The thread calling this method should own this object's lock. Assumes that op is compatible with any lock currently associated with this entry. holder is the the EntryHolder holding this handle.


promoteToTakeIfNeeded

boolean promoteToTakeIfNeeded()
It this entry is read locked promote to take locked and return true, otherwise return false. Assumes that the object is locked and the take is being performed under the one transaction that owns a lock on the entry.


isProvisionallyRemoved

boolean isProvisionallyRemoved()
Returns true it this entry has been removed outside of a transaction, but that removal has not yet been committed to disk.The thread calling this method should own this object's lock.


provisionallyRemove

void provisionallyRemove()
Marks this entry as being removed outside of a transaction but not yet committed to disk. The thread calling this method should own this object's lock.


removalComplete

void removalComplete()
Called after the removal of a provisionally removed entry has been committed to disk and the handle has been removed from its holder. The thread calling this method should own this object's lock.


waitOnCompleteRemoval

void waitOnCompleteRemoval()
                     throws InterruptedException
If this entry has been marked for removal by a non-transactional operation, but that operation has not be yet been committed to disk, block until the operation has been committed to disk, otherwise return immediately. The thread calling this method should own this object's lock.

Throws:
InterruptedException

prepare

public int prepare(TransactableMgr mgr,
                   OutriggerServerImpl space)
Methods required by the Transactable interface

Specified by:
prepare in interface Transactable

abort

public void abort(TransactableMgr mgr,
                  OutriggerServerImpl space)
Description copied from interface: Transactable
Abort this object's part of the transaction.

Specified by:
abort in interface Transactable

commit

public void commit(TransactableMgr mgr,
                   OutriggerServerImpl space)
Description copied from interface: Transactable
Commit this object's part of the transaction. The space is the OutriggerServerImpl on which the operation happens -- some commit operations have space-wide side effects (for example, a commit of a write operation can cause event notifications for clients registered under the transaction's parent).

Specified by:
commit in interface Transactable


Copyright 2007-2010, multiple authors.
Licensed under the Apache License, Version 2.0, see the NOTICE file for attributions.