예제 #1
0
func (self *ctrlblk) Bytes() []byte {
	bytes := make([]byte, CONTROLSIZE)
	copy(bytes[0:8], bs.ByteSlice64(uint64(self.end)))
	copy(bytes[8:16], bs.ByteSlice64(uint64(self.free_head)))
	copy(bytes[16:20], bs.ByteSlice32(uint32(self.free_len)))
	return bytes
}
예제 #2
0
func (self *ctrlblk) Bytes() []byte {
	bytes := make([]byte, CONTROLSIZE)
	copy(bytes[0:4], bs.ByteSlice32(self.buckets))
	copy(bytes[4:12], bs.ByteSlice64(self.records))
	copy(bytes[12:20], bs.ByteSlice64(uint64(self.table)))
	bytes[20] = self.i
	return bytes
}
예제 #3
0
func (self *list_header) Bytes() []byte {
	bytes := make(bs.ByteSlice, LIST_HEADER_LEN)
	copy(bytes[0:8], bs.ByteSlice64(uint64(self.next)))
	copy(bytes[8:16], bs.ByteSlice64(uint64(self.head)))
	copy(bytes[16:24], bs.ByteSlice64(uint64(self.tail)))
	copy(bytes[24:32], bs.ByteSlice64(uint64(self.insert_point)))
	copy(bytes[32:36], bs.ByteSlice32(self.block_count))
	copy(bytes[36:40], bs.ByteSlice32(self.list_length))
	return bytes
}
예제 #4
0
func NewLinearHash(file file.BlockDevice, kv bucket.KVStore) (self *LinearHash, err error) {
	const NUMBUCKETS = 16
	const I = 5
	table, err := bucket.NewBlockTable(file, 4, 8)
	if err != nil {
		return nil, err
	}
	for n := uint32(0); n < NUMBUCKETS; n++ {
		bkt, err := bucket.NewHashBucket(file, HASHSIZE, kv)
		if err != nil {
			return nil, err
		}
		err = table.Put(bs.ByteSlice32(n), bs.ByteSlice64(uint64(bkt.Key())))
		if err != nil {
			return nil, err
		}
	}
	self = &LinearHash{
		file:  file,
		kv:    kv,
		table: table,
		ctrl: ctrlblk{
			buckets: NUMBUCKETS,
			records: 0,
			table:   table.Key(),
			i:       I,
		},
	}
	return self, self.write_ctrlblk()
}
예제 #5
0
func (self *VarcharStore) Put(key, value bs.ByteSlice) (bytes bs.ByteSlice, err error) {
	vc := self.varchar
	kv := new_varchar_kv(key, value).Bytes()
	vkey, err := vc.Write(kv)
	if err != nil {
		return nil, err
	}
	return bs.ByteSlice64(uint64(vkey)), nil
}
예제 #6
0
func (self *LinearHash) Get(key bs.ByteSlice) (value bs.ByteSlice, err error) {
	hash := hash(key)
	bkt_idx := self.bucket(hash)
	bkt, err := self.get_bucket(bkt_idx)
	if err != nil {
		return nil, err
	}
	return bkt.Get(bs.ByteSlice64(hash), key)
}
예제 #7
0
func (self *Varchar) set_length(key int64, blk *block, length uint64) (err error) {
	block_size := datasize(self.file)
	offset := self.block_offset(key)
	if offset > block_size {
		return fmt.Errorf("Would write length off the end of the block")
	}

	copy(blk.data[offset:offset+LENSIZE], bs.ByteSlice64(length))
	return nil
}
예제 #8
0
func (self *header) Bytes() (bytes []byte) {
	bytes = make([]byte, HEADER_SIZE)
	bytes[0] = self.flag
	bytes[1] = self.keysize
	bytes[2] = self.valsize
	copy(bytes[4:8], bs.ByteSlice32(self.records))
	copy(bytes[8:16], bs.ByteSlice64(uint64(self.next)))
	copy(bytes[16:18], bs.ByteSlice16(self.blocks))
	return bytes
}
예제 #9
0
func (self *LinearHash) Has(key bs.ByteSlice) (has bool, err error) {
	hash := hash(key)
	bkt_idx := self.bucket(hash)
	bkt, err := self.get_bucket(bkt_idx)
	if err != nil {
		return false, err
	}
	has = bkt.Has(bs.ByteSlice64(hash), key)
	// fmt.Println("LinearHash.Has", bs.ByteSlice64(hash), key, bkt_idx, has)
	return has, nil
}
예제 #10
0
func (self *LinearHash) split() (err error) {
	bkt_idx := self.ctrl.buckets % (1 << (self.ctrl.i - 1))
	bkt, err := self.get_bucket(bkt_idx)
	if err != nil {
		return err
	}
	keys := bkt.Keys()
	self.ctrl.buckets += 1
	if self.ctrl.buckets > (1 << self.ctrl.i) {
		self.ctrl.i += 1
	}
	newbkt, err := bkt.Split(func(key bs.ByteSlice) bool {
		this_idx := self.bucket(key.Int64())
		return this_idx == bkt_idx
	})
	err = self.table.Put(bs.ByteSlice32(self.ctrl.buckets-1), bs.ByteSlice64(uint64(newbkt.Key())))
	if err != nil {
		return err
	}
	err = self.write_ctrlblk()
	if err != nil {
		return err
	}
	for _, key := range keys {
		if has, err := self.Has(key); err != nil {
			return err
		} else if !has {
			hash := bs.ByteSlice64(hash(key))
			in_first := bkt.Has(hash, key)
			in_second := newbkt.Has(hash, key)
			fmt.Println()
			fmt.Println("i", self.ctrl.i, "records", self.ctrl.records, "buckets", self.ctrl.buckets)
			fmt.Println("key", key, "hash", hash)
			fmt.Println("in_first", in_first, bkt_idx)
			fmt.Println("in_second", in_second, self.ctrl.buckets-1)
			return fmt.Errorf("Key went missing during split")
		}
	}
	return nil
}
예제 #11
0
func (self *LinearHash) DefaultGet(key bs.ByteSlice, default_value bs.ByteSlice) (value bs.ByteSlice, err error) {
	hash := hash(key)
	hash_bytes := bs.ByteSlice64(hash)
	bkt_idx := self.bucket(hash)
	bkt, err := self.get_bucket(bkt_idx)
	if err != nil {
		return nil, err
	}
	if bkt.Has(hash_bytes, key) {
		return bkt.Get(hash_bytes, key)
	}
	return default_value, nil
}
예제 #12
0
func (self *LinearHash) Remove(key bs.ByteSlice) (err error) {
	hash := hash(key)
	bkt_idx := self.bucket(hash)
	bkt, err := self.get_bucket(bkt_idx)
	if err != nil {
		return err
	}
	err = bkt.Remove(bs.ByteSlice64(hash), key)
	if err != nil {
		return err
	}
	self.ctrl.records -= 1
	return self.write_ctrlblk()
}
예제 #13
0
func (self *VarcharStore) Update(bytes, key, value bs.ByteSlice) (rbytes bs.ByteSlice, err error) {
	vc := self.varchar
	vkey := int64(bytes.Int64())
	kv := new_varchar_kv(key, value).Bytes()
	oldkv, err := vc.Read(vkey)
	if err != nil {
		return nil, err
	}
	if len(oldkv) == len(kv) {
		err = vc.Update(vkey, kv)
		if err != nil {
			return nil, err
		}
		return bs.ByteSlice64(uint64(vkey)), nil
	} else {
		err := vc.Remove(vkey)
		if err != nil {
			return nil, err
		}
		return self.Put(key, value)
	}
}
예제 #14
0
func (self *LinearHash) Put(key bs.ByteSlice, value bs.ByteSlice) (err error) {
	hash := hash(key)
	bkt_idx := self.bucket(hash)
	bkt, err := self.get_bucket(bkt_idx)
	if err != nil {
		fmt.Println("Couldn't get bucket idx", bkt_idx)
		return err
	}
	updated, err := bkt.Put(bs.ByteSlice64(hash), key, value)
	if err != nil {
		return err
	}
	if !updated {
		self.ctrl.records += 1
		if self.split_needed() {
			// fmt.Println("did split")
			return self.split()
		}
		// fmt.Println("no split")
		return self.write_ctrlblk()
	}
	return nil
}
예제 #15
0
func TestPutHasGetRemoveLinearHash(t *testing.T) {
	fmt.Println("start test")
	const RECORDS = 300
	g := testfile(t, VPATH)
	defer func() {
		if e := g.Close(); e != nil {
			panic(e)
		}
		if e := g.Remove(); e != nil {
			panic(e)
		}
	}()
	store, err := bucket.NewVarcharStore(g)
	if err != nil {
		panic(err)
	}
	f := testfile(t, PATH)
	defer func() {
		if e := f.Close(); e != nil {
			panic(e)
		}
		if e := f.Remove(); e != nil {
			panic(e)
		}
	}()
	linhash, err := NewLinearHash(f, store)
	if err != nil {
		t.Fatal(err)
	}

	type record struct {
		key   bs.ByteSlice
		value bs.ByteSlice
	}

	keyset := make(map[string]bool)
	var records []*record
	var values2 []bs.ByteSlice
	for i := 0; i < RECORDS; i++ {
		key := randslice(rand.Intn(16) + 1)
		for {
			if _, has := keyset[string(key)]; !has {
				break
			}
			key = randslice(rand.Intn(16) + 1)
		}
		keyset[string(key)] = true
		records = append(records, &record{key, randslice(rand.Intn(150) + 25)})
		values2 = append(values2, randslice(rand.Intn(150)+25))
	}
	fmt.Println("real start test")

	for i, record := range records {
		err := linhash.Put(record.key, record.value)
		if err != nil {
			t.Fatal(err)
		}
		has, err := linhash.Has(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !has {
			hash := hash(record.key)
			bkt_idx := linhash.bucket(hash)
			bkt, _ := linhash.get_bucket(bkt_idx)
			bkt.PrintBucket()
			bkt_idx2 := bkt_idx - (1 << (linhash.ctrl.i - 1))
			if bkt_idx2 < linhash.ctrl.buckets {
				bkt2, _ := linhash.get_bucket(bkt_idx2)
				bkt2.PrintBucket()
			}
			fmt.Println(i, bs.ByteSlice64(hash), record.key, bkt_idx, bkt_idx2, linhash.ctrl.buckets, linhash.ctrl.i)
			t.Fatal("Expected key")
		}
		value, err := linhash.Get(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !value.Eq(record.value) {
			t.Fatal("Error getting record, value was not as expected")
		}
	}

	if linhash.ctrl.records != RECORDS {
		t.Fatalf("Expected record count == %d got %d", RECORDS,
			linhash.ctrl.records)
	}

	rkeys, err := linhash.Keys()
	if err != nil {
		t.Fatal(err)
	}
	rkeyset := make(map[string]bool)
	for _, bkey := range rkeys {
		key := string(bkey)
		if _, has := keyset[key]; !has {
			t.Fatal("got non-existent key", bs.ByteSlice(key))
		}
		rkeyset[key] = true
	}

	for key, _ := range keyset {
		if _, has := rkeyset[key]; !has {
			t.Fatal("missed key", bs.ByteSlice(key))
		}
	}

	for i, record := range records {
		has, err := linhash.Has(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !has {
			hash := hash(record.key)
			bkt_idx := linhash.bucket(hash)
			bkt, _ := linhash.get_bucket(bkt_idx)
			bkt.PrintBucket()
			bkt_idx2 := bkt_idx - (1 << (linhash.ctrl.i - 1))
			if bkt_idx2 < linhash.ctrl.buckets {
				bkt2, _ := linhash.get_bucket(bkt_idx2)
				bkt2.PrintBucket()
			}
			fmt.Println(i, bs.ByteSlice64(hash), record.key, bkt_idx, bkt_idx2, linhash.ctrl.buckets, linhash.ctrl.i)
			t.Fatal("Expected key")
		}
		value, err := linhash.Get(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !value.Eq(record.value) {
			t.Fatal("Error getting record, value was not as expected")
		}
		ran := randslice(rand.Intn(25) + 1)
		if _, has := keyset[string(ran)]; !has {
			value, err := linhash.DefaultGet(ran, bs.ByteSlice64(0))
			if err != nil {
				t.Fatal(err)
			}
			if !value.Eq(bs.ByteSlice64(0)) {
				t.Fatal("Error getting default")
			}
		} else {
			_, err := linhash.DefaultGet(ran, bs.ByteSlice64(0))
			if err != nil {
				t.Fatal(err)
			}
		}
	}

	for i, record := range records {
		has, err := linhash.Has(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !has {
			t.Fatal("Expected key")
		}
		value, err := linhash.Get(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !value.Eq(record.value) {
			t.Fatal("Error getting record, value was not as expected")
		}
		err = linhash.Put(record.key, values2[i])
		if err != nil {
			t.Fatal(err)
		}
		value, err = linhash.Get(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !value.Eq(values2[i]) {
			t.Fatal("Error getting record, value was not as expected")
		}
		if linhash.Length() != RECORDS {
			t.Fatalf("Expected record count == %d got %d", RECORDS,
				linhash.ctrl.records)
		}
	}

	length := linhash.Length()
	for _, record := range records[length/2:] {
		err := linhash.Remove(record.key)
		if err != nil {
			t.Fatal(err)
		}
	}

	for _, record := range records[length/2:] {
		has, err := linhash.Has(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if has {
			t.Fatal("expected key to be gone")
		}
	}

	for i, record := range records[:length/2] {
		has, err := linhash.Has(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !has {
			t.Fatal("Expected key")
		}
		value, err := linhash.Get(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if !value.Eq(values2[i]) {
			t.Fatal("Error getting record, value was not as expected")
		}
	}

	for _, record := range records[:length/2] {
		err := linhash.Remove(record.key)
		if err != nil {
			t.Fatal(err)
		}
	}

	for _, record := range records {
		has, err := linhash.Has(record.key)
		if err != nil {
			t.Fatal(err)
		}
		if has {
			t.Fatal("expected key to be gone")
		}
	}

	if linhash.Length() != 0 {
		t.Fatalf("Expected record count == %d got %d", 0,
			linhash.ctrl.records)
	}
}
예제 #16
0
func (self *metadata) Bytes() []byte {
	bytes := make([]byte, METADATASIZE)
	copy(bytes[0:8], bs.ByteSlice64(uint64(self.next)))
	return bytes
}
예제 #17
0
func (self *free_varchar) Bytes() []byte {
	bytes := make([]byte, FREE_VARCHAR_SIZE)
	copy(bytes[0:8], bs.ByteSlice64(self.length))
	copy(bytes[8:16], bs.ByteSlice64(uint64(self.next)))
	return bytes
}