comparison orpg/networking/meta_server_lib.py @ 135:dcf4fbe09b70 beta

Traipse Beta 'OpenRPG' {091010-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 (Beta) Added Bookmarks Fix to Remote Admin Commands Minor fix to text based Server Fix to Pretty Print, from Core Fix to Splitter Nodes not being created Fix to massive amounts of images loading, from Core Added 'boot' command to remote admin Added confirmation window for sent nodes Minor changes to allow for portability to an OpenSUSE linux OS Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG Zoom Mouse plugin added Images added to Plugin UI Switching to Element Tree Map efficiency, from FlexiRPG Added Status Bar to Update Manager default_manifest.xml renamed to default_upmana.xml Cleaner clode for saved repositories New TrueDebug Class in orpg_log (See documentation for usage) Mercurial's hgweb folder is ported to upmana **Pretty important update that can help remove thousands of dead children from your gametree. **Children, <forms />, <group_atts />, <horizontal />, <cols />, <rows />, <height />, etc... are all tags now. Check your gametree and look for dead children!! **New Gamtree Recusion method, mapping, and context sensitivity. !!Alpha - Watch out for infinite loops!!
author sirebral
date Tue, 10 Nov 2009 14:11:28 -0600
parents 7ed4979cc1cf
children 6081bdc2b8d5
comparison
equal deleted inserted replaced
101:394ebb3b6a0f 135:dcf4fbe09b70
35 35
36 from orpg.orpg_version import PROTOCOL_VERSION 36 from orpg.orpg_version import PROTOCOL_VERSION
37 from orpg.orpgCore import component 37 from orpg.orpgCore import component
38 from orpg.tools.validate import validate 38 from orpg.tools.validate import validate
39 from orpg.dirpath import dir_struct 39 from orpg.dirpath import dir_struct
40 import urllib 40
41 import orpg.minidom 41 import urllib, time, sys, traceback, re
42 #import orpg.minidom
43
42 from threading import * 44 from threading import *
43 import time 45 from random import uniform
44 import sys 46 from urllib import urlopen, urlencode
45 import random 47 from orpg.tools.orpg_log import debug
46 import traceback 48
47 import re 49 from xml.etree.ElementTree import Element, fromstring
48 50
49 metacache_lock = RLock() 51 metacache_lock = RLock()
50 52
51 def get_server_dom(data=None,path=None): 53 def get_server_dom(data=None,path=None, string=False):
52 # post data at server and get the resulting DOM 54 # post data at server and get the resulting DOM
53 55 #debug()
54 if path == None: 56 if path == None:
55 # get meta server URI 57 # get meta server URI
56 path = getMetaServerBaseURL() 58 path = getMetaServerBaseURL()
57 59
58 # POST the data 60 # POST the data
60 print 62 print
61 print "Sending the following POST info to Meta at " + path + ":" 63 print "Sending the following POST info to Meta at " + path + ":"
62 print "==========================================" 64 print "=========================================="
63 print data 65 print data
64 print 66 print
65 file = urllib.urlopen(path, data) 67 file = urlopen(path, data)
66 data = file.read() 68 data = file.read()
67 file.close() 69 file.close()
68 70
69 # Remove any leading or trailing data. This can happen on some satellite connections 71 # Remove any leading or trailing data. This can happen on some satellite connections
70 p = re.compile('(<servers>.*?</servers>)',re.DOTALL|re.IGNORECASE) 72 p = re.compile('(<servers>.*?</servers>)',re.DOTALL|re.IGNORECASE)
76 print "Got this string from the Meta at " + path + ":" 78 print "Got this string from the Meta at " + path + ":"
77 print "===============================================" 79 print "==============================================="
78 print data 80 print data
79 print 81 print
80 # build dom 82 # build dom
81 xml = component.get('xml') 83 etreeEl = data
82 xml_dom = xml.parseXml(data) 84 if not string: return fromstring(etreeEl)
83 xml_dom = xml_dom._get_documentElement() 85 else: return etreeEl
84 return xml_dom 86
85 87 def post_server_data(name, realHostName=None):
86 def post_server_data( name, realHostName=None): 88 #debug()
87 if realHostName: 89 if realHostName: data = urlencode({"server_data[name]":name,
88 data = urllib.urlencode( {"server_data[name]":name,
89 "server_data[version]":PROTOCOL_VERSION, 90 "server_data[version]":PROTOCOL_VERSION,
90 "act":"new", 91 "act":"new",
91 "REMOTE_ADDR": realHostName } ) 92 "REMOTE_ADDR": realHostName })
92 93 # print "Letting meta server decide the hostname to list..."
93 else: 94 else: data = urlencode({"server_data[name]":name,
94 #print "Letting meta server decide the hostname to list..."
95 data = urllib.urlencode( {"server_data[name]":name,
96 "server_data[version]":PROTOCOL_VERSION, 95 "server_data[version]":PROTOCOL_VERSION,
97 "act":"new"} ) 96 "act":"new"})
98 97 path = component.get('settings').get('MetaServerBaseURL') #getMetaServerBaseURL()
99 #xml_dom = get_server_dom( data , "http://openrpg.sf.net/openrpg_servers.php")#Sourceforge still? 98 etreeEl = get_server_dom(data, path)
100 path = component.get('settings').get_setting('MetaServerBaseURL') #getMetaServerBaseURL() 99 return int(etreeEl.get('id'))
101 xml_dom = get_server_dom(data, path)
102 ret_val = int( xml_dom.getAttribute( "id" ) )
103 return ret_val
104 100
105 def post_failed_connection(id,meta=None,address=None,port=None): 101 def post_failed_connection(id,meta=None,address=None,port=None):
102 #debug((meta, address, port))
106 # For now, turning this off. This needs to be re-vamped for 103 # For now, turning this off. This needs to be re-vamped for
107 # handling multiple Metas. 104 # handling multiple Metas.
108 return 0 105 return 0
109 #data = urllib.urlencode({"id":id,"act":"failed"}); 106 #data = urlencode({"id":id,"act":"failed"});
110 #xml_dom = get_server_dom(data) 107 #xml_dom = get_server_dom(data)
111 #ret_val = int(xml_dom.getAttribute("return")) 108 #ret_val = int(xml_dom.getAttribute("return"))
112 #return ret_val 109 #return ret_val
113 110
114 def remove_server(id): 111 def remove_server(id):
115 data = urllib.urlencode({"id":id,"act":"del"}); 112 #debug(id)
116 xml_dom = get_server_dom(data) 113 data = urlencode({"id":id,"act":"del"});
117 ret_val = int(xml_dom.getAttribute("return")) 114 etreeEl = get_server_dom(data)
118 return ret_val 115 return int(etreeEl.get("return"))
119 116
120 117 def byStartAttribute(first, second):
121 def byStartAttribute(first,second): 118 # This function is used to easily sort a list of nodes by their start time
122 # This function is used to easily sort a list of nodes 119 # Ensure there is something to sort with for each
123 # by their start time 120
124 121 first_start = int(first.get('start')) or 0
125 if first.hasAttribute("start"): first_start = int(first.getAttribute("start")) 122 second_start = int(second.get('start')) or 0
126 else: first_start = 0
127
128 if second.hasAttribute("start"): second_start = int(second.getAttribute("start"))
129 else: second_start = 0
130 123
131 # Return the result of the cmp function on the two strings 124 # Return the result of the cmp function on the two strings
132 return cmp(first_start,second_start) 125 return cmp(first_start, second_start)
133 126
134 def byNameAttribute(first,second): 127 def byNameAttribute(first, second):
135 # This function is used to easily sort a list of nodes 128 # This function is used to easily sort a list of nodes by their name attribute
136 # by their name attribute
137
138 # Ensure there is something to sort with for each 129 # Ensure there is something to sort with for each
139 130
140 if first.hasAttribute("name"): first_name = str(first.getAttribute("name")).lower() 131 first_name = first.get('name') or ''
141 else: first_name = "" 132 second_name = second.get('name') or ''
142 133
143 if second.hasAttribute("name"): second_name = str(second.getAttribute("name")).lower()
144 else: second_name = ""
145
146 # Return the result of the cmp function on the two strings 134 # Return the result of the cmp function on the two strings
147 return cmp(first_name,second_name) 135 return cmp(first_name,second_name)
148 136
149 137
150 def get_server_list(versions = None,sort_by="start"): 138 def get_server_list(versions = None, sort_by="start"):
151 data = urllib.urlencode({"version":PROTOCOL_VERSION,"ports":"%"}) 139 data = urlencode({"version":PROTOCOL_VERSION,"ports":"%"})
152 all_metas = getMetaServers(versions,1) # get the list of metas 140 all_metas = getMetaServers(versions, 1) # get the list of metas
153 base_meta = getMetaServerBaseURL() 141 base_meta = getMetaServerBaseURL()
154 142
155 #all_metas.reverse() # The last one checked will take precedence, so reverse the order 143 #all_metas.reverse() # The last one checked will take precedence, so reverse the order
156 # so that the top one on the actual list is checked last 144 # so that the top one on the actual list is checked last
157 145 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 146
159 147 for meta in all_metas: # check all of the metas
160 for meta in all_metas: # check all of the metas
161
162 #get the server's xml from the current meta 148 #get the server's xml from the current meta
163 bad_meta = 0 149 bad_meta = 0
164 #print "Getting server list from " + meta + "..." 150 #print "Getting server list from " + meta + "..."
165 try: xml_dom = get_server_dom(data=data,path=meta) 151 try: xml_dom = get_server_dom(data=data, path=meta)
166 except: 152 except: bad_meta = 1 #print "Trouble getting servers from " + meta + "..."
167 #print "Trouble getting servers from " + meta + "..." 153 if bad_meta: continue
168 bad_meta = 1 154 if base_meta == meta: updateMetaCache(xml_dom) #print "This is our base meta: " + meta
169 155 node_list = xml_dom.findall('server')
170 if bad_meta: 156 if len(node_list): # if there are entries in the node list
171 continue 157 # otherwise, just loop to next meta
172
173 if base_meta == meta:
174 #print "This is our base meta: " + meta
175 updateMetaCache(xml_dom)
176
177 node_list = xml_dom.getElementsByTagName('server')
178
179 if len(node_list): # if there are entries in the node list
180 # otherwise, just loop to next meta
181 158
182 # for each node found, we're going to check the nodes from prior 159 # for each node found, we're going to check the nodes from prior
183 # metas in the list. If a match is found, then use the new values. 160 # metas in the list. If a match is found, then use the new values.
184 for n in node_list: 161 for n in node_list:
185
186 # set them from current node 162 # set them from current node
187 163 if not n.get('name'): n.set('name','NO_NAME_GIVEN')
188 if not n.hasAttribute('name'): n.setAttribute('name','NO_NAME_GIVEN') 164 name = n.get('name')
189 name = n.getAttribute('name') 165 if not n.get('num_users'): n.set('num_users','N/A')
190 if not n.hasAttribute('num_users'): n.setAttribute('num_users','N/A') 166 num_users = n.get('num_users')
191 num_users = n.getAttribute('num_users') 167 if not n.get('address'): n.set('address','NO_ADDRESS_GIVEN')
192 if not n.hasAttribute('address'): n.setAttribute('address','NO_ADDRESS_GIVEN') 168 address = n.get('address')
193 address = n.getAttribute('address') 169 if not n.get('port'): n.set('port','6774')
194 if not n.hasAttribute('port'): n.setAttribute('port','6774') 170 port = n.get('port')
195 port = n.getAttribute('port') 171 n.set('meta',meta)
196 n.setAttribute('meta',meta)
197 end_point = str(address) + ":" + str(port) 172 end_point = str(address) + ":" + str(port)
198 if return_hash.has_key(end_point): 173 if return_hash.has_key(end_point):
199 if META_DEBUG: print "Replacing duplicate server entry at " + end_point 174 if META_DEBUG: print "Replacing duplicate server entry at " + end_point
200 return_hash[end_point] = n 175 return_hash[end_point] = n
201 176
202 # At this point, we have an amalgamated list of servers 177 # At this point, we have an amalgamated list of servers
203 # Now, we have to construct a new DOM to pass back. 178 # Now, we have to construct a new DOM to pass back.
204 179
205 # Create a servers element 180 # Create a servers element
206 return_dom = orpg.minidom.Element("servers") 181 server_list = Element('servers')
207 182
208 # get the nodes stored in return_hash 183 # get the nodes stored in return_hash
209 return_list = return_hash.values() 184 sort_list = return_hash.values()
210 185
211 # sort them by their name attribute. Uses byNameAttribute() 186 # sort them by their name attribute. Uses byNameAttribute()
212 # defined above as a comparison function 187 # defined above as a comparison function
213 188 if sort_by == "start": sort_list.sort(byStartAttribute)
214 if sort_by == "start": return_list.sort(byStartAttribute) 189 elif sort_by == "name": sort_list.sort(byNameAttribute)
215 elif sort_by == "name": return_list.sort(byNameAttribute)
216 190
217 # Add each node to the DOM 191 # Add each node to the DOM
218 for n in return_list: return_dom.appendChild(n) 192 for n in sort_list: server_list.append(n)
219 return return_dom 193 return server_list
220 194
221 ## List Format: 195 ## List Format:
222 ## <servers> 196 ## <servers>
223 ## <server address=? id=? name=? failed_count=? > 197 ## <server address=? id=? name=? failed_count=? >
224 ## </servers> 198 ## </servers>
225 199
226 def updateMetaCache(xml_dom): 200 def updateMetaCache(xml_dom):
227 try: 201 try:
228 if META_DEBUG: print "Updating Meta Server Cache" 202 if META_DEBUG: print "Updating Meta Server Cache"
229 metaservers = xml_dom.getElementsByTagName( 'metaservers' ) # pull out the metaservers bit 203 metaservers = xml_dom.findall('metaservers') # pull out the metaservers bit
230 if len(metaservers) == 0: 204 if len(metaservers) == 0:
231 cmetalist = getRawMetaList() 205 cmetalist = getRawMetaList()
232 xml_dom = get_server_dom(cmetalist[0]) 206 xml_dom = get_server_dom(cmetalist[0])
233 metaservers = xml_dom.getElementsByTagName( 'metaservers' ) 207 metaservers = xml_dom.findall('metaservers')
234 authoritative = metaservers[0].getAttribute('auth') 208 authoritative = metaservers[0].get('auth')
235 if META_DEBUG: print " Authoritive Meta: "+str(authoritative) 209 if META_DEBUG: print " Authoritive Meta: "+str(authoritative)
236 metas = metaservers[0].getElementsByTagName("meta") # get the list of metas 210 metas = metaservers[0].findall("meta") # get the list of metas
237 if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)" 211 if META_DEBUG: print " Meta List ("+str(len(metas))+" servers)"
238 try: 212 try:
239 metacache_lock.acquire() 213 metacache_lock.acquire()
240 ini = open(dir_struct["user"]+"metaservers.cache","w") 214 ini = open(dir_struct["user"]+"metaservers.cache","w")
241 for meta in metas: 215 for meta in metas:
242 if META_DEBUG: print " Writing: "+str(meta.getAttribute('path')) 216 if META_DEBUG: print " Writing: "+str(meta.get('path'))
243 ini.write(str(meta.getAttribute('path')) + " " + str(meta.getAttribute('versions')) + "\n") 217 ini.write(str(meta.get('path')) + " " + str(meta.get('versions')) + "\n")
244 ini.close() 218 ini.close()
245 finally: 219 finally:
246 metacache_lock.release() 220 metacache_lock.release()
247 except Exception, e: 221 except Exception, e:
248 if META_DEBUG: traceback.print_exc() 222 if META_DEBUG: traceback.print_exc()
249 print "Meta Server Lib: UpdateMetaCache(): " + str(e) 223 print "Meta Server Lib: UpdateMetaCache(): " + str(e)
250 224
251 def getRawMetaList(): 225 def getRawMetaList(path=None):
226 ### Alpha ###
227 """This code will allow for a list of metas to be created. Future developement will more integrate the list of metas"""
228 if path != None:
229 metas = []
230 data = urlencode({"version":PROTOCOL_VERSION,"ports":"%"})
231 xml_dom = get_server_dom(data, path)
232 node_list = fromstring(xml_dom).findall('meta_server')
233 if len(node_list):
234 for n in node_list:
235 metas.append(n.get('path'))
236 return metas
252 try: 237 try:
253 try: 238 try:
254 metacache_lock.acquire() 239 metacache_lock.acquire()
255 # Read in the metas 240 # Read in the metas
256 validate.config_file("metaservers.cache","metaservers.cache") 241 validate.config_file("metaservers.cache","metaservers.cache")
266 return [] 251 return []
267 252
268 def getMetaServers(versions = None, pick_random=0): 253 def getMetaServers(versions = None, pick_random=0):
269 """ 254 """
270 get meta server URLs as a list 255 get meta server URLs as a list
271
272 versions is a list of acceptable version numbers. 256 versions is a list of acceptable version numbers.
273 A False truth value will use getMetaServerBaseURL() 257 A False truth value will use getMetaServerBaseURL()
274
275 set a default if we have weird reading problems 258 set a default if we have weird reading problems
276 default_url = "http://www.openrpg.com/openrpg_servers.php" 259 default_url = "http://www.openrpg.com/openrpg_servers.php"
277 """ 260 """
278 261
262 ### Pre Alpha Design ###
263 """ Here is how to handle Multiple Meta servers, and probably the best way to do it. Create an XML file that contains nodes with the various servers. Users will grab that meta data and have the option to connect to multiple meta servers which will allow them to find all the rooms. A check box should be used so if one server faile the users can continue without much lag. When creating a server hosts will need to select a meta to go too. This should be in the final of Ornery Orc."""
279 meta_names = [] 264 meta_names = []
280
281 if(versions): # If versions are supplied, then look in metaservers.conf 265 if(versions): # If versions are supplied, then look in metaservers.conf
282 try: 266 try:
283 """ 267 """
284 read in the metas from file 268 read in the metas from file
285 format of file is one meta entry per line 269 format of file is one meta entry per line
286 each entry will be the meta url, followed by one or more version numbers that it 270 each entry will be the meta url, followed by one or more version numbers that it
287 handle. Generally, this will be either a 1 for the original Meta format, or 271 handle. Generally, this will be either a 1 for the original Meta format, or
288 2 for the new one. 272 2 for the new one.
289 """ 273 """
290
291 # Read in the metas 274 # Read in the metas
275 #Adding a path object will attempt to look for a meta_network.
292 metas = getRawMetaList() 276 metas = getRawMetaList()
293 #print str(metas)
294 277
295 # go through each one to check if it should be returned, based on the 278 # go through each one to check if it should be returned, based on the
296 # version numbers allowed. 279 # version numbers allowed.
297 for meta in metas: 280 for meta in metas:
298
299 # split the line on whitespace 281 # split the line on whitespace
300 # obviously, your meta servers urls shouldn't contain whitespace. duh. 282 # obviously, your meta servers urls shouldn't contain whitespace. duh.
301 words = meta.split() 283 words = meta.split()
302 success = 0 # init success flag for version check 284 success = 0 # init success flag for version check
303 for version in versions: # run through each allowed version from caller 285 for version in versions: # run through each allowed version from caller
314 # print "Warning!!\nNo valid metaservers cached." 296 # print "Warning!!\nNo valid metaservers cached."
315 # print "Using meta from MetaServerBaseURL: " + default_meta + "\n" 297 # print "Using meta from MetaServerBaseURL: " + default_meta + "\n"
316 # if we have more than one and want a random one 298 # if we have more than one and want a random one
317 elif pick_random: 299 elif pick_random:
318 if META_DEBUG: print "choosing random meta from: " + str(meta_names) 300 if META_DEBUG: print "choosing random meta from: " + str(meta_names)
319 i = int(random.uniform(0,len(meta_names))) 301 i = int(uniform(0,len(meta_names)))
320 #meta = meta_names[i] 302 #meta = meta_names[i]
321 meta_names = [meta_names[i]] 303 meta_names = [meta_names[i]]
322 if META_DEBUG: print "using: " + str(meta_names) 304 if META_DEBUG: print "using: " + str(meta_names)
323 else: 305 else:
324 if META_DEBUG: print "using all metas: " + str(meta_names) 306 if META_DEBUG: print "using all metas: " + str(meta_names)
345 tree = xml.parseXml(txt)._get_documentElement() 327 tree = xml.parseXml(txt)._get_documentElement()
346 ini.close() 328 ini.close()
347 node_list = tree.getElementsByTagName("MetaServerBaseURL") 329 node_list = tree.getElementsByTagName("MetaServerBaseURL")
348 if node_list: 330 if node_list:
349 url = node_list[0].getAttribute("value") 331 url = node_list[0].getAttribute("value")
350
351 # allow tree to be collected 332 # allow tree to be collected
352 try: tree.unlink() 333 try: tree.unlink()
353 except: pass 334 except: pass
354 335
355 except Exception,e: 336 except Exception,e:
389 Because of this fact, there are some methods from wxThread 370 Because of this fact, there are some methods from wxThread
390 that I implemented to minimize changes to the code I had 371 that I implemented to minimize changes to the code I had
391 just written, i.e. TestDeleteStatus() and Delete() 372 just written, i.e. TestDeleteStatus() and Delete()
392 """ 373 """
393 374
394 def __init__(self,name=None,realHostName=None,num_users = "Hmmm",MetaPath=None,port=6774,register_callback=None): 375 def __init__(self, name=None, realHostName=None, num_users="0",
395 376 MetaPath=None, port=6774, register_callback=None):
396 Thread.__init__(self,name="registerThread") 377 Thread.__init__(self, name="registerThread")
397 self.rlock = RLock() # Re-entrant lock used to make this class thread safe 378 self.rlock = RLock() # Re-entrant lock used to make this class thread safe
398 self.die_event = Event() # The main loop in run() will wait with timeout on this 379 self.die_event = Event() # The main loop in run() will wait with timeout on this
399 if name: 380 self.name = name or 'Unnamed Server' # Name that the server want's displayed on the Meta
400 self.name = name # Name that the server want's displayed on the Meta 381 # But use Unnamed Server if for some crazy reason
401 else: 382 # no name is passed to the constructor
402 self.name = "Unnamed server" # But use this if for some crazy reason no name is 383 self.num_users = num_users # the number of users currently on this server
403 # passed to the constructor
404 self.num_users = num_users # the number of users currently on this server
405 self.realHostName = realHostName # Name to advertise for connection 384 self.realHostName = realHostName # Name to advertise for connection
406 self.id = "0" # id returned from Meta. Defaults to "0", which 385 self.id = "0" # id returned from Meta. Defaults to "0", which
407 # indicates a new registration. 386 # indicates a new registration.
408 self.cookie = "0" # cookie returned from Meta. Defaults to "0",which 387 self.cookie = "0" # cookie returned from Meta. Defaults to "0", which
409 # indicates a new registration. 388 # indicates a new registration.
410 self.interval = 0 # interval returned from Meta. Is how often to 389 self.interval = 0 # interval returned from Meta. Is how often to
411 # re-register, in minutes. 390 # re-register, in minutes.
412 self.destroy = 0 # Used to flag that this thread should die 391 self.destroy = 0 # Used to flag that this thread should die
413 self.port = str(port) 392 self.port = str(port)
420 399
421 Also, if MetaPath is specified, then use that. Makes 400 Also, if MetaPath is specified, then use that. Makes
422 it easier to have multiple registerThreads going to keep the server registered 401 it easier to have multiple registerThreads going to keep the server registered
423 on multiple (compatible) Metas. 402 on multiple (compatible) Metas.
424 """ 403 """
425 404 if MetaPath == None: self.path = getMetaServerBaseURL() # Do this if no Meta specified
426 if MetaPath == None: 405 else: self.path = MetaPath
427 self.path = getMetaServerBaseURL() # Do this if no Meta specified
428 else:
429 self.path = MetaPath
430 406
431 def getIdAndCookie(self): 407 def getIdAndCookie(self):
432 return self.id, self.cookie 408 return self.id, self.cookie
433 409
434 def TestDeleteStatus(self): 410 def TestDeleteStatus(self):
435 try: 411 try:
436 self.rlock.acquire() 412 self.rlock.acquire()
437 return self.die_event.isSet() 413 return self.die_event.isSet()
438 finally: 414 finally: self.rlock.release()
439 self.rlock.release()
440 415
441 def Delete(self): 416 def Delete(self):
442 try: 417 try:
443 self.rlock.acquire() 418 self.rlock.acquire()
444 self.die_event.set() 419 self.die_event.set()
445 finally: 420 finally: self.rlock.release()
446 self.rlock.release()
447 421
448 def run(self): 422 def run(self):
449 """ 423 """
450 This method gets called by Thread implementation 424 This method gets called by Thread implementation
451 when self.start() is called to begin the thread's 425 when self.start() is called to begin the thread's
453 427
454 We will basically enter a loop that continually 428 We will basically enter a loop that continually
455 re-registers this server and sleeps Interval 429 re-registers this server and sleeps Interval
456 minutes until the thread is ordered to die in place 430 minutes until the thread is ordered to die in place
457 """ 431 """
458 while(not self.TestDeleteStatus()): # Loop while until told to die 432 while(not self.TestDeleteStatus()): # Loop while until told to die
459 # Otherwise, call thread safe register(). 433 # Otherwise, call thread safe register().
460 self.register(self.name, self.realHostName, self.num_users) 434 self.register(self.name, self.realHostName, self.num_users)
461 if META_DEBUG: print "Sent Registration Data" 435 if META_DEBUG: print "Sent Registration Data"
462 # register() will end up setting the state variables 436 # register() will end up setting the state variables
463 # for us, including self.interval. 437 # for us, including self.interval.
464 try: 438 try:
465 self.rlock.acquire() # Serialize access to this state information 439 self.rlock.acquire() # Serialize access to this state information
466 440
467 if self.interval >= 3: # If the number of minutes is one or greater 441 if self.interval >= 3: # If the number of minutes is one or greater
468 self.interval -= 1 # wake up with 30 seconds left to re-register 442 self.interval -= 1 # wake up with 30 seconds left to re-register
469 else: 443 else:
470 self.interval = .5 # Otherwise, we probably experienced some kind 444 self.interval = .5 # Otherwise, we probably experienced some kind
471 # of error from the Meta in register(). Sleep 445 # of error from the Meta in register(). Sleep
472 # for 6 seconds and start from scratch. 446 # for 6 seconds and start from scratch.
473 447
474 finally: # no matter what, release the lock 448 finally: self.rlock.release() # no matter what, release the lock
475 self.rlock.release()
476 # Wait interval minutes for a command to die 449 # Wait interval minutes for a command to die
477 die_signal = self.die_event.wait(self.interval*60) 450 die_signal = self.die_event.wait(self.interval*60)
478 451
479 # If we get past the while loop, it's because we've been asked to die, 452 # If we get past the while loop, it's because we've been asked to die,
480 # so just let run() end. Once this occurs, the thread is dead and 453 # so just let run() end. Once this occurs, the thread is dead and
499 try: 472 try:
500 self.rlock.acquire() 473 self.rlock.acquire()
501 if not self.isAlive(): # check to see if this thread is dead 474 if not self.isAlive(): # check to see if this thread is dead
502 return 1 # If so, return an error result 475 return 1 # If so, return an error result
503 # Do the actual unregistering here 476 # Do the actual unregistering here
504 data = urllib.urlencode( {"server_data[id]":self.id, 477 data = urlencode( {"server_data[id]":self.id,
505 "server_data[cookie]":self.cookie, 478 "server_data[cookie]":self.cookie,
506 "server_data[version]":PROTOCOL_VERSION, 479 "server_data[version]":PROTOCOL_VERSION,
507 "act":"unregister"} ) 480 "act":"unregister"} )
508 try: 481 try: # this POSTS the request and returns the result
509 xml_dom = get_server_dom(data=data, path=self.path) # this POSTS the request and returns the result 482 xml_dom = get_server_dom(data=data, path=self.path)
510 if xml_dom.hasAttribute("errmsg"): 483 if xml_dom.get("errmsg"):
511 print "Error durring unregistration: " + xml_dom.getAttribute("errmsg") 484 print "Error durring unregistration: " + xml_dom.get("errmsg")
512 except: 485 except:
513 if META_DEBUG: print "Problem talking to Meta. Will go ahead and die, letting Meta remove us." 486 if META_DEBUG: print "Problem talking to Meta. Will go ahead and die, letting Meta remove us."
514 # If there's an error, echo it to the console 487 # If there's an error, echo it to the console
515 488
516 # No special handling is required. If the de-registration worked we're done. If 489 # No special handling is required. If the de-registration worked we're done. If
522 except: pass 495 except: pass
523 return 0 496 return 0
524 finally: self.rlock.release() 497 finally: self.rlock.release()
525 498
526 def register(self, name=None, realHostName=None, num_users=None): 499 def register(self, name=None, realHostName=None, num_users=None):
500 #debug((name, realHostName, num_users))
527 """ 501 """
528 Designed to handle the registration, both new and 502 Designed to handle the registration, both new and
529 repeated. 503 repeated.
530 504
531 It is intended to be called once every interval 505 It is intended to be called once every interval
543 if name: self.name = name 517 if name: self.name = name
544 if num_users != None: self.num_users = num_users 518 if num_users != None: self.num_users = num_users
545 if realHostName: self.realHostName = realHostName 519 if realHostName: self.realHostName = realHostName
546 # build POST data 520 # build POST data
547 if self.realHostName: 521 if self.realHostName:
548 data = urllib.urlencode( {"server_data[id]":self.id, 522 data = urlencode( {"server_data[id]":self.id,
549 "server_data[cookie]":self.cookie, 523 "server_data[cookie]":self.cookie,
550 "server_data[name]":self.name, 524 "server_data[name]":self.name,
551 "server_data[port]":self.port, 525 "server_data[port]":self.port,
552 "server_data[version]":PROTOCOL_VERSION, 526 "server_data[version]":PROTOCOL_VERSION,
553 "server_data[num_users]":self.num_users, 527 "server_data[num_users]":self.num_users,
554 "act":"register", 528 "act":"register",
555 "server_data[address]": self.realHostName } ) 529 "server_data[address]": self.realHostName } )
556 else: 530 else:
557 if META_DEBUG: print "Letting meta server decide the hostname to list..." 531 if META_DEBUG: print "Letting meta server decide the hostname to list..."
558 data = urllib.urlencode( {"server_data[id]":self.id, 532 data = urlencode( {"server_data[id]":self.id,
559 "server_data[cookie]":self.cookie, 533 "server_data[cookie]":self.cookie,
560 "server_data[name]":self.name, 534 "server_data[name]":self.name,
561 "server_data[port]":self.port, 535 "server_data[port]":self.port,
562 "server_data[version]":PROTOCOL_VERSION, 536 "server_data[version]":PROTOCOL_VERSION,
563 "server_data[num_users]":self.num_users, 537 "server_data[num_users]":self.num_users,
564 "act":"register"} ) 538 "act":"register"} )
565 try: 539 try: # this POSTS the request and returns the result
566 xml_dom = get_server_dom(data=data,path=self.path) # this POSTS the request and returns the result 540 etreeEl = get_server_dom(data=data, path=self.path)
541 #debug(etreeEl)
567 except: 542 except:
568 if META_DEBUG: print "Problem talking to server. Setting interval for retry ..." 543 if META_DEBUG: print "Problem talking to server. Setting interval for retry ..."
569 if META_DEBUG: print data 544 if META_DEBUG: print data
570 if META_DEBUG: print 545 if META_DEBUG: print
571 self.interval = 0 546 self.interval = 0
582 the main thread calls register(). 557 the main thread calls register().
583 """ 558 """
584 return 0 # indicates that it was okay to call, not that no errors occurred 559 return 0 # indicates that it was okay to call, not that no errors occurred
585 560
586 # If there is a DOM returned .... 561 # If there is a DOM returned ....
587 if xml_dom: 562 if etreeEl:
563 #debug(etreeEl)
588 # If there's an error, echo it to the console 564 # If there's an error, echo it to the console
589 if xml_dom.hasAttribute("errmsg"): 565 if etreeEl.get("errmsg"):
590 print "Error durring registration: " + xml_dom.getAttribute("errmsg") 566 print "Error durring registration: " + etreeEl.get("errmsg")
591 if META_DEBUG: print data 567 if META_DEBUG: print data
592 if META_DEBUG: print 568 if META_DEBUG: print
593 """ 569 """
594 No special handling is required. If the registration worked, id, cookie, and interval 570 No special handling is required. If the registration worked, id, cookie, and interval
595 can be stored and used for the next time. 571 can be stored and used for the next time.
607 the interval will be less than 1, and the main thread's while loop will reset it 583 the interval will be less than 1, and the main thread's while loop will reset it
608 to 6 seconds for the next retry. 584 to 6 seconds for the next retry.
609 Is it wrong to have a method where there's more comments than code? :) 585 Is it wrong to have a method where there's more comments than code? :)
610 """ 586 """
611 try: 587 try:
612 self.interval = int(xml_dom.getAttribute("interval")) 588 self.interval = int(etreeEl.get("interval"))
613 self.id = xml_dom.getAttribute("id") 589 self.id = etreeEl.get("id")
614 self.cookie = xml_dom.getAttribute("cookie") 590 self.cookie = etreeEl.get("cookie")
615 if not xml_dom.hasAttribute("errmsg"): 591 if not etreeEl.get("errmsg"): updateMetaCache(xml_dom)
616 updateMetaCache(xml_dom)
617 except: 592 except:
618 if META_DEBUG: print 593 if META_DEBUG: print
619 if META_DEBUG: print "OOPS! Is the Meta okay? It should be returning an id, cookie, and interval." 594 if META_DEBUG: print "OOPS! Is the Meta okay? It should be returning an id, cookie, and interval."
620 if META_DEBUG: print "Check to see what it really returned.\n" 595 if META_DEBUG: print "Check to see what it really returned.\n"
621 # Let xml_dom get garbage collected 596 # Let xml_dom get garbage collected
622 try: 597 try: xml_dom.unlink()
623 xml_dom.unlink() 598 except: pass
624 except:
625 pass
626 else: # else if no DOM is returned from get_server_dom() 599 else: # else if no DOM is returned from get_server_dom()
627 print "Error - no DOM constructed from Meta message!" 600 print "Error - no DOM constructed from Meta message!"
628 return 0 # Let caller know it was okay to call us 601 return 0 # Let caller know it was okay to call us
629 finally: 602 finally: self.rlock.release()
630 self.rlock.release()
631 # End of class registerThread 603 # End of class registerThread
632 ################################################################################ 604 ################################################################################