Mercurial > projects > ldc
diff tango/tango/net/cluster/NetworkCache.d @ 132:1700239cab2e trunk
[svn r136] MAJOR UNSTABLE UPDATE!!!
Initial commit after moving to Tango instead of Phobos.
Lots of bugfixes...
This build is not suitable for most things.
author | lindquist |
---|---|
date | Fri, 11 Jan 2008 17:57:40 +0100 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/tango/net/cluster/NetworkCache.d Fri Jan 11 17:57:40 2008 +0100 @@ -0,0 +1,246 @@ +/******************************************************************************* + + copyright: Copyright (c) 2004 Kris Bell. All rights reserved + + license: BSD style: $(LICENSE) + + version: July 2004: Initial release + + author: Kris + +*******************************************************************************/ + +module tango.net.cluster.NetworkCache; + +private import tango.core.Thread; + +private import tango.net.cluster.model.IMessage; + +private import tango.net.cluster.QueuedCache, + tango.net.cluster.CacheInvalidator, + tango.net.cluster.CacheInvalidatee; + +/******************************************************************************* + + A gateway to the network cache. From here you can easily place + IMessage objects into the network cluster, copy them and remove + them. A cluster cache is spread out across many servers within + the network. Each cache entry is associated with a 'channel', + which is effectively the name of a cache instance within the + cluster. See ComboCache also. The basic procedure is so: + --- + import tango.net.cluster.NetworkCache; + import tango.net.cluster.tina.Cluster; + + auto cluster = new Cluster (...); + auto cache = new NetworkCache (cluster, ...); + + cache.put (...); + cache.get (); + cache.invalidate (...); + --- + + Note that any content placed into the cache must implement the + IMessage interface, and must be enrolled with the Registry, as + it may be frozen and thawed as it travels around the network. + +*******************************************************************************/ + +class NetworkCache : CacheInvalidator +{ + /*********************************************************************** + + Construct a NetworkCache using the QOS (cluster) provided, + and hook it onto the specified channel. Each subsequent + operation is tied to this channel. + + ***********************************************************************/ + + this (ICluster cluster, char[] channel) + { + super (cluster, channel); + } + + /*********************************************************************** + + Returns a copy of the cluster cache entry corresponding to + the provided key. Returns null if there is no such entry. + + ***********************************************************************/ + + IMessage get (char[] key) + { + assert (key.length); + return channel.getCache (key, false); + } + + /*********************************************************************** + + Remove and return the cache entry corresponding to the + provided key. + + ***********************************************************************/ + + IMessage extract (char[] key) + { + assert (key.length); + return channel.getCache (key, true); + } + + /*********************************************************************** + + Set a cluster cache entry. + + Place an entry into the network cache, replacing the + entry with the identical key. Where message.time is + set, it will be used to test for newer cache entries + than the one being sent i.e. if someone else placed + a newer entry into the cache, that one will remain. + + The msg will be placed into one or more cluster hosts + (depending upon QOS) + + Returns true if the cache entry was inserted, false if + the cache server already has an exiting key with a more + recent timestamp (where message.time is set). + + ***********************************************************************/ + + bool put (char[] key, IMessage message) + { + assert (message); + assert (key.length); + + return channel.putCache (key, message); + } +} + + +/******************************************************************************* + + A combination of a local cache, cluster cache, and CacheInvalidatee. + The two cache instances are combined such that they represent a + classic level1/level2 cache. The CacheInvalidatee ensures that the + level1 cache maintains coherency with the cluster. + +*******************************************************************************/ + +class NetworkCombo : NetworkCache +{ + private QueuedCache!(char[], IMessage) cache; + private CacheInvalidatee invalidatee; + + /*********************************************************************** + + Construct a ComboCache for the specified local cache, and + on the given cluster channel. + + ***********************************************************************/ + + this (ICluster cluster, char[] channel, uint capacity) + { + super (cluster, channel); + + cache = new QueuedCache!(char[], IMessage) (capacity); + invalidatee = new CacheInvalidatee (cluster, channel, cache); + } + + /*********************************************************************** + + Get an IMessage from the local cache, and revert to the + cluster cache if it's not found. + + Cluster lookups will *not* place new content into the + local cache without confirmation: the supplied delegate + must perform the appropriate cloning of cluster entries + before they will be placed into the local cache. This + delegate would typically invoke the clone() method on + the provided network message; behaviour is undefined + where a delegate simply returns a message without the + appropriate cloning steps. + + Returns null if the entry does not exist in either the + local or remote cache, or if the delegate returned null. + Returns the cache entry otherwise. + + ***********************************************************************/ + + IMessage get (char[] key, IMessage delegate(IMessage) dg) + { + auto cached = cache.get (key); + if (cached is null) + { + cached = super.get (key); + + // if delegate cloned the entry, + // place said clone into the cache + if (cached && (cached = dg(cached)) !is null) + cache.put (key, cached, cached.time); + } + return cached; + } + + /*********************************************************************** + + Place a new entry into the cache. This will also place + the entry into the cluster, and optionally invalidate + all other local cache instances across the network. If + a cache entry exists with the same key, it is replaced. + + Where message.time is set, it will be used to test for + newer cache entries than the one being sent i.e. if a + newer entry exists in the cache, that one will remain. + + Note that when using the coherency option you should + ensure your IMessage has a valid time stamp, since that + is used to invalidate appropriate cache listeners in the + cluster. You can use the getTime() method to retrieve a + current millisecond count. + + Returns true if the cache entry was inserted, false if + the cache server already has an exiting key with a more + recent timestamp (where message.time is set). + + ***********************************************************************/ + + bool put (char[] key, IMessage message, bool coherent = false) + { + // this will throw an exception if there's a problem + if (super.put (key, message)) + { + // place into local cache also + cache.put (key, message, message.time); + + // invalidate all other cache instances except this new one, + // such that no other listening cache has the same key + if (coherent) + invalidate (key, message.time); + + return true; + } + return false; + } + + /*********************************************************************** + + Remove and return the cache entry corresponding to the + provided key. + + Synchronously extracts the entry from the cluster, and + returns the entry from the local cache if there is one + there; null otherwise + + ***********************************************************************/ + + IMessage extract (char[] key) + { + // do this first, since its return value may have to be cloned + super.extract (key); + + // return the local entry if there is one + return cache.remove (key); + } +} + + +