예제 #1
0
파일: core.py 프로젝트: lazerhawk/acid
    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
예제 #2
0
파일: core.py 프로젝트: lazerhawk/acid
    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
예제 #3
0
파일: core_test.py 프로젝트: lazerhawk/acid
 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)
예제 #4
0
 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__
예제 #5
0
 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
예제 #6
0
 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)
예제 #7
0
파일: core.py 프로젝트: lazerhawk/acid
 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
예제 #8
0
파일: core.py 프로젝트: lazerhawk/acid
 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)
예제 #9
0
파일: core.py 프로젝트: lazerhawk/acid
    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))
예제 #10
0
 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())
예제 #11
0
 def test_not_already_tuple(self):
     eq(keylib.Key(""), keylib.Key(""))
예제 #12
0
 def test_already_key(self):
     eq(keylib.Key(), keylib.Key(keylib.Key()))
예제 #13
0
 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])
예제 #14
0
 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])