Mercurial > traipse_dev
comparison orpg/networking/meta_server_lib.py @ 100:7ed4979cc1cf beta
Traipse Beta 'OpenRPG' {090925-00}
Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc''s main goal is to offer more advanced features and enhance the productivity of the user.
Update Summary:
090925-00:
Adds menu changes to draw attention to important updates, errors, or other events. (image info coming soon)
Traipse URL is not included in the repos tab and is set as default.
Fixes Copy for Windows and Linux (finally!!) users.
Fixes incomplete update to Grid and List nodes.
Fixes incomplete update to Chat Commands.
Fixes problems with Remote Image Upload.
Fixes Drop and Drag of Minis to Map.
CherryPy can now use any image in the webfiles/ folder and sub-folders.
CherryPy can now Drop and Drag Minis to the Map.
Minor changes to Update Manager's GUI.
Expert recommendation warning added to Revision Update.
Step down compatibility with open_rpg & component added to orpgCore.
Fixes CherryPit misspelling.
Makes Traipse Suite 'Attention' item portable, and executes it on 'Critical' debug notices.
Adds incomplete Shift + Enter to Text Entry, currently creates a 'Critical' warning.
New default Lobby Map, designed for Traipse. Feel free to change it.
Updates to Server GUI:
* Admin can Ban from Backend.
* Admin can Modify Ban List and Un Ban users.
* Server GUI finds your Lobby Name
* New users default as Lurker unless a Role is set
Cleaner TraipseSuiteAttention portability and clean up in Main.
Die Roll Commands addition from Core code allowing Math Ordering with ()'s
New About Dialog. A more uniform About Dialog.
Corrects image loading of duplicate images.
author | sirebral |
---|---|
date | Fri, 25 Sep 2009 20:46:02 -0500 |
parents | 68c7bd272f27 |
children | 9314d63c0941 dcf4fbe09b70 |
comparison
equal
deleted
inserted
replaced
94:118fbe111922 | 100:7ed4979cc1cf |
---|---|
32 META_DEBUG = 0 | 32 META_DEBUG = 0 |
33 | 33 |
34 __version__ = "$Id: meta_server_lib.py,v 1.40 2007/04/04 01:18:42 digitalxero Exp $" | 34 __version__ = "$Id: meta_server_lib.py,v 1.40 2007/04/04 01:18:42 digitalxero Exp $" |
35 | 35 |
36 from orpg.orpg_version import PROTOCOL_VERSION | 36 from orpg.orpg_version import PROTOCOL_VERSION |
37 from orpg.orpg_xml import xml | 37 from orpg.orpgCore import component |
38 import orpg.dirpath | 38 from orpg.tools.validate import validate |
39 import orpg.tools.validate | 39 from orpg.dirpath import dir_struct |
40 import urllib | 40 import urllib |
41 import orpg.minidom | 41 import orpg.minidom |
42 from threading import * | 42 from threading import * |
43 import time | 43 import time |
44 import sys | 44 import sys |
67 file.close() | 67 file.close() |
68 | 68 |
69 # Remove any leading or trailing data. This can happen on some satellite connections | 69 # Remove any leading or trailing data. This can happen on some satellite connections |
70 p = re.compile('(<servers>.*?</servers>)',re.DOTALL|re.IGNORECASE) | 70 p = re.compile('(<servers>.*?</servers>)',re.DOTALL|re.IGNORECASE) |
71 mo = p.search(data) | 71 mo = p.search(data) |
72 if mo: | 72 if mo: data = mo.group(0) |
73 data = mo.group(0) | |
74 | 73 |
75 if META_DEBUG: | 74 if META_DEBUG: |
76 print | 75 print |
77 print "Got this string from the Meta at " + path + ":" | 76 print "Got this string from the Meta at " + path + ":" |
78 print "===============================================" | 77 print "===============================================" |
79 print data | 78 print data |
80 print | 79 print |
81 # build dom | 80 # build dom |
81 xml = component.get('xml') | |
82 xml_dom = xml.parseXml(data) | 82 xml_dom = xml.parseXml(data) |
83 xml_dom = xml_dom._get_documentElement() | 83 xml_dom = xml_dom._get_documentElement() |
84 return xml_dom | 84 return xml_dom |
85 | 85 |
86 def post_server_data( name, realHostName=None): | 86 def post_server_data( name, realHostName=None): |
87 # build POST data | |
88 ## data = urllib.urlencode( {"server_data[name]":name, | |
89 ## "server_data[version]":PROTOCOL_VERSION, | |
90 ## "act":"new"} ) | |
91 ## | |
92 if realHostName: | 87 if realHostName: |
93 data = urllib.urlencode( {"server_data[name]":name, | 88 data = urllib.urlencode( {"server_data[name]":name, |
94 "server_data[version]":PROTOCOL_VERSION, | 89 "server_data[version]":PROTOCOL_VERSION, |
95 "act":"new", | 90 "act":"new", |
96 "REMOTE_ADDR": realHostName } ) | 91 "REMOTE_ADDR": realHostName } ) |
99 #print "Letting meta server decide the hostname to list..." | 94 #print "Letting meta server decide the hostname to list..." |
100 data = urllib.urlencode( {"server_data[name]":name, | 95 data = urllib.urlencode( {"server_data[name]":name, |
101 "server_data[version]":PROTOCOL_VERSION, | 96 "server_data[version]":PROTOCOL_VERSION, |
102 "act":"new"} ) | 97 "act":"new"} ) |
103 | 98 |
104 xml_dom = get_server_dom( data , "http://openrpg.sf.net/openrpg_servers.php") | 99 #xml_dom = get_server_dom( data , "http://openrpg.sf.net/openrpg_servers.php")#Sourceforge still? |
100 path = component.get('settings').get_setting('MetaServerBaseURL') #getMetaServerBaseURL() | |
101 xml_dom = get_server_dom(data, path) | |
105 ret_val = int( xml_dom.getAttribute( "id" ) ) | 102 ret_val = int( xml_dom.getAttribute( "id" ) ) |
106 return ret_val | 103 return ret_val |
107 | 104 |
108 def post_failed_connection(id,meta=None,address=None,port=None): | 105 def post_failed_connection(id,meta=None,address=None,port=None): |
109 # For now, turning this off. This needs to be re-vamped for | 106 # For now, turning this off. This needs to be re-vamped for |
110 # handling multiple Metas. | 107 # handling multiple Metas. |
111 return 0 | 108 return 0 |
112 # data = urllib.urlencode({"id":id,"act":"failed"}); | 109 #data = urllib.urlencode({"id":id,"act":"failed"}); |
113 # xml_dom = get_server_dom(data) | 110 #xml_dom = get_server_dom(data) |
114 # ret_val = int(xml_dom.getAttribute("return")) | 111 #ret_val = int(xml_dom.getAttribute("return")) |
115 # return ret_val | 112 #return ret_val |
116 | 113 |
117 def remove_server(id): | 114 def remove_server(id): |
118 data = urllib.urlencode({"id":id,"act":"del"}); | 115 data = urllib.urlencode({"id":id,"act":"del"}); |
119 xml_dom = get_server_dom(data) | 116 xml_dom = get_server_dom(data) |
120 ret_val = int(xml_dom.getAttribute("return")) | 117 ret_val = int(xml_dom.getAttribute("return")) |
123 | 120 |
124 def byStartAttribute(first,second): | 121 def byStartAttribute(first,second): |
125 # This function is used to easily sort a list of nodes | 122 # This function is used to easily sort a list of nodes |
126 # by their start time | 123 # by their start time |
127 | 124 |
128 if first.hasAttribute("start"): | 125 if first.hasAttribute("start"): first_start = int(first.getAttribute("start")) |
129 first_start = int(first.getAttribute("start")) | 126 else: first_start = 0 |
130 else: | 127 |
131 first_start = 0 | 128 if second.hasAttribute("start"): second_start = int(second.getAttribute("start")) |
132 | 129 else: second_start = 0 |
133 if second.hasAttribute("start"): | |
134 second_start = int(second.getAttribute("start")) | |
135 else: | |
136 second_start = 0 | |
137 | 130 |
138 # Return the result of the cmp function on the two strings | 131 # Return the result of the cmp function on the two strings |
139 return cmp(first_start,second_start) | 132 return cmp(first_start,second_start) |
140 | 133 |
141 def byNameAttribute(first,second): | 134 def byNameAttribute(first,second): |
142 # This function is used to easily sort a list of nodes | 135 # This function is used to easily sort a list of nodes |
143 # by their name attribute | 136 # by their name attribute |
144 | 137 |
145 # Ensure there is something to sort with for each | 138 # Ensure there is something to sort with for each |
146 | 139 |
147 if first.hasAttribute("name"): | 140 if first.hasAttribute("name"): first_name = str(first.getAttribute("name")).lower() |
148 first_name = str(first.getAttribute("name")).lower() | 141 else: first_name = "" |
149 else: | 142 |
150 first_name = "" | 143 if second.hasAttribute("name"): second_name = str(second.getAttribute("name")).lower() |
151 | 144 else: second_name = "" |
152 if second.hasAttribute("name"): | |
153 second_name = str(second.getAttribute("name")).lower() | |
154 else: | |
155 second_name = "" | |
156 | 145 |
157 # Return the result of the cmp function on the two strings | 146 # Return the result of the cmp function on the two strings |
158 | |
159 return cmp(first_name,second_name) | 147 return cmp(first_name,second_name) |
160 | 148 |
161 | 149 |
162 def get_server_list(versions = None,sort_by="start"): | 150 def get_server_list(versions = None,sort_by="start"): |
163 data = urllib.urlencode({"version":PROTOCOL_VERSION,"ports":"%"}) | 151 data = urllib.urlencode({"version":PROTOCOL_VERSION,"ports":"%"}) |
169 | 157 |
170 return_hash = {} # this will end up with an amalgamated list of servers | 158 return_hash = {} # this will end up with an amalgamated list of servers |
171 | 159 |
172 for meta in all_metas: # check all of the metas | 160 for meta in all_metas: # check all of the metas |
173 | 161 |
174 # get the server's xml from the current meta | 162 #get the server's xml from the current meta |
175 bad_meta = 0 | 163 bad_meta = 0 |
176 #print "Getting server list from " + meta + "..." | 164 #print "Getting server list from " + meta + "..." |
177 try: | 165 try: xml_dom = get_server_dom(data=data,path=meta) |
178 xml_dom = get_server_dom(data=data,path=meta) | |
179 except: | 166 except: |
180 #print "Trouble getting servers from " + meta + "..." | 167 #print "Trouble getting servers from " + meta + "..." |
181 bad_meta = 1 | 168 bad_meta = 1 |
182 | 169 |
183 if bad_meta: | 170 if bad_meta: |
196 # metas in the list. If a match is found, then use the new values. | 183 # metas in the list. If a match is found, then use the new values. |
197 for n in node_list: | 184 for n in node_list: |
198 | 185 |
199 # set them from current node | 186 # set them from current node |
200 | 187 |
201 if not n.hasAttribute('name'): | 188 if not n.hasAttribute('name'): n.setAttribute('name','NO_NAME_GIVEN') |
202 n.setAttribute('name','NO_NAME_GIVEN') | |
203 name = n.getAttribute('name') | 189 name = n.getAttribute('name') |
204 if not n.hasAttribute('num_users'): | 190 if not n.hasAttribute('num_users'): n.setAttribute('num_users','N/A') |
205 n.setAttribute('num_users','N/A') | |
206 num_users = n.getAttribute('num_users') | 191 num_users = n.getAttribute('num_users') |
207 if not n.hasAttribute('address'): | 192 if not n.hasAttribute('address'): n.setAttribute('address','NO_ADDRESS_GIVEN') |
208 n.setAttribute('address','NO_ADDRESS_GIVEN') | |
209 address = n.getAttribute('address') | 193 address = n.getAttribute('address') |
210 if not n.hasAttribute('port'): | 194 if not n.hasAttribute('port'): n.setAttribute('port','6774') |
211 n.setAttribute('port','6774') | |
212 port = n.getAttribute('port') | 195 port = n.getAttribute('port') |
213 n.setAttribute('meta',meta) | 196 n.setAttribute('meta',meta) |
214 end_point = str(address) + ":" + str(port) | 197 end_point = str(address) + ":" + str(port) |
215 if return_hash.has_key(end_point): | 198 if return_hash.has_key(end_point): |
216 if META_DEBUG: print "Replacing duplicate server entry at " + end_point | 199 if META_DEBUG: print "Replacing duplicate server entry at " + end_point |
226 return_list = return_hash.values() | 209 return_list = return_hash.values() |
227 | 210 |
228 # sort them by their name attribute. Uses byNameAttribute() | 211 # sort them by their name attribute. Uses byNameAttribute() |
229 # defined above as a comparison function | 212 # defined above as a comparison function |
230 | 213 |
231 if sort_by == "start": | 214 if sort_by == "start": return_list.sort(byStartAttribute) |
232 return_list.sort(byStartAttribute) | 215 elif sort_by == "name": return_list.sort(byNameAttribute) |
233 elif sort_by == "name": | |
234 return_list.sort(byNameAttribute) | |
235 | 216 |
236 # Add each node to the DOM | 217 # Add each node to the DOM |
237 for n in return_list: | 218 for n in return_list: return_dom.appendChild(n) |
238 return_dom.appendChild(n) | |
239 return return_dom | 219 return return_dom |
240 | 220 |
241 ## List Format: | 221 ## List Format: |
242 ## <servers> | 222 ## <servers> |
243 ## <server address=? id=? name=? failed_count=? > | 223 ## <server address=? id=? name=? failed_count=? > |
255 if META_DEBUG: print " Authoritive Meta: "+str(authoritative) | 235 if META_DEBUG: print " Authoritive Meta: "+str(authoritative) |
256 metas = metaservers[0].getElementsByTagName("meta") # get the list of metas | 236 metas = metaservers[0].getElementsByTagName("meta") # get the list of metas |
257 if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)" | 237 if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)" |
258 try: | 238 try: |
259 metacache_lock.acquire() | 239 metacache_lock.acquire() |
260 ini = open(orpg.dirpath.dir_struct["user"]+"metaservers.cache","w") | 240 ini = open(dir_struct["user"]+"metaservers.cache","w") |
261 for meta in metas: | 241 for meta in metas: |
262 if META_DEBUG: print " Writing: "+str(meta.getAttribute('path')) | 242 if META_DEBUG: print " Writing: "+str(meta.getAttribute('path')) |
263 ini.write(str(meta.getAttribute('path')) + " " + str(meta.getAttribute('versions')) + "\n") | 243 ini.write(str(meta.getAttribute('path')) + " " + str(meta.getAttribute('versions')) + "\n") |
264 ini.close() | 244 ini.close() |
265 finally: | 245 finally: |
271 def getRawMetaList(): | 251 def getRawMetaList(): |
272 try: | 252 try: |
273 try: | 253 try: |
274 metacache_lock.acquire() | 254 metacache_lock.acquire() |
275 # Read in the metas | 255 # Read in the metas |
276 orpg.tools.validate.Validate().config_file("metaservers.cache","metaservers.cache") | 256 validate.config_file("metaservers.cache","metaservers.cache") |
277 ini = open(orpg.dirpath.dir_struct["user"]+"metaservers.cache","r") | 257 ini = open(dir_struct["user"]+"metaservers.cache","r") |
278 metas = ini.readlines() | 258 metas = ini.readlines() |
279 ini.close() | 259 ini.close() |
280 return metas | 260 return metas |
281 finally: | 261 finally: |
282 metacache_lock.release() | 262 metacache_lock.release() |
284 if META_DEBUG: traceback.print_exc() | 264 if META_DEBUG: traceback.print_exc() |
285 print "Meta Server Lib: getRawMetaList(): " + str(e) | 265 print "Meta Server Lib: getRawMetaList(): " + str(e) |
286 return [] | 266 return [] |
287 | 267 |
288 def getMetaServers(versions = None, pick_random=0): | 268 def getMetaServers(versions = None, pick_random=0): |
289 # get meta server URLs as a list | 269 """ |
290 | 270 get meta server URLs as a list |
291 # versions is a list of acceptable version numbers. | 271 |
292 # A False truth value will use getMetaServerBaseURL() | 272 versions is a list of acceptable version numbers. |
293 | 273 A False truth value will use getMetaServerBaseURL() |
294 # set a default if we have weird reading problems | 274 |
295 # default_url = "http://www.openrpg.com/openrpg_servers.php" | 275 set a default if we have weird reading problems |
276 default_url = "http://www.openrpg.com/openrpg_servers.php" | |
277 """ | |
296 | 278 |
297 meta_names = [] | 279 meta_names = [] |
298 | 280 |
299 if(versions): # If versions are supplied, then look in metaservers.conf | 281 if(versions): # If versions are supplied, then look in metaservers.conf |
300 try: | 282 try: |
301 # read in the metas from file | 283 """ |
302 # format of file is one meta entry per line | 284 read in the metas from file |
303 # each entry will be the meta url, followed by one or more version numbers that it | 285 format of file is one meta entry per line |
304 # handle. Generally, this will be either a 1 for the original Meta format, or | 286 each entry will be the meta url, followed by one or more version numbers that it |
305 # 2 for the new one. | 287 handle. Generally, this will be either a 1 for the original Meta format, or |
288 2 for the new one. | |
289 """ | |
306 | 290 |
307 # Read in the metas | 291 # Read in the metas |
308 metas = getRawMetaList() | 292 metas = getRawMetaList() |
309 #print str(metas) | 293 #print str(metas) |
310 | 294 |
313 for meta in metas: | 297 for meta in metas: |
314 | 298 |
315 # split the line on whitespace | 299 # split the line on whitespace |
316 # obviously, your meta servers urls shouldn't contain whitespace. duh. | 300 # obviously, your meta servers urls shouldn't contain whitespace. duh. |
317 words = meta.split() | 301 words = meta.split() |
318 | |
319 success = 0 # init success flag for version check | 302 success = 0 # init success flag for version check |
320 | |
321 for version in versions: # run through each allowed version from caller | 303 for version in versions: # run through each allowed version from caller |
322 if version in words[1:]: # if the allowed version token was found | 304 if version in words[1:]: # if the allowed version token was found |
323 success += 1 # then increment the success indicator | 305 success += 1 # then increment the success indicator |
324 | |
325 if success: # if the meta entry is acceptable to the caller | 306 if success: # if the meta entry is acceptable to the caller |
326 meta_names.append(words[0]) # add the entry | 307 meta_names.append(words[0]) # add the entry |
327 if META_DEBUG: print "adding metaserver " + meta | 308 if META_DEBUG: print "adding metaserver " + meta |
328 | 309 |
329 # at this point, we should have at least one name from the cache. If not ... | 310 # at this point, we should have at least one name from the cache. If not ... |
330 if not meta_names: | 311 if not meta_names: |
331 default_meta = getMetaServerBaseURL() # grab the meta from ini.xml | 312 default_meta = getMetaServerBaseURL() # grab the meta from ini.xml |
332 meta_names.append(default_meta) # add it to the return list | 313 meta_names.append(default_meta) # add it to the return list |
333 # print "Warning!!\nNo valid metaservers cached." | 314 # print "Warning!!\nNo valid metaservers cached." |
334 # print "Using meta from MetaServerBaseURL: " + default_meta + "\n" | 315 # print "Using meta from MetaServerBaseURL: " + default_meta + "\n" |
335 # if we have more than one and want a random one | 316 # if we have more than one and want a random one |
336 elif pick_random: | 317 elif pick_random: |
337 if META_DEBUG: print "choosing random meta from: " + str(meta_names) | 318 if META_DEBUG: print "choosing random meta from: " + str(meta_names) |
338 i = int(random.uniform(0,len(meta_names))) | 319 i = int(random.uniform(0,len(meta_names))) |
339 #meta = meta_names[i] | 320 #meta = meta_names[i] |
355 | 336 |
356 def getMetaServerBaseURL(): | 337 def getMetaServerBaseURL(): |
357 # get meta server URL | 338 # get meta server URL |
358 url = "http://www.openrpg.com/openrpg_servers.php" | 339 url = "http://www.openrpg.com/openrpg_servers.php" |
359 try: | 340 try: |
360 orpg.tools.validate.Validate().config_file("settings.xml","default_settings.xml") | 341 component.get('validate').config_file("settings.xml","default_settings.xml") |
361 ini = open(orpg.dirpath.dir_struct["user"]+"settings.xml","r") | 342 ini = open(dir_struct["user"]+"settings.xml","r") |
362 txt = ini.read() | 343 txt = ini.read() |
344 xml = component.get('xml') | |
363 tree = xml.parseXml(txt)._get_documentElement() | 345 tree = xml.parseXml(txt)._get_documentElement() |
364 ini.close() | 346 ini.close() |
365 node_list = tree.getElementsByTagName("MetaServerBaseURL") | 347 node_list = tree.getElementsByTagName("MetaServerBaseURL") |
366 if node_list: | 348 if node_list: |
367 url = node_list[0].getAttribute("value") | 349 url = node_list[0].getAttribute("value") |
368 | 350 |
369 # allow tree to be collected | 351 # allow tree to be collected |
370 try: | 352 try: tree.unlink() |
371 tree.unlink() | 353 except: pass |
372 except: | |
373 pass | |
374 | 354 |
375 except Exception,e: | 355 except Exception,e: |
376 print e | 356 print e |
377 # print "using meta server URI: " + url | 357 #print "using meta server URI: " + url |
378 return url | 358 return url |
379 | 359 |
380 ####################################################################################### | 360 """ |
381 # Beginning of Class registerThread | 361 Beginning of Class registerThread |
382 # | 362 |
383 # A Class to Manage Registration with the Meta2 | 363 A Class to Manage Registration with the Meta2 |
384 # Create an instance and call it's start() method | 364 Create an instance and call it's start() method |
385 # if you want to be (and stay) registered. This class | 365 if you want to be (and stay) registered. This class |
386 # will take care of registering and re-registering as | 366 will take care of registering and re-registering as |
387 # often as necessary to stay in the Meta list. | 367 often as necessary to stay in the Meta list. |
388 # | 368 |
389 # You may call register() yourself if you wish to change your | 369 You may call register() yourself if you wish to change your |
390 # server's name. It will immediately update the Meta. There | 370 server's name. It will immediately update the Meta. There |
391 # is no need to unregister first. | 371 is no need to unregister first. |
392 # | 372 |
393 # Call unregister() when you no longer want to be registered. | 373 Call unregister() when you no longer want to be registered. |
394 # This will result in the registerThread dying after | 374 This will result in the registerThread dying after |
395 # attempting to immediately remove itself from the Meta. | 375 attempting to immediately remove itself from the Meta. |
396 # | 376 |
397 # If you need to become registered again after that, you | 377 If you need to become registered again after that, you |
398 # must create a new instance of class registerThread. Don't | 378 must create a new instance of class registerThread. Don't |
399 # just try to call register() on the old, dead thread class. | 379 just try to call register() on the old, dead thread class. |
400 | 380 """ |
401 | 381 |
402 class registerThread(Thread): | 382 class registerThread(Thread): |
403 # Originally, I wrote this as a sub-class of wxThread, but | 383 """ |
404 # A) I couldn't get it to import right | 384 Originally, I wrote this as a sub-class of wxThread, but |
405 # B) I realized that I want this to be used in a server, | 385 A) I couldn't get it to import right |
406 # which I don't want needing wxWindows to run! | 386 B) I realized that I want this to be used in a server, |
407 # | 387 which I don't want needing wxWindows to run! |
408 # Because of this fact, there are some methods from wxThread | 388 |
409 # that I implemented to minimize changes to the code I had | 389 Because of this fact, there are some methods from wxThread |
410 # just written, i.e. TestDeleteStatus() and Delete() | 390 that I implemented to minimize changes to the code I had |
391 just written, i.e. TestDeleteStatus() and Delete() | |
392 """ | |
411 | 393 |
412 def __init__(self,name=None,realHostName=None,num_users = "Hmmm",MetaPath=None,port=6774,register_callback=None): | 394 def __init__(self,name=None,realHostName=None,num_users = "Hmmm",MetaPath=None,port=6774,register_callback=None): |
413 | 395 |
414 Thread.__init__(self,name="registerThread") | 396 Thread.__init__(self,name="registerThread") |
415 self.rlock = RLock() # Re-entrant lock used to make this class thread safe | 397 self.rlock = RLock() # Re-entrant lock used to make this class thread safe |
427 # indicates a new registration. | 409 # indicates a new registration. |
428 self.interval = 0 # interval returned from Meta. Is how often to | 410 self.interval = 0 # interval returned from Meta. Is how often to |
429 # re-register, in minutes. | 411 # re-register, in minutes. |
430 self.destroy = 0 # Used to flag that this thread should die | 412 self.destroy = 0 # Used to flag that this thread should die |
431 self.port = str(port) | 413 self.port = str(port) |
432 self.register_callback = register_callback # set a method to call to report result of register | 414 self.register_callback = register_callback # set a method to call to report result of register |
433 # This thread will communicate with one and only one | 415 """ |
434 # Meta. If the Meta in ini.xml is changed after | 416 This thread will communicate with one and only one |
435 # instantiation, then this instance must be | 417 Meta. If the Meta in ini.xml is changed after |
436 # unregistered and a new instance instantiated. | 418 instantiation, then this instance must be |
437 # | 419 unregistered and a new instance instantiated. |
438 # Also, if MetaPath is specified, then use that. Makes | 420 |
439 # it easier to have multiple registerThreads going to keep the server registered | 421 Also, if MetaPath is specified, then use that. Makes |
440 # on multiple (compatible) Metas. | 422 it easier to have multiple registerThreads going to keep the server registered |
423 on multiple (compatible) Metas. | |
424 """ | |
441 | 425 |
442 if MetaPath == None: | 426 if MetaPath == None: |
443 self.path = getMetaServerBaseURL() # Do this if no Meta specified | 427 self.path = getMetaServerBaseURL() # Do this if no Meta specified |
444 else: | 428 else: |
445 self.path = MetaPath | 429 self.path = MetaPath |
460 self.die_event.set() | 444 self.die_event.set() |
461 finally: | 445 finally: |
462 self.rlock.release() | 446 self.rlock.release() |
463 | 447 |
464 def run(self): | 448 def run(self): |
465 # This method gets called by Thread implementation | 449 """ |
466 # when self.start() is called to begin the thread's | 450 This method gets called by Thread implementation |
467 # execution | 451 when self.start() is called to begin the thread's |
468 # | 452 execution |
469 # We will basically enter a loop that continually | 453 |
470 # re-registers this server and sleeps Interval | 454 We will basically enter a loop that continually |
471 # minutes until the thread is ordered to die in place | 455 re-registers this server and sleeps Interval |
456 minutes until the thread is ordered to die in place | |
457 """ | |
472 while(not self.TestDeleteStatus()): # Loop while until told to die | 458 while(not self.TestDeleteStatus()): # Loop while until told to die |
473 # Otherwise, call thread safe register(). | 459 # Otherwise, call thread safe register(). |
474 self.register(self.name, self.realHostName, self.num_users) | 460 self.register(self.name, self.realHostName, self.num_users) |
475 if META_DEBUG: print "Sent Registration Data" | 461 if META_DEBUG: print "Sent Registration Data" |
476 | |
477 # register() will end up setting the state variables | 462 # register() will end up setting the state variables |
478 # for us, including self.interval. | 463 # for us, including self.interval. |
479 try: | 464 try: |
480 self.rlock.acquire() # Serialize access to this state information | 465 self.rlock.acquire() # Serialize access to this state information |
481 | 466 |
494 # If we get past the while loop, it's because we've been asked to die, | 479 # If we get past the while loop, it's because we've been asked to die, |
495 # so just let run() end. Once this occurs, the thread is dead and | 480 # so just let run() end. Once this occurs, the thread is dead and |
496 # calls to Thread.isAlive() return False. | 481 # calls to Thread.isAlive() return False. |
497 | 482 |
498 def unregister(self): | 483 def unregister(self): |
499 # This method can (I hope) be called from both within the thread | 484 """ |
500 # and from other threads. It will attempt to unregister this | 485 This method can (I hope) be called from both within the thread |
501 # server from the Meta database | 486 and from other threads. It will attempt to unregister this |
502 # When this is either accomplished or has been tried hard enough | 487 server from the Meta database |
503 # (after which it just makes sense to let the Meta remove the | 488 When this is either accomplished or has been tried hard enough |
504 # entry itself when we don't re-register using this id), | 489 (after which it just makes sense to let the Meta remove the |
505 # this method will either cause the thread to immediately die | 490 entry itself when we don't re-register using this id), |
506 # (if called from this thread's context) or set the Destroy flag | 491 this method will either cause the thread to immediately die |
507 # (if called from the main thread), a positive test for which will cause | 492 (if called from this thread's context) or set the Destroy flag |
508 # the code in Entry() to exit() when the thread wakes up and | 493 (if called from the main thread), a positive test for which will cause |
509 # checks TestDeleteStatus(). | 494 the code in Entry() to exit() when the thread wakes up and |
510 # lock the critical section. The unlock will | 495 checks TestDeleteStatus(). |
511 # automatically occur at the end of the function in the finally clause | 496 lock the critical section. The unlock will |
497 automatically occur at the end of the function in the finally clause | |
498 """ | |
512 try: | 499 try: |
513 self.rlock.acquire() | 500 self.rlock.acquire() |
514 if not self.isAlive(): # check to see if this thread is dead | 501 if not self.isAlive(): # check to see if this thread is dead |
515 return 1 # If so, return an error result | 502 return 1 # If so, return an error result |
516 # Do the actual unregistering here | 503 # Do the actual unregistering here |
529 # No special handling is required. If the de-registration worked we're done. If | 516 # No special handling is required. If the de-registration worked we're done. If |
530 # not, then it's because we've already been removed or have a bad cookie. Either | 517 # not, then it's because we've already been removed or have a bad cookie. Either |
531 # way, we can't do anything else, so die. | 518 # way, we can't do anything else, so die. |
532 self.Delete() # This will cause the registerThread to die in register() | 519 self.Delete() # This will cause the registerThread to die in register() |
533 # prep xml_dom for garbage collection | 520 # prep xml_dom for garbage collection |
534 try: | 521 try: xml_dom.unlink() |
535 xml_dom.unlink() | 522 except: pass |
536 except: | |
537 pass | |
538 return 0 | 523 return 0 |
539 finally: | 524 finally: self.rlock.release() |
540 self.rlock.release() | |
541 | 525 |
542 def register(self, name=None, realHostName=None, num_users=None): | 526 def register(self, name=None, realHostName=None, num_users=None): |
543 # Designed to handle the registration, both new and | 527 """ |
544 # repeated. | 528 Designed to handle the registration, both new and |
545 # | 529 repeated. |
546 # It is intended to be called once every interval | 530 |
547 # (or interval - delta) minutes. | 531 It is intended to be called once every interval |
548 | 532 (or interval - delta) minutes. |
549 # lock the critical section. The unlock will | 533 |
550 # automatically occur at the end of the function in the finally clause | 534 lock the critical section. The unlock will |
535 automatically occur at the end of the function in the finally clause | |
536 """ | |
551 try: | 537 try: |
552 self.rlock.acquire() | 538 self.rlock.acquire() |
553 if not self.isAlive(): # check to see if this thread is dead | 539 if not self.isAlive(): # check to see if this thread is dead |
554 return 1 # If so, return an error result | 540 return 1 # If so, return an error result |
555 | 541 |
556 # Set the server's attibutes, if specified. | 542 # Set the server's attibutes, if specified. |
557 if name: | 543 if name: self.name = name |
558 self.name = name | 544 if num_users != None: self.num_users = num_users |
559 if num_users != None: | 545 if realHostName: self.realHostName = realHostName |
560 self.num_users = num_users | |
561 if realHostName: | |
562 self.realHostName = realHostName | |
563 # build POST data | 546 # build POST data |
564 if self.realHostName: | 547 if self.realHostName: |
565 data = urllib.urlencode( {"server_data[id]":self.id, | 548 data = urllib.urlencode( {"server_data[id]":self.id, |
566 "server_data[cookie]":self.cookie, | 549 "server_data[cookie]":self.cookie, |
567 "server_data[name]":self.name, | 550 "server_data[name]":self.name, |
584 except: | 567 except: |
585 if META_DEBUG: print "Problem talking to server. Setting interval for retry ..." | 568 if META_DEBUG: print "Problem talking to server. Setting interval for retry ..." |
586 if META_DEBUG: print data | 569 if META_DEBUG: print data |
587 if META_DEBUG: print | 570 if META_DEBUG: print |
588 self.interval = 0 | 571 self.interval = 0 |
589 # If we are in the registerThread thread, then setting interval to 0 | 572 """ |
590 # will end up causing a retry in about 6 seconds (see self.run()) | 573 If we are in the registerThread thread, then setting interval to 0 |
591 # If we are in the main thread, then setting interval to 0 will do one | 574 will end up causing a retry in about 6 seconds (see self.run()) |
592 # of two things: | 575 If we are in the main thread, then setting interval to 0 will do one |
593 # 1) Do the same as if we were in the registerThread | 576 of two things: |
594 # 2) Cause the next, normally scheduled register() call to use the values | 577 1) Do the same as if we were in the registerThread |
595 # provided in this call. | 578 2) Cause the next, normally scheduled register() call to use the values |
596 # | 579 provided in this call. |
597 # Which case occurs depends on where the registerThread thread is when | 580 |
598 # the main thread calls register(). | 581 Which case occurs depends on where the registerThread thread is when |
582 the main thread calls register(). | |
583 """ | |
599 return 0 # indicates that it was okay to call, not that no errors occurred | 584 return 0 # indicates that it was okay to call, not that no errors occurred |
585 | |
600 # If there is a DOM returned .... | 586 # If there is a DOM returned .... |
601 if xml_dom: | 587 if xml_dom: |
602 # If there's an error, echo it to the console | 588 # If there's an error, echo it to the console |
603 if xml_dom.hasAttribute("errmsg"): | 589 if xml_dom.hasAttribute("errmsg"): |
604 print "Error durring registration: " + xml_dom.getAttribute("errmsg") | 590 print "Error durring registration: " + xml_dom.getAttribute("errmsg") |
605 if META_DEBUG: print data | 591 if META_DEBUG: print data |
606 if META_DEBUG: print | 592 if META_DEBUG: print |
607 # No special handling is required. If the registration worked, id, cookie, and interval | 593 """ |
608 # can be stored and used for the next time. | 594 No special handling is required. If the registration worked, id, cookie, and interval |
609 # If an error occurred, then the Meta will delete us and we need to re-register as | 595 can be stored and used for the next time. |
610 # a new server. The way to indicate this is with a "0" id and "0" cookie sent to | 596 If an error occurred, then the Meta will delete us and we need to re-register as |
611 # the server during the next registration. Since that's what the server returns to | 597 a new server. The way to indicate this is with a "0" id and "0" cookie sent to |
612 # us on an error anyway, we just store them and the next registration will | 598 the server during the next registration. Since that's what the server returns to |
613 # automatically be set up as a new one. | 599 us on an error anyway, we just store them and the next registration will |
614 # | 600 automatically be set up as a new one. |
615 # Unless the server calls register() itself in the meantime. Of course, that's okay | 601 |
616 # too, because a success on THAT register() call will set up the next one to use | 602 Unless the server calls register() itself in the meantime. Of course, that's okay |
617 # the issued id and cookie. | 603 too, because a success on THAT register() call will set up the next one to use |
618 # | 604 the issued id and cookie. |
619 # The interval is stored unconditionally for similar reasons. If there's an error, | 605 |
620 # the interval will be less than 1, and the main thread's while loop will reset it | 606 The interval is stored unconditionally for similar reasons. If there's an error, |
621 # to 6 seconds for the next retry. | 607 the interval will be less than 1, and the main thread's while loop will reset it |
622 # Is it wrong to have a method where there's more comments than code? :) | 608 to 6 seconds for the next retry. |
609 Is it wrong to have a method where there's more comments than code? :) | |
610 """ | |
623 try: | 611 try: |
624 self.interval = int(xml_dom.getAttribute("interval")) | 612 self.interval = int(xml_dom.getAttribute("interval")) |
625 self.id = xml_dom.getAttribute("id") | 613 self.id = xml_dom.getAttribute("id") |
626 self.cookie = xml_dom.getAttribute("cookie") | 614 self.cookie = xml_dom.getAttribute("cookie") |
627 if not xml_dom.hasAttribute("errmsg"): | 615 if not xml_dom.hasAttribute("errmsg"): |