00001 /******************************************************************************* 00002 00003 @file Message.d 00004 00005 Copyright (C) 2004 Kris Bell 00006 00007 This software is provided 'as-is', without any express or implied 00008 warranty. In no event will the authors be held liable for damages 00009 of any kind arising from the use of this software. 00010 00011 Permission is hereby granted to anyone to use this software for any 00012 purpose, including commercial applications, and to alter it and/or 00013 redistribute it freely, subject to the following restrictions: 00014 00015 1. The origin of this software must not be misrepresented; you must 00016 not claim that you wrote the original software. If you use this 00017 software in a product, an acknowledgment within documentation of 00018 said product would be appreciated but is not required. 00019 00020 2. Altered source versions must be plainly marked as such, and must 00021 not be misrepresented as being the original software. 00022 00023 3. This notice may not be removed or altered from any distribution 00024 of the source. 00025 00026 00027 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00028 00029 00030 @version Initial version, July 2004 00031 @author Kris 00032 00033 00034 *******************************************************************************/ 00035 00036 module mango.cluster.Message; 00037 00038 private import mango.cache.Payload; 00039 00040 private import mango.io.Exception, 00041 mango.io.PickleRegistry; 00042 00043 public import mango.cluster.model.ICluster; 00044 00045 /******************************************************************************* 00046 00047 A cluster-based messaging class. You should implement the various 00048 abstract methods, and optionally override the read() and write() 00049 methods to transport any non-transient content along with the task. 00050 Note that when using read() and write(), you should invoke the 00051 superclass first. That is, read() and write() should look something 00052 like this: 00053 00054 @code 00055 void read (IReader reader) 00056 { 00057 super.read (reader); 00058 reader.get (myAttribute1); 00059 reader.get (myAttribute2); 00060 reader.get (myAttribute3); 00061 } 00062 00063 void write (IWriter writer) 00064 { 00065 super.write (writer); 00066 writer.put (myAttribute1); 00067 writer.put (myAttribute2); 00068 writer.put (myAttribute3); 00069 } 00070 @endcode 00071 00072 You should do it this way so that your Message can be deserialized 00073 as a superclass instance (if ever necessary). 00074 00075 *******************************************************************************/ 00076 00077 class Message : Payload, IMessage 00078 { 00079 private char[] reply; 00080 00081 /********************************************************************** 00082 00083 Overridable create method that simply instantiates a 00084 new instance. May be used to allocate subclassses from 00085 a freelist 00086 00087 **********************************************************************/ 00088 00089 abstract Object create (); 00090 00091 /********************************************************************** 00092 00093 Return the guid for this payload. This should be unique 00094 per payload class, if said class is used in conjunction 00095 with the clustering facilities. Inspected by the Pickle 00096 utilitiy classes. 00097 00098 **********************************************************************/ 00099 00100 abstract char[] getGuid (); 00101 00102 /*********************************************************************** 00103 00104 ***********************************************************************/ 00105 00106 void setReply (char[] channel) 00107 { 00108 reply = channel; 00109 } 00110 00111 /*********************************************************************** 00112 00113 ***********************************************************************/ 00114 00115 char[] getReply () 00116 { 00117 return reply; 00118 } 00119 00120 /*********************************************************************** 00121 00122 ***********************************************************************/ 00123 00124 bool isReplyExpected () 00125 { 00126 return reply.length > 0; 00127 } 00128 00129 /********************************************************************** 00130 00131 Recover the reply-channel from the provided reader 00132 00133 **********************************************************************/ 00134 00135 override void read (IReader reader) 00136 { 00137 super.read (reader); 00138 00139 // allocate some space for the reply 00140 reply.length = reader.length(); 00141 reader.get (reply); 00142 } 00143 00144 /********************************************************************** 00145 00146 Emit our reply-channel to the provided writer 00147 00148 **********************************************************************/ 00149 00150 override void write (IWriter writer) 00151 { 00152 super.write (writer); 00153 writer.put (reply.length).put(reply); 00154 } 00155 00156 /*********************************************************************** 00157 00158 Create a new instance of a payload, and populate it via 00159 read() using the specified reader 00160 00161 ***********************************************************************/ 00162 00163 override Object create (IReader reader) 00164 { 00165 return super.create (reader); 00166 } 00167 } 00168 00169 00170 /******************************************************************************* 00171 00172 An empty Message that can be used for network signaling, or simply 00173 as an example. 00174 00175 *******************************************************************************/ 00176 00177 class NullMessage : Message 00178 { 00179 /********************************************************************** 00180 00181 Register ourselves with the pickle factory 00182 00183 **********************************************************************/ 00184 00185 static this () 00186 { 00187 PickleRegistry.enroll (new NullMessage); 00188 } 00189 00190 /********************************************************************** 00191 00192 Overridable create method that simply instantiates a 00193 new instance. May be used to allocate subclassses from 00194 a freelist 00195 00196 **********************************************************************/ 00197 00198 override Object create () 00199 { 00200 return new NullMessage; 00201 } 00202 00203 /********************************************************************** 00204 00205 Return the guid for this payload. This should be unique 00206 per payload class, if said class is used in conjunction 00207 with the clustering facilities. Inspected by the Pickle 00208 utility classes. 00209 00210 **********************************************************************/ 00211 00212 override char[] getGuid () 00213 { 00214 return this.classinfo.name; 00215 } 00216 } 00217 00218 00219 /******************************************************************************* 00220 00221 A cluster-based executable class. You should implement the various 00222 abstract methods, and optionally override the read() and write() 00223 methods to transport any non-transient content along with the task. 00224 Note that when using read() and write(), you should invoke the 00225 superclass first. That is, read() and write() should look something 00226 like this: 00227 00228 @code 00229 void read (IReader reader) 00230 { 00231 super.read (reader); 00232 reader.get (myAttribute1); 00233 reader.get (myAttribute2); 00234 reader.get (myAttribute3); 00235 } 00236 00237 void write (IWriter writer) 00238 { 00239 super.write (writer); 00240 writer.put (myAttribute1); 00241 writer.put (myAttribute2); 00242 writer.put (myAttribute3); 00243 } 00244 @endcode 00245 00246 You should do it this way so that your Task can be deserialized as 00247 a superclass instance (if ever necessary). 00248 00249 *******************************************************************************/ 00250 00251 class Task : Message, ITask 00252 { 00253 /*********************************************************************** 00254 00255 ***********************************************************************/ 00256 00257 abstract void execute (); 00258 00259 /********************************************************************** 00260 00261 Overridable create method that simply instantiates a 00262 new instance. May be used to allocate subclassses from 00263 a freelist 00264 00265 **********************************************************************/ 00266 00267 abstract Object create (); 00268 00269 /********************************************************************** 00270 00271 Return the guid for this payload. This should be unique 00272 per payload class, if said class is used in conjunction 00273 with the clustering facilities. Inspected by the Pickle 00274 utilitiy classes. 00275 00276 **********************************************************************/ 00277 00278 abstract char[] getGuid (); 00279 00280 /********************************************************************** 00281 00282 Recover attributes from the provided reader 00283 00284 **********************************************************************/ 00285 00286 override void read (IReader reader) 00287 { 00288 super.read (reader); 00289 } 00290 00291 /********************************************************************** 00292 00293 Emit attributes to the provided writer 00294 00295 **********************************************************************/ 00296 00297 override void write (IWriter writer) 00298 { 00299 super.write (writer); 00300 } 00301 00302 /*********************************************************************** 00303 00304 Create a new instance of a payload, and populate it via 00305 read() using the specified reader 00306 00307 ***********************************************************************/ 00308 00309 override Object create (IReader reader) 00310 { 00311 return super.create (reader); 00312 } 00313 } 00314