diff --git a/weed/storage/needle/file_id.go b/weed/storage/needle/file_id.go index 906877b8c..5dabb0f25 100644 --- a/weed/storage/needle/file_id.go +++ b/weed/storage/needle/file_id.go @@ -2,6 +2,8 @@ package needle import ( "encoding/hex" + "fmt" + "strings" . "github.com/chrislusf/seaweedfs/weed/storage/types" ) @@ -20,6 +22,41 @@ func NewFileId(VolumeId VolumeId, key uint64, cookie uint32) *FileId { return &FileId{VolumeId: VolumeId, Key: Uint64ToNeedleId(key), Cookie: Uint32ToCookie(cookie)} } +// Deserialize the file id +func ParseFileIdFromString(fid string) (*FileId, error) { + vid, needleKeyCookie, err := splitVolumeId(fid) + if err != nil { + return nil, err + } + volumeId, err := NewVolumeId(vid) + if err != nil { + return nil, err + } + + nid, cookie, err := ParseNeedleIdCookie(needleKeyCookie) + if err != nil { + return nil, err + } + fileId := &FileId{VolumeId: volumeId, Key: nid, Cookie: cookie} + return fileId, nil +} + +func (n *FileId) GetVolumeId() VolumeId { + return n.VolumeId +} + +func (n *FileId) GetNeedleId() NeedleId { + return n.Key +} + +func (n *FileId) GetCookie() Cookie { + return n.Cookie +} + +func (n *FileId) GetNeedleIdCookie() string { + return formatNeedleIdCookie(n.Key, n.Cookie) +} + func (n *FileId) String() string { return n.VolumeId.String() + "," + formatNeedleIdCookie(n.Key, n.Cookie) } @@ -33,3 +70,12 @@ func formatNeedleIdCookie(key NeedleId, cookie Cookie) string { } return hex.EncodeToString(bytes[nonzero_index:]) } + +// copied from operation/delete_content.go, to cut off cycle dependency +func splitVolumeId(fid string) (vid string, key_cookie string, err error) { + commaIndex := strings.Index(fid, ",") + if commaIndex <= 0 { + return "", "", fmt.Errorf("wrong fid format") + } + return fid[:commaIndex], fid[commaIndex+1:], nil +} diff --git a/weed/storage/needle/file_id_test.go b/weed/storage/needle/file_id_test.go new file mode 100644 index 000000000..a1a2c61fc --- /dev/null +++ b/weed/storage/needle/file_id_test.go @@ -0,0 +1,55 @@ +package needle + +import ( + "github.com/chrislusf/seaweedfs/weed/storage/types" + "testing" +) + +func TestParseFileIdFromString(t *testing.T) { + fidStr1 := "100,12345678" + _, err := ParseFileIdFromString(fidStr1) + if err == nil { + t.Errorf("%s : KeyHash is too short", fidStr1) + } + + fidStr1 = "100, 12345678" + _, err = ParseFileIdFromString(fidStr1) + if err == nil { + t.Errorf("%s : needlId invalid syntax", fidStr1) + } + + fidStr1 = "100,123456789" + _, err = ParseFileIdFromString(fidStr1) + if err != nil { + t.Errorf("%s : should be OK", fidStr1) + } + + var fileId *FileId + fidStr1 = "100,123456789012345678901234" + fileId, err = ParseFileIdFromString(fidStr1) + if err != nil { + t.Errorf("%s : should be OK", fidStr1) + } + if !(fileId.VolumeId == VolumeId(100) && + fileId.Key == types.NeedleId(0x1234567890123456) && + fileId.Cookie == types.Cookie(types.Uint32ToCookie(uint32(0x78901234)))) { + t.Errorf("src : %s, dest : %v", fidStr1, fileId) + } + + fidStr1 = "100,abcd0000abcd" + fileId, err = ParseFileIdFromString(fidStr1) + if err != nil { + t.Errorf("%s : should be OK", fidStr1) + } + if !(fileId.VolumeId == VolumeId(100) && + fileId.Key == types.NeedleId(0xabcd) && + fileId.Cookie == types.Cookie(types.Uint32ToCookie(uint32(0xabcd)))) { + t.Errorf("src : %s, dest : %v", fidStr1, fileId) + } + + fidStr1 = "100,1234567890123456789012345" + _, err = ParseFileIdFromString(fidStr1) + if err == nil { + t.Errorf("%s : needleId is too long", fidStr1) + } +} diff --git a/weed/storage/needle/volume_id.go b/weed/storage/needle/volume_id.go index be56e42fa..3366c14bf 100644 --- a/weed/storage/needle/volume_id.go +++ b/weed/storage/needle/volume_id.go @@ -10,9 +10,9 @@ func NewVolumeId(vid string) (VolumeId, error) { volumeId, err := strconv.ParseUint(vid, 10, 64) return VolumeId(volumeId), err } -func (vid *VolumeId) String() string { - return strconv.FormatUint(uint64(*vid), 10) +func (vid VolumeId) String() string { + return strconv.FormatUint(uint64(vid), 10) } -func (vid *VolumeId) Next() VolumeId { - return VolumeId(uint32(*vid) + 1) +func (vid VolumeId) Next() VolumeId { + return VolumeId(uint32(vid) + 1) } diff --git a/weed/storage/needle/volume_id_test.go b/weed/storage/needle/volume_id_test.go new file mode 100644 index 000000000..c1c426989 --- /dev/null +++ b/weed/storage/needle/volume_id_test.go @@ -0,0 +1,45 @@ +package needle + +import "testing" + +func TestNewVolumeId(t *testing.T) { + if _,err := NewVolumeId("1"); err != nil { + t.Error(err) + } + + if _, err := NewVolumeId("a");err != nil { + t.Logf("a is not legal volume id, %v", err) + } +} + +func TestVolumeId_String(t *testing.T) { + if str := VolumeId(10).String(); str != "10" { + t.Errorf("to string failed") + } + + vid := VolumeId(11) + if str := vid.String(); str != "11" { + t.Errorf("to string failed") + } + + pvid := &vid + if str := pvid.String(); str != "11" { + t.Errorf("to string failed") + } +} + +func TestVolumeId_Next(t *testing.T) { + if vid := VolumeId(10).Next(); vid != VolumeId(11) { + t.Errorf("get next volume id failed") + } + + vid := VolumeId(11) + if new := vid.Next(); new != 12 { + t.Errorf("get next volume id failed") + } + + pvid := &vid + if new := pvid.Next(); new != 12 { + t.Errorf("get next volume id failed") + } +} \ No newline at end of file