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.

clientCommand.go 18 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
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. package main
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "os"
  7. "path/filepath"
  8. agentcaller "proto"
  9. "strconv"
  10. "sync"
  11. raclient "gitlink.org.cn/cloudream/rabbitmq/client"
  12. "gitlink.org.cn/cloudream/utils"
  13. "gitlink.org.cn/cloudream/utils/consts"
  14. "gitlink.org.cn/cloudream/utils/consts/errorcode"
  15. myio "gitlink.org.cn/cloudream/utils/io"
  16. //"reflect"
  17. //"github.com/pborman/uuid"
  18. //"github.com/streadway/amqp"
  19. "ec"
  20. "google.golang.org/grpc"
  21. _ "google.golang.org/grpc/balancer/grpclb"
  22. )
  23. const (
  24. // TODO2 改为配置文件读取
  25. port = ":5010"
  26. packetSizeInBytes = 10
  27. )
  28. func Move(bucketName string, objectName string, destination string) error {
  29. //将bucketName, objectName, destination发给协调端
  30. fmt.Println("move " + bucketName + "/" + objectName + " to " + destination)
  31. userId := 0
  32. //获取块hash,ip,序号,编码参数等
  33. //发送写请求,分配写入节点Ip
  34. // 先向协调端请求文件相关的数据
  35. coorClient, err := raclient.NewCoordinatorClient()
  36. if err != nil {
  37. return fmt.Errorf("create coordinator client failed, err: %w", err)
  38. }
  39. defer coorClient.Close()
  40. moveResp, err := coorClient.Move(bucketName, objectName, userId, destination)
  41. if err != nil {
  42. return fmt.Errorf("request to coordinator failed, err: %w", err)
  43. }
  44. if moveResp.ErrorCode != errorcode.OK {
  45. return fmt.Errorf("coordinator operation failed, code: %s, message: %s", moveResp.ErrorCode, moveResp.Message)
  46. }
  47. // 然后向代理端发送移动文件的请求
  48. agentClient, err := raclient.NewAgentClient(destination)
  49. if err != nil {
  50. return fmt.Errorf("create agent client to %s failed, err: %w", destination, err)
  51. }
  52. defer agentClient.Close()
  53. switch moveResp.Redundancy {
  54. case consts.REDUNDANCY_REP:
  55. agentMoveResp, err := agentClient.RepMove(moveResp.Hashes, bucketName, objectName, userId, moveResp.FileSizeInBytes)
  56. if err != nil {
  57. return fmt.Errorf("request to agent %s failed, err: %w", destination, err)
  58. }
  59. if agentMoveResp.ErrorCode != errorcode.OK {
  60. return fmt.Errorf("agent %s operation failed, code: %s, messsage: %s", destination, agentMoveResp.ErrorCode, agentMoveResp.Message)
  61. }
  62. case consts.REDUNDANCY_EC:
  63. agentMoveResp, err := agentClient.ECMove(moveResp.Hashes, moveResp.IDs, moveResp.ECName, bucketName, objectName, userId, moveResp.FileSizeInBytes)
  64. if err != nil {
  65. return fmt.Errorf("request to agent %s failed, err: %w", destination, err)
  66. }
  67. if agentMoveResp.ErrorCode != errorcode.OK {
  68. return fmt.Errorf("agent %s operation failed, code: %s, messsage: %s", destination, agentMoveResp.ErrorCode, agentMoveResp.Message)
  69. }
  70. }
  71. return nil
  72. }
  73. func Read(localFilePath string, bucketName string, objectName string) error {
  74. fmt.Println("read " + bucketName + "/" + objectName + " to " + localFilePath)
  75. //获取块hash,ip,序号,编码参数等
  76. //发送写请求,分配写入节点Ip
  77. userId := 0
  78. // 先向协调端请求文件相关的数据
  79. coorClient, err := raclient.NewCoordinatorClient()
  80. if err != nil {
  81. return fmt.Errorf("create coordinator client failed, err: %w", err)
  82. }
  83. defer coorClient.Close()
  84. readResp, err := coorClient.Read(bucketName, objectName, userId)
  85. if err != nil {
  86. return fmt.Errorf("request to coordinator failed, err: %w", err)
  87. }
  88. if readResp.ErrorCode != errorcode.OK {
  89. return fmt.Errorf("coordinator operation failed, code: %s, message: %s", readResp.ErrorCode, readResp.Message)
  90. }
  91. switch readResp.Redundancy {
  92. case "rep":
  93. err = repRead(readResp.FileSizeInBytes, readResp.IPs[0], readResp.Hashes[0], localFilePath)
  94. if err != nil {
  95. return fmt.Errorf("rep read failed, err: %w", err)
  96. }
  97. case "ec":
  98. // TODO EC部分的代码要考虑重构
  99. ecRead(readResp.FileSizeInBytes, readResp.IPs, readResp.Hashes, readResp.BlockIDs, readResp.ECName, localFilePath)
  100. }
  101. return nil
  102. }
  103. func repRead(fileSizeInBytes int64, ip string, repHash string, localFilePath string) error {
  104. grpcAddr := ip + port
  105. conn, err := grpc.Dial(grpcAddr, grpc.WithInsecure())
  106. if err != nil {
  107. return fmt.Errorf("connect to grpc server at %s failed, err: %w", grpcAddr, err)
  108. }
  109. defer conn.Close()
  110. client := agentcaller.NewTranBlockOrReplicaClient(conn)
  111. curExecPath, err := os.Executable()
  112. if err != nil {
  113. return fmt.Errorf("get executable directory failed, err: %w", err)
  114. }
  115. outputFilePath := filepath.Join(filepath.Dir(curExecPath), localFilePath)
  116. outputFileDir := filepath.Dir(outputFilePath)
  117. err = os.MkdirAll(outputFileDir, os.ModePerm)
  118. if err != nil {
  119. return fmt.Errorf("create output file directory %s failed, err: %w", outputFileDir, err)
  120. }
  121. outputFile, err := os.Create(outputFilePath)
  122. if err != nil {
  123. return fmt.Errorf("create output file %s failed, err: %w", outputFilePath, err)
  124. }
  125. defer outputFile.Close()
  126. /*
  127. TO DO: 判断本地有没有ipfs daemon、能否获取相应对象的cid
  128. 如果本地有ipfs daemon且能获取相应对象的cid,则获取对象cid对应的ipfsblock的cid,通过ipfs网络获取这些ipfsblock
  129. 否则,像目前一样,使用grpc向指定节点获取
  130. */
  131. stream, err := client.GetBlockOrReplica(context.Background(), &agentcaller.GetReq{
  132. BlockOrReplicaHash: repHash,
  133. })
  134. if err != nil {
  135. return fmt.Errorf("request grpc failed, err: %w", err)
  136. }
  137. numPacket := (fileSizeInBytes + packetSizeInBytes - 1) / (packetSizeInBytes)
  138. for i := int64(0); i < numPacket; i++ {
  139. resp, err := stream.Recv()
  140. if err != nil {
  141. return fmt.Errorf("read file data on grpc stream failed, err: %w", err)
  142. }
  143. err = myio.WriteAll(outputFile, resp.BlockOrReplicaData)
  144. if err != nil {
  145. return fmt.Errorf("write file data to local file failed, err: %w", err)
  146. }
  147. }
  148. return nil
  149. }
  150. func ecRead(fileSizeInBytes int64, ips []string, blockHashs []string, blockIds []int, ecName string, localFilePath string) {
  151. //根据ecName获得以下参数
  152. wg := sync.WaitGroup{}
  153. ecPolicies := *utils.GetEcPolicy()
  154. ecPolicy := ecPolicies[ecName]
  155. fmt.Println(ecPolicy)
  156. ecK := ecPolicy.GetK()
  157. ecN := ecPolicy.GetN()
  158. var coefs = [][]int64{{1, 1, 1}, {1, 2, 3}} //2应替换为ecK,3应替换为ecN
  159. numPacket := (fileSizeInBytes + int64(ecK)*packetSizeInBytes - 1) / (int64(ecK) * packetSizeInBytes)
  160. fmt.Println(numPacket)
  161. //创建channel
  162. getBufs := make([]chan []byte, ecN)
  163. decodeBufs := make([]chan []byte, ecK)
  164. for i := 0; i < ecN; i++ {
  165. getBufs[i] = make(chan []byte)
  166. }
  167. for i := 0; i < ecK; i++ {
  168. decodeBufs[i] = make(chan []byte)
  169. }
  170. //从协调端获取有哪些编码块
  171. //var blockSeq = []int{0,1}
  172. blockSeq := blockIds
  173. wg.Add(1)
  174. for i := 0; i < len(blockSeq); i++ {
  175. go get(blockHashs[i], ips[i], getBufs[blockSeq[i]], numPacket)
  176. }
  177. go decode(getBufs[:], decodeBufs[:], blockSeq, ecK, coefs, numPacket)
  178. go persist(decodeBufs[:], numPacket, localFilePath, &wg)
  179. wg.Wait()
  180. }
  181. func RepWrite(localFilePath string, bucketName string, objectName string, numRep int) error {
  182. userId := 0
  183. //获取文件大小
  184. fileInfo, err := os.Stat(localFilePath)
  185. if err != nil {
  186. return fmt.Errorf("get file %s state failed, err: %w", localFilePath, err)
  187. }
  188. fileSizeInBytes := fileInfo.Size()
  189. //写入对象的packet数
  190. numWholePacket := fileSizeInBytes / packetSizeInBytes
  191. lastPacketInBytes := fileSizeInBytes % packetSizeInBytes
  192. numPacket := numWholePacket
  193. if lastPacketInBytes > 0 {
  194. numPacket++
  195. }
  196. coorClient, err := raclient.NewCoordinatorClient()
  197. if err != nil {
  198. return fmt.Errorf("create coordinator client failed, err: %w", err)
  199. }
  200. defer coorClient.Close()
  201. //发送写请求,请求Coor分配写入节点Ip
  202. repWriteResp, err := coorClient.RepWrite(bucketName, objectName, fileSizeInBytes, numRep, userId)
  203. if err != nil {
  204. return fmt.Errorf("request to coordinator failed, err: %w", err)
  205. }
  206. if repWriteResp.ErrorCode != errorcode.OK {
  207. return fmt.Errorf("coordinator RepWrite failed, err: %w", err)
  208. }
  209. //创建channel
  210. loadDistributeBufs := make([]chan []byte, numRep)
  211. for i := 0; i < numRep; i++ {
  212. loadDistributeBufs[i] = make(chan []byte)
  213. }
  214. //正式开始写入
  215. hashs := make([]string, numRep)
  216. go loadDistribute(localFilePath, loadDistributeBufs[:], numWholePacket, lastPacketInBytes) //从本地文件系统加载数据
  217. var wg sync.WaitGroup
  218. wg.Add(numRep)
  219. for i := 0; i < numRep; i++ {
  220. //TODO xh: send的第一个参数不需要了
  221. // TODO2 见上
  222. go send("rep.json"+strconv.Itoa(i), repWriteResp.IPs[i], loadDistributeBufs[i], numPacket, &wg, hashs, i) //"block1.json"这样参数不需要
  223. }
  224. wg.Wait()
  225. // 记录写入的文件的Hash
  226. writeRepHashResp, err := coorClient.WriteRepHash(bucketName, objectName, hashs, repWriteResp.IPs, userId)
  227. if err != nil {
  228. return fmt.Errorf("request to coordinator failed, err: %w", err)
  229. }
  230. if writeRepHashResp.ErrorCode != errorcode.OK {
  231. return fmt.Errorf("coordinator WriteRepHash failed, err: %w", err)
  232. }
  233. return nil
  234. }
  235. func EcWrite(localFilePath string, bucketName string, objectName string, ecName string) error {
  236. fmt.Println("write " + localFilePath + " as " + bucketName + "/" + objectName)
  237. //获取文件大小
  238. fileInfo, err := os.Stat(localFilePath)
  239. if err != nil {
  240. return fmt.Errorf("get file %s state failed, err: %w", localFilePath, err)
  241. }
  242. fileSizeInBytes := fileInfo.Size()
  243. //调用纠删码库,获取编码参数及生成矩阵
  244. ecPolicies := *utils.GetEcPolicy()
  245. ecPolicy := ecPolicies[ecName]
  246. ipss := utils.GetAgentIps()
  247. fmt.Println(ipss)
  248. print("@!@!@!@!@!@!")
  249. //var policy utils.EcConfig
  250. //policy = ecPolicy[0]
  251. ecK := ecPolicy.GetK()
  252. ecN := ecPolicy.GetN()
  253. //const ecK int = ecPolicy.GetK()
  254. //const ecN int = ecPolicy.GetN()
  255. var coefs = [][]int64{{1, 1, 1}, {1, 2, 3}} //2应替换为ecK,3应替换为ecN
  256. //计算每个块的packet数
  257. numPacket := (fileSizeInBytes + int64(ecK)*packetSizeInBytes - 1) / (int64(ecK) * packetSizeInBytes)
  258. fmt.Println(numPacket)
  259. userId := 0
  260. coorClient, err := raclient.NewCoordinatorClient()
  261. if err != nil {
  262. return fmt.Errorf("create coordinator client failed, err: %w", err)
  263. }
  264. defer coorClient.Close()
  265. //发送写请求,请求Coor分配写入节点Ip
  266. ecWriteResp, err := coorClient.ECWrite(bucketName, objectName, fileSizeInBytes, ecName, userId)
  267. if err != nil {
  268. return fmt.Errorf("request to coordinator failed, err: %w", err)
  269. }
  270. if ecWriteResp.ErrorCode != errorcode.OK {
  271. return fmt.Errorf("coordinator ECWrite failed, err: %w", err)
  272. }
  273. //创建channel
  274. loadBufs := make([]chan []byte, ecN)
  275. encodeBufs := make([]chan []byte, ecN)
  276. for i := 0; i < ecN; i++ {
  277. loadBufs[i] = make(chan []byte)
  278. }
  279. for i := 0; i < ecN; i++ {
  280. encodeBufs[i] = make(chan []byte)
  281. }
  282. blockNames := make([]string, ecN)
  283. for i := 0; i < ecN; i++ {
  284. blockNames[i] = (bucketName + "_" + objectName + "_" + strconv.Itoa(i))
  285. print(blockNames[i])
  286. print("miemiemie")
  287. }
  288. hashs := make([]string, ecN)
  289. //正式开始写入
  290. go load(localFilePath, loadBufs[:ecN], ecK, numPacket*int64(ecK), fileSizeInBytes) //从本地文件系统加载数据
  291. go encode(loadBufs[:ecN], encodeBufs[:ecN], ecK, coefs, numPacket)
  292. var wg sync.WaitGroup
  293. wg.Add(ecN)
  294. for i := 0; i < ecN; i++ {
  295. go send(blockNames[i], ecWriteResp.IPs[i], encodeBufs[i], numPacket, &wg, hashs, i)
  296. }
  297. wg.Wait()
  298. //第二轮通讯:插入元数据hashs
  299. writeRepHashResp, err := coorClient.WriteECHash(bucketName, objectName, hashs, ecWriteResp.IPs, userId)
  300. if err != nil {
  301. return fmt.Errorf("request to coordinator failed, err: %w", err)
  302. }
  303. if writeRepHashResp.ErrorCode != errorcode.OK {
  304. return fmt.Errorf("coordinator WriteECHash failed, err: %w", err)
  305. }
  306. return nil
  307. }
  308. func repMove(ip string, hash string) {
  309. //TO DO: 通过消息队列发送调度命令
  310. }
  311. func ecMove(ip string, hashs []string, ids []int, ecName string) {
  312. //TO DO: 通过消息队列发送调度命令
  313. }
  314. func loadDistribute(localFilePath string, loadDistributeBufs []chan []byte, numWholePacket int64, lastPacketInBytes int64) {
  315. fmt.Println("loadDistribute " + localFilePath)
  316. file, _ := os.Open(localFilePath)
  317. for i := 0; int64(i) < numWholePacket; i++ {
  318. buf := make([]byte, packetSizeInBytes)
  319. _, err := file.Read(buf)
  320. if err != nil && err != io.EOF {
  321. break
  322. }
  323. for j := 0; j < len(loadDistributeBufs); j++ {
  324. loadDistributeBufs[j] <- buf
  325. }
  326. }
  327. if lastPacketInBytes > 0 {
  328. buf := make([]byte, lastPacketInBytes)
  329. file.Read(buf)
  330. for j := 0; j < len(loadDistributeBufs); j++ {
  331. loadDistributeBufs[j] <- buf
  332. }
  333. }
  334. fmt.Println("load over")
  335. for i := 0; i < len(loadDistributeBufs); i++ {
  336. close(loadDistributeBufs[i])
  337. }
  338. file.Close()
  339. }
  340. func load(localFilePath string, loadBufs []chan []byte, ecK int, totalNumPacket int64, fileSizeInBytes int64) {
  341. fmt.Println("load " + localFilePath)
  342. file, _ := os.Open(localFilePath)
  343. for i := 0; int64(i) < totalNumPacket; i++ {
  344. print(totalNumPacket)
  345. buf := make([]byte, packetSizeInBytes)
  346. idx := i % ecK
  347. print(len(loadBufs))
  348. _, err := file.Read(buf)
  349. loadBufs[idx] <- buf
  350. if idx == ecK-1 {
  351. print("***")
  352. for j := ecK; j < len(loadBufs); j++ {
  353. print(j)
  354. zeroPkt := make([]byte, packetSizeInBytes)
  355. fmt.Printf("%v", zeroPkt)
  356. loadBufs[j] <- zeroPkt
  357. }
  358. }
  359. if err != nil && err != io.EOF {
  360. break
  361. }
  362. }
  363. fmt.Println("load over")
  364. for i := 0; i < len(loadBufs); i++ {
  365. print(i)
  366. close(loadBufs[i])
  367. }
  368. file.Close()
  369. }
  370. func encode(inBufs []chan []byte, outBufs []chan []byte, ecK int, coefs [][]int64, numPacket int64) {
  371. fmt.Println("encode ")
  372. var tmpIn [][]byte
  373. tmpIn = make([][]byte, len(outBufs))
  374. enc := ec.NewRsEnc(ecK, len(outBufs))
  375. for i := 0; int64(i) < numPacket; i++ {
  376. for j := 0; j < len(outBufs); j++ { //3
  377. tmpIn[j] = <-inBufs[j]
  378. //print(i)
  379. //fmt.Printf("%v",tmpIn[j])
  380. //print("@#$")
  381. }
  382. enc.Encode(tmpIn)
  383. fmt.Printf("%v", tmpIn)
  384. print("$$$$$$$$$$$$$$$$$$")
  385. for j := 0; j < len(outBufs); j++ { //1,2,3//示意,需要调用纠删码编解码引擎: tmp[k] = tmp[k]+(tmpIn[w][k]*coefs[w][j])
  386. outBufs[j] <- tmpIn[j]
  387. }
  388. }
  389. fmt.Println("encode over")
  390. for i := 0; i < len(outBufs); i++ {
  391. close(outBufs[i])
  392. }
  393. }
  394. func decode(inBufs []chan []byte, outBufs []chan []byte, blockSeq []int, ecK int, coefs [][]int64, numPacket int64) {
  395. fmt.Println("decode ")
  396. var tmpIn [][]byte
  397. var zeroPkt []byte
  398. tmpIn = make([][]byte, len(inBufs))
  399. hasBlock := map[int]bool{}
  400. for j := 0; j < len(blockSeq); j++ {
  401. hasBlock[blockSeq[j]] = true
  402. }
  403. needRepair := false //检测是否传入了所有数据块
  404. for j := 0; j < len(outBufs); j++ {
  405. if blockSeq[j] != j {
  406. needRepair = true
  407. }
  408. }
  409. enc := ec.NewRsEnc(ecK, len(inBufs))
  410. for i := 0; int64(i) < numPacket; i++ {
  411. for j := 0; j < len(inBufs); j++ { //3
  412. if hasBlock[j] {
  413. tmpIn[j] = <-inBufs[j]
  414. } else {
  415. tmpIn[j] = zeroPkt
  416. }
  417. }
  418. fmt.Printf("%v", tmpIn)
  419. if needRepair {
  420. err := enc.Repair(tmpIn)
  421. print("&&&&&")
  422. if err != nil {
  423. fmt.Fprintf(os.Stderr, "Decode Repair Error: %s", err.Error())
  424. }
  425. }
  426. //fmt.Printf("%v",tmpIn)
  427. for j := 0; j < len(outBufs); j++ { //1,2,3//示意,需要调用纠删码编解码引擎: tmp[k] = tmp[k]+(tmpIn[w][k]*coefs[w][j])
  428. outBufs[j] <- tmpIn[j]
  429. }
  430. }
  431. fmt.Println("decode over")
  432. for i := 0; i < len(outBufs); i++ {
  433. close(outBufs[i])
  434. }
  435. }
  436. func send(blockName string, ip string, inBuf chan []byte, numPacket int64, wg *sync.WaitGroup, hashs []string, idx int) {
  437. fmt.Println("send " + blockName)
  438. /*
  439. TO DO ss: 判断本地有没有ipfs daemon、能否与目标agent的ipfs daemon连通、本地ipfs目录空间是否充足
  440. 如果本地有ipfs daemon、能与目标agent的ipfs daemon连通、本地ipfs目录空间充足,将所有内容写入本地ipfs目录,得到对象的cid,发送cid给目标agent让其pin相应的对象
  441. 否则,像目前一样,使用grpc向指定节点获取
  442. */
  443. //rpc相关
  444. conn, err := grpc.Dial(ip+port, grpc.WithInsecure())
  445. if err != nil {
  446. panic(err)
  447. }
  448. client := agentcaller.NewTranBlockOrReplicaClient(conn)
  449. stream, err := client.SendBlockOrReplica(context.Background())
  450. if err != nil {
  451. panic(err)
  452. }
  453. for i := 0; int64(i) < numPacket; i++ {
  454. buf := <-inBuf
  455. fmt.Println(buf)
  456. err := stream.Send(&agentcaller.BlockOrReplica{
  457. BlockOrReplicaName: blockName,
  458. BlockOrReplicaHash: blockName,
  459. BlockOrReplicaData: buf,
  460. })
  461. if err != nil && err != io.EOF {
  462. panic(err)
  463. }
  464. }
  465. res, err := stream.CloseAndRecv()
  466. fmt.Println(res)
  467. hashs[idx] = res.BlockOrReplicaHash
  468. conn.Close()
  469. wg.Done()
  470. return
  471. }
  472. func get(blockHash string, ip string, getBuf chan []byte, numPacket int64) {
  473. //rpc相关
  474. print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
  475. conn, err := grpc.Dial(ip+port, grpc.WithInsecure())
  476. if err != nil {
  477. panic(err)
  478. }
  479. /*
  480. TO DO: 判断本地有没有ipfs daemon、能否获取相应对象的cid
  481. 如果本地有ipfs daemon且能获取相应编码块的cid,则获取编码块cid对应的ipfsblock的cid,通过ipfs网络获取这些ipfsblock
  482. 否则,像目前一样,使用grpc向指定节点获取
  483. */
  484. client := agentcaller.NewTranBlockOrReplicaClient(conn)
  485. //rpc get
  486. stream, _ := client.GetBlockOrReplica(context.Background(), &agentcaller.GetReq{
  487. BlockOrReplicaHash: blockHash,
  488. })
  489. fmt.Println(numPacket)
  490. for i := 0; int64(i) < numPacket; i++ {
  491. fmt.Println(i)
  492. res, _ := stream.Recv()
  493. fmt.Println(res.BlockOrReplicaData)
  494. getBuf <- res.BlockOrReplicaData
  495. }
  496. close(getBuf)
  497. conn.Close()
  498. }
  499. func persist(inBuf []chan []byte, numPacket int64, localFilePath string, wg *sync.WaitGroup) {
  500. fDir, err := os.Executable()
  501. if err != nil {
  502. panic(err)
  503. }
  504. fURL := filepath.Join(filepath.Dir(fDir), "assets")
  505. _, err = os.Stat(fURL)
  506. if os.IsNotExist(err) {
  507. os.MkdirAll(fURL, os.ModePerm)
  508. }
  509. file, err := os.Create(filepath.Join(fURL, localFilePath))
  510. if err != nil {
  511. return
  512. }
  513. for i := 0; int64(i) < numPacket; i++ {
  514. for j := 0; j < len(inBuf); j++ {
  515. tmp := <-inBuf[j]
  516. fmt.Println(tmp)
  517. file.Write(tmp)
  518. }
  519. }
  520. file.Close()
  521. wg.Done()
  522. }

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