comparison 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
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
4
5 license: BSD style: $(LICENSE)
6
7 version: July 2004: Initial release
8
9 author: Kris
10
11 *******************************************************************************/
12
13 module tango.net.cluster.NetworkCache;
14
15 private import tango.core.Thread;
16
17 private import tango.net.cluster.model.IMessage;
18
19 private import tango.net.cluster.QueuedCache,
20 tango.net.cluster.CacheInvalidator,
21 tango.net.cluster.CacheInvalidatee;
22
23 /*******************************************************************************
24
25 A gateway to the network cache. From here you can easily place
26 IMessage objects into the network cluster, copy them and remove
27 them. A cluster cache is spread out across many servers within
28 the network. Each cache entry is associated with a 'channel',
29 which is effectively the name of a cache instance within the
30 cluster. See ComboCache also. The basic procedure is so:
31 ---
32 import tango.net.cluster.NetworkCache;
33 import tango.net.cluster.tina.Cluster;
34
35 auto cluster = new Cluster (...);
36 auto cache = new NetworkCache (cluster, ...);
37
38 cache.put (...);
39 cache.get ();
40 cache.invalidate (...);
41 ---
42
43 Note that any content placed into the cache must implement the
44 IMessage interface, and must be enrolled with the Registry, as
45 it may be frozen and thawed as it travels around the network.
46
47 *******************************************************************************/
48
49 class NetworkCache : CacheInvalidator
50 {
51 /***********************************************************************
52
53 Construct a NetworkCache using the QOS (cluster) provided,
54 and hook it onto the specified channel. Each subsequent
55 operation is tied to this channel.
56
57 ***********************************************************************/
58
59 this (ICluster cluster, char[] channel)
60 {
61 super (cluster, channel);
62 }
63
64 /***********************************************************************
65
66 Returns a copy of the cluster cache entry corresponding to
67 the provided key. Returns null if there is no such entry.
68
69 ***********************************************************************/
70
71 IMessage get (char[] key)
72 {
73 assert (key.length);
74 return channel.getCache (key, false);
75 }
76
77 /***********************************************************************
78
79 Remove and return the cache entry corresponding to the
80 provided key.
81
82 ***********************************************************************/
83
84 IMessage extract (char[] key)
85 {
86 assert (key.length);
87 return channel.getCache (key, true);
88 }
89
90 /***********************************************************************
91
92 Set a cluster cache entry.
93
94 Place an entry into the network cache, replacing the
95 entry with the identical key. Where message.time is
96 set, it will be used to test for newer cache entries
97 than the one being sent i.e. if someone else placed
98 a newer entry into the cache, that one will remain.
99
100 The msg will be placed into one or more cluster hosts
101 (depending upon QOS)
102
103 Returns true if the cache entry was inserted, false if
104 the cache server already has an exiting key with a more
105 recent timestamp (where message.time is set).
106
107 ***********************************************************************/
108
109 bool put (char[] key, IMessage message)
110 {
111 assert (message);
112 assert (key.length);
113
114 return channel.putCache (key, message);
115 }
116 }
117
118
119 /*******************************************************************************
120
121 A combination of a local cache, cluster cache, and CacheInvalidatee.
122 The two cache instances are combined such that they represent a
123 classic level1/level2 cache. The CacheInvalidatee ensures that the
124 level1 cache maintains coherency with the cluster.
125
126 *******************************************************************************/
127
128 class NetworkCombo : NetworkCache
129 {
130 private QueuedCache!(char[], IMessage) cache;
131 private CacheInvalidatee invalidatee;
132
133 /***********************************************************************
134
135 Construct a ComboCache for the specified local cache, and
136 on the given cluster channel.
137
138 ***********************************************************************/
139
140 this (ICluster cluster, char[] channel, uint capacity)
141 {
142 super (cluster, channel);
143
144 cache = new QueuedCache!(char[], IMessage) (capacity);
145 invalidatee = new CacheInvalidatee (cluster, channel, cache);
146 }
147
148 /***********************************************************************
149
150 Get an IMessage from the local cache, and revert to the
151 cluster cache if it's not found.
152
153 Cluster lookups will *not* place new content into the
154 local cache without confirmation: the supplied delegate
155 must perform the appropriate cloning of cluster entries
156 before they will be placed into the local cache. This
157 delegate would typically invoke the clone() method on
158 the provided network message; behaviour is undefined
159 where a delegate simply returns a message without the
160 appropriate cloning steps.
161
162 Returns null if the entry does not exist in either the
163 local or remote cache, or if the delegate returned null.
164 Returns the cache entry otherwise.
165
166 ***********************************************************************/
167
168 IMessage get (char[] key, IMessage delegate(IMessage) dg)
169 {
170 auto cached = cache.get (key);
171 if (cached is null)
172 {
173 cached = super.get (key);
174
175 // if delegate cloned the entry,
176 // place said clone into the cache
177 if (cached && (cached = dg(cached)) !is null)
178 cache.put (key, cached, cached.time);
179 }
180 return cached;
181 }
182
183 /***********************************************************************
184
185 Place a new entry into the cache. This will also place
186 the entry into the cluster, and optionally invalidate
187 all other local cache instances across the network. If
188 a cache entry exists with the same key, it is replaced.
189
190 Where message.time is set, it will be used to test for
191 newer cache entries than the one being sent i.e. if a
192 newer entry exists in the cache, that one will remain.
193
194 Note that when using the coherency option you should
195 ensure your IMessage has a valid time stamp, since that
196 is used to invalidate appropriate cache listeners in the
197 cluster. You can use the getTime() method to retrieve a
198 current millisecond count.
199
200 Returns true if the cache entry was inserted, false if
201 the cache server already has an exiting key with a more
202 recent timestamp (where message.time is set).
203
204 ***********************************************************************/
205
206 bool put (char[] key, IMessage message, bool coherent = false)
207 {
208 // this will throw an exception if there's a problem
209 if (super.put (key, message))
210 {
211 // place into local cache also
212 cache.put (key, message, message.time);
213
214 // invalidate all other cache instances except this new one,
215 // such that no other listening cache has the same key
216 if (coherent)
217 invalidate (key, message.time);
218
219 return true;
220 }
221 return false;
222 }
223
224 /***********************************************************************
225
226 Remove and return the cache entry corresponding to the
227 provided key.
228
229 Synchronously extracts the entry from the cluster, and
230 returns the entry from the local cache if there is one
231 there; null otherwise
232
233 ***********************************************************************/
234
235 IMessage extract (char[] key)
236 {
237 // do this first, since its return value may have to be cloned
238 super.extract (key);
239
240 // return the local entry if there is one
241 return cache.remove (key);
242 }
243 }
244
245
246