Save new packs in index atomically

This commit fixes a situation reported by a user where two indexes
contained information about the same pack without overlap, e.g.:

Index 3e6a32 contained:

    {
      "id": "c02e3b",
      "blobs": [
        {
          "id": "8114b1",
          "type": "data",
          "offset": 0,
          "length": 530107
        }
      ]
    }

And index 62da5f contained:

    {
      "id": "c02e3b",
      "blobs": [
        {
          "id": "e344f8",
          "type": "data",
          "offset": 1975848,
          "length": 3426468
        },
        {
          "id": "939ed9",
          "type": "data",
          "offset": 530107,
          "length": 1445741
        }
      ]
    }

This commit adds all blobs in a pack in one atomic operation so that
intermediate such as these do not happen.
This commit is contained in:
Alexander Neumann 2015-11-20 22:35:35 +01:00
parent 34bf70faea
commit 567de35df4
2 changed files with 19 additions and 2 deletions

View file

@ -109,6 +109,22 @@ func (idx *Index) Store(blob PackedBlob) {
idx.store(blob)
}
// StoreBlobs saves information about the blobs to the index in one atomic transaction.
func (idx *Index) StoreBlobs(blobs []PackedBlob) {
idx.m.Lock()
defer idx.m.Unlock()
if idx.final {
panic("store new item in finalized index")
}
debug.Log("Index.StoreBlobs", "stored %d blobs", len(blobs))
for _, blob := range blobs {
idx.store(blob)
}
}
// Lookup queries the index for the blob ID and returns a PackedBlob.
func (idx *Index) Lookup(id backend.ID) (pb PackedBlob, err error) {
idx.m.Lock()

View file

@ -268,9 +268,9 @@ func (r *Repository) savePacker(p *pack.Packer) error {
debug.Log("Repo.savePacker", "saved as %v", sid.Str())
// update blobs in the index
var packedBlobs []PackedBlob
for _, b := range p.Blobs() {
debug.Log("Repo.savePacker", " updating blob %v to pack %v", b.ID.Str(), sid.Str())
r.idx.Current().Store(PackedBlob{
packedBlobs = append(packedBlobs, PackedBlob{
Type: b.Type,
ID: b.ID,
PackID: sid,
@ -279,6 +279,7 @@ func (r *Repository) savePacker(p *pack.Packer) error {
})
r.idx.RemoveFromInFlight(b.ID)
}
r.idx.Current().StoreBlobs(packedBlobs)
return nil
}