From 4afc5d32f06a5ce5a34452b533984c30f5818264 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Fri, 7 Feb 2014 10:46:35 -0800 Subject: [PATCH] diskpacked: don't append duplicate blobs. Change-Id: I3adce39641458a67a3cdee09bb66411dd1111acd --- pkg/blobserver/diskpacked/diskpacked.go | 11 +++++ pkg/blobserver/diskpacked/diskpacked_test.go | 48 ++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/pkg/blobserver/diskpacked/diskpacked.go b/pkg/blobserver/diskpacked/diskpacked.go index 13d5ac5c8..93776b69b 100644 --- a/pkg/blobserver/diskpacked/diskpacked.go +++ b/pkg/blobserver/diskpacked/diskpacked.go @@ -417,7 +417,18 @@ func (s *storage) ReceiveBlob(br blob.Ref, source io.Reader) (sbr blob.SizedRef, if err != nil { return } + sbr = blob.SizedRef{Ref: br, Size: n} + + // Check if it's a dup. Still accept it if the pack file on disk seems to be corrupt + // or truncated. + if m, err := s.meta(br); err == nil { + fi, err := os.Stat(s.filename(m.file)) + if err == nil && fi.Size() >= m.offset+m.size { + return sbr, nil + } + } + err = s.append(sbr, &b) return } diff --git a/pkg/blobserver/diskpacked/diskpacked_test.go b/pkg/blobserver/diskpacked/diskpacked_test.go index 21b2d6c92..7a82431ad 100644 --- a/pkg/blobserver/diskpacked/diskpacked_test.go +++ b/pkg/blobserver/diskpacked/diskpacked_test.go @@ -19,10 +19,12 @@ package diskpacked import ( "io/ioutil" "os" + "strings" "testing" "camlistore.org/pkg/blobserver" "camlistore.org/pkg/blobserver/storagetest" + "camlistore.org/pkg/test" ) func newTempDiskpacked(t *testing.T) (sto blobserver.Storage, cleanup func()) { @@ -44,3 +46,49 @@ func newTempDiskpacked(t *testing.T) (sto blobserver.Storage, cleanup func()) { func TestDiskpacked(t *testing.T) { storagetest.Test(t, newTempDiskpacked) } + +func TestDoubleReceive(t *testing.T) { + sto, cleanup := newTempDiskpacked(t) + defer cleanup() + + size := func(n int) int64 { + path := sto.(*storage).filename(n) + fi, err := os.Stat(path) + if err != nil { + t.Fatal(err) + } + return fi.Size() + } + + const blobSize = 5 << 10 + b := &test.Blob{Contents: strings.Repeat("a", blobSize)} + br := b.BlobRef() + + _, err := blobserver.Receive(sto, br, b.Reader()) + if err != nil { + t.Fatal(err) + } + if size(0) < blobSize { + t.Fatalf("size = %d; want at least %d", size(0), blobSize) + } + sto.(*storage).nextPack() + + _, err = blobserver.Receive(sto, br, b.Reader()) + if err != nil { + t.Fatal(err) + } + sizePostDup := size(1) + if sizePostDup >= blobSize { + t.Fatalf("size(pack1) = %d; appeared to double-write.", sizePostDup) + } + + os.Remove(sto.(*storage).filename(0)) + _, err = blobserver.Receive(sto, br, b.Reader()) + if err != nil { + t.Fatal(err) + } + sizePostDelete := size(1) + if sizePostDelete < blobSize { + t.Fatalf("after packfile delete + reupload, not big enough. want size of a blob") + } +}