132
|
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.NetworkMessage;
|
|
14
|
|
15 private import tango.core.Exception;
|
|
16
|
|
17 public import tango.net.cluster.model.ICluster;
|
|
18
|
|
19 /*******************************************************************************
|
|
20
|
|
21 A cluster-based messaging class. You should override both read() and
|
|
22 write() methods to transport non-transient content along with the msg.
|
|
23
|
|
24 Note that when using read() and write(), invoke the superclass first
|
|
25 so that your Message can potentially be deserialized as a superclass
|
|
26 instance. That is, read() and write() might look something like this:
|
|
27 ---
|
|
28 void read (IReader input)
|
|
29 {
|
|
30 super.read (input);
|
|
31 input (myAttribute) (myOtherAttribute);
|
|
32 }
|
|
33
|
|
34 void write (IWriter output)
|
|
35 {
|
|
36 super.write (output);
|
|
37 output (myAttribute) (myOtherAttribute2);
|
|
38 }
|
|
39 ---
|
|
40
|
|
41 *******************************************************************************/
|
|
42
|
|
43 class NetworkMessage : IMessage
|
|
44 {
|
|
45 private uint id_;
|
|
46 private long time_; // converted to Time as necessary
|
|
47 private char[] reply_;
|
|
48
|
|
49 /***********************************************************************
|
|
50
|
|
51 Have to proxy this to satisfy interface requirements. It's
|
|
52 both annoying and fragile to be forced into this kind of
|
|
53 call-brokering, but then interfaces also don't expose the
|
|
54 methods from Object either. Interfaces in D are still a
|
|
55 bit too immature
|
|
56
|
|
57 ***********************************************************************/
|
|
58
|
|
59 char[] toString ()
|
|
60 {
|
|
61 return super.toString;
|
|
62 }
|
|
63
|
|
64 /***********************************************************************
|
|
65
|
|
66 Set the optional reply-channel
|
|
67
|
|
68 ***********************************************************************/
|
|
69
|
|
70 void reply (char[] channel)
|
|
71 {
|
|
72 reply_ = channel;
|
|
73 }
|
|
74
|
|
75 /***********************************************************************
|
|
76
|
|
77 Return the optional reply-channel
|
|
78
|
|
79 ***********************************************************************/
|
|
80
|
|
81 char[] reply ()
|
|
82 {
|
|
83 return reply_;
|
|
84 }
|
|
85
|
|
86 /***********************************************************************
|
|
87
|
|
88 Set the waterline of the cache-entries that should not be
|
|
89 touched by an invalidation. This is typically the time of
|
|
90 an entry in a local cache on the machine originating the
|
|
91 invalidation. Without the ability to guard against local
|
|
92 invalidation, the cache entry just added locally would be
|
|
93 removed along with others across the cluster.
|
|
94
|
|
95 An alternative would be to invalidate before adding, though
|
|
96 that can become complicated by network race conditions.
|
|
97
|
|
98 ***********************************************************************/
|
|
99
|
|
100 void time (Time time)
|
|
101 {
|
|
102 time_ = time.ticks;
|
|
103 }
|
|
104
|
|
105 /***********************************************************************
|
|
106
|
|
107 Return our time value
|
|
108
|
|
109 ***********************************************************************/
|
|
110
|
|
111 Time time ()
|
|
112 {
|
|
113 return Time(time_);
|
|
114 }
|
|
115
|
|
116 /***********************************************************************
|
|
117
|
|
118 ***********************************************************************/
|
|
119
|
|
120 void id (uint value)
|
|
121 {
|
|
122 id_ = value;
|
|
123 }
|
|
124
|
|
125 /***********************************************************************
|
|
126
|
|
127 ***********************************************************************/
|
|
128
|
|
129 uint id ()
|
|
130 {
|
|
131 return id_;
|
|
132 }
|
|
133
|
|
134 /**********************************************************************
|
|
135
|
|
136 Recover the reply-channel from the provided reader
|
|
137
|
|
138 **********************************************************************/
|
|
139
|
|
140 void read (IReader input)
|
|
141 {
|
|
142 input (id_) (time_) (reply_);
|
|
143 }
|
|
144
|
|
145 /**********************************************************************
|
|
146
|
|
147 Emit our reply-channel to the provided writer
|
|
148
|
|
149 **********************************************************************/
|
|
150
|
|
151 void write (IWriter output)
|
|
152 {
|
|
153 output (id_) (time_) (reply_);
|
|
154 }
|
|
155
|
|
156 /***********************************************************************
|
|
157
|
|
158 Creates a shallow object copy. This is used internally
|
|
159 for setting up templates/hosts of registered objects and
|
|
160 should be overridden where deep(er) copying is desired.
|
|
161 Specifically: it makes a bit-copy only. Dynamic arrays or
|
|
162 pointer/reference oriented attributes are not duplicated.
|
|
163
|
|
164 In general, there should be zero heap activity ocurring
|
|
165 during cluster requests. Thus, specific cluster services
|
|
166 utilize this method to construct message hosts, up-front,
|
|
167 helping to ensure the heap remains untouched during normal
|
|
168 operation.
|
|
169
|
|
170 ***********************************************************************/
|
|
171
|
|
172 IMessage clone ()
|
|
173 {
|
|
174 auto ci = this.classinfo;
|
|
175 auto end = ci.init.length;
|
|
176 auto start = Object.classinfo.init.length;
|
|
177
|
|
178 auto clone = ci.create;
|
|
179 if (! clone)
|
|
180 throw new ClusterException ("cannot clone msg with no default ctor: "~ci.name);
|
|
181
|
|
182 (cast(void*)clone)[start .. end] = (cast(void*)this)[start .. end];
|
|
183 return cast(IMessage) clone;
|
|
184 }
|
|
185
|
|
186 /**********************************************************************
|
|
187
|
|
188 Interface issues mean that we'd have to reimplement all
|
|
189 the above methods again to support the ITask derivative.
|
|
190 Just hack this in here instead :[
|
|
191
|
|
192 **********************************************************************/
|
|
193
|
|
194 void execute ()
|
|
195 {
|
|
196 }
|
|
197 }
|