Example #1
0
    def __init__(self):
        self.__pool_by_id = {
        }  #this is reference pool. All users should be here
        self.__pool_len = 0
        self.__black_list = []  #user_ids that we should not load
        self.loading_users = LoadingUser()
        self.rel_candidates = ReleaseCandidates()
        self.lock = threading.RLock()  #dictionary lock

        stat_main.getStatKeeper().registerStat("user_pool_hits", "int")
        stat_main.getStatKeeper().registerStat("user_pool_misses", "int")
Example #2
0
    def __init__(self):
	self.__pool_by_id={} #this is reference pool. All users should be here
	self.__pool_len=0
	self.__black_list=[] #user_ids that we should not load
	self.loading_users=LoadingUser()
	self.rel_candidate=ReleaseCandidates()
	self.lock=threading.RLock()
	self.misses=0
	self.hits=0
Example #3
0
class UserPool:
    """
	XXX MISSING: Normal And VoIP mapping to user_ids in memory!
    """
    def __init__(self):
	self.__pool_by_id={} #this is reference pool. All users should be here
	self.__pool_len=0
	self.__black_list=[] #user_ids that we should not load
	self.loading_users=LoadingUser()
	self.rel_candidate=ReleaseCandidates()
	self.lock=threading.RLock()
	self.misses=0
	self.hits=0

    def __fixUserID(self,user_id):
	return long(user_id)
	
    def __isInPoolByID(self,user_id):
	"""
	    check if user with id "user_id" is in pool return LoadedUser instance if 
	    it's in pool or None if it isn't
	"""
	self.lock.acquire()
	try:
	    if self.__pool_by_id.has_key(user_id):
		self.hits+=1
		return self.__pool_by_id[user_id]
	    self.misses+=1
	    return None
	finally:
	    self.lock.release()

    def __saveInPool(self,loaded_user):
	"""
	    Save LoadedUser instance into pool
	"""
	self.__checkPoolSize()
	self.rel_candidate.addUser(loaded_user)
	self.__addToPool(loaded_user)

    def __addToPool(self,loaded_user):
    	self.lock.acquire()
        try:
	    self.__pool_by_id[loaded_user.getUserID()]=loaded_user
	finally:
	    self.lock.release()

    def __checkPoolSize(self):
	"""
	    check pool size and release a user if we are more then defs.MAX_USER_POOL_SIZE
	"""
    	self.lock.acquire()
        try:
	    self.__pool_len+=1
	finally:
	    self.lock.release()
	if self.__pool_len>defs.MAX_USER_POOL_SIZE: 
	    self.__releaseOneUser()

    def __releaseOneUser(self):
	"""
	    release a user from pool, if possible
	"""
	loaded_user_obj=self.rel_candidate.getCandidate()
        if loaded_user_obj!=None:
	    self.lock.acquire()
	    try:
	        if loaded_user_obj.isOnline() or self.loading_users.isLoading(loaded_user_obj.getUserID()):
		    self.__releaseOneUser()
		    self.rel_candidates.addUser(loaded_user)
		else:
		    try:
		        self.__delFromPool(loaded_user_obj.getUserID())
		    except KeyError: #user has been deleted previously by userChanged method
		        self.__releaseOneUser()
	    finally:
	        self.lock.release()

    def __delFromPool(self,user_id):
	"""
	    delete user with id "user_id" from pool
	"""
	self.lock.acquire()
	try:
	    self.__pool_len-=1
	    del(self.__pool_by_id[user_id])
	finally:
	    self.lock.release()


    def __loadUserByID(self,user_id):
	"""
	    load user into memory using user id and return a LoadedUser instance
	    also put user in pool
	"""	
	loaded_user=user_main.getUserLoader().getLoadedUserByUserID(user_id)
	self.__saveInPool(loaded_user)
	return loaded_user


