package blobovnicza import ( "bytes" "encoding/binary" "go.etcd.io/bbolt" ) const ( dataSizeAndItemsCountBufLength = 8 ) var ( metaBucketName = []byte("META") dataSizeKey = []byte("data_size") itemsCountKey = []byte("items_count") ) func isNonDataBucket(bucketName []byte) bool { return bytes.Equal(bucketName, incompletedMoveBucketName) || bytes.Equal(bucketName, metaBucketName) } func hasDataSize(tx *bbolt.Tx) (uint64, bool) { b := tx.Bucket(metaBucketName) if b == nil { return 0, false } v := b.Get(dataSizeKey) if v == nil { return 0, false } if len(v) != dataSizeAndItemsCountBufLength { return 0, false } return binary.LittleEndian.Uint64(v), true } func hasItemsCount(tx *bbolt.Tx) (uint64, bool) { b := tx.Bucket(metaBucketName) if b == nil { return 0, false } v := b.Get(itemsCountKey) if v == nil { return 0, false } if len(v) != dataSizeAndItemsCountBufLength { return 0, false } return binary.LittleEndian.Uint64(v), true } func saveDataSize(tx *bbolt.Tx, size uint64) error { b, err := tx.CreateBucketIfNotExists(metaBucketName) if err != nil { return err } buf := make([]byte, dataSizeAndItemsCountBufLength) binary.LittleEndian.PutUint64(buf, size) return b.Put(dataSizeKey, buf) } func saveItemsCount(tx *bbolt.Tx, count uint64) error { b, err := tx.CreateBucketIfNotExists(metaBucketName) if err != nil { return err } buf := make([]byte, dataSizeAndItemsCountBufLength) binary.LittleEndian.PutUint64(buf, count) return b.Put(itemsCountKey, buf) } func updateMeta(tx *bbolt.Tx, updateValues func(count, size uint64) (uint64, uint64)) error { b, err := tx.CreateBucketIfNotExists(metaBucketName) if err != nil { return err } var count uint64 var size uint64 v := b.Get(itemsCountKey) if v != nil { count = binary.LittleEndian.Uint64(v) } v = b.Get(dataSizeKey) if v != nil { size = binary.LittleEndian.Uint64(v) } count, size = updateValues(count, size) sizeBuf := make([]byte, dataSizeAndItemsCountBufLength) binary.LittleEndian.PutUint64(sizeBuf, size) if err := b.Put(dataSizeKey, sizeBuf); err != nil { return err } countBuf := make([]byte, dataSizeAndItemsCountBufLength) binary.LittleEndian.PutUint64(countBuf, count) return b.Put(itemsCountKey, countBuf) }