Server locks rooms when sending states now to prevent exceptions

This commit is contained in:
Uriziel 2013-01-01 13:01:34 +01:00
parent 2941cd1849
commit da94607885

View File

@ -7,6 +7,7 @@ import syncplay
from syncplay.protocols import SyncServerProtocol from syncplay.protocols import SyncServerProtocol
import time import time
from syncplay import constants from syncplay import constants
import threading
class SyncFactory(Factory): class SyncFactory(Factory):
def __init__(self, password = ''): def __init__(self, password = ''):
@ -16,19 +17,21 @@ class SyncFactory(Factory):
self.password = password self.password = password
self._rooms = {} self._rooms = {}
self._roomStates = {} self._roomStates = {}
self._roomUpdate = threading.RLock()
def buildProtocol(self, addr): def buildProtocol(self, addr):
return SyncServerProtocol(self) return SyncServerProtocol(self)
def _createRoomIfDoesntExist(self, roomName): def _createRoomIfDoesntExist(self, roomName):
if (not self._rooms.has_key(roomName)): if (not self._rooms.has_key(roomName)):
self._rooms[roomName] = {} with self._roomUpdate:
self._roomStates[roomName] = { self._rooms[roomName] = {}
"position": 0.0, self._roomStates[roomName] = {
"paused": True, "position": 0.0,
"setBy": None, "paused": True,
"lastUpdate": time.time() "setBy": None,
} "lastUpdate": time.time()
}
def addWatcher(self, watcherProtocol, username, roomName, roomPassword): def addWatcher(self, watcherProtocol, username, roomName, roomPassword):
allnames = [] allnames = []
@ -39,7 +42,8 @@ class SyncFactory(Factory):
username += '_' username += '_'
self._createRoomIfDoesntExist(roomName) self._createRoomIfDoesntExist(roomName)
watcher = Watcher(self, watcherProtocol, username, roomName) watcher = Watcher(self, watcherProtocol, username, roomName)
self._rooms[roomName][watcherProtocol] = watcher with self._roomUpdate:
self._rooms[roomName][watcherProtocol] = watcher
print "{0}({2}) connected to room '{1}'".format(username, roomName, watcherProtocol.transport.getPeer().host) print "{0}({2}) connected to room '{1}'".format(username, roomName, watcherProtocol.transport.getPeer().host)
reactor.callLater(0.1, watcher.scheduleSendState) reactor.callLater(0.1, watcher.scheduleSendState)
l = lambda w: w.sendUserSetting(username, roomName, None, {"joined": True}) l = lambda w: w.sendUserSetting(username, roomName, None, {"joined": True})
@ -50,7 +54,7 @@ class SyncFactory(Factory):
if(room.has_key(watcherProtocol)): if(room.has_key(watcherProtocol)):
return room[watcherProtocol] return room[watcherProtocol]
def getAllWatchers(self, watcherProtocol): def getAllWatchers(self, watcherProtocol): #TODO: Optimize me
watchers = {} watchers = {}
for room in self._rooms.itervalues(): for room in self._rooms.itervalues():
for watcher in room.itervalues(): for watcher in room.itervalues():
@ -59,14 +63,16 @@ class SyncFactory(Factory):
def _removeWatcherFromTheRoom(self, watcherProtocol): def _removeWatcherFromTheRoom(self, watcherProtocol):
for room in self._rooms.itervalues(): for room in self._rooms.itervalues():
watcher = room.pop(watcherProtocol, None) with self._roomUpdate:
watcher = room.pop(watcherProtocol, None)
if(watcher): if(watcher):
return watcher return watcher
def _deleteRoomIfEmpty(self, room): def _deleteRoomIfEmpty(self, room):
if (self._rooms[room] == {}): if (self._rooms[room] == {}):
self._rooms.pop(room) with self._roomUpdate:
self._roomStates.pop(room) self._rooms.pop(room)
self._roomStates.pop(room)
def getRoomPausedAndPosition(self, room): def getRoomPausedAndPosition(self, room):
position = self._roomStates[room]["position"] position = self._roomStates[room]["position"]
@ -160,7 +166,8 @@ class SyncFactory(Factory):
watcher.resetStateTimer() watcher.resetStateTimer()
oldRoom = watcher.room oldRoom = watcher.room
self._createRoomIfDoesntExist(room) self._createRoomIfDoesntExist(room)
self._rooms[room][watcherProtocol] = watcher with self._roomUpdate:
self._rooms[room][watcherProtocol] = watcher
self._roomStates[room]["position"] = watcher.position self._roomStates[room]["position"] = watcher.position
self._roomStates[room]["setBy"] = watcher.name self._roomStates[room]["setBy"] = watcher.name
self._roomStates[room]["lastUpdate"] = time.time() self._roomStates[room]["lastUpdate"] = time.time()
@ -178,13 +185,15 @@ class SyncFactory(Factory):
def broadcastRoom(self, sender, what): def broadcastRoom(self, sender, what):
room = self._rooms[self.watcherGetRoom(sender)] room = self._rooms[self.watcherGetRoom(sender)]
if(room): if(room):
for receiver in room: with self._roomUpdate:
what(receiver) for receiver in room:
what(receiver)
def broadcast(self, sender, what): def broadcast(self, sender, what):
for room in self._rooms.itervalues(): with self._roomUpdate:
for receiver in room: for room in self._rooms.itervalues():
what(receiver) for receiver in room:
what(receiver)
class SyncIsolatedFactory(SyncFactory): class SyncIsolatedFactory(SyncFactory):
def broadcast(self, sender, what): def broadcast(self, sender, what):