def put(self, rec, key=None): """Create or overwrite a record. `rec`: The value to put; must be a value recognised by the collection's `encoder`. `key`: Optionaly use this exact key, otherwise assign a key using the collection's key function. """ txn = self.store._txn_context.get() if key is None: key = self.key_func(rec) key = keylib.Key(key) dispatch(self._on_update, key, rec) new = self.encoder.pack(rec) # If a listener is registered that must observe the prior record value, # use replace(), which may result in a slow path on engines like # LevelDB. Otherwise use put(), which does not observe the old value. if self._after_replace or self._after_create: old = self.strategy.replace(txn, key, new) if old: oldrec = self.encoder.unpack(key, old) dispatch(self._after_replace, key, oldrec, rec) elif self._after_create: dispatch(self._after_create, key, rec) else: self.strategy.put(txn, key, new) dispatch(self._after_update, key, rec) return key
def count(self, name, n=1, init=1): """Increment a counter and return its previous value. The counter is created if it doesn't exist. `name`: Name of the counter. Names beginning with ``"\\x00"`` are reserved by the implementation. `n`: Number to add to the counter. If ``0`` or ``None``, return the counter's value without incrementing it. `init`: Initial value to give counter if it doesn't exist. """ try: key = self._counter_key_cache[name] except KeyError: key = keylib.Key(KIND_COUNTER, name, None) self._counter_key_cache[name] = key value, = self._meta.get(key, default=(init, )) if n: self._meta.put(value + n, key=key) return 0L + value
def test_delete_pop(self): self.insert_items() self.coll.strategy.batch(max_recs=len(self.ITEMS)) # Pop should trigger split of batch and return of old value. data = self.coll.strategy.pop(self.txn.get(), keylib.Key(3)) eq(data, '"jim"') # Should now contain metadata + 2 remaining records. assert len(self.e.items) == (self.old_len + 2)
def set_exact(self, key): """Set the lower and upper bounds such that `key` is the only key returned, if it exists.""" key = keylib.Key(key) self._lo = key self._hi = key self._lo_pred = key.__le__ self._hi_pred = key.__ge__
def batch_items(self): """Yield `(key, value)` pairs that are present in the current batch. Used to implement batch split, may be removed in future.""" for index in xrange(len(self.keys) - 1, -1, -1): start = self._offsets[index] stop = self._offsets[index + 1] key = self.keys[-1 + -index] data = self.concat[start:stop] yield keylib.Key(key), data
def set_prefix(self, key): """Set the lower bound to `>= key` and the upper bound to `< prefix_bound(key)`. If :py:meth:`prefix_bound <acid.keylib.Key.prefix_bound>` returns ``None``, then set no upper bound (i.e. iterate to the end of the collection). """ key = keylib.Key(key) self.set_lo(key, True) pbound = key.prefix_bound() if pbound is not None: self.set_hi(pbound, False)
def get(self, key, default=None, raw=False): """Fetch a record given its key. If `key` is not a tuple, it is wrapped in a 1-tuple. If the record does not exist, return ``None`` or if `default` is provided, return it instead.""" key = keylib.Key(key) data = self.strategy.get(self.store._txn_context.get(), key) if data: if raw: return data return self.encoder.unpack(key, data) return default
def delete(self, key): """Delete any existing record filed under `key`. """ key = keylib.Key(key) txn = self.store._txn_context.get() if self._after_delete: data = self.strategy.pop(txn, key) if data: obj = self.encoder.unpack(key, data) dispatch(self._after_delete, key, obj) else: self.strategy.delete(txn, key)
def _prepare_batch(self, items): if len(items) == 1: phys = keylib.Key(items[0][0]).to_raw(self.prefix) return phys, items[0][1] high_key_s = items[-1][0].to_raw() low_key_s = items[0][0].to_raw() cp_len = iterators.common_prefix_len(high_key_s, low_key_s) raw = bytearray(2 + (2 * (1 + len(items)))) raw[0:2] = struct.pack('>HH', len(items), len(raw)) for idx, (key, value) in enumerate(items): opos = 2 + (2 * idx) raw[opos:opos + 2] = struct.pack('>H', len(raw)) suffix = key.to_raw()[cp_len:] raw.append(len(suffix)) raw.extend(suffix) raw.extend(value) opos = 2 + (2 * len(items)) raw[opos:opos + 2] = struct.pack('>H', len(raw)) phys = keylib.packs([items[-1][0], items[0][0]], self.prefix) return phys, self.compressor.pack(bytes(raw))
def test_1(self): for key in self.KEYS: kp = keylib.Key(key) kc = _keylib.Key(key) eq(kp.prefix_bound().to_raw(), kc.prefix_bound().to_raw())
def test_not_already_tuple(self): eq(keylib.Key(""), keylib.Key(""))
def test_already_key(self): eq(keylib.Key(), keylib.Key(keylib.Key()))
def set_hi(self, key, closed=False): """Set the upper bound to `key`. If `closed` is ``True``, include the upper bound in the result set, otherwise exclude it.""" self._hi = keylib.Key(key) self._hi_pred = getattr(self._hi, ('__gt__', '__ge__')[closed])
def set_lo(self, key, closed=True): """Set the lower bound to `key`. If `closed` is ``True``, include the lower bound in the result set, otherwise exclude it.""" self._lo = keylib.Key(key) self._lo_pred = getattr(self._lo, ('__lt__', '__le__')[closed])