[ARVADOS] updated: c15f086483884fb21d04ceac0ea8bd96308051bd
git at public.curoverse.com
git at public.curoverse.com
Fri Aug 22 13:56:02 EDT 2014
Summary of changes:
services/keepstore/keepstore_test.go | 49 +++++++++++++++++++++++++++++++++-
services/keepstore/volume.go | 14 ++++++++++
services/keepstore/volume_unix.go | 13 ++++++++-
services/keepstore/volume_unix_test.go | 35 ++++++++++++++++++++++++
4 files changed, 109 insertions(+), 2 deletions(-)
via c15f086483884fb21d04ceac0ea8bd96308051bd (commit)
from e386d20665a2bf9a59e314ad9efa5fddfffb8058 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
commit c15f086483884fb21d04ceac0ea8bd96308051bd
Author: Tim Pierce <twp at curoverse.com>
Date: Fri Aug 22 13:52:33 2014 -0400
3448: unit tests, bug fixes
UnixVolume.Delete tests the return status of lockfile (oops, left out of
previous commit)
New unit/integration tests:
* TestPutTouch (volume_unix_test.go): issues a volume.Put for a block
that already exists, and confirms that the mtime of the existing block
is updated.
* TestPutBlockTouchFails (keepstore_test.go): issues PutBlock for a
block that already exists but cannot be modified, confirms that the
mtime on the old block is unchanged and that a new copy has been
stored.
Added a volume.Mtime() method to return the block mtime, to assist in
testing.
diff --git a/services/keepstore/keepstore_test.go b/services/keepstore/keepstore_test.go
index d43a00e..2b7e411 100644
--- a/services/keepstore/keepstore_test.go
+++ b/services/keepstore/keepstore_test.go
@@ -217,7 +217,7 @@ func TestPutBlockCorrupt(t *testing.T) {
}
}
-// PutBlockCollision
+// TestPutBlockCollision
// PutBlock returns a 400 Collision error when attempting to
// store a block that collides with another block on disk.
//
@@ -245,6 +245,53 @@ func TestPutBlockCollision(t *testing.T) {
}
}
+// TestPutBlockTouchFails
+// When PutBlock is asked to PUT an existing block, but cannot
+// modify the timestamp, it should write a second block.
+//
+func TestPutBlockTouchFails(t *testing.T) {
+ defer teardown()
+
+ // Prepare two test Keep volumes.
+ KeepVM = MakeTestVolumeManager(2)
+ defer func() { KeepVM.Quit() }()
+ vols := KeepVM.Volumes()
+
+ // Store a block and then make the underlying volume bad,
+ // so a subsequent attempt to update the file timestamp
+ // will fail.
+ vols[0].Put(TEST_HASH, BAD_BLOCK)
+ old_mtime, err := vols[0].Mtime(TEST_HASH)
+ if err != nil {
+ t.Fatalf("vols[0].Mtime(%s): %s\n", TEST_HASH, err)
+ }
+
+ // Mark the volume bad and call PutBlock.
+ vols[0].(*MockVolume).Bad = true
+ if err := PutBlock(TEST_BLOCK, TEST_HASH); err != nil {
+ t.Fatalf("PutBlock: %v", err)
+ }
+ vols[0].(*MockVolume).Bad = false
+
+ // Now the mtime on the block on vols[0] should be unchanged, and
+ // there should be a copy of the block on vols[1].
+ new_mtime, err := vols[0].Mtime(TEST_HASH)
+ if err != nil {
+ t.Fatalf("vols[0].Mtime(%s): %s\n", TEST_HASH, err)
+ }
+ if !new_mtime.Equal(old_mtime) {
+ t.Errorf("bad block mtimes do not match:\nold_mtime = %v\nnew_mtime = %v\n",
+ old_mtime, new_mtime)
+ }
+ result, err := vols[1].Get(TEST_HASH)
+ if err != nil {
+ t.Fatalf("vols[1]: %v", err)
+ }
+ if bytes.Compare(result, TEST_BLOCK) != 0 {
+ t.Errorf("new block does not match test block\nnew block = %v\n", result)
+ }
+}
+
// ========================================
// FindKeepVolumes tests.
// ========================================
diff --git a/services/keepstore/volume.go b/services/keepstore/volume.go
index 0406c3d..6fb1a1e 100644
--- a/services/keepstore/volume.go
+++ b/services/keepstore/volume.go
@@ -16,6 +16,7 @@ type Volume interface {
Get(loc string) ([]byte, error)
Put(loc string, block []byte) error
Touch(loc string) error
+ Mtime(loc string) (time.Time, error)
Index(prefix string) string
Delete(loc string) error
Status() *VolumeStatus
@@ -66,6 +67,19 @@ func (v *MockVolume) Touch(loc string) error {
return nil
}
+func (v *MockVolume) Mtime(loc string) (time.Time, error) {
+ var mtime time.Time
+ var err error
+ if v.Bad {
+ err = errors.New("Bad volume")
+ } else if t, ok := v.Timestamps[loc]; ok {
+ mtime = t
+ } else {
+ err = os.ErrNotExist
+ }
+ return mtime, err
+}
+
func (v *MockVolume) Index(prefix string) string {
var result string
for loc, block := range v.Store {
diff --git a/services/keepstore/volume_unix.go b/services/keepstore/volume_unix.go
index f439978..75a7522 100644
--- a/services/keepstore/volume_unix.go
+++ b/services/keepstore/volume_unix.go
@@ -112,6 +112,15 @@ func (v *UnixVolume) Touch(loc string) error {
return syscall.Utime(p, &utime)
}
+func (v *UnixVolume) Mtime(loc string) (time.Time, error) {
+ p := v.blockPath(loc)
+ if fi, err := os.Stat(p); err != nil {
+ return time.Time{}, err
+ } else {
+ return fi.ModTime(), nil
+ }
+}
+
// Read retrieves a block identified by the locator string "loc", and
// returns its contents as a byte slice.
//
@@ -250,7 +259,9 @@ func (v *UnixVolume) Delete(loc string) error {
if err != nil {
return err
}
- lockfile(f)
+ if e := lockfile(f); e != nil {
+ return e
+ }
defer unlockfile(f)
// If the block has been PUT more recently than -permission_ttl,
diff --git a/services/keepstore/volume_unix_test.go b/services/keepstore/volume_unix_test.go
index 278e656..7a1c06c 100644
--- a/services/keepstore/volume_unix_test.go
+++ b/services/keepstore/volume_unix_test.go
@@ -100,6 +100,41 @@ func TestPutBadVolume(t *testing.T) {
}
}
+// TestPutTouch
+// Test that when applying PUT to a block that already exists,
+// the block's modification time is updated.
+func TestPutTouch(t *testing.T) {
+ v := TempUnixVolume(t, false)
+ defer _teardown(v)
+
+ if err := v.Put(TEST_HASH, TEST_BLOCK); err != nil {
+ t.Error(err)
+ }
+ old_mtime, err := v.Mtime(TEST_HASH)
+ if err != nil {
+ t.Error(err)
+ }
+ if old_mtime.IsZero() {
+ t.Errorf("v.Mtime(%s) returned a zero mtime\n", TEST_HASH)
+ }
+ // Sleep for 1s, then put the block again. The volume
+ // should report a more recent mtime.
+ // TODO(twp): this would be better handled with a mock Time object.
+ time.Sleep(time.Second)
+ if err := v.Put(TEST_HASH, TEST_BLOCK); err != nil {
+ t.Error(err)
+ }
+ new_mtime, err := v.Mtime(TEST_HASH)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if !new_mtime.After(old_mtime) {
+ t.Errorf("v.Put did not update the block mtime:\nold_mtime = %v\nnew_mtime = %v\n",
+ old_mtime, new_mtime)
+ }
+}
+
// Serialization tests: launch a bunch of concurrent
//
// TODO(twp): show that the underlying Read/Write operations executed
-----------------------------------------------------------------------
hooks/post-receive
--
More information about the arvados-commits
mailing list