Exemplo n.º 1
0
    def create_sharing_record(user_id, collection_name, callback):
        """
        Returns:
            -The sharing secret key for the create sharing record
        """

        #check to see whether that particular collection has been shared before
        exsisting_sharing_secret = yield gen.Task(SharingController.get_sharing_secret_from_subscriber_info,
            user_id, collection_name)
        if exsisting_sharing_secret is not None:
            SharingController.__log.info('SharingController - exsiting sharing record found for user %s and collection %s' % (user_id, collection_name))
            callback(exsisting_sharing_secret)

        #we couldn't find the sharing secret so create a new sharing record
        else:
            sharing_secret = SharingController.__generate_sharing_secret()
            sharing_collection = DatabaseFactory.get_sharing_collection()
            sharing_record = {SharingRecord.SECRET_KEY : sharing_secret,
                              SharingRecord.OWNER_KEY : user_id,
                              SharingRecord.COLLECTION_NAME_KEY : collection_name,
                              SharingRecord.SUBSCIRBERS_KEY : [(user_id,collection_name)]}

            #add sharing record to the cache
            yield gen.Task(sharing_collection.insert, sharing_record)
            yield gen.Task(SharingController.add_subscriber, user_id, collection_name,
                sharing_secret)

            #cache both the subscription info and the sharing record itself
            sharing_record_json = json.dumps(sharing_record)
            yield gen.Task(SharingController.__cache.set_sharing_record,
                sharing_secret, sharing_record_json)
            callback(sharing_secret)
Exemplo n.º 2
0
    def remove_all_subscribers(sharing_secret, callback):
        """
        Removes all the subscribers to a sharing space identified by
        a sharing_secret

        implementation detail, does not gurantee sharing record updates.
        do not use for logic
        """
        subscriber_collection = DatabaseFactory.get_subscribers_collection()
        query = {SharingController.SHARING_SPACE_SECRET_KEY: sharing_secret}
        #first get the sharing record
        sharing_record  = yield gen.Task(SharingController.get_sharing_record_by_secret,
            sharing_secret)

        if sharing_record is None:
            SharingController.__log.info('SharingController - Sharing record is None for secret %s' % sharing_secret)
            callback(None)
        else:
            subscribers_list = sharing_record.get_subscribers()
            for subscriber_info in subscribers_list:
                subscriber_id = subscriber_info[0]
                subscriber_collection_name = subscriber_info[1]
                #just remove it from the cache
                SharingController.__cache.remove_subscriber_info(subscriber_id,
                    subscriber_collection_name, callback=None)

            #remove everything from the db in one shot
            yield gen.Task(subscriber_collection.remove, query)
            callback()
Exemplo n.º 3
0
    def get_sharing_record_by_secret(sharing_secret, callback):
        """
        Returns:
            -A Sharing record object containing information of the
            sharing space with the sharing_secret and None if the
            sharing record for the specified sharing secret does not
            exist
        """
        #try the cache
        sharing_record_json_str = yield gen.Task(SharingController.__cache.get_sharing_record,
            sharing_secret)
        #cache hit
        if sharing_record_json_str is not None:
            if sharing_record_json_str == 'false':
                callback(None)
            else:
                sharing_record_obj = json.loads(sharing_record_json_str)
                sharing_record = SharingRecord(
                    sharing_record_obj[SharingRecord.SECRET_KEY],
                    sharing_record_obj[SharingRecord.OWNER_KEY],
                    sharing_record_obj[SharingRecord.COLLECTION_NAME_KEY],
                    sharing_record_obj[SharingRecord.SUBSCIRBERS_KEY])
                callback(sharing_record)

        #cache miss
        else:
            sharing_collection = DatabaseFactory.get_sharing_collection()
            query = {SharingRecord.SECRET_KEY : sharing_secret}
            sharing_records_cursor = yield gen.Task(sharing_collection.find, query)
            result_count = len(sharing_records_cursor[0][0])
            #if we have more sharing spaces with this sharing secret
            #something is horribly wrong
            if result_count >= 2:
                SharingController.__log.warning('SharingController - More than two sharing info found for: %s' % sharing_secret)
                yield gen.Task(SharingController.__cache.set_sharing_record, sharing_secret, 'false')
                callback(None)

            if not result_count:
                SharingController.__log.warning('SharingController - no sharing info found for: %s' % sharing_secret)
                yield gen.Task(SharingController.__cache.set_sharing_record, sharing_secret, 'false')
                callback(None)

            else:
                #FIXME: is there a better way to these in asyncMongo other
                #than these ugly indicies
                sharing_record_bson = sharing_records_cursor[0][0][0]
                try:
                    sharing_record = SharingRecord(
                                    sharing_record_bson[SharingRecord.SECRET_KEY],
                                    sharing_record_bson[SharingRecord.OWNER_KEY],
                                    sharing_record_bson[SharingRecord.COLLECTION_NAME_KEY],
                                    sharing_record_bson[SharingRecord.SUBSCIRBERS_KEY])
                    callback(sharing_record)
                except Exception:
                    SharingController.__log.warning('SharingController - corrupted sharing info found for: %s' % sharing_secret)
                    yield gen.Task(SharingController.__cache.set_sharing_record, sharing_secret, 'false')
                    callback(None)
