2 // CustomPeerResolverService.cs
5 // Marcos Cobena (marcoscobena@gmail.com)
6 // Atsushi Enomoto <atsushi@ximian.com>
8 // Copyright 2007 Marcos Cobena (http://www.youcannoteatbits.org/)
10 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections.Generic;
34 using System.Transactions;
37 namespace System.ServiceModel.PeerResolvers
39 [MonoTODO ("Implement cleanup and refresh")]
40 // FIXME: TransactionTimeout must be null by-default.
41 [ServiceBehavior (AutomaticSessionShutdown = true, ConcurrencyMode = ConcurrencyMode.Multiple,
42 InstanceContextMode = InstanceContextMode.Single, ReleaseServiceInstanceOnTransactionComplete = true,
43 TransactionIsolationLevel = IsolationLevel.Unspecified, /*TransactionTimeout = null, */
44 UseSynchronizationContext = false, ValidateMustUnderstand = true)]
45 public class CustomPeerResolverService : IPeerResolverContract
49 // Maybe it's worth to change List<T> for a better distributed and faster collection.
50 List<Node> mesh = new List<Node> ();
51 object mesh_lock = new object ();
52 Timer refresh_timer, cleanup_timer;
53 DateTime last_refresh_time = DateTime.Now;
55 public CustomPeerResolverService ()
57 refresh_timer = new Timer () { AutoReset = true };
58 RefreshInterval = new TimeSpan (0, 10, 0);
59 refresh_timer.Elapsed += delegate {
62 cleanup_timer = new Timer () { AutoReset = true };
63 CleanupInterval = new TimeSpan (0, 1, 0);
64 cleanup_timer.Elapsed += delegate {
67 control_shape = false;
71 public TimeSpan CleanupInterval {
72 get { return TimeSpan.FromMilliseconds ((int) cleanup_timer.Interval); }
74 if ((value < TimeSpan.Zero) || (value > TimeSpan.MaxValue))
75 throw new ArgumentOutOfRangeException (
76 "The interval is either zero or greater than max value.");
78 throw new InvalidOperationException ("The interval must be set before it is opened");
80 cleanup_timer.Interval = value.TotalMilliseconds;
84 public bool ControlShape {
85 get { return control_shape; }
86 set { control_shape = value; }
89 public TimeSpan RefreshInterval {
90 get { return TimeSpan.FromMilliseconds ((int) refresh_timer.Interval); }
92 if ((value < TimeSpan.Zero) || (value > TimeSpan.MaxValue))
93 throw new ArgumentOutOfRangeException (
94 "The interval is either zero or greater than max value.");
96 throw new InvalidOperationException ("The interval must be set before it is opened");
98 refresh_timer.Interval = value.TotalMilliseconds;
102 [MonoTODO ("Do we have to unregister nodes here?")]
103 public virtual void Close ()
106 throw new InvalidOperationException ("The service has never been opened or it was closed by a previous call to this method.");
107 refresh_timer.Stop ();
108 cleanup_timer.Stop ();
112 public virtual ServiceSettingsResponseInfo GetServiceSettings ()
115 throw new InvalidOperationException ("The service has never been opened or it was closed previously.");
117 // return new ServiceSettingsResponseInfo ();
118 throw new NotImplementedException ();
121 public virtual void Open ()
123 if ((CleanupInterval == TimeSpan.Zero) || (RefreshInterval == TimeSpan.Zero))
124 throw new ArgumentException ("Cleanup interval or refresh interval are set to a time span interval of zero.");
127 throw new InvalidOperationException ("The service has been started by a previous call to this method.");
131 refresh_timer.Start ();
132 cleanup_timer.Start ();
136 public virtual RefreshResponseInfo Refresh (RefreshInfo refreshInfo)
138 if (refreshInfo == null)
139 throw new ArgumentException ("Refresh info cannot be null.");
142 throw new InvalidOperationException ("The service has never been opened or it was closed previously.");
144 var node = mesh.FirstOrDefault (n => n.MeshId == refreshInfo.MeshId && n.RegistrationId.Equals (refreshInfo.RegistrationId));
146 return new RefreshResponseInfo (TimeSpan.Zero, RefreshResult.RegistrationNotFound);
148 // FIXME: implement actual refresh.
149 last_refresh_time = DateTime.Now;
151 return new RefreshResponseInfo (RefreshInterval - (DateTime.Now - last_refresh_time), RefreshResult.Success);
154 public virtual RegisterResponseInfo Register (RegisterInfo registerInfo)
156 if (registerInfo == null)
157 throw new ArgumentException ("Register info cannot be null.");
160 throw new InvalidOperationException ("The service has never been opened or it was closed previously.");
162 return Register (registerInfo.ClientId, registerInfo.MeshId, registerInfo.NodeAddress);
165 public virtual RegisterResponseInfo Register (Guid clientId, string meshId, PeerNodeAddress address)
167 Node n = new Node () { RegistrationId = Guid.NewGuid (), MeshId = meshId, ClientId = clientId, NodeAddress = address };
168 RegisterResponseInfo rri = new RegisterResponseInfo ();
169 rri.RegistrationId = n.RegistrationId;
176 public virtual ResolveResponseInfo Resolve (ResolveInfo resolveInfo)
178 ResolveResponseInfo rri = new ResolveResponseInfo ();
179 if (resolveInfo == null)
180 throw new ArgumentException ("Resolve info cannot be null.");
183 throw new InvalidOperationException ("The service has never been opened or it was closed previously.");
185 foreach (var node in mesh)
186 if (node.MeshId == resolveInfo.MeshId &&
187 node.ClientId == resolveInfo.ClientId)
188 rri.Addresses.Add (node.NodeAddress);
193 public virtual void Unregister (UnregisterInfo unregisterInfo)
195 if (unregisterInfo == null)
196 throw new ArgumentException ("Unregister info cannot be null.");
199 throw new InvalidOperationException ("The service has never been opened or it was closed previously.");
202 foreach (var node in mesh)
203 if (node.MeshId == unregisterInfo.MeshId &&
204 node.RegistrationId == unregisterInfo.RegistrationId) {
211 public virtual RegisterResponseInfo Update (UpdateInfo updateInfo)
213 if (updateInfo == null)
214 throw new ArgumentException ("Update info cannot be null.");
217 throw new InvalidOperationException ("The service has never been opened or it was closed previously.");
219 // return new RegisterResponseInfo ();
220 throw new NotImplementedException ();
226 public Guid ClientId { get; set; }
227 public string MeshId { get; set; }
228 public Guid RegistrationId { get; set; }
229 public PeerNodeAddress NodeAddress { get; set; }