Mercurial > projects > ldc
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 |