Exemplo n.º 4
0
    def get_sharing_secret_from_subscriber_info(user_id, collection_name, callback):
        """
        Retrieves the sharing secret of a sharing space, uniquely identified
        by the user_id and collection name.

        -Returns:
            - The secret is passed to the callback. If there is no such
            subscriber then None is passed
        """
        #first look up in the cache
        sharing_secret = yield gen.Task(SharingController.__cache.get_subscriber_info,
            user_id, collection_name)
        if sharing_secret is not None:
            #this means we have looked up in the DB before and the sharing secret wasn't there
            if sharing_secret == 'false':
                callback(None)
            else:
                callback(sharing_secret)

        #if cache miss it look up in the DB
        else:
            subscriber_collection = DatabaseFactory.get_subscribers_collection()
            query = {SharingController.SUBSCRIBER_ID_KEY : user_id,
                     SharingController.SUBSCRIBER_COLLECTION_NAME_KEY : collection_name}
            subscriber_record_cursor = yield gen.Task(subscriber_collection.find, query)
            result_count = len(subscriber_record_cursor[0][0])
            #if user_id and collection_name are not uniquely identifying the
            #share space then we are in trouble
            if result_count >= 2:
                SharingController.__log.warning('SharingController - More than two sharing info found for: ' + user_id + ' - ' + collection_name)
                result_count = 0

            if not result_count:
                SharingController.__log.info('SharingController - No sharing record found for user %s and collection %s' % (user_id, collection_name))
                #cache the lack of info so we don't hit the DB every time we ask for a non existing sharing record
                yield gen.Task(SharingController.__cache.set_subscriber_info, user_id, collection_name, 'false')
                callback(None)

            else:
                subscriber_record_bson = subscriber_record_cursor[0][0][0]
                sharing_secret = subscriber_record_bson[SharingController.SHARING_SPACE_SECRET_KEY]
                if sharing_secret is None or not len(sharing_secret):
                    SharingController.__log.info('SharingController - Sharing secret is None or Empty for user %s and collection %s' % (user_id, collection_name))
                    yield gen.Task(SharingController.__cache.set_subscriber_info, user_id, collection_name, 'false')
                    callback(None)
                else:
                    #set the cache for future usage
                    yield gen.Task(SharingController.__cache.set_subscriber_info,
                        user_id, collection_name, sharing_secret)
                    #now call back to the user
                    callback(sharing_secret)
Exemplo n.º 5
0
    def remove_sharing_record_by_secret(sharing_secret, callback):
        """
        Removes a sharing record identified by the sharing_secret

        Returns:
            - void. The callback will be called
        """
        sharing_collection = DatabaseFactory.get_sharing_collection()
        query = {SharingRecord.SECRET_KEY : sharing_secret}
        #first remove subscribers
        yield gen.Task(SharingController.remove_all_subscribers, sharing_secret)
        #the collection itself
        yield gen.Task(sharing_collection.remove, query)
        #remove the record from the cache too
        yield gen.Task(SharingController.__cache.remove_sharing_record, sharing_secret)
        callback()
