github.com/npaton/distribution@v2.3.1-rc.0+incompatible/registry/storage/driver/azure/blockid.go (about) 1 package azure 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "math/rand" 7 "sync" 8 "time" 9 10 azure "github.com/Azure/azure-sdk-for-go/storage" 11 ) 12 13 type blockIDGenerator struct { 14 pool map[string]bool 15 r *rand.Rand 16 m sync.Mutex 17 } 18 19 // Generate returns an unused random block id and adds the generated ID 20 // to list of used IDs so that the same block name is not used again. 21 func (b *blockIDGenerator) Generate() string { 22 b.m.Lock() 23 defer b.m.Unlock() 24 25 var id string 26 for { 27 id = toBlockID(int(b.r.Int())) 28 if !b.exists(id) { 29 break 30 } 31 } 32 b.pool[id] = true 33 return id 34 } 35 36 func (b *blockIDGenerator) exists(id string) bool { 37 _, used := b.pool[id] 38 return used 39 } 40 41 func (b *blockIDGenerator) Feed(blocks azure.BlockListResponse) { 42 b.m.Lock() 43 defer b.m.Unlock() 44 45 for _, bl := range append(blocks.CommittedBlocks, blocks.UncommittedBlocks...) { 46 b.pool[bl.Name] = true 47 } 48 } 49 50 func newBlockIDGenerator() *blockIDGenerator { 51 return &blockIDGenerator{ 52 pool: make(map[string]bool), 53 r: rand.New(rand.NewSource(time.Now().UnixNano()))} 54 } 55 56 // toBlockId converts given integer to base64-encoded block ID of a fixed length. 57 func toBlockID(i int) string { 58 s := fmt.Sprintf("%029d", i) // add zero padding for same length-blobs 59 return base64.StdEncoding.EncodeToString([]byte(s)) 60 }