You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

152 lines
3.3 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
6 years ago
  1. package wdclient
  2. import (
  3. "errors"
  4. "fmt"
  5. "math"
  6. "strconv"
  7. "strings"
  8. "sync"
  9. "sync/atomic"
  10. "github.com/chrislusf/seaweedfs/weed/glog"
  11. )
  12. type Location struct {
  13. Url string `json:"url,omitempty"`
  14. PublicUrl string `json:"publicUrl,omitempty"`
  15. }
  16. type vidMap struct {
  17. sync.RWMutex
  18. vid2Locations map[uint32][]Location
  19. cursor int64
  20. }
  21. func newVidMap() vidMap {
  22. return vidMap{
  23. vid2Locations: make(map[uint32][]Location),
  24. cursor: -1,
  25. }
  26. }
  27. func (vc *vidMap) getLocationIndex(length int64) (int64, error) {
  28. if length <= 0 {
  29. return 0, fmt.Errorf("invalid length: %d", length)
  30. }
  31. if atomic.LoadInt64(&vc.cursor) == math.MaxInt64 {
  32. atomic.CompareAndSwapInt64(&vc.cursor, math.MaxInt64, -1)
  33. }
  34. return atomic.AddInt64(&vc.cursor, 1) % length, nil
  35. }
  36. func (vc *vidMap) LookupVolumeServerUrl(vid string) (serverUrl string, err error) {
  37. id, err := strconv.Atoi(vid)
  38. if err != nil {
  39. glog.V(1).Infof("Unknown volume id %s", vid)
  40. return "", err
  41. }
  42. return vc.GetRandomLocation(uint32(id))
  43. }
  44. func (vc *vidMap) LookupFileId(fileId string) (fullUrl string, err error) {
  45. parts := strings.Split(fileId, ",")
  46. if len(parts) != 2 {
  47. return "", errors.New("Invalid fileId " + fileId)
  48. }
  49. serverUrl, lookupError := vc.LookupVolumeServerUrl(parts[0])
  50. if lookupError != nil {
  51. return "", lookupError
  52. }
  53. return "http://" + serverUrl + "/" + fileId, nil
  54. }
  55. func (vc *vidMap) LookupVolumeServer(fileId string) (volumeServer string, err error) {
  56. parts := strings.Split(fileId, ",")
  57. if len(parts) != 2 {
  58. return "", errors.New("Invalid fileId " + fileId)
  59. }
  60. serverUrl, lookupError := vc.LookupVolumeServerUrl(parts[0])
  61. if lookupError != nil {
  62. return "", lookupError
  63. }
  64. return serverUrl, nil
  65. }
  66. func (vc *vidMap) GetVidLocations(vid string) (locations []Location, err error) {
  67. id, err := strconv.Atoi(vid)
  68. if err != nil {
  69. glog.V(1).Infof("Unknown volume id %s", vid)
  70. return nil, fmt.Errorf("Unknown volume id %s", vid)
  71. }
  72. foundLocations, found := vc.GetLocations(uint32(id))
  73. if found {
  74. return foundLocations, nil
  75. }
  76. return nil, fmt.Errorf("volume id %s not found", vid)
  77. }
  78. func (vc *vidMap) GetLocations(vid uint32) (locations []Location, found bool) {
  79. vc.RLock()
  80. defer vc.RUnlock()
  81. locations, found = vc.vid2Locations[vid]
  82. return
  83. }
  84. func (vc *vidMap) GetRandomLocation(vid uint32) (serverUrl string, err error) {
  85. vc.RLock()
  86. defer vc.RUnlock()
  87. locations := vc.vid2Locations[vid]
  88. if len(locations) == 0 {
  89. return "", fmt.Errorf("volume %d not found", vid)
  90. }
  91. index, err := vc.getLocationIndex(int64(len(locations)))
  92. if err != nil {
  93. return "", fmt.Errorf("volume %d. %v", vid, err)
  94. }
  95. return locations[index].Url, nil
  96. }
  97. func (vc *vidMap) addLocation(vid uint32, location Location) {
  98. vc.Lock()
  99. defer vc.Unlock()
  100. locations, found := vc.vid2Locations[vid]
  101. if !found {
  102. vc.vid2Locations[vid] = []Location{location}
  103. return
  104. }
  105. for _, loc := range locations {
  106. if loc.Url == location.Url {
  107. return
  108. }
  109. }
  110. vc.vid2Locations[vid] = append(locations, location)
  111. }
  112. func (vc *vidMap) deleteLocation(vid uint32, location Location) {
  113. vc.Lock()
  114. defer vc.Unlock()
  115. locations, found := vc.vid2Locations[vid]
  116. if !found {
  117. return
  118. }
  119. for i, loc := range locations {
  120. if loc.Url == location.Url {
  121. vc.vid2Locations[vid] = append(locations[0:i], locations[i+1:]...)
  122. break
  123. }
  124. }
  125. }