Exemplo n.º 6
0
    def remove_subscriber(user_id, collection_name, callback):
        """
        Removes the subscriber from the subscribers collection.
        user_id and collection_name identify a sharing space uniquely.

        This is implementation detail. Do not use for actual logic, does
        not guarauntee  updates to sharing record
        """
        subscriber_collection = DatabaseFactory.get_subscribers_collection()
        query = {SharingController.SUBSCRIBER_ID_KEY : user_id,
                 SharingController.SUBSCRIBER_COLLECTION_NAME_KEY : collection_name}
        yield gen.Task(subscriber_collection.remove, query)
        #remove from cache too
        yield gen.Task(SharingController.__cache.remove_subscriber_info,
            user_id, collection_name)
        if callback is not None:
            callback()
Exemplo n.º 7
0
    def __update_sharing_record(sharing_record, callback):
        """
        updates the sharing recrod in the mongoDB database.
        The passed in sharing record will replace the one
        in the db

        This method is very dangerous as the user must make sure that
        they also update the subscribers collection in mongo
        """
        sharing_collection = DatabaseFactory.get_sharing_collection()
        doc_key = {SharingRecord.SECRET_KEY: sharing_record.get_sharing_secret()}
        doc_content = sharing_record.toDictionary()
        sharing_record_json = sharing_record.to_json_str()
        yield gen.Task(sharing_collection.update, doc_key, doc_content)
        #update the cache
        yield gen.Task(SharingController.__cache.set_sharing_record,
            sharing_record.get_sharing_secret(), sharing_record_json)
        callback()
Exemplo n.º 8
0
    def __rename_subscriber_collection_name(user_id, old_collection_name,
                                            new_collection_name, sharing_secret,
                                            callback):
        """
        Updates the subscriber table for the user with user_id with the new name
        for its collection
        """

        sharing_collection = DatabaseFactory.get_subscribers_collection()
        key = {SharingController.SUBSCRIBER_ID_KEY : user_id,
                 SharingController.SUBSCRIBER_COLLECTION_NAME_KEY : old_collection_name}
        new_content = {SharingController.SUBSCRIBER_ID_KEY : user_id,
                       SharingController.SUBSCRIBER_COLLECTION_NAME_KEY : new_collection_name,
                       SharingController.SHARING_SPACE_SECRET_KEY : sharing_secret}
        yield gen.Task(sharing_collection.update, key, new_content)

        #remove the old content from cache
        yield gen.Task(SharingController.__cache.remove_subscriber_info,
            user_id, old_collection_name)
        #add new content to the cache
        yield gen.Task(SharingController.__cache.set_subscriber_info,
            user_id, new_collection_name, sharing_secret)
        #TODO I can probalby use the replace cmd in memcache to reduce these two calls to one
        callback()
Exemplo n.º 9
0
    def add_subscriber(user_id, collection_name, sharing_secret, callback):
        """
        Adds a subscriber with user id and collection and sharing secret
        to the subscribers db. user_id and collection_name uniquely identify
        the subscriber and maps it to the sharing_secret of the sharing space

        This is implementation detail. Do not use for actual logic
        """

        if sharing_secret is None or user_id is None or collection_name is None:
            SharingController.__log.warning('Sharing Controller - A value was none in add subscriber')
            callback()

        else:
            subscriber_collection = DatabaseFactory.get_subscribers_collection()
            subscriber_record = {SharingController.SUBSCRIBER_ID_KEY : user_id,
                                 SharingController.SUBSCRIBER_COLLECTION_NAME_KEY : collection_name,
                                 SharingController.SHARING_SPACE_SECRET_KEY : sharing_secret}
            yield gen.Task(subscriber_collection.insert, subscriber_record)
            #add it to the cache to, since we get synchronization for free. this should be
            #optimal
            yield gen.Task(SharingController.__cache.set_subscriber_info,
                user_id, collection_name, sharing_secret)
            callback()
Exemplo n.º 10
0
 def __get_collection():
     return DatabaseFactory.get_accounts_collection()