@@ -6,59 +6,62 @@ import (
66 "github.com/akrylysov/pogreb/fs"
77)
88
9+ const (
10+ slotsPerBucket = 31
11+ bucketSize = 512
12+ )
13+
14+ // slot corresponds to a single item in the hash table.
915type slot struct {
1016 hash uint32
17+ segmentID uint16
1118 keySize uint16
1219 valueSize uint32
13- kvOffset int64
20+ offset uint32 // Segment offset.
1421}
1522
1623func (sl slot ) kvSize () uint32 {
1724 return uint32 (sl .keySize ) + sl .valueSize
1825}
1926
27+ // bucket is an array of slots.
2028type bucket struct {
2129 slots [slotsPerBucket ]slot
22- next int64
30+ next int64 // Offset of overflow bucket.
2331}
2432
33+ // bucketHandle is a bucket, plus its offset and the file it's written to.
2534type bucketHandle struct {
2635 bucket
2736 file fs.MmapFile
2837 offset int64
2938}
3039
31- const (
32- bucketSize uint32 = 512
33- )
34-
35- func align512 (n uint32 ) uint32 {
36- return (n + 511 ) &^ 511
37- }
38-
3940func (b bucket ) MarshalBinary () ([]byte , error ) {
4041 buf := make ([]byte , bucketSize )
4142 data := buf
4243 for i := 0 ; i < slotsPerBucket ; i ++ {
4344 sl := b .slots [i ]
4445 binary .LittleEndian .PutUint32 (buf [:4 ], sl .hash )
45- binary .LittleEndian .PutUint16 (buf [4 :6 ], sl .keySize )
46- binary .LittleEndian .PutUint32 (buf [6 :10 ], sl .valueSize )
47- binary .LittleEndian .PutUint64 (buf [10 :18 ], uint64 (sl .kvOffset ))
48- buf = buf [18 :]
46+ binary .LittleEndian .PutUint16 (buf [4 :6 ], sl .segmentID )
47+ binary .LittleEndian .PutUint16 (buf [6 :8 ], sl .keySize )
48+ binary .LittleEndian .PutUint32 (buf [8 :12 ], sl .valueSize )
49+ binary .LittleEndian .PutUint32 (buf [12 :16 ], sl .offset )
50+ buf = buf [16 :]
4951 }
5052 binary .LittleEndian .PutUint64 (buf [:8 ], uint64 (b .next ))
5153 return data , nil
5254}
5355
5456func (b * bucket ) UnmarshalBinary (data []byte ) error {
5557 for i := 0 ; i < slotsPerBucket ; i ++ {
56- _ = data [18 ] // bounds check hint to compiler; see golang.org/issue/14808
58+ _ = data [16 ] // bounds check hint to compiler; see golang.org/issue/14808
5759 b .slots [i ].hash = binary .LittleEndian .Uint32 (data [:4 ])
58- b .slots [i ].keySize = binary .LittleEndian .Uint16 (data [4 :6 ])
59- b .slots [i ].valueSize = binary .LittleEndian .Uint32 (data [6 :10 ])
60- b .slots [i ].kvOffset = int64 (binary .LittleEndian .Uint64 (data [10 :18 ]))
61- data = data [18 :]
60+ b .slots [i ].segmentID = binary .LittleEndian .Uint16 (data [4 :6 ])
61+ b .slots [i ].keySize = binary .LittleEndian .Uint16 (data [6 :8 ])
62+ b .slots [i ].valueSize = binary .LittleEndian .Uint32 (data [8 :12 ])
63+ b .slots [i ].offset = binary .LittleEndian .Uint32 (data [12 :16 ])
64+ data = data [16 :]
6265 }
6366 b .next = int64 (binary .LittleEndian .Uint64 (data [:8 ]))
6467 return nil
@@ -89,15 +92,17 @@ func (b *bucketHandle) write() error {
8992 return err
9093}
9194
95+ // slotWriter inserts and writes slots into a bucket.
9296type slotWriter struct {
9397 bucket * bucketHandle
9498 slotIdx int
9599 prevBuckets []* bucketHandle
96100}
97101
98- func (sw * slotWriter ) insert (sl slot , db * DB ) error {
102+ func (sw * slotWriter ) insert (sl slot , idx * index ) error {
99103 if sw .slotIdx == slotsPerBucket {
100- nextBucket , err := db .createOverflowBucket ()
104+ // Bucket is full, create a new overflow bucket.
105+ nextBucket , err := idx .createOverflowBucket ()
101106 if err != nil {
102107 return err
103108 }
@@ -112,6 +117,7 @@ func (sw *slotWriter) insert(sl slot, db *DB) error {
112117}
113118
114119func (sw * slotWriter ) write () error {
120+ // Write previous buckets first.
115121 for i := len (sw .prevBuckets ) - 1 ; i >= 0 ; i -- {
116122 if err := sw .prevBuckets [i ].write (); err != nil {
117123 return err
0 commit comments