func (self *HashBucket) Put(hash, key, value bs.ByteSlice) (updated bool, err error) { defer func() { if e := recover(); e != nil { err = e.(error) } }() bytes, err := self.kv.Put(key, value) if err != nil { return false, err } updated = false err = self.bt.put(hash, bytes, func(rec *record) (bool, bs.ByteSlice) { k2, _, err := self.kv.Get(rec.value) if err != nil { panic(err) } if key.Eq(k2) { newbytes, err := self.kv.Update(bytes, key, value) if err != nil { panic(err) } updated = true return true, newbytes } else { return false, nil } }) if err != nil { return false, err } return updated, self.bt.save() }
func (self *BlockTable) put(key, value bs.ByteSlice, doreplace func(*record) (bool, bs.ByteSlice)) (err error) { if len(key) != int(self.header.keysize) { return fmt.Errorf( "Key size is wrong, %d != %d", self.header.keysize, len(key)) } if len(value) > int(self.header.valsize) { return fmt.Errorf( "Value size is wrong, %d >= %d", self.header.valsize, len(value)) } all_records := self.records if len(all_records) <= int(self.header.records)+1 { // alloc another block err := self.add_block() if err != nil { return err } all_records = self.records } records := record_slice(all_records[:self.header.records]) i, found := records.find(key) replace := false bytes := value if found { for j := i; j < len(records); j++ { if key.Eq(records[j].key) { var tmp bs.ByteSlice replace, tmp = doreplace(records[j]) if replace { i = j bytes = tmp break } } else { break } } } if !found || (found && !replace) { j := len(all_records) j -= 1 for ; j > int(i); j-- { cur := all_records[j-1] next := all_records[j] copy(next.key, cur.key) copy(next.value, cur.value) } self.header.records += 1 } spot := all_records[i] copy(spot.key, key) copy(spot.value, bytes) return self.save() }
func (self *HashBucket) Get(hash, key bs.ByteSlice) (value bs.ByteSlice, err error) { all_records := self.bt.records records := record_slice(all_records[:self.bt.header.records]) found := records.find_all(hash) for _, rec := range found { k2, value, err := self.kv.Get(rec.value) if err != nil { return nil, err } if key.Eq(k2) { return value, nil } } return nil, fmt.Errorf("Key not found") }
func (self *HashBucket) Has(hash, key bs.ByteSlice) bool { all_records := self.bt.records records := record_slice(all_records[:self.bt.header.records]) found := records.find_all(hash) for _, rec := range found { k2, _, err := self.kv.Get(rec.value) if err != nil { panic(err) } if key.Eq(k2) { return true } } return false }
func (self record_slice) find_all(key bs.ByteSlice) (found record_slice) { found = make(record_slice, 0, 5) i, ok := self.find(key) if !ok { return found } for ; i < len(self); i++ { if key.Eq(self[i].key) { found = append(found, self[i]) } else { break } } return found }
func (self record_slice) find(key bs.ByteSlice) (int, bool) { var l int = 0 var r int = len(self) - 1 var m int for l <= r { m = ((r - l) >> 1) + l if key.Lt(self[m].key) { r = m - 1 } else if key.Eq(self[m].key) { for j := m; j >= 0; j-- { if j == 0 || !key.Eq(self[j-1].key) { return j, true } } } else { l = m + 1 } } return l, false }
func (self *HashBucket) Remove(hash, key bs.ByteSlice) (err error) { all_records := self.bt.records records := record_slice(all_records[:self.bt.header.records]) i, found := records.find(hash) if found { for j := i; j < len(records); j++ { if hash.Eq(records[j].key) { k2, _, err := self.kv.Get(records[j].value) if err != nil { return err } if key.Eq(k2) { if err := self.kv.Remove(records[j].value); err != nil { return err } return self.bt.remove_index(j) } } else { break } } } return fmt.Errorf("Key not found") }