aboutsummaryrefslogtreecommitdiff
path: root/weed/operation/lookup.go
diff options
context:
space:
mode:
Diffstat (limited to 'weed/operation/lookup.go')
-rw-r--r--weed/operation/lookup.go118
1 files changed, 118 insertions, 0 deletions
diff --git a/weed/operation/lookup.go b/weed/operation/lookup.go
new file mode 100644
index 000000000..19d9dbb94
--- /dev/null
+++ b/weed/operation/lookup.go
@@ -0,0 +1,118 @@
+package operation
+
+import (
+ "encoding/json"
+ "errors"
+ "fmt"
+ "math/rand"
+ "net/url"
+ "strings"
+ "time"
+
+ "github.com/chrislusf/seaweedfs/weed/util"
+)
+
+type Location struct {
+ Url string `json:"url,omitempty"`
+ PublicUrl string `json:"publicUrl,omitempty"`
+}
+type LookupResult struct {
+ VolumeId string `json:"volumeId,omitempty"`
+ Locations []Location `json:"locations,omitempty"`
+ Error string `json:"error,omitempty"`
+}
+
+func (lr *LookupResult) String() string {
+ return fmt.Sprintf("VolumeId:%s, Locations:%v, Error:%s", lr.VolumeId, lr.Locations, lr.Error)
+}
+
+var (
+ vc VidCache // caching of volume locations, re-check if after 10 minutes
+)
+
+func Lookup(server string, vid string) (ret *LookupResult, err error) {
+ locations, cache_err := vc.Get(vid)
+ if cache_err != nil {
+ if ret, err = do_lookup(server, vid); err == nil {
+ vc.Set(vid, ret.Locations, 10*time.Minute)
+ }
+ } else {
+ ret = &LookupResult{VolumeId: vid, Locations: locations}
+ }
+ return
+}
+
+func do_lookup(server string, vid string) (*LookupResult, error) {
+ values := make(url.Values)
+ values.Add("volumeId", vid)
+ jsonBlob, err := util.Post("http://"+server+"/dir/lookup", values)
+ if err != nil {
+ return nil, err
+ }
+ var ret LookupResult
+ err = json.Unmarshal(jsonBlob, &ret)
+ if err != nil {
+ return nil, err
+ }
+ if ret.Error != "" {
+ return nil, errors.New(ret.Error)
+ }
+ return &ret, nil
+}
+
+func LookupFileId(server string, fileId string) (fullUrl string, err error) {
+ parts := strings.Split(fileId, ",")
+ if len(parts) != 2 {
+ return "", errors.New("Invalid fileId " + fileId)
+ }
+ lookup, lookupError := Lookup(server, parts[0])
+ if lookupError != nil {
+ return "", lookupError
+ }
+ if len(lookup.Locations) == 0 {
+ return "", errors.New("File Not Found")
+ }
+ return "http://" + lookup.Locations[rand.Intn(len(lookup.Locations))].Url + "/" + fileId, nil
+}
+
+// LookupVolumeIds find volume locations by cache and actual lookup
+func LookupVolumeIds(server string, vids []string) (map[string]LookupResult, error) {
+ ret := make(map[string]LookupResult)
+ var unknown_vids []string
+
+ //check vid cache first
+ for _, vid := range vids {
+ locations, cache_err := vc.Get(vid)
+ if cache_err == nil {
+ ret[vid] = LookupResult{VolumeId: vid, Locations: locations}
+ } else {
+ unknown_vids = append(unknown_vids, vid)
+ }
+ }
+ //return success if all volume ids are known
+ if len(unknown_vids) == 0 {
+ return ret, nil
+ }
+
+ //only query unknown_vids
+ values := make(url.Values)
+ for _, vid := range unknown_vids {
+ values.Add("volumeId", vid)
+ }
+ jsonBlob, err := util.Post("http://"+server+"/vol/lookup", values)
+ if err != nil {
+ return nil, err
+ }
+ err = json.Unmarshal(jsonBlob, &ret)
+ if err != nil {
+ return nil, errors.New(err.Error() + " " + string(jsonBlob))
+ }
+
+ //set newly checked vids to cache
+ for _, vid := range unknown_vids {
+ locations := ret[vid].Locations
+ vc.Set(vid, locations, 10*time.Minute)
+ }
+
+ return ret, nil
+}