github.com/weaviate/weaviate@v1.24.6/adapters/repos/db/indexcounter/counter.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package indexcounter 13 14 import ( 15 "encoding/binary" 16 "fmt" 17 "os" 18 "sync" 19 20 "github.com/pkg/errors" 21 ) 22 23 type Counter struct { 24 count uint64 25 sync.Mutex 26 f *os.File 27 } 28 29 func New(shardPath string) (*Counter, error) { 30 fileName := fmt.Sprintf("%s/indexcount", shardPath) 31 f, err := os.OpenFile(fileName, os.O_RDWR|os.O_CREATE, 0o666) 32 if err != nil { 33 return nil, err 34 } 35 36 stat, err := f.Stat() 37 if err != nil { 38 return nil, err 39 } 40 41 var initialCount uint64 = 0 42 if stat.Size() > 0 { 43 // the file has existed before, we need to initialize with its content 44 err := binary.Read(f, binary.LittleEndian, &initialCount) 45 if err != nil { 46 return nil, errors.Wrap(err, "read initial count from file") 47 } 48 49 } 50 51 return &Counter{ 52 count: initialCount, 53 f: f, 54 }, nil 55 } 56 57 func (c *Counter) Get() uint64 { 58 c.Lock() 59 defer c.Unlock() 60 return c.count 61 } 62 63 func (c *Counter) GetAndInc() (uint64, error) { 64 c.Lock() 65 defer c.Unlock() 66 before := c.count 67 c.count++ 68 c.f.Seek(0, 0) 69 err := binary.Write(c.f, binary.LittleEndian, &c.count) 70 if err != nil { 71 return 0, errors.Wrap(err, "increase counter on disk") 72 } 73 c.f.Seek(0, 0) 74 return before, nil 75 } 76 77 // PreviewNext can be used to check if there is data present in the index, if 78 // it returns 0, you can be certain that no data exists 79 func (c *Counter) PreviewNext() uint64 { 80 c.Lock() 81 defer c.Unlock() 82 83 return c.count 84 } 85 86 func (c *Counter) Drop() error { 87 c.Lock() 88 defer c.Unlock() 89 if c.f == nil { 90 return nil 91 } 92 filename := c.FileName() 93 c.f.Close() 94 err := os.Remove(filename) 95 if err != nil { 96 return errors.Wrap(err, "drop counter file") 97 } 98 return nil 99 } 100 101 func (c *Counter) FileName() string { 102 return c.f.Name() 103 }