github.com/nutsdb/nutsdb@v1.0.4/bucket_manager.go (about) 1 package nutsdb 2 3 import ( 4 "errors" 5 "os" 6 ) 7 8 var ErrBucketNotExist = errors.New("bucket not exist") 9 10 const BucketStoreFileName = "bucket.Meta" 11 12 type Ds = uint16 13 type BucketId = uint64 14 type BucketName = string 15 type IDMarkerInBucket map[BucketName]map[Ds]BucketId 16 type InfoMapperInBucket map[BucketId]*Bucket 17 18 type BucketManager struct { 19 fd *os.File 20 // BucketInfoMapper BucketID => Bucket itself 21 BucketInfoMapper InfoMapperInBucket 22 23 BucketIDMarker IDMarkerInBucket 24 25 // IDGenerator helps generates an ID for every single bucket 26 Gen *IDGenerator 27 } 28 29 func NewBucketManager(dir string) (*BucketManager, error) { 30 bm := &BucketManager{ 31 BucketInfoMapper: map[BucketId]*Bucket{}, 32 BucketIDMarker: map[BucketName]map[Ds]BucketId{}, 33 } 34 bucketFilePath := dir + "/" + BucketStoreFileName 35 _, err := os.Stat(bucketFilePath) 36 mode := os.O_RDWR 37 if err != nil { 38 mode |= os.O_CREATE 39 } 40 fd, err := os.OpenFile(bucketFilePath, mode, os.ModePerm) 41 if err != nil { 42 return nil, err 43 } 44 bm.fd = fd 45 bm.Gen = &IDGenerator{currentMaxId: 0} 46 return bm, nil 47 } 48 49 type bucketSubmitRequest struct { 50 ds Ds 51 name BucketName 52 bucket *Bucket 53 } 54 55 func (bm *BucketManager) SubmitPendingBucketChange(reqs []*bucketSubmitRequest) error { 56 bytes := make([]byte, 0) 57 for _, req := range reqs { 58 bs := req.bucket.Encode() 59 bytes = append(bytes, bs...) 60 // update the marker info 61 if _, exist := bm.BucketIDMarker[req.name]; !exist { 62 bm.BucketIDMarker[req.name] = map[Ds]BucketId{} 63 } 64 switch req.bucket.Meta.Op { 65 case BucketInsertOperation: 66 bm.BucketInfoMapper[req.bucket.Id] = req.bucket 67 bm.BucketIDMarker[req.name][req.bucket.Ds] = req.bucket.Id 68 case BucketDeleteOperation: 69 if len(bm.BucketIDMarker[req.name]) == 1 { 70 delete(bm.BucketIDMarker, req.name) 71 } else { 72 delete(bm.BucketIDMarker[req.name], req.bucket.Ds) 73 } 74 delete(bm.BucketInfoMapper, req.bucket.Id) 75 } 76 } 77 _, err := bm.fd.Write(bytes) 78 return err 79 } 80 81 type IDGenerator struct { 82 currentMaxId uint64 83 } 84 85 func (g *IDGenerator) GenId() uint64 { 86 g.currentMaxId++ 87 return g.currentMaxId 88 } 89 90 func (bm *BucketManager) ExistBucket(ds Ds, name BucketName) bool { 91 bucket, err := bm.GetBucket(ds, name) 92 if bucket != nil && err == nil { 93 return true 94 } 95 return false 96 } 97 98 func (bm *BucketManager) GetBucket(ds Ds, name BucketName) (b *Bucket, err error) { 99 ds2IdMapper := bm.BucketIDMarker[name] 100 if ds2IdMapper == nil { 101 return nil, ErrBucketNotExist 102 } 103 104 if id, exist := ds2IdMapper[ds]; exist { 105 if bucket, ok := bm.BucketInfoMapper[id]; ok { 106 return bucket, nil 107 } else { 108 return nil, ErrBucketNotExist 109 } 110 } else { 111 return nil, ErrBucketNotExist 112 } 113 } 114 115 func (bm *BucketManager) GetBucketById(id BucketId) (*Bucket, error) { 116 if bucket, exist := bm.BucketInfoMapper[id]; exist { 117 return bucket, nil 118 } else { 119 return nil, ErrBucketNotExist 120 } 121 } 122 123 func (bm *BucketManager) GetBucketID(ds Ds, name BucketName) (BucketId, error) { 124 if bucket, err := bm.GetBucket(ds, name); err != nil { 125 return 0, err 126 } else { 127 return bucket.Id, nil 128 } 129 }