################################
    def getUserByID(self,user_id,online_flag=False):
	"""
	    return a LoadedUser instance of user with id "user_id"
	"""
	user_id=self.__fixUserID(user_id)
	self.loading_users.loadingStart(user_id)
	try:
	    loaded_user=self.__isInPoolByID(user_id)
	    if loaded_user==None:
		loaded_user=self.__loadUserByID(user_id)
	    
	    if online_flag: #it should be done here, because we don't want to release this user while he's trying to log in
	        self.__checkBlackList(user_id)
		loaded_user.setOnlineFlag(True)
	finally:
	    self.loading_users.loadingEnd(user_id)
	return loaded_user
	
#################################
    def getUserByNormalUsername(self,normal_username,online_flag=False):
	"""
	    XXX: current implemention can be optimized by not querying normal_users table twice
	    return a LoadedUser instance of user with normal username "normal_username"
	"""
	user_id=user_main.getUserLoader().normalUsername2UserID(normal_username)
	return self.getUserByID(user_id,online_flag)

#################################
    def getUserByVoIPUsername(self,voip_username,online_flag=False):
	"""
	    XXX: current implemention can be optimized by not querying normal_users table twice
	    return a LoadedUser instance of user with voip username "voip_username"
	"""
	user_id=user_main.getUserLoader().voipUsername2UserID(voip_username)
	return self.getUserByID(user_id,online_flag)

#################################
    def userChanged(self,user_id):
	"""
	    called when attributes or information of user with id "user_id" changed
	"""
	user_id=self.__fixUserID(user_id)
	self.loading_users.loadingStart(user_id)
	try:
	    loaded_user=self.__isInPoolByID(user_id)
	    if loaded_user!=None:
	        if loaded_user.isOnline():
		    self.__reloadOnlineUser(loaded_user)
	        else:
	    	    self.__delFromPool(user_id)
	finally:
	    self.loading_users.loadingEnd(user_id)

    def __reloadOnlineUser(self,loaded_user):
	new_loaded_user=user_main.getUserLoader().getLoadedUserByUserID(loaded_user.getUserID())
	loaded_user._reload(new_loaded_user)
	user_main.getOnline().reloadUser(loaded_user.getUserID())
	
##################################
    def addToBlackList(self,user_id):
	"""
	    add user_id to blacklist
	    blacklist is used to not allow users to get online, not allowing them to set
	    online flag
	"""
	user_id=self.__fixUserID(user_id)
	self.__black_list.append(user_ids)

    def removeFromBlackList(self,user_id):
	"""
	    remove user_id from blacklist
	"""
	user_id=self.__fixUserID(user_id)
	self.__black_list.remove(user_id)

    def __checkBlackList(self,user_id):
	if user_id in self.__black_list:
	    raise GeneralException(errorText("USER","USER_IN_BLACKLIST")%user_id)
