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  }