veyron/services/mgmt/lib/fs/*: support empty simplestores

This change extends simplstore to support persisting an empty simplestore.

Change-Id: I2f36ac30e316cd868042854b7dd78f89680e5505
diff --git a/services/mgmt/lib/fs/simplestore.go b/services/mgmt/lib/fs/simplestore.go
index 9314cc0..4fdd45b 100644
--- a/services/mgmt/lib/fs/simplestore.go
+++ b/services/mgmt/lib/fs/simplestore.go
@@ -67,13 +67,22 @@
 		// The file doesn't exist. Attempt to create it instead.
 		file, cerr := os.Create(configuredPersistentFile)
 		if cerr != nil {
-			return nil, fmt.Errorf("File (%q) could neither be opened (%v) or created (%v)", configuredPersistentFile, err, cerr)
+			return nil, fmt.Errorf("File (%q) could neither be opened (%v) nor created (%v)", configuredPersistentFile, err, cerr)
 		}
 		defer file.Close()
 	} else {
 		decoder := gob.NewDecoder(file)
-		if err := decoder.Decode(&data); err != nil {
-			return nil, fmt.Errorf("Decode() failed: %v", err)
+		if err := decoder.Decode(&data); err != nil  {
+			// Two situations. One is not an error.
+			fi, err := os.Stat(configuredPersistentFile)
+			if err != nil {
+				// Someone probably deleted the file out from underneath us. Give up.
+				return nil, fmt.Errorf("Decode() failed, file went missing: %v", err)
+			}
+			if fi.Size() != 0 {
+				return nil, fmt.Errorf("Decode() failed, backing file truncated: %v", err)
+			}
+			// An empty backing file deserializes to an empty memstore.
 		}
 	}
 	return &Memstore{
diff --git a/services/mgmt/lib/fs/simplestore_test.go b/services/mgmt/lib/fs/simplestore_test.go
index 46f37c6..fc893d8 100644
--- a/services/mgmt/lib/fs/simplestore_test.go
+++ b/services/mgmt/lib/fs/simplestore_test.go
@@ -435,3 +435,22 @@
 		t.Fatalf("Remove() failed: got %v, expected %v", err, verror.Internalf("Remove() without a transactional binding"))
 	}
 }
+
+func TestOpenEmptyMemstore(t *testing.T) {
+	path := filepath.Join(os.TempDir(), "namedms")
+	defer os.Remove(path)
+
+	// Create a brand new memstore persisted to namedms. This will
+	// have the side-effect of creating an empty backing file.
+	_, err := NewMemstore(path)
+	if err != nil {
+		t.Fatalf("NewMemstore() failed: %v", err)
+	}
+
+	// Create another memstore that will attempt to deserialize the empty
+	// backing file. 
+	_, err = NewMemstore(path)
+	if err != nil {
+		t.Fatalf("NewMemstore() failed: %v", err)
+	}
+}