def insert(self, **kwargs): # usually kwargs would be a Storage with several keys: # 'locked', 'client_ip','created_datetime','modified_datetime' # 'unique_key', 'session_data' # retrieve a new key newid = str(self.db.r_server.incr(self.serial)) key = self.keyprefix + ':' + newid if self.with_lock: key_lock = key + ':lock' acquire_lock(self.db.r_server, key_lock, newid) with self.db.r_server.pipeline() as pipe: # add it to the index pipe.sadd(self.id_idx, key) # set a hash key with the Storage pipe.hmset(key, kwargs) if self.session_expiry: pipe.expire(key, self.session_expiry) pipe.execute() if self.with_lock: release_lock(self.db, key_lock, newid) return newid
def select(self): if self.op == 'eq' and self.field == 'id' and self.value: # means that someone wants to retrieve the key self.value key = self.keyprefix + ':' + str(self.value) if self.with_lock: acquire_lock(self.db.r_server, key + ':lock', self.value, 2) rtn = { to_native(k): v for k, v in self.db.r_server.hgetall(key).items() } if rtn: if self.unique_key: # make sure the id and unique_key are correct if rtn['unique_key'] == to_native(self.unique_key): rtn['update_record'] = self.update # update record support else: rtn = None return [Storage(self.db.convert_dict_string(rtn))] if rtn else [] elif self.op in ('ge', 'gt') and self.field == 'id' and self.value == 0: # means that someone wants the complete list rtn = [] id_idx = "%s:id_idx" % self.keyprefix # find all session keys of this app allkeys = self.db.r_server.smembers(id_idx) for sess in allkeys: val = self.db.r_server.hgetall(sess) if not val: if self.session_expiry: # clean up the idx, because the key expired self.db.r_server.srem(id_idx, sess) continue val = Storage(self.db.convert_dict_string(val)) # add a delete_record method (necessary for sessions2trash.py) val.delete_record = RecordDeleter(self.db, sess, self.keyprefix) rtn.append(val) return rtn else: raise Exception("Operation not supported")
def select(self): if self.op == 'eq' and self.field == 'id' and self.value: # means that someone wants to retrieve the key self.value key = self.keyprefix + ':' + str(self.value) if self.with_lock: acquire_lock(self.db.r_server, key + ':lock', self.value, 2) rtn = self.db.r_server.hgetall(key) if rtn: if self.unique_key: # make sure the id and unique_key are correct if rtn[b'unique_key'] == to_bytes(self.unique_key): rtn[b'update_record'] = self.update # update record support else: rtn = None return [Storage(rtn)] if rtn else [] elif self.op == 'ge' and self.field == 'id' and self.value == 0: # means that someone wants the complete list rtn = [] id_idx = "%s:id_idx" % self.keyprefix # find all session keys of this app allkeys = self.db.r_server.smembers(id_idx) for sess in allkeys: val = self.db.r_server.hgetall(sess) if not val: if self.session_expiry: # clean up the idx, because the key expired self.db.r_server.srem(id_idx, sess) continue val = Storage(val) # add a delete_record method (necessary for sessions2trash.py) val.delete_record = RecordDeleter( self.db, sess, self.keyprefix) rtn.append(val) return rtn else: raise Exception("Operation not supported")
def __call__(self, key, f, time_expire=300, with_lock=None): if with_lock is None: with_lock = self.with_lock if time_expire is None: time_expire = 24 * 60 * 60 newKey = self.__keyFormat__(key) value = None ttl = 0 try: if f is None: # delete and never look back self.r_server.delete(newKey) return None # is there a value obj = self.r_server.get(newKey) # what's its ttl if obj: ttl = self.r_server.ttl(newKey) if ttl > time_expire: obj = None if obj: # was cached if self.debug: self.r_server.incr('web2py_cache_statistics:hit_total') value = pickle.loads(obj) else: # naive distributed locking if with_lock: lock_key = '%s:__lock' % newKey randomvalue = time.time() al = acquire_lock(self.r_server, lock_key, randomvalue) try: # someone may have computed it obj = self.r_server.get(newKey) if obj is None: value = self.cache_it(newKey, f, time_expire) else: value = pickle.loads(obj) finally: release_lock(self, lock_key, al) else: # without distributed locking value = self.cache_it(newKey, f, time_expire) return value except RConnectionError: return self.retry_call(key, f, time_expire, with_lock)