diff --git a/ledis/ledis_db.go b/ledis/ledis_db.go index 0e76d17..cdb4e94 100644 --- a/ledis/ledis_db.go +++ b/ledis/ledis_db.go @@ -1,11 +1,16 @@ package ledis +import ( + "github.com/siddontang/ledisdb/leveldb" +) + func (db *DB) FlushAll() (drop int64, err error) { all := [...](func() (int64, error)){ db.flush, db.lFlush, db.hFlush, - db.zFlush} + db.zFlush, + db.bFlush} for _, flush := range all { if n, e := flush(); e != nil { @@ -25,6 +30,22 @@ func (db *DB) newEliminator() *elimination { eliminator.regRetireContext(lExpType, db.listTx, db.lDelete) eliminator.regRetireContext(hExpType, db.hashTx, db.hDelete) eliminator.regRetireContext(zExpType, db.zsetTx, db.zDelete) + eliminator.regRetireContext(bExpType, db.binTx, db.bDelete) return eliminator } + +func (db *DB) flushRegion(t *tx, minKey []byte, maxKey []byte) (drop int64, err error) { + it := db.db.RangeIterator(minKey, maxKey, leveldb.RangeROpen) + for ; it.Valid(); it.Next() { + t.Delete(it.Key()) + drop++ + if drop&1023 == 0 { + if err = t.Commit(); err != nil { + return + } + } + } + it.Close() + return +} diff --git a/ledis/t_bin.go b/ledis/t_bin.go index f09aea6..d435400 100644 --- a/ledis/t_bin.go +++ b/ledis/t_bin.go @@ -4,6 +4,7 @@ import ( "encoding/binary" "errors" "github.com/siddontang/ledisdb/leveldb" + "time" ) const ( @@ -13,6 +14,11 @@ const ( OPnot ) +type BitPair struct { + Pos int32 + Val uint8 +} + const ( // byte segByteWidth uint32 = 9 @@ -227,57 +233,7 @@ func (db *DB) bDelete(t *tx, key []byte) (drop int64) { return drop } -func (db *DB) BGet(key []byte) (data []byte, err error) { - if err = checkKeySize(key); err != nil { - return - } - - var ts, to int32 - if ts, to, err = db.bGetMeta(key); err != nil || ts < 0 { - return - } - - var tailSeq, tailOff = uint32(ts), uint32(to) - var capByteSize uint32 = db.bCapByteSize(tailSeq, tailOff) - data = make([]byte, capByteSize, capByteSize) - - minKey := db.bEncodeBinKey(key, minSeq) - maxKey := db.bEncodeBinKey(key, tailSeq) - it := db.db.RangeIterator(minKey, maxKey, leveldb.RangeClose) - - var seq, s, e uint32 - for ; it.Valid(); it.Next() { - if _, seq, err = db.bDecodeBinKey(it.Key()); err != nil { - data = nil - break - } - - s = seq << segByteWidth - e = MinUInt32(s+segByteSize, capByteSize) - copy(data[s:e], it.Value()) - } - it.Close() - - return -} - -func (db *DB) BDelete(key []byte) (drop int64, err error) { - if err = checkKeySize(key); err != nil { - return - } - - t := db.binTx - t.Lock() - defer t.Unlock() - - drop = db.bDelete(t, key) - db.rmExpire(t, bExpType, key) - - err = t.Commit() - return -} - -func (db *DB) getSegment(key []byte, seq uint32) ([]byte, []byte, error) { +func (db *DB) bGetSegment(key []byte, seq uint32) ([]byte, []byte, error) { bk := db.bEncodeBinKey(key, seq) segment, err := db.db.Get(bk) if err != nil { @@ -286,113 +242,14 @@ func (db *DB) getSegment(key []byte, seq uint32) ([]byte, []byte, error) { return bk, segment, nil } -func (db *DB) allocateSegment(key []byte, seq uint32) ([]byte, []byte, error) { - bk, segment, err := db.getSegment(key, seq) +func (db *DB) bAllocateSegment(key []byte, seq uint32) ([]byte, []byte, error) { + bk, segment, err := db.bGetSegment(key, seq) if err == nil && segment == nil { segment = make([]byte, segByteSize, segByteSize) } return bk, segment, err } -func (db *DB) BSetBit(key []byte, offset int32, val uint8) (ori uint8, err error) { - if err = checkKeySize(key); err != nil { - return - } - - // todo : check offset - var seq, off uint32 - if seq, off, err = db.bParseOffset(key, offset); err != nil { - return 0, err - } - - var bk, segment []byte - if bk, segment, err = db.allocateSegment(key, seq); err != nil { - return 0, err - } - - if segment != nil { - ori = getBit(segment, off) - setBit(segment, off, val) - - t := db.binTx - t.Lock() - t.Put(bk, segment) - if _, _, e := db.bUpdateMeta(t, key, seq, off); e != nil { - err = e - return - } - err = t.Commit() - t.Unlock() - } - - return -} - -func (db *DB) BGetBit(key []byte, offset int32) (uint8, error) { - if seq, off, err := db.bParseOffset(key, offset); err != nil { - return 0, err - } else { - _, segment, err := db.getSegment(key, seq) - if err != nil { - return 0, err - } - - if segment == nil { - return 0, nil - } else { - return getBit(segment, off), nil - } - } -} - -// func (db *DB) BGetRange(key []byte, start int32, end int32) ([]byte, error) { -// section := make([]byte) - -// return -// } - -func (db *DB) BCount(key []byte, start int32, end int32) (cnt int32, err error) { - var sseq uint32 - if sseq, _, err = db.bParseOffset(key, start); err != nil { - return - } - - var eseq uint32 - if eseq, _, err = db.bParseOffset(key, end); err != nil { - return - } - - var segment []byte - skey := db.bEncodeBinKey(key, sseq) - ekey := db.bEncodeBinKey(key, eseq) - - it := db.db.RangeIterator(skey, ekey, leveldb.RangeClose) - for ; it.Valid(); it.Next() { - segment = it.Value() - for _, bit := range segment { - cnt += bitsInByte[bit] - } - } - it.Close() - - return -} - -func (db *DB) BTail(key []byte) (int32, error) { - // effective length of data, the highest bit-pos set in history - tailSeq, tailOff, err := db.bGetMeta(key) - if err != nil { - return 0, err - } - - tail := int32(-1) - if tailSeq >= 0 { - tail = int32(uint32(tailSeq)<= 0 { + tail = int32(uint32(tailSeq)<