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.

client_command_ec.go 10 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "os"
  6. "path/filepath"
  7. "sync"
  8. "gitlink.org.cn/cloudream/client/config"
  9. "gitlink.org.cn/cloudream/ec"
  10. "gitlink.org.cn/cloudream/utils"
  11. )
  12. func EcWrite(localFilePath string, bucketID int, objectName string, ecName string) error {
  13. panic("not implement yet!")
  14. /*
  15. fmt.Println("write " + localFilePath + " as " + bucketName + "/" + objectName)
  16. // TODO 需要参考RepWrite函数的代码逻辑,做好错误处理
  17. //获取文件大小
  18. fileInfo, err := os.Stat(localFilePath)
  19. if err != nil {
  20. return fmt.Errorf("get file %s state failed, err: %w", localFilePath, err)
  21. }
  22. fileSizeInBytes := fileInfo.Size()
  23. //调用纠删码库,获取编码参数及生成矩阵
  24. ecPolicies := *utils.GetEcPolicy()
  25. ecPolicy := ecPolicies[ecName]
  26. ipss := utils.GetAgentIps()
  27. fmt.Println(ipss)
  28. print("@!@!@!@!@!@!")
  29. //var policy utils.EcConfig
  30. //policy = ecPolicy[0]
  31. ecK := ecPolicy.GetK()
  32. ecN := ecPolicy.GetN()
  33. //const ecK int = ecPolicy.GetK()
  34. //const ecN int = ecPolicy.GetN()
  35. var coefs = [][]int64{{1, 1, 1}, {1, 2, 3}} //2应替换为ecK,3应替换为ecN
  36. //计算每个块的packet数
  37. numPacket := (fileSizeInBytes + int64(ecK)*config.Cfg().GRCPPacketSize - 1) / (int64(ecK) * config.Cfg().GRCPPacketSize)
  38. fmt.Println(numPacket)
  39. userId := 0
  40. coorClient, err := racli.NewCoordinatorClient()
  41. if err != nil {
  42. return fmt.Errorf("create coordinator client failed, err: %w", err)
  43. }
  44. defer coorClient.Close()
  45. //发送写请求,请求Coor分配写入节点Ip
  46. ecWriteResp, err := coorClient.ECWrite(bucketName, objectName, fileSizeInBytes, ecName, userId)
  47. if err != nil {
  48. return fmt.Errorf("request to coordinator failed, err: %w", err)
  49. }
  50. if ecWriteResp.ErrorCode != errorcode.OK {
  51. return fmt.Errorf("coordinator ECWrite failed, err: %w", err)
  52. }
  53. //创建channel
  54. loadBufs := make([]chan []byte, ecN)
  55. encodeBufs := make([]chan []byte, ecN)
  56. for i := 0; i < ecN; i++ {
  57. loadBufs[i] = make(chan []byte)
  58. }
  59. for i := 0; i < ecN; i++ {
  60. encodeBufs[i] = make(chan []byte)
  61. }
  62. hashs := make([]string, ecN)
  63. //正式开始写入
  64. go load(localFilePath, loadBufs[:ecN], ecK, numPacket*int64(ecK), fileSizeInBytes) //从本地文件系统加载数据
  65. go encode(loadBufs[:ecN], encodeBufs[:ecN], ecK, coefs, numPacket)
  66. var wg sync.WaitGroup
  67. wg.Add(ecN)
  68. for i := 0; i < ecN; i++ {
  69. go send(ecWriteResp.NodeIPs[i], encodeBufs[i], numPacket, &wg, hashs, i)
  70. }
  71. wg.Wait()
  72. //第二轮通讯:插入元数据hashs
  73. writeECHashResp, err := coorClient.WriteECHash(bucketName, objectName, hashs, ecWriteResp.NodeIPs, userId)
  74. if err != nil {
  75. return fmt.Errorf("request to coordinator failed, err: %w", err)
  76. }
  77. if writeECHashResp.ErrorCode != errorcode.OK {
  78. return fmt.Errorf("coordinator WriteECHash failed, err: %w", err)
  79. }
  80. return nil
  81. */
  82. }
  83. func load(localFilePath string, loadBufs []chan []byte, ecK int, totalNumPacket int64, fileSizeInBytes int64) {
  84. fmt.Println("load " + localFilePath)
  85. file, _ := os.Open(localFilePath)
  86. for i := 0; int64(i) < totalNumPacket; i++ {
  87. print(totalNumPacket)
  88. buf := make([]byte, config.Cfg().GRCPPacketSize)
  89. idx := i % ecK
  90. print(len(loadBufs))
  91. _, err := file.Read(buf)
  92. loadBufs[idx] <- buf
  93. if idx == ecK-1 {
  94. print("***")
  95. for j := ecK; j < len(loadBufs); j++ {
  96. print(j)
  97. zeroPkt := make([]byte, config.Cfg().GRCPPacketSize)
  98. fmt.Printf("%v", zeroPkt)
  99. loadBufs[j] <- zeroPkt
  100. }
  101. }
  102. if err != nil && err != io.EOF {
  103. break
  104. }
  105. }
  106. fmt.Println("load over")
  107. for i := 0; i < len(loadBufs); i++ {
  108. print(i)
  109. close(loadBufs[i])
  110. }
  111. file.Close()
  112. }
  113. func encode(inBufs []chan []byte, outBufs []chan []byte, ecK int, coefs [][]int64, numPacket int64) {
  114. fmt.Println("encode ")
  115. var tmpIn [][]byte
  116. tmpIn = make([][]byte, len(outBufs))
  117. enc := ec.NewRsEnc(ecK, len(outBufs))
  118. for i := 0; int64(i) < numPacket; i++ {
  119. for j := 0; j < len(outBufs); j++ { //3
  120. tmpIn[j] = <-inBufs[j]
  121. //print(i)
  122. //fmt.Printf("%v",tmpIn[j])
  123. //print("@#$")
  124. }
  125. enc.Encode(tmpIn)
  126. fmt.Printf("%v", tmpIn)
  127. print("$$$$$$$$$$$$$$$$$$")
  128. for j := 0; j < len(outBufs); j++ { //1,2,3//示意,需要调用纠删码编解码引擎: tmp[k] = tmp[k]+(tmpIn[w][k]*coefs[w][j])
  129. outBufs[j] <- tmpIn[j]
  130. }
  131. }
  132. fmt.Println("encode over")
  133. for i := 0; i < len(outBufs); i++ {
  134. close(outBufs[i])
  135. }
  136. }
  137. func decode(inBufs []chan []byte, outBufs []chan []byte, blockSeq []int, ecK int, coefs [][]int64, numPacket int64) {
  138. fmt.Println("decode ")
  139. var tmpIn [][]byte
  140. var zeroPkt []byte
  141. tmpIn = make([][]byte, len(inBufs))
  142. hasBlock := map[int]bool{}
  143. for j := 0; j < len(blockSeq); j++ {
  144. hasBlock[blockSeq[j]] = true
  145. }
  146. needRepair := false //检测是否传入了所有数据块
  147. for j := 0; j < len(outBufs); j++ {
  148. if blockSeq[j] != j {
  149. needRepair = true
  150. }
  151. }
  152. enc := ec.NewRsEnc(ecK, len(inBufs))
  153. for i := 0; int64(i) < numPacket; i++ {
  154. for j := 0; j < len(inBufs); j++ { //3
  155. if hasBlock[j] {
  156. tmpIn[j] = <-inBufs[j]
  157. } else {
  158. tmpIn[j] = zeroPkt
  159. }
  160. }
  161. fmt.Printf("%v", tmpIn)
  162. if needRepair {
  163. err := enc.Repair(tmpIn)
  164. print("&&&&&")
  165. if err != nil {
  166. fmt.Fprintf(os.Stderr, "Decode Repair Error: %s", err.Error())
  167. }
  168. }
  169. //fmt.Printf("%v",tmpIn)
  170. for j := 0; j < len(outBufs); j++ { //1,2,3//示意,需要调用纠删码编解码引擎: tmp[k] = tmp[k]+(tmpIn[w][k]*coefs[w][j])
  171. outBufs[j] <- tmpIn[j]
  172. }
  173. }
  174. fmt.Println("decode over")
  175. for i := 0; i < len(outBufs); i++ {
  176. close(outBufs[i])
  177. }
  178. }
  179. func send(ip string, inBuf chan []byte, numPacket int64, wg *sync.WaitGroup, hashs []string, idx int) error {
  180. panic("not implement yet!")
  181. /*
  182. // TO DO ss: 判断本地有没有ipfs daemon、能否与目标agent的ipfs daemon连通、本地ipfs目录空间是否充足
  183. // 如果本地有ipfs daemon、能与目标agent的ipfs daemon连通、本地ipfs目录空间充足,将所有内容写入本地ipfs目录,得到对象的cid,发送cid给目标agent让其pin相应的对象
  184. // 否则,像目前一样,使用grpc向指定节点获取
  185. // TODO 如果发生错误,需要考虑将错误传递出去
  186. defer wg.Done()
  187. grpcAddr := fmt.Sprintf("%s:%d", ip, config.Cfg().GRPCPort)
  188. conn, err := grpc.Dial(grpcAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
  189. if err != nil {
  190. return fmt.Errorf("connect to grpc server at %s failed, err: %w", grpcAddr, err)
  191. }
  192. defer conn.Close()
  193. client := agentcaller.NewFileTransportClient(conn)
  194. stream, err := client.SendFile(context.Background())
  195. if err != nil {
  196. return fmt.Errorf("request to send file failed, err: %w", err)
  197. }
  198. for i := 0; int64(i) < numPacket; i++ {
  199. buf := <-inBuf
  200. err := stream.Send(&agentcaller.FileDataPacket{
  201. Code: agentcaller.FileDataPacket_OK,
  202. Data: buf,
  203. })
  204. if err != nil {
  205. stream.CloseSend()
  206. return fmt.Errorf("send file data failed, err: %w", err)
  207. }
  208. }
  209. err = stream.Send(&agentcaller.FileDataPacket{
  210. Code: agentcaller.FileDataPacket_EOF,
  211. })
  212. if err != nil {
  213. stream.CloseSend()
  214. return fmt.Errorf("send file data failed, err: %w", err)
  215. }
  216. resp, err := stream.CloseAndRecv()
  217. if err != nil {
  218. return fmt.Errorf("receive response failed, err: %w", err)
  219. }
  220. hashs[idx] = resp.FileHash
  221. return nil
  222. */
  223. }
  224. func get(blockHash string, nodeIP string, getBuf chan []byte, numPacket int64) error {
  225. panic("not implement yet!")
  226. /*
  227. grpcAddr := fmt.Sprintf("%s:%d", nodeIP, config.Cfg().GRPCPort)
  228. conn, err := grpc.Dial(grpcAddr, grpc.WithTransportCredentials(insecure.NewCredentials()))
  229. if err != nil {
  230. return fmt.Errorf("connect to grpc server at %s failed, err: %w", grpcAddr, err)
  231. }
  232. defer conn.Close()
  233. // TO DO: 判断本地有没有ipfs daemon、能否获取相应对象的cid
  234. // 如果本地有ipfs daemon且能获取相应编码块的cid,则获取编码块cid对应的ipfsblock的cid,通过ipfs网络获取这些ipfsblock
  235. // 否则,像目前一样,使用grpc向指定节点获取
  236. client := agentcaller.NewFileTransportClient(conn)
  237. //rpc get
  238. // TODO 要考虑读取失败后,如何中断后续解码过程
  239. stream, err := client.GetFile(context.Background(), &agentcaller.GetReq{
  240. FileHash: blockHash,
  241. })
  242. for i := 0; int64(i) < numPacket; i++ {
  243. fmt.Println(i)
  244. // TODO 同上
  245. res, _ := stream.Recv()
  246. fmt.Println(res.BlockOrReplicaData)
  247. getBuf <- res.BlockOrReplicaData
  248. }
  249. close(getBuf)
  250. return nil
  251. */
  252. }
  253. func persist(inBuf []chan []byte, numPacket int64, localFilePath string, wg *sync.WaitGroup) {
  254. fDir, err := os.Executable()
  255. if err != nil {
  256. panic(err)
  257. }
  258. fURL := filepath.Join(filepath.Dir(fDir), "assets")
  259. _, err = os.Stat(fURL)
  260. if os.IsNotExist(err) {
  261. os.MkdirAll(fURL, os.ModePerm)
  262. }
  263. file, err := os.Create(filepath.Join(fURL, localFilePath))
  264. if err != nil {
  265. return
  266. }
  267. for i := 0; int64(i) < numPacket; i++ {
  268. for j := 0; j < len(inBuf); j++ {
  269. tmp := <-inBuf[j]
  270. fmt.Println(tmp)
  271. file.Write(tmp)
  272. }
  273. }
  274. file.Close()
  275. wg.Done()
  276. }
  277. func ecRead(fileSizeInBytes int64, nodeIPs []string, blockHashs []string, blockIds []int, ecName string, localFilePath string) {
  278. //根据ecName获得以下参数
  279. wg := sync.WaitGroup{}
  280. ecPolicies := *utils.GetEcPolicy()
  281. ecPolicy := ecPolicies[ecName]
  282. fmt.Println(ecPolicy)
  283. ecK := ecPolicy.GetK()
  284. ecN := ecPolicy.GetN()
  285. var coefs = [][]int64{{1, 1, 1}, {1, 2, 3}} //2应替换为ecK,3应替换为ecN
  286. numPacket := (fileSizeInBytes + int64(ecK)*config.Cfg().GRCPPacketSize - 1) / (int64(ecK) * config.Cfg().GRCPPacketSize)
  287. fmt.Println(numPacket)
  288. //创建channel
  289. getBufs := make([]chan []byte, ecN)
  290. decodeBufs := make([]chan []byte, ecK)
  291. for i := 0; i < ecN; i++ {
  292. getBufs[i] = make(chan []byte)
  293. }
  294. for i := 0; i < ecK; i++ {
  295. decodeBufs[i] = make(chan []byte)
  296. }
  297. //从协调端获取有哪些编码块
  298. //var blockSeq = []int{0,1}
  299. blockSeq := blockIds
  300. wg.Add(1)
  301. for i := 0; i < len(blockSeq); i++ {
  302. go get(blockHashs[i], nodeIPs[i], getBufs[blockSeq[i]], numPacket)
  303. }
  304. go decode(getBufs[:], decodeBufs[:], blockSeq, ecK, coefs, numPacket)
  305. go persist(decodeBufs[:], numPacket, localFilePath, &wg)
  306. wg.Wait()
  307. }

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