From c7b155c06452315396ec98f42cf5b502be38b221 Mon Sep 17 00:00:00 2001 From: Tim Pierce Date: Wed, 9 Apr 2014 18:03:19 -0400 Subject: [PATCH] Added /index handlers. (refs #2561) --- services/keep/keep.go | 63 ++++++++++++++++++++++++++++++++++++-- services/keep/keep_test.go | 36 ++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/services/keep/keep.go b/services/keep/keep.go index 5083e690a1..adffaa477c 100644 --- a/services/keep/keep.go +++ b/services/keep/keep.go @@ -11,6 +11,7 @@ import ( "net/http" "os" "os/exec" + "path/filepath" "strconv" "strings" "time" @@ -64,8 +65,10 @@ func main() { // appropriate handler. // rest := mux.NewRouter() - rest.HandleFunc("/{hash:[0-9a-f]{32}}", GetBlockHandler).Methods("GET") - rest.HandleFunc("/{hash:[0-9a-f]{32}}", PutBlockHandler).Methods("PUT") + rest.HandleFunc(`/{hash:[0-9a-f]{32}}`, GetBlockHandler).Methods("GET", "HEAD") + rest.HandleFunc(`/{hash:[0-9a-f]{32}}`, PutBlockHandler).Methods("PUT") + rest.HandleFunc(`/index`, IndexHandler).Methods("GET", "HEAD") + rest.HandleFunc(`/index/{prefix:[0-9a-f]{0,32}}`, IndexHandler).Methods("GET", "HEAD") // Tell the built-in HTTP server to direct all requests to the REST // router. @@ -144,6 +147,62 @@ func PutBlockHandler(w http.ResponseWriter, req *http.Request) { } } +func IndexHandler(w http.ResponseWriter, req *http.Request) { + prefix := mux.Vars(req)["prefix"] + + index := IndexLocators(prefix) + w.Write([]byte(index)) +} + +// IndexLocators +// Returns a string containing a list of locator ids found on this +// Keep server. If {prefix} is given, return only those locator +// ids that begin with the given prefix string. +// +// The return string consists of a sequence of newline-separated +// strings in the format +// +// locator+size modification-time +// +// e.g.: +// +// e4df392f86be161ca6ed3773a962b8f3+67108864 1388894303 +// e4d41e6fd68460e0e3fc18cc746959d2+67108864 1377796043 +// e4de7a2810f5554cd39b36d8ddb132ff+67108864 1388701136 +// +func IndexLocators(prefix string) string { + var output string + for _, vol := range KeepVolumes { + filepath.Walk(vol, + func(path string, info os.FileInfo, err error) error { + // This WalkFunc inspects each path in the volume + // and prints an index line for all files that begin + // with prefix. + if err != nil { + log.Printf("IndexHandler: %s: walking to %s: %s", + vol, path, err) + return nil + } + locator := filepath.Base(path) + // Skip directories that do not match prefix. + // We know there is nothing interesting inside. + if info.IsDir() && + !strings.HasPrefix(locator, prefix) && + !strings.HasPrefix(prefix, locator) { + return filepath.SkipDir + } + // Print filenames beginning with prefix + if !info.IsDir() && strings.HasPrefix(locator, prefix) { + output = output + fmt.Sprintf( + "%s+%d %d\n", locator, info.Size(), info.ModTime().Unix()) + } + return nil + }) + } + + return output +} + func GetBlock(hash string) ([]byte, error) { var buf = make([]byte, BLOCKSIZE) diff --git a/services/keep/keep_test.go b/services/keep/keep_test.go index cb5e89cfb9..2aa8aff77c 100644 --- a/services/keep/keep_test.go +++ b/services/keep/keep_test.go @@ -5,11 +5,21 @@ import ( "io/ioutil" "os" "path" + "regexp" "testing" ) var TEST_BLOCK = []byte("The quick brown fox jumps over the lazy dog.") var TEST_HASH = "e4d909c290d0fb1ca068ffaddf22cbd0" + +var TEST_BLOCK_2 = []byte("Pack my box with five dozen liquor jugs.") +var TEST_HASH_2 = "f15ac516f788aec4f30932ffb6395c39" + +var TEST_BLOCK_3 = []byte("Now is the time for all good men to come to the aid of their country.") +var TEST_HASH_3 = "eed29bbffbc2dbe5e5ee0bb71888e61f" + +// BAD_BLOCK is used to test collisions and corruption. +// It must not match any test hashes. var BAD_BLOCK = []byte("The magic words are squeamish ossifrage.") // ======================================== @@ -244,6 +254,32 @@ func TestFindKeepVolumesFail(t *testing.T) { } } +// TestIndex +// Test an /index request. +func TestIndex(t *testing.T) { + defer teardown() + + // Set up Keep volumes and populate them. + KeepVolumes = setup(t, 2) + store(t, KeepVolumes[0], TEST_HASH, TEST_BLOCK) + store(t, KeepVolumes[1], TEST_HASH_2, TEST_BLOCK_2) + store(t, KeepVolumes[0], TEST_HASH_3, TEST_BLOCK_3) + + index := IndexLocators("") + expected := `^` + TEST_HASH + `\+\d+ \d+\n` + + TEST_HASH_3 + `\+\d+ \d+\n` + + TEST_HASH_2 + `\+\d+ \d+\n$` + + match, err := regexp.MatchString(expected, index) + if err == nil { + if !match { + t.Errorf("IndexLocators returned:\n-----\n%s-----\n", index) + } + } else { + t.Errorf("regexp.MatchString: %s", err) + } +} + // ======================================== // Helper functions for unit tests. // ======================================== -- 2.30.2