Example #4
0
class UserPool:
    """
        XXX MISSING: Normal And VoIP mapping to user_ids in memory!
    """
    DEBUG = False

    def __init__(self):
        self.__pool_by_id = {
        }  #this is reference pool. All users should be here
        self.__pool_len = 0
        self.__black_list = []  #user_ids that we should not load
        self.loading_users = LoadingUser()
        self.rel_candidates = ReleaseCandidates()
        self.lock = threading.RLock()  #dictionary lock

        stat_main.getStatKeeper().registerStat("user_pool_hits", "int")
        stat_main.getStatKeeper().registerStat("user_pool_misses", "int")

    def __incHits(self):
        stat_main.getStatKeeper().inc("user_pool_hits")

    def __incMisses(self):
        stat_main.getStatKeeper().inc("user_pool_misses")

    def __fixUserID(self, user_id):
        return long(user_id)

    def __isInPoolByID(self, user_id):
        """
            check if user with id "user_id" is in pool return LoadedUser instance if 
            it's in pool or None if it isn't
        """
        self.lock.acquire()
        try:
            if self.__pool_by_id.has_key(user_id):
                self.__incHits()
                return self.__pool_by_id[user_id]

            self.__incMisses()
            return None
        finally:
            self.lock.release()

    def __saveInPool(self, loaded_user):
        """
            Save LoadedUser instance into pool
        """
        self.__checkPoolSize()
        self.rel_candidates.addUser(loaded_user)
        self.__addToPool(loaded_user)

    def __addToPool(self, loaded_user):
        self.lock.acquire()
        try:
            self.__pool_by_id[loaded_user.getUserID()] = loaded_user
        finally:
            self.lock.release()

    def __checkPoolSize(self):
        """
            check pool size and release a user if we are more then defs.MAX_USER_POOL_SIZE
        """
        self.lock.acquire()
        try:
            self.__pool_len += 1
        finally:
            self.lock.release()

        if self.__pool_len > defs.MAX_USER_POOL_SIZE:
            self.__releaseOneUser()

    def __releaseOneUser(self):
        """
            release a user from pool, if possible
        """
        loaded_user = self.rel_candidates.getCandidate()
        while loaded_user:
            self.loading_users.loadingStart(loaded_user.getUserID())
            try:
                if not loaded_user.isOnline():
                    try:
                        self.__delFromPool(loaded_user.getUserID())
                        break
                    except KeyError:  #user has been deleted previously by userChanged method
                        pass

            finally:
                self.loading_users.loadingEnd(loaded_user.getUserID())

            loaded_user = self.rel_candidates.getCandidate()

    def __delFromPool(self, user_id):
        """
            delete user with id "user_id" from pool
        """
        self.lock.acquire()
        try:
            self.__pool_len -= 1
            del (self.__pool_by_id[user_id])
        finally:
            self.lock.release()

    def __loadUserByID(self, user_id):
        """
            load user into memory using user id and return a LoadedUser instance
            also put user in pool
        """
        loaded_user = user_main.getUserLoader().getLoadedUserByUserIDs(
            (user_id, ))[0]
        self.__saveInPool(loaded_user)
        return loaded_user

    def __loadUsersByID(self, user_ids):
        """
            load user with ids in memory and return a list of LoadedUser instances
        """
        loaded_users = user_main.getUserLoader().getLoadedUserByUserIDs(
            user_ids)
        map(self.__saveInPool, loaded_users)
        return loaded_users

################################

    def getUserByID(self, user_id, online_flag=False):
        """
            return a LoadedUser instance of user with id "user_id"
        """
        user_id = self.__fixUserID(user_id)
        self.loading_users.loadingStart(user_id)
        try:
            loaded_user = self.__isInPoolByID(user_id)
            if loaded_user == None:
                loaded_user = self.__loadUserByID(user_id)

            if online_flag:  #it should be done here, because we don't want to release this user while he's trying to log in
                self.__checkBlackList(user_id)
                loaded_user.setOnlineFlag(True)
        finally:
            self.loading_users.loadingEnd(user_id)
        return loaded_user

    def getUsersByID(self, user_ids, keep_order=False):
        """
            return a list of LoadedUser instance of users with ids "user_ids"
            keep_order(boolean): if set to true, try keeping order of loaded_users as same order as user_ids
                                 this job is fairly expensive
        """
        loaded_users = []

        all_user_ids = map(self.__fixUserID, user_ids)
        all_user_ids.sort()  #prevent dead lock by loading users in order

        i = 0
        to_load_ids = []
        while i < len(all_user_ids):
            user_id = all_user_ids[i]
            self.loading_users.loadingStart(user_id)
            try:
                loaded_user = self.__isInPoolByID(user_id)
                if loaded_user == None:  # is user cached?
                    to_load_ids.append(user_id)

                    if len(to_load_ids) == defs.POSTGRES_MAGIC_NUMBER:
                        if self.DEBUG:
                            toLog(
                                "UserPool(getUsersById): bulk loading %s number of users"
                                % len(to_load_ids), LOG_DEBUG)

                        loaded_users += self.__loadUsersByID(to_load_ids)
                        map(self.loading_users.loadingEnd, to_load_ids)
                        to_load_ids = []

                else:
                    loaded_users.append(loaded_user)
                    self.loading_users.loadingEnd(user_id)

            except:
                if user_id not in to_load_ids:
                    to_load_ids.append(user_id)

                map(self.loading_users.loadingEnd, to_load_ids)
                raise

            i += 1

        #load rest of users
        try:
            if self.DEBUG:
                toLog(
                    "UserPool(getUsersById): rest loading %s number of users" %
                    len(to_load_ids), LOG_DEBUG)

            loaded_users += self.__loadUsersByID(to_load_ids)
        finally:
            map(self.loading_users.loadingEnd, to_load_ids)

        if keep_order:
            return self.__fixLoadedUsersOrder(map(self.__fixUserID, user_ids),
                                              loaded_users)
        else:
            return loaded_users

    def __fixLoadedUsersOrder(self, user_ids, loaded_users):
        """
            fix order of loaded_users as same order as user_ids
        """
        def cmp_func(
                loaded_user1,
                loaded_user2):  #compare function based on index of user_ids
            if user_ids.index(loaded_user1.getUserID()) > user_ids.index(
                    loaded_user2.getUserID()):
                return 1
            else:
                return -1

        loaded_users.sort(cmp_func)
        return loaded_users

#################################

    def getUserByNormalUsername(self, normal_username, online_flag=False):
        """
            XXX: current implemention can be optimized by not querying normal_users table twice
            return a LoadedUser instance of user with normal username "normal_username"
        """
        user_id = user_main.getUserLoader().normalUsername2UserID(
            normal_username)
        return self.getUserByID(user_id, online_flag)

#################################

    def getUserByVoIPUsername(self, voip_username, online_flag=False):
        """
            XXX: current implemention can be optimized by not querying voip_users table twice
            return a LoadedUser instance of user with voip username "voip_username"
        """
        user_id = user_main.getUserLoader().voipUsername2UserID(voip_username)
        return self.getUserByID(user_id, online_flag)

#################################

    def getUserByCallerID(self, caller_id, online_flag=False):
        """
            return a LoadedUser instance of user with caller id "caller_id"
        """
        user_id = user_main.getUserLoader().callerID2UserID(caller_id)
        return self.getUserByID(user_id, online_flag)

#################################

    def userChanged(self, user_id):
        """
            called when attributes or information of user with id "user_id" changed
        """
        user_id = self.__fixUserID(user_id)
        self.loading_users.loadingStart(user_id)
        try:
            loaded_user = self.__isInPoolByID(user_id)
            if loaded_user != None:
                if loaded_user.isOnline():
                    self.__reloadOnlineUser(loaded_user)
                else:
                    self.__delFromPool(user_id)
        finally:
            self.loading_users.loadingEnd(user_id)

    def __reloadOnlineUser(self, loaded_user):
        new_loaded_user = user_main.getUserLoader().getLoadedUserByUserIDs(
            (loaded_user.getUserID(), ))[0]
        loaded_user._reload(new_loaded_user)
        user_main.getOnline().reloadUser(loaded_user.getUserID())

##################################

    def addToBlackList(self, user_id):
        """
            add user_id to blacklist
            blacklist is used to not allow users to get online, 
            not allowing them to set online flag
        """
        user_id = self.__fixUserID(user_id)
        self.__black_list.append(user_id)

    def removeFromBlackList(self, user_id):
        """
            remove user_id from blacklist
        """
        user_id = self.__fixUserID(user_id)
        self.__black_list.remove(user_id)

    def __checkBlackList(self, user_id):
        if user_id in self.__black_list:
            raise GeneralException(
                errorText("USER", "USER_IN_BLACKLIST") % user_id)
######################################

    def reloadUsersWithFilter(self, filter_func):
        """
            run reload users if filter_func return true
            filter_func should accept an loaded_user instance and return a bool
        """
        for user_id in self.__pool_by_id.keys():
            self.loading_users.loadingStart(user_id)
            try:
                try:
                    loaded_user = self.__pool_by_id[user_id]
                except KeyError:
                    continue

                if apply(filter_func, [loaded_user]):
                    self.userChanged(user_id)
            finally:
                self.loading_users.loadingEnd(user_id)