func (s *storeSuite) TestConcurrentCreateRemove(c *gc.C) { data := []byte(`some file data`) hash := hashOf(data) var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() session := s.Session.Clone() defer session.Close() store := blobstore.New(session.DB("a-database"), "prefix") for i := 0; i < 100; i++ { exists, err := store.Create(hash, bytes.NewReader(data)) c.Check(err, gc.IsNil) c.Logf("exists %v", exists) err = store.Remove(hash) c.Check(err, gc.IsNil) } }() } wg.Wait() store := blobstore.New(s.Session.DB("a-database"), "prefix") // All references should have been removed, and the blob with it. f, err := store.Open(hash) c.Assert(err, gc.Equals, mgo.ErrNotFound) c.Assert(f, gc.IsNil) }
func (s *storeSuite) TestCreateOpenCheck(c *gc.C) { store := blobstore.New(s.Session.DB("a-database"), "prefix") data := []byte(`some file data`) hash := hashOf(data) exists, err := store.Create(hash, bytes.NewReader(data)) c.Assert(err, gc.IsNil) c.Assert(exists, gc.Equals, false) f, err := store.Open(hash) c.Assert(err, gc.IsNil) defer f.Close() gotData, err := ioutil.ReadAll(f) c.Assert(err, gc.IsNil) c.Assert(gotData, gc.DeepEquals, data) ok, size, err := store.Check(hash) c.Assert(err, gc.IsNil) c.Assert(ok, gc.Equals, true) c.Assert(size, gc.Equals, int64(len(data))) ok, size, err = store.Check(hashOf([]byte("foo"))) c.Assert(err, gc.IsNil) c.Assert(ok, gc.Equals, false) c.Assert(size, gc.Equals, int64(0)) }
func (s *storeSuite) TestCreateRemove(c *gc.C) { store := blobstore.New(s.Session.DB("a-database"), "prefix") data := []byte(`some file data`) hash := hashOf(data) exists, err := store.Create(hash, bytes.NewReader(data)) c.Assert(err, gc.IsNil) c.Assert(exists, gc.Equals, false) r := bytes.NewReader(data) exists, err = store.Create(hash, bytes.NewReader(data)) c.Assert(err, gc.IsNil) c.Assert(exists, gc.Equals, true) // Check that no bytes have been read. n, _ := r.Read(make([]byte, len(data))) c.Assert(n, gc.Equals, len(data)) err = store.Remove(hash) c.Assert(err, gc.IsNil) // The blob should still exist because there's still a reference to it. assertBlob(c, store, hash) err = store.Remove(hash) c.Assert(err, gc.IsNil) // The last reference has been removed, and the blob with it. f, err := store.Open(hash) c.Assert(err, gc.Equals, mgo.ErrNotFound) c.Assert(f, gc.IsNil) }
func (s *storeSuite) TestInvalidHash(c *gc.C) { store := blobstore.New(s.Session.DB("a-database"), "prefix") data := []byte(`some file data`) hash := hashOf([]byte("foo")) exists, err := store.Create(hash, bytes.NewReader(data)) c.Assert(err, gc.ErrorMatches, "file checksum mismatch") c.Assert(exists, gc.Equals, false) f, err := store.Open(hash) c.Assert(err, gc.Equals, mgo.ErrNotFound) c.Assert(f, gc.IsNil) }
func (s *benchmarkSuite) BenchmarkCreate(c *gc.C) { db := s.Session.DB("a-database") store := blobstore.New(db, "prefix") const fileSize = 30 * 1024 hasher := sha256.New() c.ResetTimer() for i := 0; i < c.N; i++ { hasher.Reset() src := newDataSource(int64(i), fileSize) io.Copy(hasher, src) hash := hex(hasher.Sum(nil)) exists, err := store.Create(hash, newDataSource(int64(i), fileSize)) c.Assert(err, gc.IsNil) c.Assert(exists, gc.Equals, false) } }
func (s *storeSuite) TestSimultaneousUploads(c *gc.C) { store := blobstore.New(s.Session.DB("a-database"), "prefix") const size = 10 * 1024 * 1024 hasher := sha256.New() io.Copy(hasher, newDataSource(0, size)) hash := hex(hasher.Sum(nil)) src1 := newDataSource(0, size) src2 := newDataSource(0, size) resume := make(chan chan struct{}) src1 = newDelayedEOFReader(src1, resume) src2 = newDelayedEOFReader(src2, resume) done1 := make(chan error) go func() { exists, err := store.Create(hash, src1) c.Check(exists, gc.Equals, false) done1 <- err }() done2 := make(chan error) go func() { exists, err := store.Create(hash, src2) c.Check(exists, gc.Equals, false) done2 <- err }() // Wait for all data to be read from both. reply1 := <-resume reply2 := <-resume // Race to finish. close(reply1) close(reply2) // Wait for the Creates to succeed err1 := <-done1 err2 := <-done2 c.Assert(err1, gc.IsNil) c.Assert(err2, gc.IsNil) assertBlob(c, store, hash) }