server: make app.DeleteNoSQLDatabase actually delete the data

Change-Id: If7b09df7932b29c2ebe41ff676a3d12043e356d7
diff --git a/v23/syncbase/testutil/util.go b/v23/syncbase/testutil/util.go
index 3fa8f49..405bbf5 100644
--- a/v23/syncbase/testutil/util.go
+++ b/v23/syncbase/testutil/util.go
@@ -158,9 +158,7 @@
 	service, err := server.NewService(nil, nil, server.ServiceOptions{
 		Perms:   perms,
 		RootDir: rootDir,
-		// TODO(sadovsky): Switch to leveldb once Database.Delete actually deletes
-		// the underlying storage engine data (or similar).
-		Engine: "memstore",
+		Engine:  "leveldb",
 	})
 	if err != nil {
 		vlog.Fatal("server.NewService() failed: ", err)
diff --git a/x/ref/services/syncbase/server/app.go b/x/ref/services/syncbase/server/app.go
index 1e1fe1e..f16f657 100644
--- a/x/ref/services/syncbase/server/app.go
+++ b/x/ref/services/syncbase/server/app.go
@@ -154,7 +154,7 @@
 	}
 	d, err := nosql.NewDatabase(ctx, call, a, dbName, nosql.DatabaseOptions{
 		Perms:   perms,
-		RootDir: path.Join(a.s.opts.RootDir, "apps", a.name, dbName),
+		RootDir: a.rootDirForDB(dbName),
 		Engine:  a.s.opts.Engine,
 	})
 	if err != nil {
@@ -211,7 +211,12 @@
 	}
 
 	// 3. Delete database.
-	// TODO(sadovsky): Actually delete the database.
+	if err := d.St().Close(); err != nil {
+		return err
+	}
+	if err := util.DestroyStore(a.s.opts.Engine, a.rootDirForDB(dbName)); err != nil {
+		return err
+	}
 
 	// 4. Delete dbInfo record.
 	if err := a.delDbInfo(ctx, call, a.s.st, dbName); err != nil {
@@ -249,3 +254,7 @@
 func (a *app) stKeyPart() string {
 	return a.name
 }
+
+func (a *app) rootDirForDB(dbName string) string {
+	return path.Join(a.s.opts.RootDir, "apps", a.name, dbName)
+}
diff --git a/x/ref/services/syncbase/server/util/store_util.go b/x/ref/services/syncbase/server/util/store_util.go
index ebee090..a495ebd 100644
--- a/x/ref/services/syncbase/server/util/store_util.go
+++ b/x/ref/services/syncbase/server/util/store_util.go
@@ -138,3 +138,18 @@
 		return nil, verror.New(verror.ErrBadArg, nil, engine)
 	}
 }
+
+func DestroyStore(engine, path string) error {
+	switch engine {
+	case "memstore":
+		// memstore doesn't persist any data on the disc, do nothing.
+		return nil
+	case "leveldb":
+		if err := os.RemoveAll(path); err != nil {
+			return verror.New(verror.ErrInternal, nil, err)
+		}
+		return nil
+	default:
+		return verror.New(verror.ErrBadArg, nil, engine)
+	}
+}