2015-02-04 00:29:00 +01:00
|
|
|
package azure
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/base64"
|
|
|
|
"fmt"
|
|
|
|
"math/rand"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2015-06-12 00:30:18 +02:00
|
|
|
azure "github.com/Azure/azure-sdk-for-go/storage"
|
2015-02-04 00:29:00 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
type blockIDGenerator struct {
|
|
|
|
pool map[string]bool
|
|
|
|
r *rand.Rand
|
|
|
|
m sync.Mutex
|
|
|
|
}
|
|
|
|
|
|
|
|
// Generate returns an unused random block id and adds the generated ID
|
|
|
|
// to list of used IDs so that the same block name is not used again.
|
|
|
|
func (b *blockIDGenerator) Generate() string {
|
|
|
|
b.m.Lock()
|
|
|
|
defer b.m.Unlock()
|
|
|
|
|
|
|
|
var id string
|
|
|
|
for {
|
|
|
|
id = toBlockID(int(b.r.Int()))
|
|
|
|
if !b.exists(id) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
b.pool[id] = true
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *blockIDGenerator) exists(id string) bool {
|
|
|
|
_, used := b.pool[id]
|
|
|
|
return used
|
|
|
|
}
|
|
|
|
|
|
|
|
func (b *blockIDGenerator) Feed(blocks azure.BlockListResponse) {
|
|
|
|
b.m.Lock()
|
|
|
|
defer b.m.Unlock()
|
|
|
|
|
|
|
|
for _, bl := range append(blocks.CommittedBlocks, blocks.UncommittedBlocks...) {
|
|
|
|
b.pool[bl.Name] = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func newBlockIDGenerator() *blockIDGenerator {
|
|
|
|
return &blockIDGenerator{
|
|
|
|
pool: make(map[string]bool),
|
|
|
|
r: rand.New(rand.NewSource(time.Now().UnixNano()))}
|
|
|
|
}
|
|
|
|
|
|
|
|
// toBlockId converts given integer to base64-encoded block ID of a fixed length.
|
|
|
|
func toBlockID(i int) string {
|
|
|
|
s := fmt.Sprintf("%029d", i) // add zero padding for same length-blobs
|
|
|
|
return base64.StdEncoding.EncodeToString([]byte(s))
|
|
|
|
}
|