aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go/storage/needle.go29
-rw-r--r--go/storage/needle_test.go45
2 files changed, 63 insertions, 11 deletions
diff --git a/go/storage/needle.go b/go/storage/needle.go
index e49368820..66cf5b22a 100644
--- a/go/storage/needle.go
+++ b/go/storage/needle.go
@@ -1,7 +1,6 @@
package storage
import (
- "encoding/hex"
"errors"
"fmt"
"io/ioutil"
@@ -15,7 +14,6 @@ import (
"github.com/chrislusf/seaweedfs/go/glog"
"github.com/chrislusf/seaweedfs/go/images"
"github.com/chrislusf/seaweedfs/go/operation"
- "github.com/chrislusf/seaweedfs/go/util"
)
const (
@@ -213,16 +211,25 @@ func (n *Needle) ParsePath(fid string) (err error) {
}
func ParseKeyHash(key_hash_string string) (uint64, uint32, error) {
- if len(key_hash_string)%2 == 1 {
- key_hash_string = "0" + key_hash_string
- }
- key_hash_bytes, khe := hex.DecodeString(key_hash_string)
- key_hash_len := len(key_hash_bytes)
- if khe != nil || key_hash_len <= 4 {
- glog.V(0).Infoln("Invalid key_hash", key_hash_string, "length:", key_hash_len, "error", khe)
+ key, hash, ok := parseKeyHash(key_hash_string)
+ if !ok {
return 0, 0, errors.New("Invalid key and hash:" + key_hash_string)
}
- key := util.BytesToUint64(key_hash_bytes[0 : key_hash_len-4])
- hash := util.BytesToUint32(key_hash_bytes[key_hash_len-4 : key_hash_len])
return key, hash, nil
}
+
+func parseKeyHash(keyhash string) (uint64, uint32, bool) {
+ if len(keyhash) <= 8 || len(keyhash) > 24 {
+ return 0, 0, false
+ }
+ split := len(keyhash) - 8
+ key, err := strconv.ParseUint(keyhash[:split], 16, 64)
+ if err != nil {
+ return 0, 0, false
+ }
+ hash, err := strconv.ParseUint(keyhash[split:], 16, 32)
+ if err != nil {
+ return 0, 0, false
+ }
+ return key, uint32(hash), true
+}
diff --git a/go/storage/needle_test.go b/go/storage/needle_test.go
new file mode 100644
index 000000000..c05afda2f
--- /dev/null
+++ b/go/storage/needle_test.go
@@ -0,0 +1,45 @@
+package storage
+
+import "testing"
+
+func TestParseKeyHash(t *testing.T) {
+ testcases := []struct {
+ KeyHash string
+ ID uint64
+ Cookie uint32
+ Err bool
+ }{
+ // normal
+ {"4ed4c8116e41", 0x4ed4, 0xc8116e41, false},
+ // cookie with leading zeros
+ {"4ed401116e41", 0x4ed4, 0x01116e41, false},
+ // odd length
+ {"ed400116e41", 0xed4, 0x00116e41, false},
+ // uint
+ {"fed4c8114ed4c811f0116e41", 0xfed4c8114ed4c811, 0xf0116e41, false},
+ // err: too short
+ {"4ed4c811", 0, 0, true},
+ // err: too long
+ {"4ed4c8114ed4c8114ed4c8111", 0, 0, true},
+ // err: invalid character
+ {"helloworld", 0, 0, true},
+ }
+
+ for _, tc := range testcases {
+ if id, cookie, err := ParseKeyHash(tc.KeyHash); err != nil && !tc.Err {
+ t.Fatalf("Parse %s error: %v", tc.KeyHash, err)
+ } else if err == nil && tc.Err {
+ t.Fatalf("Parse %s expected error got nil", tc.KeyHash)
+ } else if id != tc.ID || cookie != tc.Cookie {
+ t.Fatalf("Parse %s wrong result. Expected: (%d, %d) got: (%d, %d)", tc.KeyHash, tc.ID, tc.Cookie, id, cookie)
+ }
+ }
+}
+
+func BenchmarkParseKeyHash(b *testing.B) {
+ b.ReportAllocs()
+
+ for i := 0; i < b.N; i++ {
+ ParseKeyHash("4ed44ed44ed44ed4c8116e41")
+ }
+}