Example #1
0
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)
}
Example #2
0
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))
}
Example #3
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)
}
Example #4
0
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)
}
Example #5
0
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)
	}
}
Example #6
0
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)
}