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
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))
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
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()