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.

272 lines
7.7 KiB

6 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. package operation
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/seaweedfs/seaweedfs/weed/pb"
  6. "github.com/seaweedfs/seaweedfs/weed/pb/master_pb"
  7. "github.com/seaweedfs/seaweedfs/weed/security"
  8. "github.com/seaweedfs/seaweedfs/weed/storage/needle"
  9. "google.golang.org/grpc"
  10. )
  11. type VolumeAssignRequest struct {
  12. Count uint64
  13. Replication string
  14. Collection string
  15. Ttl string
  16. DiskType string
  17. DataCenter string
  18. Rack string
  19. DataNode string
  20. WritableVolumeCount uint32
  21. }
  22. type AssignResult struct {
  23. Fid string `json:"fid,omitempty"`
  24. Url string `json:"url,omitempty"`
  25. PublicUrl string `json:"publicUrl,omitempty"`
  26. GrpcPort int `json:"grpcPort,omitempty"`
  27. Count uint64 `json:"count,omitempty"`
  28. Error string `json:"error,omitempty"`
  29. Auth security.EncodedJwt `json:"auth,omitempty"`
  30. Replicas []Location `json:"replicas,omitempty"`
  31. }
  32. // This is a proxy to the master server, only for assigning volume ids.
  33. // It runs via grpc to the master server in streaming mode.
  34. // The connection to the master would only be re-established when the last connection has error.
  35. type AssignProxy struct {
  36. grpcConnection *grpc.ClientConn
  37. pool chan *singleThreadAssignProxy
  38. }
  39. func NewAssignProxy(masterFn GetMasterFn, grpcDialOption grpc.DialOption, concurrency int) (ap *AssignProxy, err error) {
  40. ap = &AssignProxy{
  41. pool: make(chan *singleThreadAssignProxy, concurrency),
  42. }
  43. ap.grpcConnection, err = pb.GrpcDial(context.Background(), masterFn().ToGrpcAddress(), true, grpcDialOption)
  44. if err != nil {
  45. return nil, fmt.Errorf("fail to dial %s: %v", masterFn().ToGrpcAddress(), err)
  46. }
  47. for i := 0; i < concurrency; i++ {
  48. ap.pool <- &singleThreadAssignProxy{}
  49. }
  50. return ap, nil
  51. }
  52. func (ap *AssignProxy) Assign(primaryRequest *VolumeAssignRequest, alternativeRequests ...*VolumeAssignRequest) (ret *AssignResult, err error) {
  53. p := <-ap.pool
  54. defer func() {
  55. ap.pool <- p
  56. }()
  57. return p.doAssign(ap.grpcConnection, primaryRequest, alternativeRequests...)
  58. }
  59. type singleThreadAssignProxy struct {
  60. assignClient master_pb.Seaweed_StreamAssignClient
  61. }
  62. func (ap *singleThreadAssignProxy) doAssign(grpcConnection *grpc.ClientConn, primaryRequest *VolumeAssignRequest, alternativeRequests ...*VolumeAssignRequest) (ret *AssignResult, err error) {
  63. if ap.assignClient == nil {
  64. client := master_pb.NewSeaweedClient(grpcConnection)
  65. ap.assignClient, err = client.StreamAssign(context.Background())
  66. if err != nil {
  67. ap.assignClient = nil
  68. return nil, fmt.Errorf("fail to create stream assign client: %v", err)
  69. }
  70. }
  71. var requests []*VolumeAssignRequest
  72. requests = append(requests, primaryRequest)
  73. requests = append(requests, alternativeRequests...)
  74. ret = &AssignResult{}
  75. for _, request := range requests {
  76. if request == nil {
  77. continue
  78. }
  79. req := &master_pb.AssignRequest{
  80. Count: request.Count,
  81. Replication: request.Replication,
  82. Collection: request.Collection,
  83. Ttl: request.Ttl,
  84. DiskType: request.DiskType,
  85. DataCenter: request.DataCenter,
  86. Rack: request.Rack,
  87. DataNode: request.DataNode,
  88. WritableVolumeCount: request.WritableVolumeCount,
  89. }
  90. if err = ap.assignClient.Send(req); err != nil {
  91. return nil, fmt.Errorf("StreamAssignSend: %v", err)
  92. }
  93. resp, grpcErr := ap.assignClient.Recv()
  94. if grpcErr != nil {
  95. return nil, grpcErr
  96. }
  97. if resp.Error != "" {
  98. return nil, fmt.Errorf("StreamAssignRecv: %v", resp.Error)
  99. }
  100. ret.Count = resp.Count
  101. ret.Fid = resp.Fid
  102. ret.Url = resp.Location.Url
  103. ret.PublicUrl = resp.Location.PublicUrl
  104. ret.GrpcPort = int(resp.Location.GrpcPort)
  105. ret.Error = resp.Error
  106. ret.Auth = security.EncodedJwt(resp.Auth)
  107. for _, r := range resp.Replicas {
  108. ret.Replicas = append(ret.Replicas, Location{
  109. Url: r.Url,
  110. PublicUrl: r.PublicUrl,
  111. DataCenter: r.DataCenter,
  112. })
  113. }
  114. if ret.Count <= 0 {
  115. continue
  116. }
  117. break
  118. }
  119. return
  120. }
  121. func Assign(masterFn GetMasterFn, grpcDialOption grpc.DialOption, primaryRequest *VolumeAssignRequest, alternativeRequests ...*VolumeAssignRequest) (*AssignResult, error) {
  122. var requests []*VolumeAssignRequest
  123. requests = append(requests, primaryRequest)
  124. requests = append(requests, alternativeRequests...)
  125. var lastError error
  126. ret := &AssignResult{}
  127. for i, request := range requests {
  128. if request == nil {
  129. continue
  130. }
  131. lastError = WithMasterServerClient(false, masterFn(), grpcDialOption, func(masterClient master_pb.SeaweedClient) error {
  132. req := &master_pb.AssignRequest{
  133. Count: request.Count,
  134. Replication: request.Replication,
  135. Collection: request.Collection,
  136. Ttl: request.Ttl,
  137. DiskType: request.DiskType,
  138. DataCenter: request.DataCenter,
  139. Rack: request.Rack,
  140. DataNode: request.DataNode,
  141. WritableVolumeCount: request.WritableVolumeCount,
  142. }
  143. resp, grpcErr := masterClient.Assign(context.Background(), req)
  144. if grpcErr != nil {
  145. return grpcErr
  146. }
  147. if resp.Error != "" {
  148. return fmt.Errorf("assignRequest: %v", resp.Error)
  149. }
  150. ret.Count = resp.Count
  151. ret.Fid = resp.Fid
  152. ret.Url = resp.Location.Url
  153. ret.PublicUrl = resp.Location.PublicUrl
  154. ret.GrpcPort = int(resp.Location.GrpcPort)
  155. ret.Error = resp.Error
  156. ret.Auth = security.EncodedJwt(resp.Auth)
  157. for _, r := range resp.Replicas {
  158. ret.Replicas = append(ret.Replicas, Location{
  159. Url: r.Url,
  160. PublicUrl: r.PublicUrl,
  161. DataCenter: r.DataCenter,
  162. })
  163. }
  164. return nil
  165. })
  166. if lastError != nil {
  167. continue
  168. }
  169. if ret.Count <= 0 {
  170. lastError = fmt.Errorf("assign failure %d: %v", i+1, ret.Error)
  171. continue
  172. }
  173. break
  174. }
  175. return ret, lastError
  176. }
  177. func LookupJwt(master pb.ServerAddress, grpcDialOption grpc.DialOption, fileId string) (token security.EncodedJwt) {
  178. WithMasterServerClient(false, master, grpcDialOption, func(masterClient master_pb.SeaweedClient) error {
  179. resp, grpcErr := masterClient.LookupVolume(context.Background(), &master_pb.LookupVolumeRequest{
  180. VolumeOrFileIds: []string{fileId},
  181. })
  182. if grpcErr != nil {
  183. return grpcErr
  184. }
  185. if len(resp.VolumeIdLocations) == 0 {
  186. return nil
  187. }
  188. token = security.EncodedJwt(resp.VolumeIdLocations[0].Auth)
  189. return nil
  190. })
  191. return
  192. }
  193. type StorageOption struct {
  194. Replication string
  195. DiskType string
  196. Collection string
  197. DataCenter string
  198. Rack string
  199. DataNode string
  200. TtlSeconds int32
  201. Fsync bool
  202. VolumeGrowthCount uint32
  203. SaveInside bool
  204. }
  205. func (so *StorageOption) TtlString() string {
  206. return needle.SecondsToTTL(so.TtlSeconds)
  207. }
  208. func (so *StorageOption) ToAssignRequests(count int) (ar *VolumeAssignRequest, altRequest *VolumeAssignRequest) {
  209. ar = &VolumeAssignRequest{
  210. Count: uint64(count),
  211. Replication: so.Replication,
  212. Collection: so.Collection,
  213. Ttl: so.TtlString(),
  214. DiskType: so.DiskType,
  215. DataCenter: so.DataCenter,
  216. Rack: so.Rack,
  217. DataNode: so.DataNode,
  218. WritableVolumeCount: so.VolumeGrowthCount,
  219. }
  220. if so.DataCenter != "" || so.Rack != "" || so.DataNode != "" {
  221. altRequest = &VolumeAssignRequest{
  222. Count: uint64(count),
  223. Replication: so.Replication,
  224. Collection: so.Collection,
  225. Ttl: so.TtlString(),
  226. DiskType: so.DiskType,
  227. DataCenter: "",
  228. Rack: "",
  229. DataNode: "",
  230. WritableVolumeCount: so.VolumeGrowthCount,
  231. }
  232. }
  233. return
  234. }