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

object.go 11 kB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. package services
  2. import (
  3. "database/sql"
  4. "errors"
  5. "github.com/samber/lo"
  6. "gitlink.org.cn/cloudream/db/model"
  7. ramsg "gitlink.org.cn/cloudream/rabbitmq/message"
  8. coormsg "gitlink.org.cn/cloudream/rabbitmq/message/coordinator"
  9. "gitlink.org.cn/cloudream/utils/consts"
  10. "gitlink.org.cn/cloudream/utils/consts/errorcode"
  11. log "gitlink.org.cn/cloudream/utils/logger"
  12. )
  13. func (svc *Service) PreDownloadObject(msg *coormsg.PreDownloadObject) *coormsg.PreDownloadObjectResp {
  14. // 查询文件对象
  15. object, err := svc.db.Object().GetUserObject(msg.Body.UserID, msg.Body.ObjectID)
  16. if err != nil {
  17. log.WithField("ObjectID", msg.Body.ObjectID).
  18. Warnf("query Object failed, err: %s", err.Error())
  19. return ramsg.ReplyFailed[coormsg.PreDownloadObjectResp](errorcode.OPERATION_FAILED, "query Object failed")
  20. }
  21. // 查询客户端所属节点
  22. belongNode, err := svc.db.Node().GetByExternalIP(msg.Body.ClientExternalIP)
  23. if err != nil {
  24. log.WithField("ClientExternalIP", msg.Body.ClientExternalIP).
  25. Warnf("query client belong node failed, err: %s", err.Error())
  26. return ramsg.ReplyFailed[coormsg.PreDownloadObjectResp](errorcode.OPERATION_FAILED, "query client belong node failed")
  27. }
  28. log.Debugf("client address %s is at location %d", msg.Body.ClientExternalIP, belongNode.LocationID)
  29. var entries []coormsg.PreDownloadObjectRespEntry
  30. //-若redundancy是rep,查询对象副本表, 获得repHash
  31. if object.Redundancy == consts.REDUNDANCY_REP {
  32. objectRep, err := svc.db.ObjectRep().GetObjectRep(object.ObjectID)
  33. if err != nil {
  34. log.WithField("ObjectID", object.ObjectID).
  35. Warnf("get ObjectRep failed, err: %s", err.Error())
  36. return ramsg.ReplyFailed[coormsg.PreDownloadObjectResp](errorcode.OPERATION_FAILED, "query ObjectRep failed")
  37. }
  38. // 注:由于采用了IPFS存储,因此每个备份文件的FileHash都是一样的
  39. nodes, err := svc.db.Cache().FindCachingFileUserNodes(msg.Body.UserID, objectRep.RepHash)
  40. if err != nil {
  41. log.WithField("RepHash", objectRep.RepHash).
  42. Warnf("query Cache failed, err: %s", err.Error())
  43. return ramsg.ReplyFailed[coormsg.PreDownloadObjectResp](errorcode.OPERATION_FAILED, "query Cache failed")
  44. }
  45. for _, node := range nodes {
  46. entries = append(entries, coormsg.NewPreDownloadObjectRespEntry(
  47. node.NodeID,
  48. node.ExternalIP,
  49. node.LocalIP,
  50. // LocationID 相同则认为是在同一个地域
  51. belongNode.LocationID == node.LocationID,
  52. objectRep.RepHash,
  53. 0))
  54. }
  55. } else {
  56. // TODO 参考上面进行重写
  57. /*blocks, err := svc.db.QueryObjectBlock(object.ObjectID)
  58. if err != nil {
  59. log.WithField("ObjectID", object.ObjectID).
  60. Warnf("query Object Block failed, err: %s", err.Error())
  61. return ramsg.ReplyFailed[coormsg.ReadResp](errorcode.OPERATION_FAILED, "query Object Block failed")
  62. }
  63. ecPolicies := *utils.GetEcPolicy()
  64. ecPolicy := ecPolicies[*object.ECName]
  65. ecN := ecPolicy.GetN()
  66. ecK := ecPolicy.GetK()
  67. nodeIPs = make([]string, ecN)
  68. hashes = make([]string, ecN)
  69. for _, tt := range blocks {
  70. id := tt.InnerID
  71. hash := tt.BlockHash
  72. hashes[id] = hash //这里有问题,采取的其实是直接顺序读的方式,等待加入自适应读模块
  73. nodes, err := svc.db.QueryCacheNodeByBlockHash(hash)
  74. if err != nil {
  75. log.WithField("BlockHash", hash).
  76. Warnf("query Cache failed, err: %s", err.Error())
  77. return ramsg.ReplyFailed[coormsg.ReadResp](errorcode.OPERATION_FAILED, "query Cache failed")
  78. }
  79. if len(nodes) == 0 {
  80. log.WithField("BlockHash", hash).
  81. Warnf("No node cache the block data for the BlockHash")
  82. return ramsg.ReplyFailed[coormsg.ReadResp](errorcode.OPERATION_FAILED, "No node cache the block data for the BlockHash")
  83. }
  84. nodeIPs[id] = nodes[0].IP
  85. }
  86. //这里也有和上面一样的问题
  87. for i := 1; i < ecK; i++ {
  88. blockIDs = append(blockIDs, i)
  89. }*/
  90. }
  91. return ramsg.ReplyOK(coormsg.NewPreDownloadObjectRespBody(
  92. object.Redundancy,
  93. object.ECName,
  94. object.FileSizeInBytes,
  95. entries,
  96. ))
  97. }
  98. func (svc *Service) PreUploadRepObject(msg *coormsg.PreUploadRepObject) *coormsg.PreUploadResp {
  99. // 判断同名对象是否存在。等到WriteRepHash时再判断一次。
  100. // 此次的判断只作为参考,具体是否成功还是看WriteRepHash的结果
  101. isBucketAvai, err := svc.db.Bucket().IsAvailable(msg.Body.BucketID, msg.Body.UserID)
  102. if err != nil {
  103. log.WithField("BucketID", msg.Body.BucketID).
  104. Warnf("check bucket available failed, err: %s", err.Error())
  105. return ramsg.ReplyFailed[coormsg.PreUploadResp](errorcode.OPERATION_FAILED, "check bucket available failed")
  106. }
  107. if !isBucketAvai {
  108. log.WithField("BucketID", msg.Body.BucketID).
  109. Warnf("bucket is not available to user")
  110. return ramsg.ReplyFailed[coormsg.PreUploadResp](errorcode.OPERATION_FAILED, "bucket is not available to user")
  111. }
  112. _, err = svc.db.Object().GetByName(msg.Body.BucketID, msg.Body.ObjectName)
  113. if err == nil {
  114. log.WithField("BucketID", msg.Body.BucketID).
  115. WithField("ObjectName", msg.Body.ObjectName).
  116. Warnf("object with given Name and BucketID already exists")
  117. return ramsg.ReplyFailed[coormsg.PreUploadResp](errorcode.OPERATION_FAILED, "object with given Name and BucketID already exists")
  118. }
  119. if !errors.Is(err, sql.ErrNoRows) {
  120. log.WithField("BucketID", msg.Body.BucketID).
  121. WithField("ObjectName", msg.Body.ObjectName).
  122. Warnf("get object by name failed, err: %s", err.Error())
  123. return ramsg.ReplyFailed[coormsg.PreUploadResp](errorcode.OPERATION_FAILED, "get object by name failed")
  124. }
  125. //查询用户可用的节点IP
  126. nodes, err := svc.db.Node().GetUserNodes(msg.Body.UserID)
  127. if err != nil {
  128. log.WithField("UserID", msg.Body.UserID).
  129. Warnf("query user nodes failed, err: %s", err.Error())
  130. return ramsg.ReplyFailed[coormsg.PreUploadResp](errorcode.OPERATION_FAILED, "query user nodes failed")
  131. }
  132. // 查询客户端所属节点
  133. belongNode, err := svc.db.Node().GetByExternalIP(msg.Body.ClientExternalIP)
  134. if err != nil {
  135. log.WithField("ClientExternalIP", msg.Body.ClientExternalIP).
  136. Warnf("query client belong node failed, err: %s", err.Error())
  137. return ramsg.ReplyFailed[coormsg.PreUploadResp](errorcode.OPERATION_FAILED, "query client belong node failed")
  138. }
  139. var retNodes []coormsg.PreUploadRespNode
  140. for _, node := range nodes {
  141. retNodes = append(retNodes, coormsg.NewPreUploadRespNode(
  142. node.NodeID,
  143. node.ExternalIP,
  144. node.LocalIP,
  145. // LocationID 相同则认为是在同一个地域
  146. belongNode.LocationID == node.LocationID,
  147. ))
  148. }
  149. return ramsg.ReplyOK(coormsg.NewPreUploadRespBody(retNodes))
  150. }
  151. func (svc *Service) CreateRepObject(msg *coormsg.CreateRepObject) *coormsg.CreateObjectResp {
  152. _, err := svc.db.Object().CreateRepObject(msg.Body.BucketID, msg.Body.ObjectName, msg.Body.FileSizeInBytes, msg.Body.ReplicateNumber, msg.Body.NodeIDs, msg.Body.FileHash)
  153. if err != nil {
  154. log.WithField("BucketName", msg.Body.BucketID).
  155. WithField("ObjectName", msg.Body.ObjectName).
  156. Warnf("create rep object failed, err: %s", err.Error())
  157. return ramsg.ReplyFailed[coormsg.CreateObjectResp](errorcode.OPERATION_FAILED, "create rep object failed")
  158. }
  159. // TODO 通知scanner检查备份数
  160. return ramsg.ReplyOK(coormsg.NewCreateObjectRespBody())
  161. }
  162. func (svc *Service) PreUpdateRepObject(msg *coormsg.PreUpdateRepObject) *coormsg.PreUpdateRepObjectResp {
  163. // 获取对象信息
  164. obj, err := svc.db.Object().GetByID(msg.Body.ObjectID)
  165. if err != nil {
  166. log.WithField("ObjectID", msg.Body.ObjectID).
  167. Warnf("get object failed, err: %s", err.Error())
  168. return ramsg.ReplyFailed[coormsg.PreUpdateRepObjectResp](errorcode.OPERATION_FAILED, "get object failed")
  169. }
  170. if obj.Redundancy != consts.REDUNDANCY_REP {
  171. log.WithField("ObjectID", msg.Body.ObjectID).
  172. Warnf("this object is not a rep object")
  173. return ramsg.ReplyFailed[coormsg.PreUpdateRepObjectResp](errorcode.OPERATION_FAILED, "this object is not a rep object")
  174. }
  175. // 获取对象Rep信息
  176. objRep, err := svc.db.ObjectRep().GetObjectRep(msg.Body.ObjectID)
  177. if err != nil {
  178. log.WithField("ObjectID", msg.Body.ObjectID).
  179. Warnf("get object rep failed, err: %s", err.Error())
  180. return ramsg.ReplyFailed[coormsg.PreUpdateRepObjectResp](errorcode.OPERATION_FAILED, "get object rep failed")
  181. }
  182. //查询用户可用的节点IP
  183. nodes, err := svc.db.Node().GetUserNodes(msg.Body.UserID)
  184. if err != nil {
  185. log.WithField("UserID", msg.Body.UserID).
  186. Warnf("query user nodes failed, err: %s", err.Error())
  187. return ramsg.ReplyFailed[coormsg.PreUpdateRepObjectResp](errorcode.OPERATION_FAILED, "query user nodes failed")
  188. }
  189. // 查询客户端所属节点
  190. belongNode, err := svc.db.Node().GetByExternalIP(msg.Body.ClientExternalIP)
  191. if err != nil {
  192. log.WithField("ClientExternalIP", msg.Body.ClientExternalIP).
  193. Warnf("query client belong node failed, err: %s", err.Error())
  194. return ramsg.ReplyFailed[coormsg.PreUpdateRepObjectResp](errorcode.OPERATION_FAILED, "query client belong node failed")
  195. }
  196. // 查询保存了旧文件的节点信息
  197. cachingNodes, err := svc.db.Cache().FindCachingFileUserNodes(msg.Body.UserID, objRep.RepHash)
  198. if err != nil {
  199. log.Warnf("find caching file user nodes failed, err: %s", err.Error())
  200. return ramsg.ReplyFailed[coormsg.PreUpdateRepObjectResp](errorcode.OPERATION_FAILED, "find caching file user nodes failed")
  201. }
  202. var retNodes []coormsg.PreUpdateRepObjectRespNode
  203. for _, node := range nodes {
  204. retNodes = append(retNodes, coormsg.NewPreUpdateRepObjectRespNode(
  205. node.NodeID,
  206. node.ExternalIP,
  207. node.LocalIP,
  208. // LocationID 相同则认为是在同一个地域
  209. belongNode.LocationID == node.LocationID,
  210. // 此节点存储了对象旧文件
  211. lo.ContainsBy(cachingNodes, func(n model.Node) bool { return n.NodeID == node.NodeID }),
  212. ))
  213. }
  214. return ramsg.ReplyOK(coormsg.NewPreUpdateRepObjectRespBody(retNodes))
  215. }
  216. func (svc *Service) UpdateRepObject(msg *coormsg.UpdateRepObject) *coormsg.UpdateRepObjectResp {
  217. err := svc.db.Object().UpdateRepObject(msg.Body.ObjectID, msg.Body.FileSizeInBytes, msg.Body.NodeIDs, msg.Body.FileHash)
  218. if err != nil {
  219. log.WithField("ObjectID", msg.Body.ObjectID).
  220. Warnf("update rep object failed, err: %s", err.Error())
  221. return ramsg.ReplyFailed[coormsg.UpdateRepObjectResp](errorcode.OPERATION_FAILED, "update rep object failed")
  222. }
  223. return ramsg.ReplyOK(coormsg.NewUpdateRepObjectRespBody())
  224. }
  225. func (svc *Service) DeleteObject(msg *coormsg.DeleteObject) *coormsg.DeleteObjectResp {
  226. err := svc.db.Object().SoftDelete(msg.Body.UserID, msg.Body.ObjectID)
  227. if err != nil {
  228. log.WithField("UserID", msg.Body.UserID).
  229. WithField("ObjectID", msg.Body.ObjectID).
  230. Warnf("set object deleted failed, err: %s", err.Error())
  231. return ramsg.ReplyFailed[coormsg.DeleteObjectResp](errorcode.OPERATION_FAILED, "set object deleted failed")
  232. }
  233. return ramsg.ReplyOK(coormsg.NewDeleteObjectRespBody())
  234. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。