1 2import sys, time, os, random 3 4import transaction 5from persistent import Persistent 6 7from ZEO import ClientStorage 8import ZODB 9from ZODB.POSException import ConflictError 10from BTrees import OOBTree 11 12class ChatSession(Persistent): 13 14 """Class for a chat session. 15 Messages are stored in a B-tree, indexed by the time the message 16 was created. (Eventually we'd want to throw messages out, 17 18 add_message(message) -- add a message to the channel 19 new_messages() -- return new messages since the last call to 20 this method 21 22 23 """ 24 25 def __init__(self, name): 26 """Initialize new chat session. 27 name -- the channel's name 28 """ 29 30 self.name = name 31 32 # Internal attribute: _messages holds all the chat messages. 33 self._messages = OOBTree.OOBTree() 34 35 36 def new_messages(self): 37 "Return new messages." 38 39 # self._v_last_time is the time of the most recent message 40 # returned to the user of this class. 41 if not hasattr(self, '_v_last_time'): 42 self._v_last_time = 0 43 44 new = [] 45 T = self._v_last_time 46 47 for T2, message in self._messages.items(): 48 if T2 > T: 49 new.append( message ) 50 self._v_last_time = T2 51 52 return new 53 54 def add_message(self, message): 55 """Add a message to the channel. 56 message -- text of the message to be added 57 """ 58 59 while 1: 60 try: 61 now = time.time() 62 self._messages[ now ] = message 63 transaction.commit() 64 except ConflictError: 65 # Conflict occurred; this process should abort, 66 # wait for a little bit, then try again. 67 transaction.abort() 68 time.sleep(.2) 69 else: 70 # No ConflictError exception raised, so break 71 # out of the enclosing while loop. 72 break 73 # end while 74 75def get_chat_session(conn, channelname): 76 """Return the chat session for a given channel, creating the session 77 if required.""" 78 79 # We'll keep a B-tree of sessions, mapping channel names to 80 # session objects. The B-tree is stored at the ZODB's root under 81 # the key 'chat_sessions'. 82 root = conn.root() 83 if not root.has_key('chat_sessions'): 84 print 'Creating chat_sessions B-tree' 85 root['chat_sessions'] = OOBTree.OOBTree() 86 transaction.commit() 87 88 sessions = root['chat_sessions'] 89 90 # Get a session object corresponding to the channel name, creating 91 # it if necessary. 92 if not sessions.has_key( channelname ): 93 print 'Creating new session:', channelname 94 sessions[ channelname ] = ChatSession(channelname) 95 transaction.commit() 96 97 session = sessions[ channelname ] 98 return session 99 100 101if __name__ == '__main__': 102 if len(sys.argv) != 2: 103 print 'Usage: %s <channelname>' % sys.argv[0] 104 sys.exit(0) 105 106 storage = ClientStorage.ClientStorage( ('localhost', 9672) ) 107 db = ZODB.DB( storage ) 108 conn = db.open() 109 110 s = session = get_chat_session(conn, sys.argv[1]) 111 112 messages = ['Hi.', 'Hello', 'Me too', "I'M 3L33T!!!!"] 113 114 while 1: 115 # Send a random message 116 msg = random.choice(messages) 117 session.add_message( '%s: pid %i' % (msg,os.getpid() )) 118 119 # Display new messages 120 for msg in session.new_messages(): 121 print msg 122 123 # Wait for a few seconds 124 pause = random.randint( 1, 4 ) 125 time.sleep( pause ) 126