Beispiel #1
0
    def get(self, user_id, create_if_missing=False, **_private_kw):
        """
        Get state for the specified user, but don't acquire a lock.
        Returns None if the state was not found.

        Note: _private_kw should never be used as part of the public API.
        It is a private interface which allows open() to acquire a lock
        and is UNSAFE for external use.
        """
        log.debug("uuss.UserState.get %r", user_id)
        user_id = str(user_id)

        if not user_id:
            raise UserstateException("user_id is empty... %r" % user_id)
        if user_id[0] == "{":
            raise UserstateException("user_id appears to be json... %r" % user_id)

        req = proto.GetRequest()
        req.game = self.game
        req.user_id = user_id
        req.create_if_missing = create_if_missing
        req.lock = _private_kw.get('_lock', False)
        req.lock_label = _private_kw.get('_lock_label', 'generic')
        req.lock_timeout = _private_kw.get('_lock_timeout', 60)
        req.lock_max_wait = _private_kw.get('_lock_max_wait', 30)
        self._protocol_send_message(req)
        resp = self._recv_expected_message(proto.GetResponse, self.game, user_id)

        if resp.state == "":
            state = None
        else:
            state = chunking.reconstitute_chunks(resp.state, self._lazy_load_chunks)
            check_user_id(user_id, state, game=self.game)

        return state
Beispiel #2
0
def check_user_id(user_id, state, chunk_config={}, game=None):
    if state is None:
        return
    # if we get a str, this is a chunked state and needs to have the master record reconstitued so we can check the user_id
    if isinstance(state, str):
        if chunk_config == {}:
            config = chunking.get_saved_chunk_config(state)
            if isinstance(config, list):
                # we can't check for the user id and game in the old format list chunk config
                state = chunking.reconstitute_chunks(state, True)
            else:
                # If no chunk config passed in to check, just check the values in the chunk config
                state = config
        else:
            # reconstitute so we can check the chunks
            state = chunking.reconstitute_chunks(state, True)
    if game is not None:
        if 'game' not in state:
            log.debug("game not set in state, adding")
            state['game'] = game
        elif state['game'] != game:
            raise UserstateException("state['game'] (%r) != game (%r)" % (state['game'], game))
    if 'user_id' not in state:
        raise UserIdMissingException("user_id missing for '%s'" % user_id)
    elif state['user_id'] != str(user_id):
        raise WrongUserIdException("wrong user_id in state for '%s', found '%s'" % (user_id, state['user_id']))

    for chunk_name, chunk_path in chunk_config.iteritems():
        container = state
        for key in chunk_path[:-1]:
            if key not in container:
                container = None
                break
            container = container[key]
            
        if container is None:
            continue

        chunk_key = chunk_path[-1]

        if chunk_key in container and container[chunk_key] is None:
            raise UserstateException("Chunk %r is None for user %r" % (chunk_name, user_id))
Beispiel #3
0
def fix_state(uid):
    userstate = model.dane.userstate
    try:
        userstate.get(uid)
        print "State OK for %r" % uid
    except uuss.WrongUserIdException, e:
        if not 'wrong user_id in state' in e.args[0]:
            raise
        print "Wrong user_id in state for %r" % uid
        
        user_state = model.dane.UserState.get(uid)
        try:
            state = chunking.reconstitute_chunks(user_state.state, True)
        except:
            chunking_exc = sys.exc_info()
            try:
                state = simplejson.loads(zlib.decompress(user_state.state))
            except Exception, e:
                print "Chunking and original formats failed"
                print e
                print chunking_exc
