Commit 6a203ad5 authored by Quentin Smith's avatar Quentin Smith

storage: support local disk for uploads

This adds a -data flag to localperfdata to specify a local data
directory. In combination with -dsn to specify a local database,
localperfdata is now useful for non-testing applications.

Change-Id: I32ddb7ba5a96483c1f93cb7b52bbc2643b5b3798
Reviewed-on: https://go-review.googlesource.com/37861Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 347e551a
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package local implements the fs.FS interface using local files.
// Metadata is not stored separately; the header of each file should
// contain metadata as written by storage/app.
package local
import (
"os"
"path/filepath"
"golang.org/x/net/context"
"golang.org/x/perf/storage/fs"
)
// impl is an fs.FS backed by local disk.
type impl struct {
root string
}
// NewFS constructs an FS that writes to the provided directory.
func NewFS(root string) fs.FS {
return &impl{root}
}
// NewWriter creates a file and assigns metadata as extended filesystem attributes.
func (fs *impl) NewWriter(ctx context.Context, name string, metadata map[string]string) (fs.Writer, error) {
if err := os.MkdirAll(filepath.Join(fs.root, filepath.Dir(name)), 0777); err != nil {
return nil, err
}
f, err := os.Create(filepath.Join(fs.root, name))
if err != nil {
return nil, err
}
return &wrapper{f}, nil
}
type wrapper struct {
*os.File
}
// CloseWithError closes the file and attempts to unlink it.
func (w *wrapper) CloseWithError(error) error {
w.Close()
return os.Remove(w.Name())
}
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package local
import (
"context"
"io/ioutil"
"os"
"path/filepath"
"testing"
"golang.org/x/perf/internal/diff"
)
func TestNewWriter(t *testing.T) {
ctx := context.Background()
dir, err := ioutil.TempDir("", "local_test")
if err != nil {
t.Fatalf("TempDir = %v", err)
}
defer os.RemoveAll(dir)
fs := NewFS(dir)
w, err := fs.NewWriter(ctx, "dir/file", map[string]string{"key": "value", "key2": "value2"})
if err != nil {
t.Fatalf("NewWriter = %v", err)
}
want := "hello world"
if _, err := w.Write([]byte(want)); err != nil {
t.Fatalf("Write = %v", err)
}
if err := w.Close(); err != nil {
t.Fatalf("Close = %v", err)
}
have, err := ioutil.ReadFile(filepath.Join(dir, "dir/file"))
if err != nil {
t.Fatalf("ReadFile = %v", err)
}
if d := diff.Diff(string(have), want); d != "" {
t.Errorf("file contents differ. have (-)/want (+)\n%s", d)
}
}
......@@ -19,12 +19,14 @@ import (
"golang.org/x/perf/storage/db"
_ "golang.org/x/perf/storage/db/sqlite3"
"golang.org/x/perf/storage/fs"
"golang.org/x/perf/storage/fs/local"
)
var (
addr = flag.String("addr", ":8080", "serve HTTP on `address`")
viewURLBase = flag.String("view_url_base", "", "/upload response with `URL` for viewing")
dsn = flag.String("dsn", ":memory:", "sqlite `dsn`")
data = flag.String("data", "", "data `directory` (in-memory if empty)")
baseDir = flag.String("base_dir", basedir.Find("golang.org/x/perf/storage/appengine"), "base `directory` for static files")
)
......@@ -40,7 +42,11 @@ func main() {
if err != nil {
log.Fatalf("open database: %v", err)
}
fs := fs.NewMemFS()
var fs fs.FS = fs.NewMemFS()
if *data != "" {
fs = local.NewFS(*data)
}
app := &app.App{
DB: db,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment