Changed the lock mechanism to use a service to ratify requests to

acquire and release locks, and to use handler objects to manage locks in 
the process of resolution.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@4542 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Andrzej Kapolka
2007-02-08 00:02:11 +00:00
parent 494cda3008
commit 9a39128322
7 changed files with 573 additions and 354 deletions
@@ -1,139 +0,0 @@
//
// $Id$
package com.threerings.presents.peer.data;
import com.samskivert.util.ObjectUtil;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.presents.dobj.DSet;
/**
* Describes a lock held by one of the peers.
*/
public class Lock extends SimpleStreamableObject
implements DSet.Entry
{
/**
* Identifies a locked resource by its type and type-specific identifier.
*/
public static class Name extends SimpleStreamableObject
implements Comparable
{
/**
* Creates a new lock name.
*
* @param type the type of resource. Only names with the same type will have their ids
* compared
* @param id the resource instance identifier. Can be <code>null</code> for resources with
* only one instance
*/
public Name (String type, Comparable id)
{
_type = type;
_id = id;
}
public Name ()
{
}
/**
* Returns the resource type.
*/
public String getType ()
{
return _type;
}
/**
* Returns the resource instance identifier.
*/
public Comparable getId ()
{
return _id;
}
// documentation inherited from interface Comparable
public int compareTo (Object other)
{
Name oname = (Name)other;
int v1 = _type.compareTo(oname._type);
if (v1 != 0 || _id == null) {
return v1;
}
@SuppressWarnings("unchecked") int v2 = _id.compareTo(oname._id);
return v2;
}
@Override // documentation inherited
public int hashCode ()
{
return _type.hashCode() + (_id == null ? 0 : _id.hashCode());
}
@Override // documentation inherited
public boolean equals (Object other)
{
Name oname = (Name)other;
return _type.equals(oname._type) &&
ObjectUtil.equals(_id, oname._id);
}
protected String _type;
protected Comparable _id;
}
/**
* Creates a newly acquired lock.
*/
public Lock (Name name, String owner)
{
_name = name;
_owner = owner;
}
/**
* No-arg constructor for deserialization.
*/
public Lock ()
{
}
/**
* Returns the name of the locked resource.
*/
public Name getName ()
{
return _name;
}
/**
* Returns the owner of the lock.
*/
public String getOwner ()
{
return _owner;
}
// documentation inherited from interface DSet.Entry
public Comparable getKey ()
{
return _name;
}
@Override // documentation inherited
public boolean equals (Object other)
{
Lock olock = (Lock)other;
return olock._name.equals(_name) &&
olock._owner.equals(_owner);
}
/** Identifies what is locked. */
protected Name _name;
/** The name of the node that owns the lock. */
protected String _owner;
}
@@ -21,6 +21,9 @@
package com.threerings.presents.peer.data;
import com.samskivert.util.ObjectUtil;
import com.threerings.io.SimpleStreamableObject;
import com.threerings.io.Streamable;
import com.threerings.presents.dobj.DObject;
@@ -32,6 +35,9 @@ import com.threerings.presents.dobj.DSet;
public class NodeObject extends DObject
{
// AUTO-GENERATED: FIELDS START
/** The field name of the <code>peerService</code> field. */
public static final String PEER_SERVICE = "peerService";
/** The field name of the <code>clients</code> field. */
public static final String CLIENTS = "clients";
@@ -48,8 +54,60 @@ public class NodeObject extends DObject
public static final String CACHE_DATA = "cacheData";
// AUTO-GENERATED: FIELDS END
/** Identifies a locked resource. */
public static class Lock extends SimpleStreamableObject
implements Comparable, DSet.Entry
{
/** The resource type. Only resources of the same type will have their ids compared. */
public String type;
/** The resource identifier, which can be <code>null</code> for singleton resources. */
public Comparable id;
public Lock ()
{
}
public Lock (String type, Comparable id)
{
this.type = type;
this.id = id;
}
// documentation inherited from interface Comparable
public int compareTo (Object other)
{
Lock olock = (Lock)other;
int v1 = type.compareTo(olock.type);
if (v1 != 0 || id == null) {
return v1;
}
@SuppressWarnings("unchecked") int v2 = id.compareTo(olock.id);
return v2;
}
// documentation inherited from interface DSet.Entry
public Comparable getKey ()
{
return this;
}
@Override // documentation inherited
public int hashCode ()
{
return type.hashCode() + (id == null ? 0 : id.hashCode());
}
@Override // documentation inherited
public boolean equals (Object other)
{
Lock olock = (Lock)other;
return type.equals(olock.type) && ObjectUtil.equals(id, olock.id);
}
}
/** Used for informing peers of changes to persistent data. */
public static class CacheData implements Streamable
public static class CacheData extends SimpleStreamableObject
{
/** The cache that should be purged. */
public String cache;
@@ -68,23 +126,41 @@ public class NodeObject extends DObject
}
}
/** The service used to make requests of the node. */
public PeerMarshaller peerService;
/** Contains information on all clients connected to this node. */
public DSet<ClientInfo> clients = new DSet<ClientInfo>();
/** This node's view of the peer lock set. A lock is acquired only when it has been added to
* all peers' sets, and is released only when it has been removed from all peers' sets. */
/** The set of locks held by this node. */
public DSet<Lock> locks = new DSet<Lock>();
/** Used to broadcast a node's desire to acquire a lock. */
public Lock.Name acquiringLock;
public Lock acquiringLock;
/** Used to broadcast a node's desire to release a lock. */
public Lock.Name releasingLock;
public Lock releasingLock;
/** A field we use to broadcast changes to possible cached data. */
public CacheData cacheData;
// AUTO-GENERATED: METHODS START
/**
* Requests that the <code>peerService</code> field be set to the
* specified value. The local value will be updated immediately and an
* event will be propagated through the system to notify all listeners
* that the attribute did change. Proxied copies of this object (on
* clients) will apply the value change when they received the
* attribute changed notification.
*/
public void setPeerService (PeerMarshaller value)
{
PeerMarshaller ovalue = this.peerService;
requestAttributeChange(
PEER_SERVICE, value, ovalue);
this.peerService = value;
}
/**
* Requests that the specified entry be added to the
* <code>clients</code> set. The set will not change until the event is
@@ -138,7 +214,7 @@ public class NodeObject extends DObject
* <code>locks</code> set. The set will not change until the event is
* actually propagated through the system.
*/
public void addToLocks (Lock elem)
public void addToLocks (NodeObject.Lock elem)
{
requestEntryAdd(LOCKS, locks, elem);
}
@@ -158,7 +234,7 @@ public class NodeObject extends DObject
* <code>locks</code> set. The set will not change until the event is
* actually propagated through the system.
*/
public void updateLocks (Lock elem)
public void updateLocks (NodeObject.Lock elem)
{
requestEntryUpdate(LOCKS, locks, elem);
}
@@ -173,10 +249,10 @@ public class NodeObject extends DObject
* change. Proxied copies of this object (on clients) will apply the
* value change when they received the attribute changed notification.
*/
public void setLocks (DSet<com.threerings.presents.peer.data.Lock> value)
public void setLocks (DSet<com.threerings.presents.peer.data.NodeObject.Lock> value)
{
requestAttributeChange(LOCKS, value, this.locks);
@SuppressWarnings("unchecked") DSet<com.threerings.presents.peer.data.Lock> clone =
@SuppressWarnings("unchecked") DSet<com.threerings.presents.peer.data.NodeObject.Lock> clone =
(value == null) ? null : value.typedClone();
this.locks = clone;
}
@@ -189,9 +265,9 @@ public class NodeObject extends DObject
* clients) will apply the value change when they received the
* attribute changed notification.
*/
public void setAcquiringLock (Lock.Name value)
public void setAcquiringLock (NodeObject.Lock value)
{
Lock.Name ovalue = this.acquiringLock;
NodeObject.Lock ovalue = this.acquiringLock;
requestAttributeChange(
ACQUIRING_LOCK, value, ovalue);
this.acquiringLock = value;
@@ -205,9 +281,9 @@ public class NodeObject extends DObject
* clients) will apply the value change when they received the
* attribute changed notification.
*/
public void setReleasingLock (Lock.Name value)
public void setReleasingLock (NodeObject.Lock value)
{
Lock.Name ovalue = this.releasingLock;
NodeObject.Lock ovalue = this.releasingLock;
requestAttributeChange(
RELEASING_LOCK, value, ovalue);
this.releasingLock = value;
@@ -0,0 +1,50 @@
//
// $Id$
//
// Narya library - tools for developing networked games
// Copyright (C) 2002-2006 Three Rings Design, Inc., All Rights Reserved
// http://www.threerings.net/code/narya/
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
package com.threerings.presents.peer.data;
import com.threerings.presents.client.Client;
import com.threerings.presents.data.InvocationMarshaller;
import com.threerings.presents.dobj.InvocationResponseEvent;
import com.threerings.presents.peer.client.PeerService;
import com.threerings.presents.peer.data.NodeObject;
/**
* Provides the implementation of the {@link PeerService} interface
* that marshalls the arguments and delivers the request to the provider
* on the server. Also provides an implementation of the response listener
* interfaces that marshall the response arguments and deliver them back
* to the requesting client.
*/
public class PeerMarshaller extends InvocationMarshaller
implements PeerService
{
/** The method id used to dispatch {@link #ratifyLockAction} requests. */
public static final int RATIFY_LOCK_ACTION = 1;
// from interface PeerService
public void ratifyLockAction (Client arg1, NodeObject.Lock arg2, boolean arg3)
{
sendRequest(arg1, RATIFY_LOCK_ACTION, new Object[] {
arg2, Boolean.valueOf(arg3)
});
}
}