def do_processing(onerun=False):
    for collection_name in mongo_db.collection_names():
        proc_time = 0
        if collection_name.startswith('user_state-modified-%s' % bucket):
            try:
                load_name = 'user_state-modified-%s-%s' % (bucket, time.time())
                try:
                    mongo_db[collection_name].rename(load_name)
                except pymongo.errors.OperationFailure:
                    # effectively this makes sure the renamed collection exists
                    if mongo_db[load_name].count() <= 0:
                        raise
                    log.error("Error encountered renaming collection %s to %s, but able to continue" %
                              (collection_name, load_name))
                
                modified = mongo_db[load_name]
                
                start_time = time.time()
                log.info("%s userstates to save for %s ..." % (modified.count(), load_name))

                # prepare for userstate size monitoring
                userstates_processed = 0
                max_userstate_size = -1
                total_userstate_size = 0
                
                mod_count = 0
                mod_rows = list(modified.find())
                batch_count = 1
                while mod_rows:
                    proc_rows = mod_rows[:max_batch_size]
                    mod_rows = mod_rows[max_batch_size:]
                    base_file_name = "%s.%s" % (load_name, batch_count)
                    with open(os.path.join(tmp_dir, base_file_name+".usrtmp"), 'w') as user_file:
                        with open(os.path.join(tmp_dir, base_file_name+".plrtmp"), 'w') as player_file:
                            for row in proc_rows:
                                mod_count += row['count']
                                try:
                                    if row['_id'] == 'null':
                                        log.error("null user_id encountered")
                                    else:
                                        if rebalancing:
                                            (state, chunked) = userstate.get(row['_id'], raw=True)
                                        else:
                                            (state, chunked) = userstate.backup(row['_id'], raw=True)
                                        if state is not None:
                                            if not chunked:
                                                # NOTE(jpatrin): Shouldn't happen, but just in case...
                                                if isinstance(state, str):
                                                    state = simplejson.loads(zlib.decompress(state))
                                                # NOTE(jpatrin): This will be just a single chunk for now,
                                                # but will serve until the state gets saved by the game
                                                raw_state = chunking.blow_chunks(state)
                                            else:
                                                raw_state = state
                                                state = chunking.reconstitute_chunks(raw_state, True)
                                            #state_zlib_json = zlib.compress(simplejson.dumps(state))
                                            #user_line = gen_userstate_line(row['_id'], state_zlib_json)
                                            user_line = gen_userstate_line(row['_id'], raw_state)
                                            player_line = gen_player_line(row['_id'], state)
                                            user_file.write(user_line+'\n')
                                            if player_line:
                                                player_file.write(player_line+'\n')
                                            
                                            # keep userstate size for average and max size tracking
                                            userstates_processed += 1
                                            userstate_size = len(raw_state) / 1024
                                            total_userstate_size += userstate_size
                                            max_userstate_size = max(userstate_size, max_userstate_size)
                                except userstate_multi.UserstateException, e:
                                    log.exception(e)
                                except Exception, e:
                                    # (jay) errors are bad here, but we don't want to keep the 
                                    # rest of the userstates from being saved, so log it and go on
                                    log.exception(e)
                    # don't want the file reader to get to these before we're done, so keep
                    # as temporary name until finished writing
                    os.rename(os.path.join(tmp_dir, base_file_name+".usrtmp"),
                              os.path.join(tmp_dir, base_file_name+".user"))
                    os.rename(os.path.join(tmp_dir, base_file_name+".plrtmp"),
                              os.path.join(tmp_dir, base_file_name+".player"))
                    log.info("processed batch, %s remaining" % len(mod_rows))
                    batch_count += 1
Beispiel #5
0
     req.source_game = 'dane'
     req.source_user_id = u1
     req.message = simplejson.dumps('dane calling india')
     protocol.send_message(req)
     resp = protocol.recv_message()
     log.info('Message id: %r', resp.message_id)
 
     log.info('Get a userstate with a lock')
     req = proto.GetRequest()
     req.game = 'dane'
     req.user_id = u1
     req.create_if_missing = True
     req.lock = True
     protocol.send_message(req)
     resp = protocol.recv_message()
     state = chunking.reconstitute_chunks(resp.state, True)    
     log.debug("state: %s...", repr(state)[:200])
     log.debug("state['uuss_test']: %r", state.get('uuss_test', None))
     
     log.info('Get another userstate without a lock')
     req = proto.GetRequest()
     req.game = 'dane'
     req.user_id = u2
     req.create_if_missing = True
     protocol.send_message(req)
     resp = protocol.recv_message()
     other_state = chunking.reconstitute_chunks(resp.state, True)
     log.debug("other_state: %s...", repr(other_state)[:200])
     
     log.info('Get another userstate with a lock')
     req = proto.GetRequest()