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);
+        }
+}
+
+
+