132
|
1 /*******************************************************************************
|
|
2
|
|
3 copyright: Copyright (c) 2004 Kris Bell. All rights reserved
|
|
4
|
|
5 license: BSD style: $(LICENSE)
|
|
6
|
|
7 version: Apr 2004: Initial release
|
|
8 Dec 2006: Outback version
|
|
9 Apr 2007: Delegate revision
|
|
10
|
|
11 author: Kris
|
|
12
|
|
13 *******************************************************************************/
|
|
14
|
|
15 module tango.net.cluster.NetworkRegistry;
|
|
16
|
|
17 private import tango.core.Exception;
|
|
18
|
|
19 private import tango.net.cluster.model.IMessage;
|
|
20
|
|
21
|
|
22 /*******************************************************************************
|
|
23
|
|
24 Bare framework for registering and creating serializable objects.
|
|
25 Such objects are intended to be transported across a local network
|
|
26 and re-instantiated at some destination node.
|
|
27
|
|
28 Each IMessage exposes the means to write, or freeze, its content. An
|
|
29 IPickleFactory provides the means to create a new instance of itself
|
|
30 populated with thawed data. Frozen objects are uniquely identified
|
|
31 by a guid exposed via the interface. Responsibility of maintaining
|
|
32 uniqueness across said identifiers lies in the hands of the developer.
|
|
33
|
|
34 *******************************************************************************/
|
|
35
|
|
36 class NetworkRegistry
|
|
37 {
|
|
38 private IMessage[char[]] registry;
|
|
39
|
|
40 public static NetworkRegistry shared;
|
|
41
|
|
42 /***********************************************************************
|
|
43
|
|
44
|
|
45 ***********************************************************************/
|
|
46
|
|
47 static this ()
|
|
48 {
|
|
49 shared = new NetworkRegistry;
|
|
50 }
|
|
51
|
|
52 /***********************************************************************
|
|
53
|
|
54
|
|
55 ***********************************************************************/
|
|
56
|
|
57 this (typeof(registry) registry = null)
|
|
58 {
|
|
59 this.registry = registry;
|
|
60 }
|
|
61
|
|
62 /***********************************************************************
|
|
63
|
|
64 Synchronized Factory lookup of the guid
|
|
65
|
|
66 ***********************************************************************/
|
|
67
|
|
68 final synchronized IMessage lookup (char[] guid)
|
|
69 {
|
|
70 auto p = guid in registry;
|
|
71 if (p is null)
|
|
72 error ("Registry.thaw :: attempt to reify via unregistered guid: ", guid);
|
|
73
|
|
74 return *p;
|
|
75 }
|
|
76
|
|
77 /***********************************************************************
|
|
78
|
|
79 Add the provided Factory to the registry. Note that one
|
|
80 cannot change a registration once it is placed. Neither
|
|
81 can one remove registered item. This is done to avoid
|
|
82 issues when trying to synchronize servers across
|
|
83 a farm, which may still have live instances of "old"
|
|
84 objects waiting to be passed around the cluster. New
|
|
85 versions of an object should be given a distinct guid
|
|
86 from the prior version; appending an incremental number
|
|
87 may well be sufficient for your needs.
|
|
88
|
|
89 ***********************************************************************/
|
|
90
|
|
91 final synchronized void enroll (IMessage target)
|
|
92 {
|
|
93 auto guid = target.toString;
|
|
94
|
|
95 if (guid in registry)
|
|
96 error ("Registry.enroll :: attempt to re-register guid: ", guid);
|
|
97
|
|
98 registry[guid] = target;
|
|
99 }
|
|
100
|
|
101 /***********************************************************************
|
|
102
|
|
103 Serialize an Object. Objects are written in Network-order,
|
|
104 and are prefixed by the guid exposed via the IMessage
|
|
105 interface. This guid is used to identify the appropriate
|
|
106 factory when reconstructing the instance.
|
|
107
|
|
108 ***********************************************************************/
|
|
109
|
|
110 final void freeze (IWriter output, IMessage target)
|
|
111 {
|
|
112 output (target.toString);
|
|
113 target.write (output);
|
|
114 }
|
|
115
|
|
116 /***********************************************************************
|
|
117
|
|
118 Create a new instance of a registered class from the content
|
|
119 made available via the given reader. The factory is located
|
|
120 using the provided guid, which must match an enrolled factory.
|
|
121
|
|
122 Note that only the factory lookup is synchronized, and not
|
|
123 the instance construction itself. This is intentional, and
|
|
124 limits how long the calling thread is stalled
|
|
125
|
|
126 ***********************************************************************/
|
|
127
|
|
128 final IMessage thaw (IReader input, IMessage host = null)
|
|
129 {
|
|
130 char[] guid;
|
|
131
|
|
132 input (guid);
|
|
133
|
|
134 if (host is null)
|
|
135 host = lookup (guid);
|
|
136 else
|
|
137 if (guid != host.toString)
|
|
138 error ("Registry.thaw :: attempt to reify into a mismatched host: ", guid);
|
|
139
|
|
140 host.read (input);
|
|
141 return host;
|
|
142 }
|
|
143
|
|
144 /***********************************************************************
|
|
145
|
|
146 Duplicate the registry
|
|
147
|
|
148 ***********************************************************************/
|
|
149
|
|
150 final NetworkRegistry dup ()
|
|
151 {
|
|
152 typeof(registry) u;
|
|
153
|
|
154 foreach (k, v; registry)
|
|
155 u[k] = v.clone;
|
|
156 return new NetworkRegistry (u);
|
|
157 }
|
|
158
|
|
159 /***********************************************************************
|
|
160
|
|
161 ***********************************************************************/
|
|
162
|
|
163 private static void error (char[] msg, char[] guid)
|
|
164 {
|
|
165 throw new RegistryException (msg ~ guid);
|
|
166 }
|
|
167 }
|
|
168
|
|
169
|
|
170
|