|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- package cmd
-
- import (
- "fmt"
- "io/fs"
- "io/ioutil"
- "os"
- "path/filepath"
- "sync"
- "time"
-
- "github.com/samber/lo"
- "gitlink.org.cn/cloudream/agent/internal/config"
- "gitlink.org.cn/cloudream/agent/internal/task"
- "gitlink.org.cn/cloudream/common/consts"
- "gitlink.org.cn/cloudream/common/pkg/logger"
- log "gitlink.org.cn/cloudream/common/pkg/logger"
- "gitlink.org.cn/cloudream/common/utils"
- "gitlink.org.cn/cloudream/common/utils/serder"
- "gitlink.org.cn/cloudream/ec"
-
- "gitlink.org.cn/cloudream/common/consts/errorcode"
- ramsg "gitlink.org.cn/cloudream/rabbitmq/message"
- agtmsg "gitlink.org.cn/cloudream/rabbitmq/message/agent"
- )
-
- func (service *Service) StartMovingObjectToStorage(msg *agtmsg.StartMovingObjectToStorage) (*agtmsg.StartMovingObjectToStorageResp, *ramsg.CodeMessage) {
- outFileName := utils.MakeMoveOperationFileName(msg.ObjectID, msg.UserID)
- outFilePath := filepath.Join(config.Cfg().StorageBaseDir, msg.Directory, outFileName)
-
- if msg.Redundancy == consts.REDUNDANCY_REP {
- taskID, err := service.moveRepObject(msg, outFilePath)
- if err != nil {
- logger.Warnf("move rep object as %s failed, err: %s", outFilePath, err.Error())
- return ramsg.ReplyFailed[agtmsg.StartMovingObjectToStorageResp](errorcode.OPERATION_FAILED, "move rep object failed")
- }
-
- return ramsg.ReplyOK(agtmsg.NewStartMovingObjectToStorageResp(taskID))
-
- } else {
- // TODO 处理其他备份类型
-
- return ramsg.ReplyFailed[agtmsg.StartMovingObjectToStorageResp](errorcode.OPERATION_FAILED, "not implement yet!")
- }
- }
-
- func (svc *Service) moveRepObject(msg *agtmsg.StartMovingObjectToStorage, outFilePath string) (string, error) {
- var repInfo ramsg.ObjectRepInfo
- err := serder.MapToObject(msg.RedundancyData.(map[string]any), &repInfo)
- if err != nil {
- return "", fmt.Errorf("redundancy data to rep info failed, err: %w", err)
- }
-
- tsk := svc.taskManager.StartComparable(task.NewIPFSRead(repInfo.FileHash, outFilePath))
- return tsk.ID(), nil
- }
-
- func (svc *Service) WaitMovingObject(msg *agtmsg.WaitMovingObject) (*agtmsg.WaitMovingObjectResp, *ramsg.CodeMessage) {
- log.WithField("TaskID", msg.TaskID).Debugf("wait moving object")
-
- tsk := svc.taskManager.FindByID(msg.TaskID)
- if tsk == nil {
- return ramsg.ReplyFailed[agtmsg.WaitMovingObjectResp](errorcode.TASK_NOT_FOUND, "task not found")
- }
-
- if msg.WaitTimeoutMs == 0 {
- tsk.Wait()
-
- errMsg := ""
- if tsk.Error() != nil {
- errMsg = tsk.Error().Error()
- }
-
- return ramsg.ReplyOK(agtmsg.NewWaitMovingObjectResp(true, errMsg))
-
- } else {
- if tsk.WaitTimeout(time.Duration(msg.WaitTimeoutMs)) {
-
- errMsg := ""
- if tsk.Error() != nil {
- errMsg = tsk.Error().Error()
- }
-
- return ramsg.ReplyOK(agtmsg.NewWaitMovingObjectResp(true, errMsg))
- }
-
- return ramsg.ReplyOK(agtmsg.NewWaitMovingObjectResp(false, ""))
- }
- }
-
- func (svc *Service) CheckStorage(msg *agtmsg.CheckStorage) (*agtmsg.CheckStorageResp, *ramsg.CodeMessage) {
- dirFullPath := filepath.Join(config.Cfg().StorageBaseDir, msg.Directory)
-
- infos, err := ioutil.ReadDir(dirFullPath)
- if err != nil {
- logger.Warnf("list storage directory failed, err: %s", err.Error())
- return ramsg.ReplyOK(agtmsg.NewCheckStorageResp(
- err.Error(),
- nil,
- ))
- }
-
- fileInfos := lo.Filter(infos, func(info fs.FileInfo, index int) bool { return !info.IsDir() })
-
- if msg.IsComplete {
- return svc.checkStorageComplete(msg, fileInfos)
- } else {
- return svc.checkStorageIncrement(msg, fileInfos)
- }
- }
-
- func (svc *Service) checkStorageIncrement(msg *agtmsg.CheckStorage, fileInfos []fs.FileInfo) (*agtmsg.CheckStorageResp, *ramsg.CodeMessage) {
- infosMap := make(map[string]fs.FileInfo)
- for _, info := range fileInfos {
- infosMap[info.Name()] = info
- }
-
- var entries []agtmsg.CheckStorageRespEntry
- for _, obj := range msg.Objects {
- fileName := utils.MakeMoveOperationFileName(obj.ObjectID, obj.UserID)
- _, ok := infosMap[fileName]
-
- if ok {
- // 不需要做处理
- // 删除map中的记录,表示此记录已被检查过
- delete(infosMap, fileName)
-
- } else {
- // 只要文件不存在,就删除StorageObject表中的记录
- entries = append(entries, agtmsg.NewCheckStorageRespEntry(obj.ObjectID, obj.UserID, agtmsg.CHECK_STORAGE_RESP_OP_DELETE))
- }
- }
-
- // 增量情况下,不需要对infosMap中没检查的记录进行处理
-
- return ramsg.ReplyOK(agtmsg.NewCheckStorageResp(consts.STORAGE_DIRECTORY_STATE_OK, entries))
- }
-
- func (svc *Service) checkStorageComplete(msg *agtmsg.CheckStorage, fileInfos []fs.FileInfo) (*agtmsg.CheckStorageResp, *ramsg.CodeMessage) {
-
- infosMap := make(map[string]fs.FileInfo)
- for _, info := range fileInfos {
- infosMap[info.Name()] = info
- }
-
- var entries []agtmsg.CheckStorageRespEntry
- for _, obj := range msg.Objects {
- fileName := utils.MakeMoveOperationFileName(obj.ObjectID, obj.UserID)
- _, ok := infosMap[fileName]
-
- if ok {
- // 不需要做处理
- // 删除map中的记录,表示此记录已被检查过
- delete(infosMap, fileName)
-
- } else {
- // 只要文件不存在,就删除StorageObject表中的记录
- entries = append(entries, agtmsg.NewCheckStorageRespEntry(obj.ObjectID, obj.UserID, agtmsg.CHECK_STORAGE_RESP_OP_DELETE))
- }
- }
-
- // Storage中多出来的文件不做处理
-
- return ramsg.ReplyOK(agtmsg.NewCheckStorageResp(consts.STORAGE_DIRECTORY_STATE_OK, entries))
- }
-
- /*
- func (service *Service) ECMove(msg *agtmsg.ECMoveCommand) *agtmsg.StartMovingObjectToStorageResp {
- panic("not implement yet!")
- wg := sync.WaitGroup{}
- fmt.Println("EcMove")
- fmt.Println(msg.Hashs)
- hashs := msg.Hashs
- fileSize := msg.FileSize
- blockIds := msg.IDs
- ecName := msg.ECName
- goalName := msg.BucketName + ":" + msg.ObjectName + ":" + strconv.Itoa(msg.UserID)
- ecPolicies := *utils.GetEcPolicy()
- ecPolicy := ecPolicies[ecName]
- ecK := ecPolicy.GetK()
- ecN := ecPolicy.GetN()
- numPacket := (fileSize + int64(ecK)*int64(config.Cfg().GRCPPacketSize) - 1) / (int64(ecK) * int64(config.Cfg().GRCPPacketSize))
-
- getBufs := make([]chan []byte, ecN)
- decodeBufs := make([]chan []byte, ecK)
- for i := 0; i < ecN; i++ {
- getBufs[i] = make(chan []byte)
- }
- for i := 0; i < ecK; i++ {
- decodeBufs[i] = make(chan []byte)
- }
-
- wg.Add(1)
-
- //执行调度操作
- // TODO 这一块需要改写以适配IPFS流式读取
- for i := 0; i < len(blockIds); i++ {
- go service.get(hashs[i], getBufs[blockIds[i]], numPacket)
- }
- go decode(getBufs[:], decodeBufs[:], blockIds, ecK, numPacket)
- // TODO 写入的文件路径需要带上msg中的Directory字段,参考RepMove
- go persist(decodeBufs[:], numPacket, goalName, &wg)
- wg.Wait()
-
- //向coor报告临时缓存hash
- coorClient, err := racli.NewCoordinatorClient()
- if err != nil {
- // TODO 日志
- return ramsg.NewAgentMoveRespFailed(errorcode.OPERATION_FAILED, fmt.Sprintf("create coordinator client failed"))
- }
- defer coorClient.Close()
- coorClient.TempCacheReport(NodeID, hashs)
-
- return ramsg.NewAgentMoveRespOK()
- }
- */
-
- func decode(inBufs []chan []byte, outBufs []chan []byte, blockSeq []int, ecK int, numPacket int64) {
- fmt.Println("decode ")
- var tmpIn [][]byte
- var zeroPkt []byte
- tmpIn = make([][]byte, len(inBufs))
- hasBlock := map[int]bool{}
- for j := 0; j < len(blockSeq); j++ {
- hasBlock[blockSeq[j]] = true
- }
- needRepair := false //检测是否传入了所有数据块
- for j := 0; j < len(outBufs); j++ {
- if blockSeq[j] != j {
- needRepair = true
- }
- }
- enc := ec.NewRsEnc(ecK, len(inBufs))
- for i := 0; int64(i) < numPacket; i++ {
- for j := 0; j < len(inBufs); j++ { //3
- if hasBlock[j] {
- tmpIn[j] = <-inBufs[j]
- } else {
- tmpIn[j] = zeroPkt
- }
- }
- fmt.Printf("%v", tmpIn)
- if needRepair {
- err := enc.Repair(tmpIn)
- print("&&&&&")
- if err != nil {
- fmt.Fprintf(os.Stderr, "Decode Repair Error: %s", err.Error())
- }
- }
- //fmt.Printf("%v",tmpIn)
-
- for j := 0; j < len(outBufs); j++ { //1,2,3//示意,需要调用纠删码编解码引擎: tmp[k] = tmp[k]+(tmpIn[w][k]*coefs[w][j])
- outBufs[j] <- tmpIn[j]
- }
- }
- fmt.Println("decode over")
- for i := 0; i < len(outBufs); i++ {
- close(outBufs[i])
- }
- }
-
- func (service *Service) get(blockHash string, getBuf chan []byte, numPacket int64) {
- /*
- data := CatIPFS(blockHash)
- for i := 0; int64(i) < numPacket; i++ {
- buf := []byte(data[i*config.Cfg().GRCPPacketSize : i*config.Cfg().GRCPPacketSize+config.Cfg().GRCPPacketSize])
- getBuf <- buf
- }
- close(getBuf)
- */
- }
-
- func persist(inBuf []chan []byte, numPacket int64, localFilePath string, wg *sync.WaitGroup) {
- //这里的localFilePath应该是要写入的filename
- fDir, err := os.Executable()
- if err != nil {
- panic(err)
- }
- fURL := filepath.Join(filepath.Dir(fDir), "assets3")
- _, err = os.Stat(fURL)
- if os.IsNotExist(err) {
- os.MkdirAll(fURL, os.ModePerm)
- }
-
- file, err := os.Create(filepath.Join(fURL, localFilePath))
- if err != nil {
- return
- }
-
- for i := 0; int64(i) < numPacket; i++ {
- for j := 0; j < len(inBuf); j++ {
- tmp := <-inBuf[j]
- fmt.Println(tmp)
- file.Write(tmp)
- }
- }
- file.Close()
- wg.Done()
- }
|