├── .idea ├── .gitignore ├── FayDFS.iml └── modules.xml ├── Development Handbook.pdf ├── README.md ├── client ├── client.go └── service │ └── clientAPI.go ├── config ├── config.yaml └── setting.go ├── datanode ├── dd_test.go ├── main.go ├── message │ └── message.go └── service │ ├── dataNode.go │ └── dataNode_test.go ├── go.mod ├── go.sum ├── namenode ├── main.go └── service │ ├── leaseManger.go │ ├── leveldb.go │ └── nameNode.go ├── proto ├── faydfs.pb.go ├── faydfs.proto └── faydfs_grpc.pb.go ├── public ├── const.go ├── errors.go └── util.go └── test.go /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/FayDFS.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Development Handbook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kirov7/FayDFS/a55bdf80b41d3fd6e6f5e674ce13e2bd3f47933d/Development Handbook.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 字节跳动青训营-大数据方向【作业三】简易的分布式存储 2 | 3 | ## 项目介绍 4 | 5 | **队名:提前批能不能别挂简历了队 队号:3306** 6 | 7 | 本项目基于Go语言以及ProtoBuf&gRPC通信协议,利用git进行了项目管理,参考了GFS的框架完成了一个简易分布式存储系统,利用Raft实现了元数据服务的一致性共识模块,并利用LevelDB持久化存储的元数据内容。 8 | 9 | ## 项目架构 10 | 11 | 本团队所设计的分布式存储系统参考了传统GFS设计,基础结构共分为三大块,分别是clinent、namenode、和datanode。 12 | 13 | - **clinent**主要负责和用户直接进行交互,是用户无感知的使用项目的相关通用接口来获取,管理,和存储数据。 14 | - **namenode**主要负责元数据的管理,是整个系统管理的核心,任何数据的读取存储都需要通过namenode来处理,为了降低整体项目的复杂度,整个项目仅有一个处于工作状态的namenode,详细的流程设计将会在开发文档中阐述。 15 | - **datanode**主要负责数据的存储,本项目的datanode设计为类似于GFS的chunk设计,在代码中体现为block。每一个datanode拥有若干个block,而每个bolck将存储文件的部分内容,实现多副本存储以及,将文件分布式存储的效果。 16 | 17 | **(详见的运行流程和设计请参考下方链接的答辩文档及其中的开发手册)** 18 | 19 | [答辩文档 - 飞书文档 (feishu.cn)](https://bqn8fhqijw.feishu.cn/docx/doxcnAajUj9AdPhzgYUsRQd1Wnd) 20 | > 注: 项目架构与具体细节以主分支最新源代码为准 21 | --- 22 | 该项目最终获得了日月同辉奖 23 | ![QQ截图20220906120452.png](http://tva1.sinaimg.cn/large/005Uj3w8ly1h5wr9wu2hyj30v7011q3n.jpg) 24 | 25 | ## TODO 26 | 1. 基于raft搭建nn集群 (自搭raft框架) 27 | 2. cmd目录设置,方法入口优化 28 | 3. 编写Makefile文件 29 | 4. ~~文件目录树数采用B-树优化(经调研后发现没有此项优化的必要)~~ 30 | 5. ~~dn接受后的数据转发优化 (目前仍是client多次连接发送数据)~~ 31 | 6. ~~新增节点直接追加,缺少判断 (可能出现节点重复添加的问题)~~ 32 | 7. ~~namenode结构体优化,leveldb三库合并~~ 33 | 8. ~~datanodeList改用集合的数据结构,快速定位避免重复~~ 34 | 9. ~~json配置文件优化 (采用.yaml或者.toml)~~ 35 | 10. ~~副本转移后元数据即时更新~~ 36 | 11. 垃圾回收机制 37 | 12. namenode部分方法两个阶段propose合并,增加简单的undo回滚机制 38 | 13. client的put操作优化长连接 39 | 14. client缓存namenode的leader地址信息 40 | 15. datanode数据的校验和 41 | 16. datanode采用EC纠删码节省冗余空间 42 | 17. datanode节点挂掉时,在副本转移之后在datanodeList中删除 (必要性有待讨论) 43 | -------------------------------------------------------------------------------- /client/client.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "faydfs/client/service" 7 | "faydfs/config" 8 | "faydfs/proto" 9 | "fmt" 10 | "github.com/satori/go.uuid" 11 | "google.golang.org/grpc" 12 | "io" 13 | "io/ioutil" 14 | "log" 15 | "os" 16 | "strings" 17 | "time" 18 | ) 19 | 20 | var ( 21 | conf = config.GetConfig() 22 | address = conf.NameNode.NameNodeHost + conf.NameNode.NameNodePort 23 | blocksize = conf.Block.BlockSize 24 | leaselimit = conf.Lease.LeaseSoftLimit 25 | replica = conf.Block.Replica 26 | blocknum int64 27 | renewleaseExit bool //采用全局变量结束续约协程 28 | clint = Client{ // uuid生成唯一标识 29 | clientname: uuid.NewV4().String(), 30 | } 31 | ) 32 | 33 | type Client struct { 34 | clientname string 35 | } 36 | 37 | func GetClient() Client { 38 | return clint 39 | } 40 | func (c *Client) Put(localFilePath, remoteFilePath string) service.Result { 41 | //io打开文件查看文件大小 42 | date, err := ioutil.ReadFile(localFilePath) 43 | size, _ := os.Stat(localFilePath) //stat方法来获取文件信息 44 | var filesize = size.Size() 45 | if int64(len(date))%blocksize != 0 { 46 | blocknum = (int64(len(date)) / blocksize) + 1 47 | } else { 48 | blocknum = int64(len(date)) / blocksize 49 | } 50 | if err != nil { 51 | log.Fatalf("not found localfile") 52 | } 53 | //将字节流写入分布式文件系统 54 | //未putsuccess前自动周期续约 55 | ticker := time.NewTicker(time.Second * time.Duration(leaselimit/2)) // 创建半个周期定时器 56 | 57 | //运行续约协程执行周期续约 58 | //ticker := time.NewTicker(5 * time.Second) 59 | go func() { 60 | for { 61 | select { 62 | case <-ticker.C: 63 | go func() { 64 | renewLease(localFilePath, clint.clientname) 65 | if renewleaseExit { 66 | return 67 | } 68 | }() 69 | } 70 | } 71 | }() 72 | filelocationarr, isture := write(remoteFilePath, date, blocknum) 73 | // write成功 74 | if isture { 75 | // 告知metanode,datanode数据传输完成 76 | conn, client, _, _ := getGrpcC2NConn(address) 77 | defer conn.Close() 78 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 79 | defer cancel() 80 | stuats, err := (*client).PutSuccess(ctx, &proto.MetaStore{ 81 | ClientName: clint.clientname, 82 | FilePath: remoteFilePath, 83 | FileLocationArr: filelocationarr, 84 | FileSize: uint64(filesize), 85 | }) 86 | 87 | if err != nil { 88 | log.Fatalf("write could not greet: %v", err) 89 | } 90 | //put成功 91 | if stuats.Success { 92 | //立即停止续约协程 93 | renewleaseExit = true 94 | return service.Result{ 95 | ResultCode: 200, 96 | ResultExtraMsg: " successes put", 97 | Data: stuats, 98 | } 99 | } else { // put失败 100 | return service.Result{ 101 | ResultCode: 500, 102 | ResultExtraMsg: "fail put", 103 | Data: err, 104 | } 105 | } 106 | } else { // write失败 107 | //log.Fatalf("fail put") 108 | return service.Result{ 109 | ResultCode: 500, 110 | ResultExtraMsg: "fail put", 111 | Data: err, 112 | } 113 | } 114 | } 115 | 116 | func (c *Client) Get(remoteFilePath, localFilePath string) service.Result { 117 | date := read(remoteFilePath) 118 | localfile, err := os.Create(localFilePath) 119 | if err != nil { 120 | log.Fatalf("create localfile fail") 121 | } 122 | defer localfile.Close() 123 | //fmt.Println("client get data: ", date) 124 | _, err = localfile.Write(date) 125 | if err != nil { 126 | //log.Fatalf("write to local fail") 127 | return service.Result{ 128 | ResultCode: 500, 129 | ResultExtraMsg: "write to local fail", 130 | Data: err, 131 | } 132 | } 133 | return service.Result{ 134 | ResultCode: 200, 135 | ResultExtraMsg: "write to local success", 136 | Data: localFilePath, 137 | } 138 | } 139 | 140 | func (c *Client) Delete(remoteFilePath string) service.Result { 141 | conn, client, _, _ := getGrpcC2NConn(address) 142 | defer conn.Close() 143 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 144 | defer cancel() 145 | status, err := (*client).OperateMeta(ctx, &proto.FileNameAndOperateMode{FileName: remoteFilePath, Mode: proto.FileNameAndOperateMode_DELETE}) 146 | if err != nil { 147 | return service.Result{ 148 | ResultCode: 500, 149 | ResultExtraMsg: "delete fail", 150 | Data: err, 151 | } 152 | } 153 | return service.Result{ 154 | ResultCode: 200, 155 | ResultExtraMsg: "delete success", 156 | Data: status.Success, 157 | } 158 | } 159 | 160 | func (c *Client) Stat(remoteFilePath string) service.Result { 161 | conn, client, _, _ := getGrpcC2NConn(address) 162 | defer conn.Close() 163 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 164 | defer cancel() 165 | status, err := (*client).GetFileMeta(ctx, &proto.PathName{PathName: remoteFilePath}) 166 | if err != nil { 167 | return service.Result{ 168 | ResultCode: 500, 169 | ResultExtraMsg: "stat fail", 170 | Data: err, 171 | } 172 | } 173 | return service.Result{ 174 | ResultCode: 200, 175 | ResultExtraMsg: "stat success", 176 | Data: status, 177 | } 178 | } 179 | 180 | func (c *Client) Rename(renameSrcPath, renameDestPath string) service.Result { 181 | //限制rename 182 | src := strings.Split(renameSrcPath, "\\") 183 | des := strings.Split(renameDestPath, "\\") 184 | if len(src) != len(des) { 185 | log.Fatalf("you can not change dir") 186 | return service.Result{} 187 | } else { 188 | for i := 0; i < len(src)-1; i++ { 189 | if src[i] != des[i] { 190 | log.Fatalf("you can not change dir") 191 | return service.Result{} 192 | } 193 | } 194 | } 195 | conn, client, _, _ := getGrpcC2NConn(address) 196 | defer conn.Close() 197 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 198 | defer cancel() 199 | status, err := (*client).RenameFileInMeta(ctx, &proto.SrcAndDestPath{RenameSrcPath: renameSrcPath, RenameDestPath: renameDestPath}) 200 | if err != nil { 201 | return service.Result{ 202 | ResultCode: 500, 203 | ResultExtraMsg: "rename fail", 204 | Data: err, 205 | } 206 | } 207 | return service.Result{ 208 | ResultCode: 200, 209 | ResultExtraMsg: "reneme success", 210 | Data: status.Success, 211 | } 212 | } 213 | 214 | func (c *Client) Mkdir(remoteFilePath string) service.Result { 215 | conn, client, _, _ := getGrpcC2NConn(address) 216 | defer conn.Close() 217 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 218 | defer cancel() 219 | status, err := (*client).OperateMeta(ctx, &proto.FileNameAndOperateMode{FileName: remoteFilePath, Mode: proto.FileNameAndOperateMode_MKDIR}) 220 | if err != nil { 221 | return service.Result{ 222 | ResultCode: 500, 223 | ResultExtraMsg: "mkdir fail", 224 | Data: err, 225 | } 226 | } 227 | return service.Result{ 228 | ResultCode: 200, 229 | ResultExtraMsg: "mkdir success", 230 | Data: status.Success, 231 | } 232 | } 233 | 234 | func (c *Client) List(remoteDirPath string) service.Result { 235 | conn, client, _, _ := getGrpcC2NConn(address) 236 | defer conn.Close() 237 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 238 | defer cancel() 239 | status, err := (*client).GetDirMeta(ctx, &proto.PathName{PathName: remoteDirPath}) 240 | if err != nil { 241 | return service.Result{ 242 | ResultCode: 500, 243 | ResultExtraMsg: "show list fail", 244 | Data: err, 245 | } 246 | } 247 | return service.Result{ 248 | ResultCode: 200, 249 | ResultExtraMsg: "show list success", 250 | Data: status, 251 | } 252 | } 253 | 254 | func getGrpcC2NConn(address string) (*grpc.ClientConn, *proto.C2NClient, *context.CancelFunc, error) { 255 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 256 | conn, err := grpc.DialContext(ctx, address, grpc.WithBlock(), grpc.WithInsecure()) 257 | //conn2, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) 258 | if err != nil { 259 | log.Println("did not connect to %v error %v", address, err) 260 | } 261 | client := proto.NewC2NClient(conn) 262 | return conn, &client, &cancel, err 263 | } 264 | 265 | func getGrpcC2DConn(address string) (*grpc.ClientConn, *proto.C2DClient, *context.CancelFunc, error) { 266 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 267 | // 加入了WithInsecure 268 | conn, err := grpc.DialContext(ctx, address, grpc.WithBlock(), grpc.WithInsecure()) 269 | //conn2, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) 270 | if err != nil { 271 | log.Println("C2N did not connect to %v error %v", address, err) 272 | } 273 | client := proto.NewC2DClient(conn) 274 | return conn, &client, &cancel, err 275 | } 276 | 277 | // 整合readBlock的分片返回上层 278 | func read(remoteFilePath string) []byte { 279 | //1. 调用getFileLocation从namenode读取文件在datanode中分片位置的数组 280 | //这里传的是无用的参数blocknum:3 281 | filelocationarr := getFileLocation(remoteFilePath, proto.FileNameAndMode_READ, blocknum) 282 | blocklist := filelocationarr.FileBlocksList 283 | file := make([]byte, 0) 284 | for _, blockreplicas := range blocklist { 285 | replicalist := blockreplicas.BlockReplicaList 286 | for j, block := range replicalist { 287 | tempblock, err := ReadBlock(block.BlockName, block.IpAddr) 288 | if err != nil { 289 | if j == replica-1 { 290 | log.Fatal("datanode doesn't work") 291 | return nil 292 | } 293 | continue 294 | } 295 | file = append(file, tempblock...) 296 | break 297 | } 298 | } 299 | //2. 按照分片数组的位置调用readBlock循环依次读取 300 | return file 301 | } 302 | 303 | // 连接dn,读取文件内容 304 | func ReadBlock(chunkName, ipAddr string) ([]byte, error) { 305 | //1. 获取rpc连接 306 | conn, client, cancel1, err := getGrpcC2DConn(ipAddr) 307 | if conn == nil { 308 | return nil, err 309 | } 310 | defer (*cancel1)() 311 | defer conn.Close() 312 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) 313 | defer cancel() 314 | fileSteam, err := (*client).GetBlock(ctx, &proto.FileNameAndMode{FileName: chunkName}) 315 | if err != nil { 316 | log.Fatalf("error getting block %v", err) 317 | } 318 | chunkDate := bytes.Buffer{} 319 | for { 320 | res, err := fileSteam.Recv() 321 | if err == io.EOF { 322 | return chunkDate.Bytes(), nil 323 | } else if err != nil { 324 | return nil, err 325 | } 326 | chunkDate.Write(res.GetContent()) 327 | } 328 | } 329 | 330 | // 连接nn,获取文件路径 331 | func getFileLocation(fileName string, mode proto.FileNameAndMode_Mode, blocknum int64) *proto.FileLocationArr { 332 | conn, client, _, _ := getGrpcC2NConn(address) 333 | defer conn.Close() 334 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 335 | defer cancel() 336 | //blockname应该加在这里,所以block要从外层函数依次传参。对应的blocknum在read和wirte的mode都需要传入,但是只有write_Mode时blocknum才有用。 337 | filelocationarr, err := (*client).GetFileLocationAndModifyMeta(ctx, &proto.FileNameAndMode{FileName: fileName, Mode: mode, BlockNum: blocknum}) 338 | if err != nil { 339 | log.Fatalf("getFileLocation could not greet: %v", err) 340 | } 341 | return filelocationarr 342 | } 343 | 344 | // 返回申请的locationArray 345 | func createFileNameNode(fileName string) *proto.FileLocationArr { 346 | conn, client, cancel1, _ := getGrpcC2NConn(address) 347 | defer conn.Close() 348 | defer (*cancel1)() 349 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 350 | defer cancel() 351 | filelocationarr, err := (*client).CreateFile(ctx, &proto.FileNameAndMode{FileName: fileName, Mode: proto.FileNameAndMode_WRITE}) 352 | if err != nil { 353 | log.Fatalf("createFil could not greet: %v", err) 354 | } 355 | return filelocationarr 356 | } 357 | 358 | // 连接nn,创建文件/目录 359 | func createFile(file string) error { 360 | filelocation := createFileNameNode(file) 361 | fileblocks := filelocation.FileBlocksList 362 | blockreplicas := fileblocks[0] 363 | _ = DwriteBlock(blockreplicas.BlockReplicaList[0].IpAddr, make([]byte, 0), blockreplicas) 364 | for _, replica := range blockreplicas.BlockReplicaList { 365 | fmt.Println(replica.IpAddr, "IpAddress") 366 | fmt.Println(replica.BlockSize, "BlockName") 367 | } 368 | return nil 369 | } 370 | 371 | // 控制writeBlock写入文件 372 | //更改返回值使返回flielocationarr 373 | func write(fileName string, data []byte, blocknum int64) (*proto.FileLocationArr, bool) { 374 | //filelocation := getFileLocation(fileName, proto.FileNameAndMode_WRITE, blocknum) 375 | // 376 | //fmt.Println("==========init datalen: ", len(data), " blocknums:", blocknum) 377 | //for i := 0; i < int(blocknum); i++ { 378 | // //getFileLocation应该有第二个写入参数 379 | // blockreplicas := filelocation.FileBlocksList[i] 380 | // fmt.Println("==========filelocation: ", filelocation) 381 | // fmt.Println("==========blockreplicas: ", blockreplicas) 382 | // // TODO 383 | // //blockreplicity := blocksize - blockreplicas.BlockReplicaList[0].BlockSize 384 | // //limit := int64(len(data)) 385 | // //if blockreplicity > int64(len(data)) { 386 | // // limit = blockreplicity 387 | // //} 388 | // //filelocation: 389 | // //FileBlocksList:{ 390 | // // BlockReplicaList:{ipAddr:"localhost:8011" blockName:"test_1661353986_0" blockSize:128} 391 | // // BlockReplicaList:{ipAddr:"localhost:8012" blockName:"test_1661353986_1" blockSize:128 replicaID:1} 392 | // // BlockReplicaList:{ipAddr:"localhost:8010" blockName:"test_1661353986_2" blockSize:128 replicaID:2} 393 | // //} 394 | // //FileBlocksList:{ 395 | // // BlockReplicaList:{ipAddr:"localhost:8011" blockName:"test_1661353986_0" blockSize:128} 396 | // // BlockReplicaList:{ipAddr:"localhost:8012" blockName:"test_1661353986_1" blockSize:128 replicaID:1} 397 | // // BlockReplicaList:{ipAddr:"localhost:8010" blockName:"test_1661353986_2" blockSize:128 replicaID:2}} 398 | // //FileBlocksList:{ 399 | // // BlockReplicaList:{ipAddr:"localhost:8011" blockName:"test_1661353986_0" blockSize:128} 400 | // // BlockReplicaList:{ipAddr:"localhost:8012" blockName:"test_1661353986_1" blockSize:128 replicaID:1} 401 | // // BlockReplicaList:{ipAddr:"localhost:8010" blockName:"test_1661353986_2" blockSize:128 replicaID:2}} 402 | // if i == int(blocknum)-1 { 403 | // _ = DwriteBlock(blockreplicas.BlockReplicaList[1].IpAddr, data[i*int(blocksize):], blockreplicas) 404 | // fmt.Println("=======================写入最后一个文件: ", string(data[i*int(blocksize):])) 405 | // fmt.Println("ip :", blockreplicas.BlockReplicaList[1].IpAddr, "blockSize: ", blockreplicas.BlockReplicaList[1].BlockName) 406 | // } else { 407 | // _ = DwriteBlock(blockreplicas.BlockReplicaList[2].IpAddr, data[i*int(blocksize):(i+1)*int(blocksize)], blockreplicas) 408 | // fmt.Println("=======================写入第", i, "个文件: ", string(data[i*int(blocksize):(i+1)*int(blocksize)])) 409 | // fmt.Println("ip :", blockreplicas.BlockReplicaList[2].IpAddr, "blockSize: ", blockreplicas.BlockReplicaList[2].BlockName) 410 | // } 411 | //} 412 | // 413 | //return filelocation, true 414 | 415 | filelocation := getFileLocation(fileName, proto.FileNameAndMode_WRITE, blocknum) 416 | //fmt.Println("==========init datalen: ", len(data), " blocknums:", blocknum) 417 | for i := 0; i < int(blocknum); i++ { 418 | blockreplicas := filelocation.FileBlocksList[i] 419 | //fmt.Println("==========filelocation: ", filelocation) 420 | //fmt.Println("==========blockreplicas: ", blockreplicas) 421 | if i == int(blocknum)-1 { 422 | for j := 0; j < len(blockreplicas.BlockReplicaList); j++ { 423 | _ = DwriteBlock(blockreplicas.BlockReplicaList[j].IpAddr, data[i*int(blocksize):], blockreplicas) 424 | //fmt.Println("=======================写入最后一个文件: ", string(data[i*int(blocksize):])) 425 | //fmt.Println("ip :", blockreplicas.BlockReplicaList[j].IpAddr, "blockSize: ", blockreplicas.BlockReplicaList[1].BlockName) 426 | } 427 | } else { 428 | for j := 0; j < len(blockreplicas.BlockReplicaList); j++ { 429 | _ = DwriteBlock(blockreplicas.BlockReplicaList[j].IpAddr, data[i*int(blocksize):(i+1)*int(blocksize)], blockreplicas) 430 | //fmt.Println("=======================写入第", i, "个文件: ", string(data[i*int(blocksize):(i+1)*int(blocksize)])) 431 | //fmt.Println("ip :", blockreplicas.BlockReplicaList[j].IpAddr, "blockSize: ", blockreplicas.BlockReplicaList[j].BlockName) 432 | } 433 | } 434 | } 435 | 436 | return filelocation, true 437 | } 438 | 439 | // 连接dn,在块上写数据 440 | func DwriteBlock(ipAddr string, data []byte, blockReplicaList *proto.BlockReplicaList) error { 441 | conn, client, _, _ := getGrpcC2DConn(ipAddr) 442 | defer conn.Close() 443 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 444 | defer cancel() 445 | writeBlockClient, err := (*client).WriteBlock(ctx) 446 | if err != nil { 447 | return err 448 | } 449 | sentdatelength := 0 450 | chunkSize := 50 451 | err = writeBlockClient.Send(&proto.FileWriteStream{BlockReplicaList: blockReplicaList}) 452 | if err != nil { 453 | return err 454 | } 455 | for sentdatelength < len(data) { 456 | max := (sentdatelength + chunkSize) 457 | if max > len(data) { 458 | max = len(data) 459 | } 460 | chunk := data[sentdatelength:max] 461 | _ = writeBlockClient.Send(&proto.FileWriteStream{File: &proto.File{Content: chunk}}) 462 | sentdatelength = chunkSize + sentdatelength 463 | } 464 | _, err = writeBlockClient.CloseAndRecv() 465 | //fmt.Println(blockstatus) 466 | if err != nil { 467 | return err 468 | } 469 | return nil 470 | } 471 | 472 | // 连接nn,调用方法延续租约 473 | func renewLease(fileName string, clientname string) { 474 | conn, client, cancel1, _ := getGrpcC2NConn(address) 475 | defer (*cancel1)() 476 | defer conn.Close() 477 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 478 | defer cancel() 479 | res, err := (*client).RenewLock(ctx, &proto.GetLease{Pathname: &proto.PathName{PathName: fileName}, ClientName: clientname}) 480 | if err != nil { 481 | log.Fatalf("renewLease could not greet:%v", err) 482 | } 483 | if res.GetSuccess() { 484 | log.Printf("renewed lease") 485 | } else { 486 | log.Printf("not able to renew lease") 487 | } 488 | } 489 | -------------------------------------------------------------------------------- /client/service/clientAPI.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | type Result struct { 4 | ResultCode int `json:"code"` 5 | ResultExtraMsg string `json:"extra_msg"` 6 | Data interface{} `json:"data"` 7 | } 8 | 9 | type clientAPI interface { 10 | Put(localFilePath, remoteFilePath string) Result 11 | Get(remoteFilePath, localFilePath string) Result 12 | Delete(remoteFilePath string) Result 13 | Stat(remoteFilePath string) Result 14 | Rename(renameSrcPath, renameDestPath string) Result 15 | Mkdir(remoteFilePath string) Result 16 | List(remoteDirPath string) Result 17 | } 18 | -------------------------------------------------------------------------------- /config/config.yaml: -------------------------------------------------------------------------------- 1 | NameNode: 2 | # NameNode IP地址 3 | NameNodeHost: 127.0.0.1 4 | # NameNode端口 5 | NameNodePort: :8001 6 | # heartMonitor 心跳超时检测周期 7 | HeartbeatTimeout: 10 8 | 9 | DataNode: 10 | # DataNode 心跳发送周期 11 | HeartbeatInterval: 3 12 | # DataNode 块信息汇报周期 13 | BlockReportInterval: 3600000 14 | # DataNode 文件读写缓冲区大小 15 | IoSize: 100 16 | 17 | 18 | Block: 19 | # 存储快大小 20 | BlockSize: 128 21 | # 副本数 22 | Replica: 3 23 | 24 | Lease: 25 | # 租约软限制 26 | LeaseSoftLimit: 60000 27 | # 租约硬限制 28 | LeaseHardLimit: 3600000 29 | -------------------------------------------------------------------------------- /config/setting.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "fmt" 5 | "gopkg.in/yaml.v2" 6 | "io/ioutil" 7 | "log" 8 | ) 9 | 10 | type Config struct { 11 | NameNode *NameNode `yaml:"NameNode"` 12 | DataNode *DataNode `yaml:"DataNode"` 13 | Block *Block `yaml:"Block"` 14 | Lease *Lease `yaml:"Lease"` 15 | } 16 | 17 | type NameNode struct { 18 | NameNodePort string `yaml:"NameNodePort"` 19 | NameNodeHost string `yaml:"NameNodeHost"` 20 | HeartbeatTimeout int `yaml:"HeartbeatTimeout"` 21 | } 22 | type DataNode struct { 23 | HeartbeatInterval int `yaml:"HeartbeatInterval"` 24 | BlockReportInterval int `yaml:"BlockReportInterval"` 25 | IoSize int `yaml:"IoSize"` 26 | } 27 | type Block struct { 28 | BlockSize int64 `yaml:"BlockSize"` 29 | Replica int `yaml:"Replica"` 30 | } 31 | type Lease struct { 32 | LeaseSoftLimit int `yaml:"LeaseSoftLimit"` 33 | LeaseHardLimit int `yaml:"LeaseHardLimit"` 34 | } 35 | 36 | var conf *Config 37 | 38 | func GetConfig() *Config { 39 | return conf 40 | } 41 | 42 | func init() { 43 | file, err := ioutil.ReadFile("config/config.yaml") 44 | if err != nil { 45 | log.Fatal("fail to read file:", err) 46 | } 47 | 48 | err = yaml.Unmarshal(file, &conf) 49 | if err != nil { 50 | log.Fatal("fail to yaml unmarshal:", err) 51 | } 52 | fmt.Println("encode success") 53 | 54 | } 55 | -------------------------------------------------------------------------------- /datanode/dd_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "faydfs/client" 5 | "fmt" 6 | "log" 7 | "testing" 8 | ) 9 | 10 | func TestString(test *testing.T) { 11 | a := "localhost:8011" 12 | a = a[len(a)-1:] 13 | fmt.Println("localhost:5000" + a) 14 | } 15 | 16 | func TestDD(test *testing.T) { 17 | go PipelineServer("localhost:50001") 18 | go RunDataNode("localhost:8011") 19 | // 防止因为main中止造成协程中止 20 | defer func() { 21 | select {} 22 | }() 23 | } 24 | 25 | func TestDD2(test *testing.T) { 26 | go PipelineServer("localhost:50002") 27 | go RunDataNode("localhost:8012") 28 | // 防止因为main中止造成协程中止 29 | defer func() { 30 | select {} 31 | }() 32 | } 33 | 34 | func TestDD3(test *testing.T) { 35 | go PipelineServer("localhost:50003") 36 | go RunDataNode("localhost:8013") 37 | // 防止因为main中止造成协程中止 38 | defer func() { 39 | select {} 40 | }() 41 | } 42 | 43 | func TestDD4(test *testing.T) { 44 | go PipelineServer("localhost:50004") 45 | go RunDataNode("localhost:8014") 46 | // 防止因为main中止造成协程中止 47 | defer func() { 48 | select {} 49 | }() 50 | } 51 | 52 | func TestClientPut(t *testing.T) { 53 | user := client.GetClient() 54 | result := user.Put("D:\\testGPU.py", "/test") 55 | if result.ResultCode != 200 { 56 | log.Fatal(result.Data) 57 | return 58 | } 59 | fmt.Println(result.ResultExtraMsg) 60 | } 61 | -------------------------------------------------------------------------------- /datanode/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "faydfs/config" 7 | message2 "faydfs/datanode/message" 8 | datanode "faydfs/datanode/service" 9 | "faydfs/proto" 10 | "flag" 11 | "fmt" 12 | "github.com/shirou/gopsutil/v3/disk" 13 | "google.golang.org/grpc" 14 | "io" 15 | "log" 16 | "net" 17 | "os" 18 | "strings" 19 | "sync" 20 | "time" 21 | ) 22 | 23 | var ( 24 | conf = config.GetConfig() 25 | nameNodeHostURL = conf.NameNode.NameNodeHost + conf.NameNode.NameNodePort 26 | heartbeatInterval = conf.DataNode.HeartbeatInterval 27 | ) 28 | 29 | // GetIP 获取本机IP 30 | func GetIP() string { 31 | conn, err := net.Dial("udp", "8.8.8.8:80") 32 | if err != nil { 33 | log.Fatal(err) 34 | } 35 | defer conn.Close() 36 | localAddr := conn.LocalAddr().(*net.UDPAddr) 37 | return strings.Split(localAddr.String(), ":")[0] 38 | } 39 | 40 | // GetDiskUsage 获取空余磁盘容量 41 | func GetDiskUsage(path string) uint64 { 42 | di, err := disk.Usage(path) 43 | if err != nil { 44 | fmt.Println(err, "err") 45 | } 46 | return di.Free 47 | } 48 | 49 | // 全局变量作为本机的所有blockList 50 | var blockList = []*proto.BlockLocation{} 51 | 52 | // 维护本地Port变量 53 | var localNodeIP string 54 | var localRepIP string 55 | 56 | // server 57 | type server struct { 58 | proto.UnimplementedC2DServer 59 | proto.UnimplementedN2DServer 60 | } 61 | 62 | // GetBlock 读chunk 63 | func (s server) GetBlock(mode *proto.FileNameAndMode, stream proto.C2D_GetBlockServer) error { 64 | b := datanode.GetBlock(mode.FileName, "r") 65 | 66 | // 一直读到末尾,chunk文件块传送 67 | for b.HasNextChunk() { 68 | chunk, n, err := b.GetNextChunk() 69 | if err != nil { 70 | return err 71 | } 72 | stream.Send(&proto.File{Content: (*chunk)[:n]}) 73 | } 74 | b.Close() 75 | return nil 76 | } 77 | 78 | // WriteBlock 写chunk 79 | func (s server) WriteBlock(blockServer proto.C2D_WriteBlockServer) error { 80 | fileWriteStream, err := blockServer.Recv() 81 | if err == io.EOF { 82 | blockStatus := proto.OperateStatus{Success: false} 83 | blockServer.SendAndClose(&blockStatus) 84 | } 85 | fileName := fileWriteStream.BlockReplicaList.BlockReplicaList[0].BlockName 86 | b := datanode.GetBlock(fileName, "w") 87 | fmt.Println(fileWriteStream, "fileWriteStream") 88 | file := make([]byte, 0) 89 | for { 90 | fileWriteStream, err := blockServer.Recv() 91 | if err == io.EOF { 92 | fmt.Println("file", string(file)) 93 | b.Close() 94 | blockStatus := proto.OperateStatus{Success: true} 95 | blockServer.SendAndClose(&blockStatus) 96 | break 97 | } 98 | content := fileWriteStream.File.Content 99 | err = b.WriteChunk(content) 100 | if err != nil { 101 | blockStatus := proto.OperateStatus{Success: false} 102 | blockServer.SendAndClose(&blockStatus) 103 | } 104 | file = append(file, content...) 105 | } 106 | fmt.Println("write success") 107 | // 更新List 108 | blockList = append(blockList, 109 | &proto.BlockLocation{ 110 | BlockName: fileName, 111 | IpAddr: localNodeIP, 112 | BlockSize: b.GetFileSize(), 113 | ReplicaState: proto.BlockLocation_ReplicaCommitted, 114 | ReplicaID: 1, 115 | }) 116 | return nil 117 | } 118 | 119 | // ReloadReplica 复制转移block 120 | func (s server) ReloadReplica(ctx context.Context, info *proto.CopyReplica2DN) (*proto.OperateStatus, error) { 121 | // TODO Attention:为了方便单机调试,采用端口 122 | new := info.NewIP[len(info.NewIP)-1:] 123 | err := ReplicateBlock(info.BlockName, "localhost:5000"+new) 124 | if err != nil { 125 | return &proto.OperateStatus{Success: false}, err 126 | } 127 | return &proto.OperateStatus{Success: true}, nil 128 | } 129 | 130 | // GetBlockReport 获取块的信息 131 | func (s server) GetBlockReport(ctx context.Context, ping *proto.Ping) (*proto.BlockReplicaList, error) { 132 | return &proto.BlockReplicaList{BlockReplicaList: blockList}, nil 133 | } 134 | 135 | // heartBeat 心跳,递归实现 136 | func heartBeat(currentPort string) { 137 | heartbeatDuration := time.Second * time.Duration(heartbeatInterval) 138 | time.Sleep(heartbeatDuration) 139 | conn, err := grpc.Dial(nameNodeHostURL, grpc.WithInsecure(), grpc.WithBlock()) 140 | if err != nil { 141 | log.Fatalf("did not connect: %v", err) 142 | } 143 | // defer conn.Close() 144 | c := proto.NewD2NClient(conn) 145 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 146 | defer cancel() 147 | // ATTENTION:需要根据磁盘路径获取空余量,所以默认为D盘 148 | beat := proto.Heartbeat{IpAddr: currentPort, DiskUsage: GetDiskUsage("D:/")} 149 | response, err := c.DatanodeHeartbeat(ctx, &beat) 150 | if err != nil { 151 | log.Fatalf("did not send heartbeat: %v", err) 152 | } 153 | fmt.Printf("response from %v\n", response) 154 | heartBeat(currentPort) 155 | } 156 | 157 | // blockReport 定时报告状态 158 | func blockReport() { 159 | heartbeatDuration := time.Second * time.Duration(heartbeatInterval) 160 | time.Sleep(heartbeatDuration * 20) 161 | conn, err := grpc.Dial(nameNodeHostURL, grpc.WithInsecure(), grpc.WithBlock()) 162 | if err != nil { 163 | log.Fatalf("did not connect: %v", err) 164 | } 165 | // defer conn.Close() 166 | c := proto.NewD2NClient(conn) 167 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 168 | defer cancel() 169 | 170 | // 添加blockList 171 | response, err := c.BlockReport(ctx, &proto.BlockReplicaList{BlockReplicaList: blockList}) 172 | 173 | if err != nil { 174 | log.Fatalf("did not send heartbeat: %v", err) 175 | } 176 | fmt.Println(response) 177 | blockReport() 178 | } 179 | 180 | // 注册DataNode 181 | func registerDataNode(currentPort string) error { 182 | fmt.Println("register") 183 | conn, err := grpc.Dial(nameNodeHostURL, grpc.WithInsecure(), grpc.WithBlock()) 184 | if err != nil { 185 | log.Fatalf("did not connect: %v", err) 186 | return err 187 | } 188 | defer conn.Close() 189 | c := proto.NewD2NClient(conn) 190 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 191 | defer cancel() 192 | registerStatus, err := c.RegisterDataNode(ctx, &proto.RegisterDataNodeReq{New: true, DiskUsage: GetDiskUsage("D:/"), IpAddr: currentPort}) 193 | if err != nil { 194 | log.Fatalf("did not register: %v", err) 195 | return err 196 | } 197 | fmt.Println(registerStatus, "registerStatus") 198 | go heartBeat(currentPort) 199 | go blockReport() 200 | return nil 201 | } 202 | 203 | // PipelineServer Replicate the datanode to another 204 | func PipelineServer(currentPort string) { 205 | localRepIP = currentPort 206 | fmt.Println("start server...") 207 | var mu sync.Mutex //创建锁,防止协程将连接的传输写入同一个文件中 208 | listener, err := net.Listen("tcp", currentPort) 209 | if err != nil { 210 | fmt.Println("listen failed,err:", err) 211 | return 212 | } 213 | //接受客户端信息 214 | defer listener.Close() 215 | for { 216 | conn, err := listener.Accept() 217 | if err != nil { 218 | fmt.Println("accept failed,err:", err) 219 | continue 220 | } 221 | //用协程建立连接 222 | go process(conn, mu) 223 | } 224 | } 225 | 226 | // process DataNode处理函数 227 | func process(conn net.Conn, mu sync.Mutex) { 228 | mu.Lock() // 并发安全,防止协程同时写入 229 | defer mu.Unlock() 230 | defer conn.Close() 231 | for { 232 | buf := make([]byte, 10240) 233 | n, err := conn.Read(buf) 234 | if err != nil { 235 | fmt.Println("read err:", err) 236 | return 237 | } 238 | // 解析buf 239 | var message message2.Message 240 | err = json.Unmarshal(buf[0:n], &message) 241 | if err != nil { 242 | fmt.Println("unmarshal error: ", err) 243 | } 244 | // 处理 245 | if message.Mode == "send" { // NameNode发来任务 246 | ReplicateBlock(message.BlockName, message.IpAddr) 247 | } else if message.Mode == "receive" { // DataNode接受信息 248 | ReceiveReplicate(message.BlockName, message.Content) 249 | } else if message.Mode == "delete" { // DataNode删除文件 250 | err := os.Remove(*datanode.DataDir + "/" + message.BlockName) 251 | if err != nil { 252 | return 253 | } 254 | } 255 | } 256 | } 257 | 258 | // ReplicateBlock 副结点向新节点发送备份文件 259 | func ReplicateBlock(blockName string, ipAddress string) error { 260 | //log.Println("DataNode1 接受 NameNode 指令,向DataNode2备份") 261 | conn, err := net.DialTimeout("tcp", ipAddress, 5*time.Second) 262 | defer conn.Close() 263 | if err != nil { 264 | fmt.Println("Error dialing", err.Error()) 265 | return err 266 | } 267 | // 获得Block 268 | b := datanode.GetBlock(blockName, "r") 269 | // 构建Message对象并序列化 270 | m := message2.Message{Mode: "receive", BlockName: blockName, Content: b.LoadBlock()} 271 | mb, err := json.Marshal(m) 272 | if err != nil { 273 | fmt.Println("Error marshal", err.Error()) 274 | return err 275 | } 276 | // 传输数据 277 | conn.Write(mb) 278 | return nil 279 | } 280 | 281 | // ReceiveReplicate 写入备份文件 282 | func ReceiveReplicate(blockName string, content []byte) { 283 | log.Println("DataNode2接受到DataNode1数据,在本地有相关block备份") 284 | b := datanode.GetBlock(blockName, "w") 285 | b.Write(content) 286 | } 287 | 288 | // DeleteReplicate 删除备份文件 289 | func DeleteReplicate(blockName string) { 290 | b := datanode.GetBlock(blockName, "w") 291 | b.DeleteBlock() 292 | } 293 | 294 | // RunDataNode 启动DataNode 295 | func RunDataNode(currentPort string) { 296 | localNodeIP = currentPort 297 | lis, err := net.Listen("tcp", currentPort) 298 | if err != nil { 299 | log.Fatalf("failed to listen: %v", err) 300 | } 301 | s := grpc.NewServer() 302 | err = registerDataNode(currentPort) 303 | if err != nil { 304 | log.Fatalf("failed to regester to namenode: %v", err) 305 | } 306 | proto.RegisterC2DServer(s, &server{}) 307 | proto.RegisterN2DServer(s, &server{}) 308 | err = s.Serve(lis) 309 | if err != nil { 310 | log.Fatalf("failed to serve: %v", err) 311 | } 312 | } 313 | 314 | // 启动DataNode 315 | func main() { 316 | datanode.DataDir = flag.String("dir", "", "the directory be used to store file section") 317 | dnAddr := flag.String("dn_addr", "", "dataNode server address") 318 | pplAddr := flag.String("ppl_addr", "", "pipeline server address") 319 | flag.Parse() 320 | if len(*datanode.DataDir) == 0 { 321 | fmt.Fprintf(os.Stderr, "dir must be init") 322 | os.Exit(1) 323 | } 324 | if len(*dnAddr) == 0 { 325 | fmt.Fprintf(os.Stderr, "dn_addr must be init") 326 | os.Exit(1) 327 | } 328 | if len(*pplAddr) == 0 { 329 | fmt.Fprintf(os.Stderr, "ppl_addr must be init") 330 | os.Exit(1) 331 | } 332 | // 新建数据文件夹 333 | os.Mkdir(*datanode.DataDir, 7050) 334 | 335 | // 启动DataNode交互服务 336 | go PipelineServer(*pplAddr) 337 | //go PipelineServer("localhost:50001") 338 | // 本地开启若干DataNode 339 | go RunDataNode(*dnAddr) 340 | //go RunDataNode("localhost:8011") 341 | 342 | // 防止因为main中止造成协程中止 343 | defer func() { 344 | select {} 345 | }() 346 | } 347 | -------------------------------------------------------------------------------- /datanode/message/message.go: -------------------------------------------------------------------------------- 1 | package message 2 | 3 | // Message 进程间通信对象 4 | type Message struct { 5 | Mode string 6 | BlockName string 7 | Content []byte 8 | IpAddr string 9 | } 10 | -------------------------------------------------------------------------------- /datanode/service/dataNode.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "errors" 7 | "faydfs/config" 8 | "fmt" 9 | "io" 10 | "log" 11 | "os" 12 | ) 13 | 14 | // Block struct provides api to read and write block 15 | type Block struct { 16 | blockName string 17 | offset int 18 | chunkSize int 19 | reader *bufio.Reader 20 | buffer *[]byte 21 | dataRead int 22 | file *os.File 23 | blockSize int64 24 | } 25 | 26 | // 读取配置 27 | // config路径问题,请在config/config.go文件中修改路径 28 | var conf = config.GetConfig() 29 | var DataDir *string 30 | 31 | // ****************定义Block的结构函数**************** 32 | 33 | // initBlock 初始化chunk,blockName姑且认为是文件名,mode表示读写模式 34 | func (b *Block) initBlock(blockName string, mode string) { 35 | var err error // error变量 36 | var reader *bufio.Reader // io读 37 | var file *os.File // 文件变量 38 | // 读模式初始化reader 39 | if mode == "r" { 40 | file, err = os.Open(*DataDir + "/" + blockName) 41 | reader = bufio.NewReader(file) 42 | // 写模式初始化 43 | } else if mode == "w" { 44 | file, err = os.OpenFile(*DataDir+"/"+blockName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0600) 45 | } 46 | if err != nil { 47 | log.Fatal("cannot open image file: ", err) 48 | } 49 | // 初始化结构 50 | b.file = file 51 | b.blockName = blockName 52 | b.reader = reader 53 | // 使用config文件设置的参数 54 | b.chunkSize = conf.DataNode.IoSize 55 | b.blockSize = conf.Block.BlockSize 56 | // 开辟一块chunkSize大小的缓冲区 57 | buffer := make([]byte, b.chunkSize) 58 | b.buffer = &buffer 59 | // dataRead = -1时表示没有到EOF,即可继续读 60 | b.dataRead = -1 61 | b.offset = 0 62 | } 63 | 64 | // GetBlock 获取新的Block 65 | func GetBlock(blockName string, mode string) *Block { 66 | // 新建struct 67 | block := Block{} 68 | block.initBlock(blockName, mode) 69 | return &block 70 | } 71 | 72 | // HasNextChunk 检查是否可扩容 73 | func (b *Block) HasNextChunk() bool { 74 | if b.dataRead != -1 { 75 | return true 76 | } 77 | // 从文件读取一块chunkSize大小的数据到block的缓冲区里 78 | n, err := b.reader.Read(*b.buffer) 79 | if err == io.EOF { 80 | b.dataRead = -1 81 | b.file.Close() 82 | return false 83 | } 84 | // 文件读取错误 85 | if err != nil { 86 | log.Fatal("cannot read chunk to buffer: ", err) 87 | } 88 | // dataRead设置为读取的字节数 89 | b.dataRead = n 90 | return true 91 | } 92 | 93 | // GetNextChunk 获取下一个Chunk的数据,返回数据和大小 94 | // error 只有nil 95 | func (b *Block) GetNextChunk() (*[]byte, int, error) { 96 | // 没有chunk了 97 | if b.dataRead == -1 { 98 | return nil, 0, nil 99 | } 100 | // 101 | n := b.dataRead 102 | b.dataRead = -1 103 | return b.buffer, n, nil 104 | } 105 | 106 | // WriteChunk 给出chunk,追加写入数据 107 | func (b *Block) WriteChunk(chunk []byte) error { 108 | // 返回文件状态结构变量 109 | info, err := b.file.Stat() 110 | if err != nil { 111 | log.Fatal("cannot open the file: ", err) 112 | } 113 | // 获取当前文件大小 114 | currentBlockSize := info.Size() 115 | if b.blockSize >= (int64(len(chunk)) + currentBlockSize) { 116 | _, err := b.file.Write(chunk) 117 | if err != nil { 118 | log.Fatal("cannot write to file: ", err) 119 | } 120 | return nil // 写入完毕,不报错 121 | } 122 | // 定义错误类型 123 | var ErrFileExceedsBlockSize = errors.New("file is greater than block size") 124 | return ErrFileExceedsBlockSize 125 | } 126 | 127 | // Close 关闭文件 128 | func (b *Block) Close() error { 129 | return b.file.Close() 130 | } 131 | 132 | // GetFileSize 获取文件大小 133 | func (b *Block) GetFileSize() int64 { 134 | file, err := os.Open(*DataDir + "/" + b.blockName) 135 | if err != nil { 136 | log.Fatal("error in reading the size: " + err.Error()) 137 | } 138 | info, err := file.Stat() 139 | if err != nil { 140 | log.Fatal("error in reading the size: " + err.Error()) 141 | } 142 | defer file.Close() 143 | return info.Size() 144 | } 145 | 146 | // LoadBlock 获取文件字节流 147 | func (b *Block) LoadBlock() []byte { 148 | var file bytes.Buffer 149 | sum := 0 150 | for b.HasNextChunk() { 151 | chunk, n, err := b.GetNextChunk() 152 | sum += n 153 | if err != nil { 154 | return nil 155 | } 156 | file.Write(*chunk) 157 | } 158 | b.Close() 159 | return file.Bytes()[0:sum] 160 | } 161 | 162 | // Write 直接写block 163 | func (b *Block) Write(content []byte) { 164 | // 默认已经Open 165 | _, err := b.file.Write(content) 166 | if err != nil { 167 | fmt.Printf("write replicate file failed: %v\n", err) 168 | return 169 | } 170 | b.Close() 171 | } 172 | 173 | // DeleteBlock 删除Block 174 | func (b *Block) DeleteBlock() error { 175 | err := os.Remove(*DataDir + "/" + b.blockName) 176 | if err != nil { 177 | return err 178 | } 179 | return nil 180 | } 181 | -------------------------------------------------------------------------------- /datanode/service/dataNode_test.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "encoding/json" 5 | "faydfs/client" 6 | "faydfs/datanode/message" 7 | "faydfs/proto" 8 | "fmt" 9 | "log" 10 | "net" 11 | "os" 12 | "strings" 13 | "testing" 14 | "time" 15 | ) 16 | 17 | // t *testing.T 18 | 19 | func Read() { 20 | tempFile := "data/temp.txt" 21 | tempContent := "here is some temp content" 22 | createTempFile(tempFile, tempContent) 23 | fmt.Println("create file success") 24 | b := GetBlock("temp.txt", "r") 25 | temp := make([]byte, 0) 26 | for b.HasNextChunk() { 27 | chunk, size, _ := b.GetNextChunk() 28 | temp = append(temp, (*chunk)[:size]...) 29 | } 30 | if tempContent != string(temp) { 31 | fmt.Println("read failed") 32 | } 33 | //deleteTempFile(tempFile) 34 | fmt.Println("read success") 35 | } 36 | 37 | func read() { 38 | tempFile := "data/temp.txt" 39 | tempContent := "here is some temp content" 40 | createTempFile(tempFile, tempContent) 41 | b := GetBlock("temp.txt", "r") 42 | temp := make([]byte, 0) 43 | for b.HasNextChunk() { 44 | chunk, size, _ := b.GetNextChunk() 45 | temp = append(temp, (*chunk)[:size]...) 46 | } 47 | if tempContent != string(temp) { 48 | fmt.Println("read failed") 49 | } 50 | //deleteTempFile(tempFile) 51 | fmt.Println("read success") 52 | // Begin to read 53 | b = GetBlock("temp.txt", "w") 54 | fileBytes := []byte(tempContent) 55 | iter := 0 56 | for iter < len(fileBytes) { 57 | end := iter + conf.IoSize 58 | if end > len(fileBytes) { 59 | end = len(fileBytes) 60 | } 61 | chunk := fileBytes[iter:end] 62 | fmt.Println("begin write") 63 | err := b.WriteChunk(chunk) 64 | fmt.Println("write done") 65 | if err != nil { 66 | fmt.Println(err) 67 | } 68 | iter = iter + conf.IoSize 69 | } 70 | for b.HasNextChunk() { 71 | chunk, size, _ := b.GetNextChunk() 72 | temp = append(temp, (*chunk)[:size]...) 73 | } 74 | fmt.Println(string(temp)) 75 | } 76 | 77 | func TestReadTwice(t *testing.T) { 78 | Read() 79 | Write() 80 | } 81 | 82 | func createTempFile(name string, content string) { 83 | file, err := os.Create(name) 84 | if err != nil { 85 | log.Fatal("cannot create file: ", err) 86 | } 87 | _, err1 := file.Write([]byte(content)) 88 | if err1 != nil { 89 | log.Fatal("cannot write file: ", err1) 90 | } 91 | } 92 | 93 | func deleteTempFile(name string) { 94 | err := os.Remove(name) 95 | if err != nil { 96 | log.Fatal("cannot delete file: "+name, err) 97 | } 98 | } 99 | 100 | func Write() { 101 | tempFile := "temp.txt" 102 | tempContent := "here is some temp content" 103 | // createTempFile(tempFile, tempContent) 104 | b := GetBlock(tempFile, "w") 105 | fileBytes := []byte(tempContent) 106 | iter := 0 107 | for iter < len(fileBytes) { 108 | end := iter + conf.IoSize 109 | if end > len(fileBytes) { 110 | end = len(fileBytes) 111 | } 112 | chunk := fileBytes[iter:end] 113 | 114 | err := b.WriteChunk(chunk) 115 | if err != nil { 116 | fmt.Println(err) 117 | } 118 | iter = iter + conf.IoSize 119 | } 120 | 121 | b = GetBlock(tempFile, "r") 122 | temp := make([]byte, 0) 123 | for b.HasNextChunk() { 124 | chunk, size, _ := b.GetNextChunk() 125 | temp = append(temp, (*chunk)[:size]...) 126 | } 127 | tempContent += tempContent 128 | if tempContent != string(temp) { 129 | fmt.Println("write failed") 130 | } 131 | fmt.Println("write success") 132 | } 133 | 134 | //func getGrpcClientConn(address string) (*grpc.ClientConn, *proto.DfsClient, *context.CancelFunc, error) { 135 | // ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 136 | // conn, err := grpc.DialContext(ctx, address, grpc.WithInsecure(), grpc.WithBlock()) 137 | // // conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock()) 138 | // if err != nil { 139 | // log.Fatalf("did not connect to %v error %v", address, err) 140 | // } 141 | // client := proto.NewDfsClient(conn) 142 | // return conn, &client, &cancel, err 143 | //} 144 | 145 | // TestReadRpc 读文件测试 146 | func TestReadRpc(t *testing.T) { 147 | //b := client.ReadBlock("temp.txt", "localhost") 148 | //fmt.Println(string(b)) 149 | } 150 | 151 | // TestWriteRpc 写文件测试 152 | func TestWriteRpc(t *testing.T) { 153 | // 基础数据 154 | content := "Love you my dear Lina~" 155 | tranport := []byte(content) 156 | // 定义replicaList 157 | var blockList = []*proto.BlockLocation{} 158 | blockList = append(blockList, &proto.BlockLocation{ 159 | BlockName: "lina.txt", 160 | IpAddr: string("localhost")}) 161 | v := proto.BlockReplicaList{BlockReplicaList: blockList} 162 | // 调用 163 | client.DwriteBlock("192.168.1.107", tranport, &v) 164 | } 165 | 166 | func TestAnother(t *testing.T) { 167 | // 链接DataNode1的socket服务 168 | conn, err := net.DialTimeout("tcp", "localhost:50000", 5*time.Second) 169 | if err != nil { 170 | fmt.Println("Error dialing", err.Error()) 171 | return 172 | } 173 | defer conn.Close() 174 | // 发送数据,使得DataNode1去备份给DataNode2 175 | me := message.Message{Mode: "send", BlockName: "love.txt", IpAddr: "localhost:50001"} 176 | se, err := json.Marshal(me) 177 | if err != nil { 178 | fmt.Println("Error marshal", err.Error()) 179 | } 180 | conn.Write(se) 181 | } 182 | 183 | // TestDelete 测试删除功能 184 | func TestDelete(t *testing.T) { 185 | // 链接DataNode1的socket服务 186 | conn, err := net.DialTimeout("tcp", "localhost:50000", 5*time.Second) 187 | if err != nil { 188 | fmt.Println("Error dialing", err.Error()) 189 | return 190 | } 191 | defer conn.Close() 192 | // 发送数据,使得DataNode1去备份给DataNode2 193 | me := message.Message{Mode: "delete", BlockName: "temp.txt", IpAddr: "localhost:50000"} 194 | se, err := json.Marshal(me) 195 | if err != nil { 196 | fmt.Println("Error marshal", err.Error()) 197 | } 198 | conn.Write(se) 199 | } 200 | 201 | // TestStringIP 测试IP转string 202 | func TestStringIP(test *testing.T) { 203 | conn, err := net.Dial("udp", "8.8.8.8:80") 204 | if err != nil { 205 | log.Fatal(err) 206 | } 207 | defer conn.Close() 208 | localAddr := conn.LocalAddr().(*net.UDPAddr) 209 | ip := strings.Split(localAddr.String(), ":")[0] 210 | fmt.Println(ip) 211 | } 212 | 213 | // TestClientPut 测试用户请求 214 | func TestClientPut(t *testing.T) { 215 | user := client.GetClient() 216 | result := user.Put("D:\\Documents\\QQdoc\\614300076\\FileRecv\\info.txt", "/info.txt") 217 | if result.ResultCode != 200 { 218 | log.Fatal(result.Data) 219 | return 220 | } 221 | fmt.Println(result.ResultExtraMsg) 222 | } 223 | 224 | func TestClientGet(t *testing.T) { 225 | client.GetClient() 226 | user := client.GetClient() 227 | fmt.Println(":haah") 228 | result := user.Get("/info.txt", "D://info.txt") 229 | if result.ResultCode != 200 { 230 | log.Fatal(result.Data) 231 | return 232 | } 233 | fmt.Println(result.ResultExtraMsg) 234 | } 235 | 236 | // 宕机的DataNode 237 | func TestDownDataNode(t *testing.T) { 238 | 239 | } 240 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module faydfs 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/satori/go.uuid v1.2.0 7 | github.com/shirou/gopsutil/v3 v3.22.6 8 | github.com/syndtr/goleveldb v1.0.0 9 | google.golang.org/grpc v1.48.0 10 | google.golang.org/protobuf v1.28.0 11 | gopkg.in/yaml.v2 v2.2.3 12 | ) 13 | 14 | require ( 15 | github.com/go-ole/go-ole v1.2.6 // indirect 16 | github.com/golang/protobuf v1.5.2 // indirect 17 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect 18 | github.com/kr/pretty v0.3.0 // indirect 19 | github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c // indirect 20 | github.com/rogpeppe/go-internal v1.8.1 // indirect 21 | github.com/yusufpapurcu/wmi v1.2.2 // indirect 22 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect 23 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect 24 | golang.org/x/text v0.3.7 // indirect 25 | google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e // indirect 26 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect 27 | ) 28 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 4 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 5 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 6 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 7 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 8 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 9 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 10 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 11 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 12 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 13 | github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 14 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 15 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 16 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 17 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 18 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 19 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 20 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 21 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 22 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 23 | github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= 24 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 25 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 26 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 27 | github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= 28 | github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= 29 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 30 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 31 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 32 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 33 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 34 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 35 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 36 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 37 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 38 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 39 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 40 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 41 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 42 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 43 | github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= 44 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 45 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= 46 | github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 47 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 48 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 49 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 50 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 51 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 52 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 53 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 54 | github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= 55 | github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 56 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 57 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 58 | github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= 59 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 60 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 61 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 62 | github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= 63 | github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= 64 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 65 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 66 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 67 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 68 | github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= 69 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 70 | github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= 71 | github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 72 | github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= 73 | github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 74 | github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 75 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 76 | github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= 77 | github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c h1:NRoLoZvkBTKvR5gQLgA3e0hqjkY9u1wm+iOL45VN/qI= 78 | github.com/power-devops/perfstat v0.0.0-20220216144756-c35f1ee13d7c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= 79 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 80 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 81 | github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= 82 | github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= 83 | github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= 84 | github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= 85 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 86 | github.com/shirou/gopsutil/v3 v3.22.6 h1:FnHOFOh+cYAM0C30P+zysPISzlknLC5Z1G4EAElznfQ= 87 | github.com/shirou/gopsutil/v3 v3.22.6/go.mod h1:EdIubSnZhbAvBS1yJ7Xi+AShB/hxwLHOMz4MCYz7yMs= 88 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 89 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 90 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 91 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 92 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 93 | github.com/stretchr/testify v1.7.5/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 94 | github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= 95 | github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= 96 | github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= 97 | github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= 98 | github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= 99 | github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= 100 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 101 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 102 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 103 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 104 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 105 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 106 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 107 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 108 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 109 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 110 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 111 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 112 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 113 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 114 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 115 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 116 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 117 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= 118 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 119 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 120 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 121 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 122 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 123 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 124 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 125 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 126 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 127 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 128 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 129 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 130 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 131 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 132 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 133 | golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 134 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 135 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 136 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 137 | golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 138 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 139 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= 140 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 141 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 142 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 143 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 144 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 145 | golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= 146 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 147 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 148 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 149 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 150 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 151 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 152 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 153 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 154 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 155 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 156 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 157 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 158 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 159 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 160 | google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e h1:gMjH4zLGs9m+dGzR7qHCHaXMOwsJHJKKkHtyXhtOrJk= 161 | google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= 162 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 163 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 164 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 165 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 166 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 167 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 168 | google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= 169 | google.golang.org/grpc v1.48.0 h1:rQOsyJ/8+ufEDJd/Gdsz7HG220Mh9HAhFHRGnIjda0w= 170 | google.golang.org/grpc v1.48.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= 171 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 172 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 173 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 174 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 175 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 176 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 177 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 178 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 179 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 180 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 181 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 182 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 183 | google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= 184 | google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 185 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 186 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 187 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 188 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 189 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 190 | gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= 191 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 192 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 193 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 194 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 195 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 196 | gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= 197 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 198 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 199 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 200 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 201 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 202 | -------------------------------------------------------------------------------- /namenode/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "faydfs/config" 6 | namenode "faydfs/namenode/service" 7 | "faydfs/proto" 8 | "faydfs/public" 9 | "fmt" 10 | "google.golang.org/grpc" 11 | "log" 12 | "net" 13 | "strconv" 14 | "time" 15 | ) 16 | 17 | var ( 18 | nameNodeHost = config.GetConfig().NameNode.NameNodeHost 19 | nameNodePort = config.GetConfig().NameNode.NameNodePort 20 | nameNodeIpAddr = nameNodeHost + nameNodePort 21 | nn = namenode.GetNewNameNode(config.GetConfig().Block.BlockSize, config.GetConfig().Block.Replica) 22 | lm = namenode.GetNewLeaseManager() 23 | ) 24 | 25 | type server struct { 26 | proto.UnimplementedC2NServer 27 | proto.UnimplementedD2NServer 28 | } 29 | 30 | func (s server) DatanodeHeartbeat(ctx context.Context, heartbeat *proto.Heartbeat) (*proto.DatanodeOperation, error) { 31 | nn.Heartbeat(heartbeat.IpAddr, heartbeat.DiskUsage) 32 | return &proto.DatanodeOperation{IpAddr: nameNodeIpAddr}, nil 33 | } 34 | 35 | func (s server) BlockReport(ctx context.Context, list *proto.BlockReplicaList) (*proto.OperateStatus, error) { 36 | 37 | for _, blockMeta := range list.BlockReplicaList { 38 | nn.GetBlockReport(blockMeta) 39 | } 40 | return &proto.OperateStatus{Success: true}, nil 41 | } 42 | 43 | func (s server) RegisterDataNode(ctx context.Context, req *proto.RegisterDataNodeReq) (*proto.OperateStatus, error) { 44 | nn.RegisterDataNode(req.IpAddr, req.DiskUsage) 45 | fmt.Println("register", req.IpAddr, "ipAddress") 46 | return &proto.OperateStatus{Success: true}, nil 47 | } 48 | 49 | func (s server) GetFileLocationAndModifyMeta(ctx context.Context, mode *proto.FileNameAndMode) (*proto.FileLocationArr, error) { 50 | if mode.Mode == proto.FileNameAndMode_READ { 51 | fileLocationArr, err := nn.GetLocation(mode.FileName) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return fileLocationArr, nil 56 | } else { 57 | fmt.Println("mode", mode) 58 | fmt.Println("nn", nn) 59 | fileLocationArr, err := nn.WriteLocation(mode.FileName, mode.BlockNum) 60 | if err != nil { 61 | return nil, err 62 | } 63 | return fileLocationArr, nil 64 | } 65 | } 66 | 67 | func (s server) CreateFile(ctx context.Context, mode *proto.FileNameAndMode) (*proto.FileLocationArr, error) { 68 | //TODO implement me 69 | panic("implement me") 70 | } 71 | 72 | func (s server) OperateMeta(ctx context.Context, mode *proto.FileNameAndOperateMode) (*proto.OperateStatus, error) { 73 | if mode.Mode == proto.FileNameAndOperateMode_MKDIR { 74 | if ok, err := nn.MakeDir(mode.FileName); !ok { 75 | return &proto.OperateStatus{Success: false}, err 76 | } 77 | return &proto.OperateStatus{Success: true}, nil 78 | } else { 79 | if ok, err := nn.DeletePath(mode.FileName); !ok { 80 | return &proto.OperateStatus{Success: false}, err 81 | } 82 | return &proto.OperateStatus{Success: true}, nil 83 | } 84 | } 85 | 86 | func (s server) RenameFileInMeta(ctx context.Context, path *proto.SrcAndDestPath) (*proto.OperateStatus, error) { 87 | if err := nn.RenameFile(path.RenameSrcPath, path.RenameDestPath); err != nil { 88 | return &proto.OperateStatus{Success: false}, err 89 | } 90 | return &proto.OperateStatus{Success: true}, nil 91 | } 92 | 93 | func (s server) GetFileMeta(ctx context.Context, name *proto.PathName) (*proto.FileMeta, error) { 94 | meta, ok := nn.FileStat(name.PathName) 95 | if !ok { 96 | return nil, public.ErrFileNotFound 97 | } 98 | 99 | return &proto.FileMeta{ 100 | FileName: meta.FileName, 101 | FileSize: strconv.FormatUint(meta.FileSize, 10), 102 | IsDir: meta.IsDir, 103 | }, nil 104 | } 105 | 106 | func (s server) GetDirMeta(ctx context.Context, name *proto.PathName) (*proto.DirMetaList, error) { 107 | if list, err := nn.GetDirMeta(name.PathName); err != nil { 108 | return nil, err 109 | } else { 110 | var resultList []*proto.FileMeta 111 | for _, meta := range list { 112 | childFile := &proto.FileMeta{ 113 | FileName: meta.FileName, 114 | FileSize: strconv.FormatUint(meta.FileSize, 10), 115 | IsDir: meta.IsDir, 116 | } 117 | resultList = append(resultList, childFile) 118 | } 119 | return &proto.DirMetaList{MetaList: resultList}, nil 120 | } 121 | } 122 | 123 | func (s server) PutSuccess(ctx context.Context, name *proto.MetaStore) (*proto.OperateStatus, error) { 124 | nn.PutSuccess(name.GetFilePath(), name.GetFileSize(), name.FileLocationArr) 125 | lm.Revoke(name.GetClientName(), name.GetFilePath()) 126 | return &proto.OperateStatus{Success: true}, nil 127 | } 128 | 129 | func (s server) RenewLock(ctx context.Context, name *proto.GetLease) (*proto.OperateStatus, error) { 130 | 131 | if lm.Grant(name.GetClientName(), name.Pathname.GetPathName()) { 132 | return &proto.OperateStatus{Success: true}, nil 133 | } 134 | if lm.Renew(name.GetClientName(), name.Pathname.GetPathName()) { 135 | return &proto.OperateStatus{Success: true}, nil 136 | } 137 | return &proto.OperateStatus{Success: false}, nil 138 | } 139 | 140 | // logData 汇报当前信息 141 | func logData() { 142 | heartbeatDuration := time.Second * time.Duration(3) 143 | time.Sleep(heartbeatDuration) 144 | log.Println("NameNode Reporting~~~~~~~~~~~~~~~") 145 | nn.ShowLog() 146 | logData() 147 | } 148 | 149 | func main() { 150 | lis, err := net.Listen("tcp", nameNodeIpAddr) 151 | if err != nil { 152 | log.Fatalf("failed to listen: %v", err) 153 | } 154 | s := grpc.NewServer() 155 | proto.RegisterC2NServer(s, &server{}) 156 | log.Println("==========C2N Server Start==========") 157 | proto.RegisterD2NServer(s, &server{}) 158 | log.Println("==========D2N Server Start==========") 159 | if err := s.Serve(lis); err != nil { 160 | log.Fatalf("failed to serve: %v", err) 161 | } 162 | fmt.Println("before Log") 163 | go logData() 164 | } 165 | -------------------------------------------------------------------------------- /namenode/service/leaseManger.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "faydfs/config" 5 | "sync" 6 | "time" 7 | ) 8 | 9 | var ( 10 | //默认1min 当前时间 - lastUpdate > softLimit 则允许其他client抢占该Client持有的filepath (防止用户死亡) 11 | softLimit int = config.GetConfig().Lease.LeaseSoftLimit 12 | //默认1hour 当前时间 - lastUpdate > hardLimit 则允许LeaseManger强制讲该租约回收销毁 , 考虑文件关闭异常 13 | hardLimit int = config.GetConfig().Lease.LeaseSoftLimit 14 | ) 15 | 16 | type lease struct { 17 | holder string 18 | lastUpdate int64 19 | paths *[]string 20 | } 21 | 22 | type LeaseManager struct { 23 | fileToMetaMap map[string]lease 24 | mu sync.Mutex 25 | } 26 | 27 | // GetNewLeaseManager 获取LM实例 28 | func GetNewLeaseManager() *LeaseManager { 29 | fileToMetaMap := make(map[string]lease) 30 | lm := LeaseManager{ 31 | fileToMetaMap: fileToMetaMap, 32 | } 33 | go lm.monitor() 34 | return &lm 35 | } 36 | 37 | // 监视租约是否过期 38 | func (lm *LeaseManager) monitor() { 39 | for { 40 | delay := 5 * time.Minute 41 | time.Sleep(delay) 42 | lm.mu.Lock() 43 | for file, fileMeta := range lm.fileToMetaMap { 44 | //比较是否超过了规定的HardLimit 45 | if time.Since(time.Unix(fileMeta.lastUpdate, 0)) > (time.Duration(hardLimit) * time.Millisecond) { 46 | lm.Revoke(fileMeta.holder, file) 47 | } 48 | } 49 | lm.mu.Unlock() 50 | } 51 | } 52 | 53 | // Grant 授予租约 54 | func (lm *LeaseManager) Grant(client string, file string) bool { 55 | lm.mu.Lock() 56 | defer lm.mu.Unlock() 57 | _, present := lm.fileToMetaMap[file] 58 | if present { 59 | return false 60 | } 61 | meta := lease{ 62 | holder: client, 63 | lastUpdate: time.Now().Unix(), 64 | } 65 | lm.fileToMetaMap[file] = meta 66 | return true 67 | } 68 | 69 | // HasLock 给客户端读权限之前检查该文件是否有别人占用租约 70 | func (lm *LeaseManager) HasLock(file string) bool { 71 | lm.mu.Lock() 72 | defer lm.mu.Unlock() 73 | lease, present := lm.fileToMetaMap[file] 74 | if present { 75 | if time.Since(time.Unix(lease.lastUpdate, 0)) > (time.Duration(softLimit) * time.Millisecond) { 76 | lm.Revoke(lease.holder, file) 77 | return false 78 | } 79 | return true 80 | } 81 | return false 82 | } 83 | 84 | // Revoke 取消租约,当client写成功之后,在修改meta的同时放掉租约 85 | func (lm *LeaseManager) Revoke(client string, file string) { 86 | lm.mu.Lock() 87 | defer lm.mu.Unlock() 88 | delete(lm.fileToMetaMap, file) 89 | } 90 | 91 | // Renew 更新租约 92 | func (lm *LeaseManager) Renew(client string, file string) bool { 93 | lm.mu.Lock() 94 | defer lm.mu.Unlock() 95 | fileMeta, present := lm.fileToMetaMap[file] 96 | if present { 97 | if fileMeta.holder == client { 98 | meta := lease{holder: client, lastUpdate: time.Now().Unix()} 99 | lm.fileToMetaMap[file] = meta 100 | return true 101 | } 102 | return lm.Grant(client, file) 103 | } 104 | return false 105 | } 106 | -------------------------------------------------------------------------------- /namenode/service/leveldb.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "bytes" 5 | "encoding/gob" 6 | "github.com/syndtr/goleveldb/leveldb" 7 | "log" 8 | "sync" 9 | ) 10 | 11 | type DB struct { 12 | Size int 13 | lock sync.RWMutex 14 | DB *leveldb.DB 15 | } 16 | 17 | func GetDB(dbPath string) *DB { 18 | db, err := leveldb.OpenFile(dbPath, nil) 19 | if err != nil { 20 | log.Fatal(err) 21 | } 22 | 23 | dnList, err := db.Get([]byte("dnList"), nil) 24 | 25 | if err != nil { 26 | log.Fatal(err) 27 | } 28 | return &DB{DB: db, Size: len(dnList)} 29 | } 30 | 31 | func (fm *DB) GetDnSize() int { 32 | return fm.Size 33 | } 34 | 35 | func (fm *DB) Put(key string, value *FileMeta) { 36 | valueBytes := fm.data2Bytes(value) 37 | err := fm.DB.Put([]byte(key), valueBytes, nil) 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | } 42 | 43 | func (fm *DB) Get(key string) (*FileMeta, bool) { 44 | data, err := fm.DB.Get([]byte(key), nil) 45 | if err != nil { 46 | if err == leveldb.ErrNotFound { 47 | return nil, false 48 | } 49 | log.Fatal(err) 50 | } 51 | result := fm.bytes2FileMetas(data) 52 | return result, true 53 | } 54 | 55 | func (fm *DB) GetValue(key string) *FileMeta { 56 | data, err := fm.DB.Get([]byte(key), nil) 57 | if err != nil { 58 | if err == leveldb.ErrNotFound { 59 | return nil 60 | } 61 | log.Fatal(err) 62 | } 63 | result := fm.bytes2FileMetas(data) 64 | return result 65 | } 66 | 67 | func (fm *DB) Delete(key string) { 68 | err := fm.DB.Delete([]byte(key), nil) 69 | if err != nil { 70 | log.Fatal(err) 71 | } 72 | } 73 | 74 | func (fm *DB) Range() ([]string, []*FileMeta) { 75 | keys := []string{} 76 | values := []*FileMeta{} 77 | iter := fm.DB.NewIterator(nil, nil) 78 | for iter.Next() { 79 | key := iter.Key() 80 | keys = append(keys, string(key)) 81 | value := iter.Value() 82 | values = append(values, fm.bytes2FileMetas(value)) 83 | } 84 | iter.Release() 85 | err := iter.Error() 86 | if err != nil { 87 | log.Fatal(err) 88 | } 89 | return keys, values 90 | } 91 | 92 | func (fm *DB) UpdateDn(value map[string]*DatanodeMeta) { 93 | valueBytes := fm.data2Bytes(value) 94 | err := fm.DB.Put([]byte("dnList"), valueBytes, nil) 95 | if err != nil { 96 | log.Fatal(err) 97 | } 98 | } 99 | 100 | func (fm *DB) AddDn(value map[string]*DatanodeMeta) { 101 | valueBytes := fm.data2Bytes(value) 102 | err := fm.DB.Put([]byte("dnList"), valueBytes, nil) 103 | if err != nil { 104 | log.Fatal(err) 105 | } 106 | fm.Size++ 107 | } 108 | 109 | func (fm *DB) GetDn() map[string]*DatanodeMeta { 110 | data, err := fm.DB.Get([]byte("dnList"), nil) 111 | if err != nil { 112 | if err == leveldb.ErrNotFound { 113 | return nil 114 | } 115 | log.Fatal(err) 116 | } 117 | result := fm.bytes2DatanodeMetas(data) 118 | return result 119 | } 120 | 121 | func (fm *DB) data2Bytes(structs interface{}) []byte { 122 | var b bytes.Buffer 123 | enc := gob.NewEncoder(&b) 124 | err := enc.Encode(structs) 125 | if err != nil { 126 | log.Fatal(err) 127 | } 128 | return b.Bytes() 129 | } 130 | 131 | func (fm *DB) bytes2FileMetas(b []byte) *FileMeta { 132 | dec := gob.NewDecoder(bytes.NewBuffer(b)) 133 | var data *FileMeta 134 | err := dec.Decode(&data) 135 | if err != nil { 136 | log.Fatal("Error decoding GOB data:", err) 137 | } 138 | return data 139 | } 140 | 141 | func (fm *DB) bytes2DatanodeMetas(b []byte) map[string]*DatanodeMeta { 142 | dec := gob.NewDecoder(bytes.NewBuffer(b)) 143 | var data map[string]*DatanodeMeta 144 | err := dec.Decode(&data) 145 | if err != nil { 146 | log.Fatal("Error decoding GOB data:", err) 147 | } 148 | return data 149 | } 150 | -------------------------------------------------------------------------------- /namenode/service/nameNode.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "context" 5 | "faydfs/config" 6 | "faydfs/proto" 7 | "faydfs/public" 8 | "fmt" 9 | "google.golang.org/grpc" 10 | "log" 11 | "strings" 12 | "sync" 13 | "time" 14 | ) 15 | 16 | // Block uhb 17 | type blockMeta struct { 18 | BlockName string 19 | TimeStamp int64 20 | BlockID int 21 | } 22 | 23 | // BlockMeta wewer 每个block在不同副本上的位置 24 | type replicaMeta struct { 25 | blockName string 26 | fileSize int64 27 | ipAddr string 28 | state replicaState 29 | replicaID int 30 | } 31 | 32 | // DatanodeMeta metadata of datanode 33 | type DatanodeMeta struct { 34 | IPAddr string 35 | DiskUsage uint64 36 | HeartbeatTimeStamp int64 37 | Status datanodeStatus 38 | } 39 | 40 | // FileMeta 文件元数据 41 | type FileMeta struct { 42 | FileName string 43 | FileSize uint64 44 | ChildFileList map[string]*FileMeta 45 | IsDir bool 46 | 47 | Blocks []blockMeta 48 | } 49 | 50 | type datanodeStatus string 51 | type replicaState string 52 | 53 | // namenode constants 54 | const ( 55 | datanodeDown = datanodeStatus("datanodeDown") 56 | datanodeUp = datanodeStatus("datanodeUp") 57 | ReplicaPending = replicaState("pending") 58 | ReplicaCommitted = replicaState("committed") 59 | ) 60 | 61 | var ( 62 | heartbeatTimeout = config.GetConfig().NameNode.HeartbeatTimeout 63 | blockSize = config.GetConfig().Block.BlockSize 64 | ) 65 | 66 | type NameNode struct { 67 | DB *DB 68 | // blockToLocation is not necessary to be in disk 69 | // blockToLocation can be obtained from datanode blockreport() 70 | blockToLocation map[string][]replicaMeta 71 | 72 | blockSize int64 73 | replicationFactor int 74 | lock sync.RWMutex 75 | } 76 | 77 | func (nn *NameNode) ShowLog() { 78 | dnList := nn.DB.GetDn() 79 | for _, v := range dnList { 80 | log.Printf("ip: %v", v.IPAddr) 81 | log.Printf("status: %v\n", v.Status) 82 | } 83 | } 84 | 85 | func GetNewNameNode(blockSize int64, replicationFactor int) *NameNode { 86 | namenode := &NameNode{ 87 | blockToLocation: make(map[string][]replicaMeta), 88 | DB: GetDB("DB/leveldb"), 89 | blockSize: blockSize, 90 | replicationFactor: replicationFactor, 91 | } 92 | namenode.DB.Put("/", &FileMeta{FileName: "/", IsDir: true, ChildFileList: map[string]*FileMeta{}}) 93 | namenode.DB.AddDn(map[string]*DatanodeMeta{}) 94 | go namenode.heartbeatMonitor() 95 | namenode.getBlockReport2DN() 96 | return namenode 97 | } 98 | 99 | // RegisterDataNode 注册新的dn 100 | func (nn *NameNode) RegisterDataNode(datanodeIPAddr string, diskUsage uint64) { 101 | nn.lock.Lock() 102 | defer nn.lock.Unlock() 103 | meta := DatanodeMeta{ 104 | IPAddr: datanodeIPAddr, 105 | DiskUsage: diskUsage, 106 | HeartbeatTimeStamp: time.Now().Unix(), 107 | Status: datanodeUp, 108 | } 109 | 110 | dnList := nn.DB.GetDn() 111 | dnList[datanodeIPAddr] = &meta 112 | if _, ok := dnList[datanodeIPAddr]; !ok { 113 | nn.DB.AddDn(dnList) 114 | } else { 115 | nn.DB.UpdateDn(dnList) 116 | } 117 | } 118 | 119 | // RenameFile 更改路径名称 120 | func (nn *NameNode) RenameFile(src, des string) error { 121 | if src == "/" { 122 | return public.ErrCanNotChangeRootDir 123 | } 124 | nn.lock.Lock() 125 | defer nn.lock.Unlock() 126 | //srcName, ok := nn.fileToBlock[src] 127 | srcName, ok := nn.DB.Get(src) 128 | if !ok { 129 | return public.ErrFileNotFound 130 | } 131 | //todo 由于键值存储的原因,rename非空目录需要递归修改子目录path,暂不支持rename非空目录 132 | if srcName.IsDir && len(srcName.ChildFileList) != 0 { 133 | return public.ErrOnlySupportRenameEmptyDir 134 | } 135 | nn.DB.Put(des, srcName) 136 | 137 | nn.DB.Delete(src) 138 | if src != "/" { 139 | index := strings.LastIndex(src, "/") 140 | parentPath := src[:index] 141 | // 例如 /cfc 父目录经过上述运算 => "",需要额外补上/ 142 | if parentPath == "" { 143 | parentPath = "/" 144 | } 145 | fileMeta := nn.DB.GetValue(parentPath) 146 | newParent := &FileMeta{ 147 | FileName: fileMeta.FileName, 148 | FileSize: fileMeta.FileSize, 149 | ChildFileList: fileMeta.ChildFileList, 150 | IsDir: fileMeta.IsDir, 151 | } 152 | newParent.ChildFileList[des] = srcName 153 | delete(newParent.ChildFileList, src) 154 | nn.DB.Put(parentPath, newParent) 155 | } 156 | return nil 157 | } 158 | 159 | func (nn *NameNode) FileStat(path string) (*FileMeta, bool) { 160 | nn.lock.RLock() 161 | defer nn.lock.RUnlock() 162 | meta, ok := nn.DB.Get(path) 163 | if !ok { 164 | return nil, false 165 | } 166 | return meta, true 167 | } 168 | 169 | // MakeDir 创建文件夹 170 | func (nn *NameNode) MakeDir(name string) (bool, error) { 171 | var path = name 172 | //校验路径是否存在 173 | for { 174 | if path == "/" { 175 | break 176 | } 177 | index := strings.LastIndex(path, "/") 178 | path = path[:index] 179 | if path == "" { 180 | break 181 | } 182 | if _, ok := nn.DB.Get(path); !ok { 183 | return false, public.ErrPathNotFind 184 | } 185 | } 186 | nn.lock.Lock() 187 | defer nn.lock.Unlock() 188 | //判断目录是否已存在 189 | if _, ok := nn.DB.Get(name); ok { 190 | return false, public.ErrDirAlreadyExists 191 | } 192 | newDir := &FileMeta{ 193 | IsDir: true, 194 | ChildFileList: map[string]*FileMeta{}, 195 | } 196 | nn.DB.Put(name, newDir) 197 | // 在父目录中追修改子文件 198 | if name != "/" { 199 | index := strings.LastIndex(name, "/") 200 | parentPath := name[:index] 201 | if parentPath == "" { 202 | parentPath = "/" 203 | } 204 | //nn.fileList[parentPath].ChildFileList[name] = 0 205 | fileMeta := nn.DB.GetValue(parentPath) 206 | newParent := &FileMeta{ 207 | FileName: fileMeta.FileName, 208 | FileSize: fileMeta.FileSize, 209 | ChildFileList: fileMeta.ChildFileList, 210 | IsDir: fileMeta.IsDir, 211 | } 212 | newParent.ChildFileList[name] = newDir 213 | nn.DB.Put(parentPath, newParent) 214 | } 215 | return true, nil 216 | } 217 | 218 | // DeletePath 删除指定路径的文件 219 | func (nn *NameNode) DeletePath(name string) (bool, error) { 220 | 221 | if name == "/" { 222 | return false, public.ErrCanNotChangeRootDir 223 | } 224 | var path = name 225 | //校验路径是否存在 226 | for { 227 | if path == "/" { 228 | break 229 | } 230 | index := strings.LastIndex(path, "/") 231 | path = path[:index] 232 | if path == "" { 233 | path = "/" 234 | } 235 | //if _, ok := nn.fileList[path]; !ok { 236 | if _, ok := nn.DB.Get(path); !ok { 237 | return false, public.ErrPathNotFind 238 | } 239 | } 240 | nn.lock.Lock() 241 | defer nn.lock.Unlock() 242 | // 判断是否为目录文件 243 | //if meta, ok := nn.fileList[name]; !ok { 244 | if meta, ok := nn.DB.Get(name); !ok { 245 | return false, public.ErrPathNotFind 246 | } else if meta.IsDir { //存在且为目录文件 247 | //判断目录中是否有其他文件 248 | if len(meta.ChildFileList) > 0 { 249 | return false, public.ErrNotEmptyDir 250 | } 251 | } 252 | //路径指定为非目录 253 | //delete(nn.fileToBlock, name) 254 | //delete(nn.fileList, name) 255 | nn.DB.Delete(name) 256 | // 在父目录中追修改子文件 257 | if name != "/" { 258 | index := strings.LastIndex(name, "/") 259 | parentPath := name[:index] 260 | if parentPath == "" { 261 | parentPath = "/" 262 | } 263 | fileMeta := nn.DB.GetValue(parentPath) 264 | newParent := &FileMeta{ 265 | FileName: fileMeta.FileName, 266 | FileSize: fileMeta.FileSize, 267 | ChildFileList: fileMeta.ChildFileList, 268 | IsDir: fileMeta.IsDir, 269 | } 270 | delete(newParent.ChildFileList, name) 271 | nn.DB.Put(parentPath, newParent) 272 | 273 | go func() { 274 | //todo 额外起一个协程标记删除dn中的数据 275 | }() 276 | // 删除父目录中记录的文件 277 | //deleteSize, _ := nn.fileList[parentPath].ChildFileList[name] 278 | //delete(nn.fileList[parentPath].ChildFileList, name) 279 | //srcSize := nn.fileList[parentPath].FileSize 280 | // 更改父目录的大小 281 | //nn.fileList[parentPath].FileSize = srcSize - deleteSize 282 | } 283 | return true, nil 284 | } 285 | 286 | // GetDirMeta 获取目录元数据 287 | func (nn *NameNode) GetDirMeta(name string) ([]*FileMeta, error) { 288 | resultList := []*FileMeta{} 289 | nn.lock.Lock() 290 | defer nn.lock.Unlock() 291 | 292 | //if dir, ok := nn.fileList[name]; ok && dir.IsDir { 293 | if dir, ok := nn.DB.Get(name); ok && dir.IsDir { // 如果路径存在且对应文件为目录 294 | for k, _ := range dir.ChildFileList { 295 | //fileMeta := nn.fileList[k] 296 | fileMeta := nn.DB.GetValue(k) 297 | resultList = append(resultList, fileMeta) 298 | } 299 | return resultList, nil 300 | } else if !ok { // 如果目录不存在 301 | return nil, public.ErrPathNotFind 302 | } else { // 非文件夹 303 | return nil, public.ErrNotDir 304 | } 305 | } 306 | 307 | // 定时检测dn的状态是否可用 308 | func (nn *NameNode) heartbeatMonitor() { 309 | log.Println("========== heartbeatMonitor start ==========") 310 | for { 311 | heartbeatTimeoutDuration := time.Second * time.Duration(heartbeatTimeout) 312 | time.Sleep(heartbeatTimeoutDuration) 313 | dnList := nn.DB.GetDn() 314 | for ip, datanode := range nn.DB.GetDn() { 315 | if time.Since(time.Unix(datanode.HeartbeatTimeStamp, 0)) > heartbeatTimeoutDuration { 316 | go func(ip string) { 317 | //downDN := nn.dnList.GetValue(i) 318 | downDN := dnList[ip] 319 | if downDN.Status == datanodeDown { 320 | return 321 | } 322 | newStateDN := &DatanodeMeta{ 323 | IPAddr: downDN.IPAddr, 324 | DiskUsage: downDN.DiskUsage, 325 | HeartbeatTimeStamp: downDN.HeartbeatTimeStamp, 326 | Status: datanodeDown, 327 | } 328 | dnList[ip] = newStateDN 329 | nn.DB.UpdateDn(dnList) 330 | log.Println("============================================== dn :", downDN.IPAddr, " was down ==============================================") 331 | downBlocks, newIP, processIP, err := nn.reloadReplica(downDN.IPAddr) 332 | fmt.Println("after reloadReplica") 333 | if err != nil { 334 | log.Println("can not reloadReplica: ", err) 335 | return 336 | } 337 | fmt.Println(len(downBlocks)) 338 | for j, downBlock := range downBlocks { 339 | err := datanodeReloadReplica(downBlocks[j], newIP[j], processIP[j]) 340 | log.Println("==========block :", downBlock, " on datanode: ", downDN, " was Transferred to datanode: ", newIP[j], "===================") 341 | if err != nil { 342 | fmt.Println("================================== transfer err ============================================================") 343 | log.Println(err) 344 | return 345 | } 346 | go func(blockName, newIP string) { 347 | nn.lock.Lock() 348 | defer nn.lock.Unlock() 349 | nn.blockToLocation[blockName] = append(nn.blockToLocation[blockName], replicaMeta{ 350 | blockName: blockName, 351 | ipAddr: newIP, 352 | state: ReplicaCommitted, 353 | replicaID: len(nn.blockToLocation[blockName]), 354 | }) 355 | }(downBlocks[j], newIP[j]) 356 | 357 | } 358 | }(ip) 359 | } 360 | } 361 | } 362 | } 363 | 364 | func (nn *NameNode) Heartbeat(datanodeIPAddr string, diskUsage uint64) { 365 | 366 | dnList := nn.DB.GetDn() 367 | for ip, _ := range dnList { 368 | if ip == datanodeIPAddr { 369 | log.Println("update dn:", ip, " ", datanodeIPAddr, "diskUsage :", diskUsage) 370 | newStateDN := &DatanodeMeta{ 371 | IPAddr: ip, 372 | DiskUsage: diskUsage, 373 | HeartbeatTimeStamp: time.Now().Unix(), 374 | Status: datanodeUp, 375 | } 376 | dnList[ip] = newStateDN 377 | nn.DB.UpdateDn(dnList) 378 | return 379 | } 380 | } 381 | 382 | } 383 | 384 | func (nn *NameNode) GetBlockReport(bl *proto.BlockLocation) { 385 | blockName := bl.BlockName 386 | ipAddr := bl.IpAddr 387 | blockSize := bl.BlockSize 388 | replicaID := int(bl.ReplicaID) 389 | var state replicaState 390 | if bl.GetReplicaState() == proto.BlockLocation_ReplicaPending { 391 | state = ReplicaPending 392 | } else { 393 | state = ReplicaCommitted 394 | } 395 | 396 | blockMetaList, ok := nn.blockToLocation[blockName] 397 | if !ok { 398 | nn.blockToLocation[blockName] = []replicaMeta{{ 399 | blockName: blockName, 400 | ipAddr: ipAddr, 401 | fileSize: blockSize, 402 | replicaID: replicaID, 403 | state: state, 404 | }} 405 | return 406 | } 407 | for i, _ := range blockMetaList { 408 | if blockMetaList[i].ipAddr == ipAddr { 409 | blockMetaList[i].fileSize = blockSize 410 | blockMetaList[i].replicaID = replicaID 411 | blockMetaList[i].state = state 412 | 413 | return 414 | } 415 | } 416 | var meta = replicaMeta{ 417 | blockName: blockName, 418 | ipAddr: ipAddr, 419 | fileSize: blockSize, 420 | replicaID: replicaID, 421 | state: state, 422 | } 423 | fmt.Println("=========================blockReport=========================") 424 | fmt.Println(meta) 425 | fmt.Println("=========================blockReport=========================") 426 | nn.blockToLocation[blockName] = append(nn.blockToLocation[blockName], meta) 427 | return 428 | } 429 | 430 | func (nn *NameNode) PutSuccess(path string, fileSize uint64, arr *proto.FileLocationArr) { 431 | var blockList []blockMeta 432 | // 循环遍历每个block 433 | nn.lock.Lock() 434 | defer nn.lock.Unlock() 435 | for i, list := range arr.FileBlocksList { 436 | //blockName := fmt.Sprintf("%v%v%v", path, "_", i) 437 | bm := blockMeta{ 438 | BlockName: list.BlockReplicaList[i].BlockName, 439 | TimeStamp: time.Now().UnixNano(), 440 | BlockID: i, 441 | } 442 | blockList = append(blockList, bm) 443 | var replicaList []replicaMeta 444 | // 循环遍历每个block存储的副本 445 | for j, list2 := range list.BlockReplicaList { 446 | var state replicaState 447 | if list2.GetReplicaState() == proto.BlockLocation_ReplicaPending { 448 | state = ReplicaPending 449 | } else { 450 | state = ReplicaCommitted 451 | } 452 | rm := replicaMeta{ 453 | blockName: list.BlockReplicaList[i].BlockName, 454 | fileSize: list2.BlockSize, 455 | ipAddr: list2.IpAddr, 456 | state: state, 457 | replicaID: j, 458 | } 459 | replicaList = append(replicaList, rm) 460 | } 461 | nn.blockToLocation[list.BlockReplicaList[i].BlockName] = replicaList 462 | } 463 | //nn.fileToBlock[path] = blockList 464 | //nn.file2Block.Put(path, blockList) 465 | //nn.fileList[path] = &FileMeta{ 466 | // FileName: path, 467 | // FileSize: fileSize, 468 | // ChildFileList: nil, 469 | // IsDir: false, 470 | //} 471 | newFile := &FileMeta{ 472 | FileName: path, 473 | FileSize: fileSize, 474 | ChildFileList: nil, 475 | IsDir: false, 476 | Blocks: blockList, 477 | } 478 | nn.DB.Put(path, newFile) 479 | // 在父目录中追加子文件 480 | if path != "/" { 481 | index := strings.LastIndex(path, "/") 482 | parentPath := path[:index] 483 | if parentPath == "" { 484 | parentPath = "/" 485 | } 486 | fileMeta := nn.DB.GetValue(parentPath) 487 | newParent := &FileMeta{ 488 | FileName: fileMeta.FileName, 489 | FileSize: fileMeta.FileSize, 490 | ChildFileList: fileMeta.ChildFileList, 491 | IsDir: fileMeta.IsDir, 492 | } 493 | newParent.ChildFileList[path] = newFile 494 | nn.DB.Put(parentPath, newParent) 495 | } 496 | } 497 | 498 | func (nn *NameNode) GetLocation(name string) (*proto.FileLocationArr, error) { 499 | 500 | blockReplicaLists := []*proto.BlockReplicaList{} 501 | //if block, ok := nn.fileToBlock[name]; !ok { 502 | if block, ok := nn.DB.Get(name); !ok { 503 | return nil, public.ErrPathNotFind 504 | } else { 505 | for _, meta := range block.Blocks { 506 | // 每个block存在副本的位置信息 507 | if replicaLocation, exit := nn.blockToLocation[meta.BlockName]; !exit { 508 | return nil, public.ErrReplicaNotFound 509 | } else { 510 | replicaList := []*proto.BlockLocation{} 511 | for _, location := range replicaLocation { 512 | var state proto.BlockLocation_ReplicaMetaState 513 | if location.state == ReplicaPending { 514 | state = proto.BlockLocation_ReplicaPending 515 | } else { 516 | state = proto.BlockLocation_ReplicaCommitted 517 | } 518 | replicaList = append(replicaList, &proto.BlockLocation{ 519 | IpAddr: location.ipAddr, 520 | BlockName: location.blockName, 521 | BlockSize: location.fileSize, 522 | ReplicaID: int64(location.replicaID), 523 | ReplicaState: state, 524 | }) 525 | } 526 | blockReplicaLists = append(blockReplicaLists, &proto.BlockReplicaList{ 527 | BlockReplicaList: replicaList, 528 | }) 529 | } 530 | } 531 | } 532 | 533 | var arr = proto.FileLocationArr{FileBlocksList: blockReplicaLists} 534 | return &arr, nil 535 | } 536 | 537 | func (nn *NameNode) WriteLocation(name string, num int64) (*proto.FileLocationArr, error) { 538 | var path = name 539 | timestamp := time.Now().UnixNano() 540 | //校验路径是否合法且存在 541 | for { 542 | if path == "/" || path == "" { 543 | break 544 | } 545 | index := strings.LastIndex(path, "/") 546 | path = path[:index] 547 | if path == "" { 548 | break 549 | } 550 | if _, ok := nn.DB.Get(path); !ok { 551 | return nil, public.ErrPathNotFind 552 | } 553 | } 554 | nn.lock.Lock() 555 | defer nn.lock.Unlock() 556 | //判断目标文件是否已存在 557 | if _, ok := nn.DB.Get(name); ok { 558 | return nil, public.ErrDirAlreadyExists 559 | } 560 | fileArr := proto.FileLocationArr{} 561 | blocks := []*proto.BlockReplicaList{} 562 | 563 | // 一共需要num * replicationFactor个块 (最少切片块数 * 副本数) 564 | // 每个分片在随机存储在四个不同的可用服务器上 565 | for i := 0; i < int(num); i++ { 566 | replicaIndex, err := nn.selectDN(nn.replicationFactor) 567 | if err != nil { 568 | return nil, err 569 | } 570 | replicaList := []*proto.BlockLocation{} 571 | // 每个block存在副本的位置信息 572 | for j, dn := range replicaIndex { 573 | realNameIndex := strings.LastIndex(name, "/") 574 | replicaList = append(replicaList, &proto.BlockLocation{ 575 | IpAddr: dn.IPAddr, 576 | BlockName: fmt.Sprintf("%v%v%v%v%v", name[realNameIndex+1:], "_", timestamp, "_", i), 577 | BlockSize: blockSize, 578 | ReplicaID: int64(j), 579 | ReplicaState: proto.BlockLocation_ReplicaPending, 580 | }) 581 | } 582 | blocks = append(blocks, &proto.BlockReplicaList{ 583 | BlockReplicaList: replicaList, 584 | }) 585 | } 586 | fileArr.FileBlocksList = blocks 587 | return &fileArr, nil 588 | } 589 | 590 | // needNum: 需要的副本数量 591 | // 采用map range时的不定起点作为随机选择方式,减少了之前大量的循环操作 592 | func (nn *NameNode) selectDN(needNum int) ([]*DatanodeMeta, error) { 593 | //存放结果的slice 594 | result := []*DatanodeMeta{} 595 | 596 | dnList := nn.DB.GetDn() 597 | for _, dn := range dnList { 598 | if dn.DiskUsage > uint64(blockSize) && dn.Status != datanodeDown { 599 | result = append(result, dn) 600 | } 601 | } 602 | if len(result) < needNum { 603 | return nil, public.ErrNotEnoughStorageSpace 604 | } 605 | return result, nil 606 | } 607 | 608 | func (nn *NameNode) selectTransferDN(disableIP []string) (string, error) { 609 | //目标DN 610 | fmt.Println("======================================================选择备份转移节点======================================================") 611 | dnList := nn.DB.GetDn() 612 | outer: 613 | for ip, dn := range dnList { 614 | if dn.DiskUsage > uint64(blockSize) && dn.Status != datanodeDown { 615 | //且不是已拥有该block的dn 616 | for _, disIp := range disableIP { 617 | if disIp == ip { 618 | continue outer 619 | } 620 | } 621 | fmt.Println("找到可用IP: ", ip) 622 | return ip, nil 623 | } 624 | } 625 | return "", public.ErrNotEnoughStorageSpace 626 | } 627 | 628 | // blockName and newIP 629 | func (nn *NameNode) reloadReplica(downIp string) ([]string, []string, []string, error) { 630 | downBlocks := []string{} 631 | newIP := []string{} 632 | processIP := []string{} 633 | //找到down掉的ip地址中所有的block 634 | for _, location := range nn.blockToLocation { 635 | for i, meta := range location { 636 | //找到存储在downIp中的block 637 | if meta.ipAddr == downIp { 638 | //添加到待转移副本切片 639 | downBlocks = append(downBlocks, meta.blockName) 640 | //挑选其他副本的dn 641 | replicaMetas := nn.blockToLocation[meta.blockName] 642 | // 不可作为副本存放的新节点的节点 643 | disableIP := []string{} 644 | fmt.Println(replicaMetas) 645 | for _, meta := range replicaMetas { 646 | disableIP = append(disableIP, meta.ipAddr) 647 | } 648 | fmt.Println("disabeIP: ", disableIP) 649 | dnIP, err := nn.selectTransferDN(disableIP) 650 | if err != nil { 651 | return nil, nil, nil, err 652 | } 653 | newIP = append(newIP, dnIP) 654 | if i != 0 { 655 | processIP = append(processIP, location[i-1].ipAddr) 656 | } else { 657 | processIP = append(processIP, location[i+1].ipAddr) 658 | } 659 | } 660 | } 661 | } 662 | fmt.Println("downBlocks:", downBlocks) 663 | fmt.Println("newIps:", newIP) 664 | fmt.Println("processIP:", processIP) 665 | return downBlocks, newIP, processIP, nil 666 | } 667 | 668 | func datanodeReloadReplica(blockName, newIP, processIP string) error { 669 | conn, client, _, _ := getGrpcN2DConn(processIP) 670 | defer conn.Close() 671 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 672 | defer cancel() 673 | //status, err := (*client).GetDirMeta(ctx, &proto.PathName{PathName: remoteDirPath}) 674 | log.Println("replicate "+blockName+" to ", newIP) 675 | _, err := (*client).ReloadReplica(ctx, &proto.CopyReplica2DN{BlockName: blockName, NewIP: newIP}) 676 | if err != nil { 677 | log.Print("datanode ReloadReplica fail: processIP :", err) 678 | return err 679 | } 680 | return nil 681 | } 682 | 683 | func (nn *NameNode) getBlockReport2DN() { 684 | dnList := nn.DB.GetDn() 685 | for ip, dn := range dnList { 686 | if dn.Status != datanodeDown { 687 | blockReplicaList, err := nn.getBlockReportRPC(ip) 688 | if err != nil { 689 | log.Println(err) 690 | return 691 | } 692 | for _, bm := range blockReplicaList.BlockReplicaList { 693 | nn.GetBlockReport(bm) 694 | } 695 | } 696 | } 697 | 698 | } 699 | 700 | func (nn *NameNode) getBlockReportRPC(addr string) (*proto.BlockReplicaList, error) { 701 | conn, client, _, _ := getGrpcN2DConn(addr) 702 | defer conn.Close() 703 | ctx, cancel := context.WithTimeout(context.Background(), time.Second) 704 | defer cancel() 705 | //status, err := (*client).GetDirMeta(ctx, &proto.PathName{PathName: remoteDirPath}) 706 | blockReplicaList, err := (*client).GetBlockReport(ctx, &proto.Ping{Ping: addr}) 707 | if err != nil { 708 | log.Print("datanode get BlockReport fail: addr :", addr) 709 | return nil, err 710 | } 711 | return blockReplicaList, nil 712 | } 713 | 714 | func getGrpcN2DConn(address string) (*grpc.ClientConn, *proto.N2DClient, *context.CancelFunc, error) { 715 | ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) 716 | //conn, err := grpc.DialContext(ctx, address, grpc.WithBlock()) 717 | conn2, err := grpc.DialContext(ctx, address, grpc.WithInsecure(), grpc.WithBlock()) 718 | if err != nil { 719 | log.Fatalf("did not connect to %v error %v", address, err) 720 | } 721 | client := proto.NewN2DClient(conn2) 722 | return conn2, &client, &cancel, err 723 | } 724 | -------------------------------------------------------------------------------- /proto/faydfs.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // versions: 3 | // protoc-gen-go v1.28.1 4 | // protoc v3.20.1 5 | // source: proto/faydfs.proto 6 | 7 | package proto 8 | 9 | import ( 10 | protoreflect "google.golang.org/protobuf/reflect/protoreflect" 11 | protoimpl "google.golang.org/protobuf/runtime/protoimpl" 12 | reflect "reflect" 13 | sync "sync" 14 | ) 15 | 16 | const ( 17 | // Verify that this generated code is sufficiently up-to-date. 18 | _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) 19 | // Verify that runtime/protoimpl is sufficiently up-to-date. 20 | _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) 21 | ) 22 | 23 | type FileNameAndMode_Mode int32 24 | 25 | const ( 26 | FileNameAndMode_READ FileNameAndMode_Mode = 0 27 | FileNameAndMode_WRITE FileNameAndMode_Mode = 1 28 | ) 29 | 30 | // Enum value maps for FileNameAndMode_Mode. 31 | var ( 32 | FileNameAndMode_Mode_name = map[int32]string{ 33 | 0: "READ", 34 | 1: "WRITE", 35 | } 36 | FileNameAndMode_Mode_value = map[string]int32{ 37 | "READ": 0, 38 | "WRITE": 1, 39 | } 40 | ) 41 | 42 | func (x FileNameAndMode_Mode) Enum() *FileNameAndMode_Mode { 43 | p := new(FileNameAndMode_Mode) 44 | *p = x 45 | return p 46 | } 47 | 48 | func (x FileNameAndMode_Mode) String() string { 49 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 50 | } 51 | 52 | func (FileNameAndMode_Mode) Descriptor() protoreflect.EnumDescriptor { 53 | return file_proto_faydfs_proto_enumTypes[0].Descriptor() 54 | } 55 | 56 | func (FileNameAndMode_Mode) Type() protoreflect.EnumType { 57 | return &file_proto_faydfs_proto_enumTypes[0] 58 | } 59 | 60 | func (x FileNameAndMode_Mode) Number() protoreflect.EnumNumber { 61 | return protoreflect.EnumNumber(x) 62 | } 63 | 64 | // Deprecated: Use FileNameAndMode_Mode.Descriptor instead. 65 | func (FileNameAndMode_Mode) EnumDescriptor() ([]byte, []int) { 66 | return file_proto_faydfs_proto_rawDescGZIP(), []int{2, 0} 67 | } 68 | 69 | type FileNameAndOperateMode_OperateMetaMode int32 70 | 71 | const ( 72 | FileNameAndOperateMode_DELETE FileNameAndOperateMode_OperateMetaMode = 0 73 | FileNameAndOperateMode_MKDIR FileNameAndOperateMode_OperateMetaMode = 1 74 | ) 75 | 76 | // Enum value maps for FileNameAndOperateMode_OperateMetaMode. 77 | var ( 78 | FileNameAndOperateMode_OperateMetaMode_name = map[int32]string{ 79 | 0: "DELETE", 80 | 1: "MKDIR", 81 | } 82 | FileNameAndOperateMode_OperateMetaMode_value = map[string]int32{ 83 | "DELETE": 0, 84 | "MKDIR": 1, 85 | } 86 | ) 87 | 88 | func (x FileNameAndOperateMode_OperateMetaMode) Enum() *FileNameAndOperateMode_OperateMetaMode { 89 | p := new(FileNameAndOperateMode_OperateMetaMode) 90 | *p = x 91 | return p 92 | } 93 | 94 | func (x FileNameAndOperateMode_OperateMetaMode) String() string { 95 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 96 | } 97 | 98 | func (FileNameAndOperateMode_OperateMetaMode) Descriptor() protoreflect.EnumDescriptor { 99 | return file_proto_faydfs_proto_enumTypes[1].Descriptor() 100 | } 101 | 102 | func (FileNameAndOperateMode_OperateMetaMode) Type() protoreflect.EnumType { 103 | return &file_proto_faydfs_proto_enumTypes[1] 104 | } 105 | 106 | func (x FileNameAndOperateMode_OperateMetaMode) Number() protoreflect.EnumNumber { 107 | return protoreflect.EnumNumber(x) 108 | } 109 | 110 | // Deprecated: Use FileNameAndOperateMode_OperateMetaMode.Descriptor instead. 111 | func (FileNameAndOperateMode_OperateMetaMode) EnumDescriptor() ([]byte, []int) { 112 | return file_proto_faydfs_proto_rawDescGZIP(), []int{3, 0} 113 | } 114 | 115 | type BlockLocation_ReplicaMetaState int32 116 | 117 | const ( 118 | BlockLocation_ReplicaPending BlockLocation_ReplicaMetaState = 0 119 | BlockLocation_ReplicaCommitted BlockLocation_ReplicaMetaState = 1 120 | ) 121 | 122 | // Enum value maps for BlockLocation_ReplicaMetaState. 123 | var ( 124 | BlockLocation_ReplicaMetaState_name = map[int32]string{ 125 | 0: "ReplicaPending", 126 | 1: "ReplicaCommitted", 127 | } 128 | BlockLocation_ReplicaMetaState_value = map[string]int32{ 129 | "ReplicaPending": 0, 130 | "ReplicaCommitted": 1, 131 | } 132 | ) 133 | 134 | func (x BlockLocation_ReplicaMetaState) Enum() *BlockLocation_ReplicaMetaState { 135 | p := new(BlockLocation_ReplicaMetaState) 136 | *p = x 137 | return p 138 | } 139 | 140 | func (x BlockLocation_ReplicaMetaState) String() string { 141 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 142 | } 143 | 144 | func (BlockLocation_ReplicaMetaState) Descriptor() protoreflect.EnumDescriptor { 145 | return file_proto_faydfs_proto_enumTypes[2].Descriptor() 146 | } 147 | 148 | func (BlockLocation_ReplicaMetaState) Type() protoreflect.EnumType { 149 | return &file_proto_faydfs_proto_enumTypes[2] 150 | } 151 | 152 | func (x BlockLocation_ReplicaMetaState) Number() protoreflect.EnumNumber { 153 | return protoreflect.EnumNumber(x) 154 | } 155 | 156 | // Deprecated: Use BlockLocation_ReplicaMetaState.Descriptor instead. 157 | func (BlockLocation_ReplicaMetaState) EnumDescriptor() ([]byte, []int) { 158 | return file_proto_faydfs_proto_rawDescGZIP(), []int{8, 0} 159 | } 160 | 161 | type DatanodeOperation_Operation int32 162 | 163 | const ( 164 | DatanodeOperation_DELETE DatanodeOperation_Operation = 0 165 | DatanodeOperation_REPLICATE DatanodeOperation_Operation = 1 166 | ) 167 | 168 | // Enum value maps for DatanodeOperation_Operation. 169 | var ( 170 | DatanodeOperation_Operation_name = map[int32]string{ 171 | 0: "DELETE", 172 | 1: "REPLICATE", 173 | } 174 | DatanodeOperation_Operation_value = map[string]int32{ 175 | "DELETE": 0, 176 | "REPLICATE": 1, 177 | } 178 | ) 179 | 180 | func (x DatanodeOperation_Operation) Enum() *DatanodeOperation_Operation { 181 | p := new(DatanodeOperation_Operation) 182 | *p = x 183 | return p 184 | } 185 | 186 | func (x DatanodeOperation_Operation) String() string { 187 | return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) 188 | } 189 | 190 | func (DatanodeOperation_Operation) Descriptor() protoreflect.EnumDescriptor { 191 | return file_proto_faydfs_proto_enumTypes[3].Descriptor() 192 | } 193 | 194 | func (DatanodeOperation_Operation) Type() protoreflect.EnumType { 195 | return &file_proto_faydfs_proto_enumTypes[3] 196 | } 197 | 198 | func (x DatanodeOperation_Operation) Number() protoreflect.EnumNumber { 199 | return protoreflect.EnumNumber(x) 200 | } 201 | 202 | // Deprecated: Use DatanodeOperation_Operation.Descriptor instead. 203 | func (DatanodeOperation_Operation) EnumDescriptor() ([]byte, []int) { 204 | return file_proto_faydfs_proto_rawDescGZIP(), []int{15, 0} 205 | } 206 | 207 | type FileWriteStream struct { 208 | state protoimpl.MessageState 209 | sizeCache protoimpl.SizeCache 210 | unknownFields protoimpl.UnknownFields 211 | 212 | File *File `protobuf:"bytes,1,opt,name=file,proto3" json:"file,omitempty"` 213 | BlockReplicaList *BlockReplicaList `protobuf:"bytes,2,opt,name=BlockReplicaList,proto3" json:"BlockReplicaList,omitempty"` 214 | } 215 | 216 | func (x *FileWriteStream) Reset() { 217 | *x = FileWriteStream{} 218 | if protoimpl.UnsafeEnabled { 219 | mi := &file_proto_faydfs_proto_msgTypes[0] 220 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 221 | ms.StoreMessageInfo(mi) 222 | } 223 | } 224 | 225 | func (x *FileWriteStream) String() string { 226 | return protoimpl.X.MessageStringOf(x) 227 | } 228 | 229 | func (*FileWriteStream) ProtoMessage() {} 230 | 231 | func (x *FileWriteStream) ProtoReflect() protoreflect.Message { 232 | mi := &file_proto_faydfs_proto_msgTypes[0] 233 | if protoimpl.UnsafeEnabled && x != nil { 234 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 235 | if ms.LoadMessageInfo() == nil { 236 | ms.StoreMessageInfo(mi) 237 | } 238 | return ms 239 | } 240 | return mi.MessageOf(x) 241 | } 242 | 243 | // Deprecated: Use FileWriteStream.ProtoReflect.Descriptor instead. 244 | func (*FileWriteStream) Descriptor() ([]byte, []int) { 245 | return file_proto_faydfs_proto_rawDescGZIP(), []int{0} 246 | } 247 | 248 | func (x *FileWriteStream) GetFile() *File { 249 | if x != nil { 250 | return x.File 251 | } 252 | return nil 253 | } 254 | 255 | func (x *FileWriteStream) GetBlockReplicaList() *BlockReplicaList { 256 | if x != nil { 257 | return x.BlockReplicaList 258 | } 259 | return nil 260 | } 261 | 262 | type File struct { 263 | state protoimpl.MessageState 264 | sizeCache protoimpl.SizeCache 265 | unknownFields protoimpl.UnknownFields 266 | 267 | Content []byte `protobuf:"bytes,1,opt,name=content,proto3" json:"content,omitempty"` 268 | } 269 | 270 | func (x *File) Reset() { 271 | *x = File{} 272 | if protoimpl.UnsafeEnabled { 273 | mi := &file_proto_faydfs_proto_msgTypes[1] 274 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 275 | ms.StoreMessageInfo(mi) 276 | } 277 | } 278 | 279 | func (x *File) String() string { 280 | return protoimpl.X.MessageStringOf(x) 281 | } 282 | 283 | func (*File) ProtoMessage() {} 284 | 285 | func (x *File) ProtoReflect() protoreflect.Message { 286 | mi := &file_proto_faydfs_proto_msgTypes[1] 287 | if protoimpl.UnsafeEnabled && x != nil { 288 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 289 | if ms.LoadMessageInfo() == nil { 290 | ms.StoreMessageInfo(mi) 291 | } 292 | return ms 293 | } 294 | return mi.MessageOf(x) 295 | } 296 | 297 | // Deprecated: Use File.ProtoReflect.Descriptor instead. 298 | func (*File) Descriptor() ([]byte, []int) { 299 | return file_proto_faydfs_proto_rawDescGZIP(), []int{1} 300 | } 301 | 302 | func (x *File) GetContent() []byte { 303 | if x != nil { 304 | return x.Content 305 | } 306 | return nil 307 | } 308 | 309 | // 文件路径名称与要做的操作 310 | type FileNameAndMode struct { 311 | state protoimpl.MessageState 312 | sizeCache protoimpl.SizeCache 313 | unknownFields protoimpl.UnknownFields 314 | 315 | FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"` 316 | Mode FileNameAndMode_Mode `protobuf:"varint,2,opt,name=mode,proto3,enum=proto.FileNameAndMode_Mode" json:"mode,omitempty"` 317 | BlockNum int64 `protobuf:"varint,3,opt,name=blockNum,proto3" json:"blockNum,omitempty"` 318 | } 319 | 320 | func (x *FileNameAndMode) Reset() { 321 | *x = FileNameAndMode{} 322 | if protoimpl.UnsafeEnabled { 323 | mi := &file_proto_faydfs_proto_msgTypes[2] 324 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 325 | ms.StoreMessageInfo(mi) 326 | } 327 | } 328 | 329 | func (x *FileNameAndMode) String() string { 330 | return protoimpl.X.MessageStringOf(x) 331 | } 332 | 333 | func (*FileNameAndMode) ProtoMessage() {} 334 | 335 | func (x *FileNameAndMode) ProtoReflect() protoreflect.Message { 336 | mi := &file_proto_faydfs_proto_msgTypes[2] 337 | if protoimpl.UnsafeEnabled && x != nil { 338 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 339 | if ms.LoadMessageInfo() == nil { 340 | ms.StoreMessageInfo(mi) 341 | } 342 | return ms 343 | } 344 | return mi.MessageOf(x) 345 | } 346 | 347 | // Deprecated: Use FileNameAndMode.ProtoReflect.Descriptor instead. 348 | func (*FileNameAndMode) Descriptor() ([]byte, []int) { 349 | return file_proto_faydfs_proto_rawDescGZIP(), []int{2} 350 | } 351 | 352 | func (x *FileNameAndMode) GetFileName() string { 353 | if x != nil { 354 | return x.FileName 355 | } 356 | return "" 357 | } 358 | 359 | func (x *FileNameAndMode) GetMode() FileNameAndMode_Mode { 360 | if x != nil { 361 | return x.Mode 362 | } 363 | return FileNameAndMode_READ 364 | } 365 | 366 | func (x *FileNameAndMode) GetBlockNum() int64 { 367 | if x != nil { 368 | return x.BlockNum 369 | } 370 | return 0 371 | } 372 | 373 | type FileNameAndOperateMode struct { 374 | state protoimpl.MessageState 375 | sizeCache protoimpl.SizeCache 376 | unknownFields protoimpl.UnknownFields 377 | 378 | FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"` 379 | Mode FileNameAndOperateMode_OperateMetaMode `protobuf:"varint,2,opt,name=mode,proto3,enum=proto.FileNameAndOperateMode_OperateMetaMode" json:"mode,omitempty"` 380 | } 381 | 382 | func (x *FileNameAndOperateMode) Reset() { 383 | *x = FileNameAndOperateMode{} 384 | if protoimpl.UnsafeEnabled { 385 | mi := &file_proto_faydfs_proto_msgTypes[3] 386 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 387 | ms.StoreMessageInfo(mi) 388 | } 389 | } 390 | 391 | func (x *FileNameAndOperateMode) String() string { 392 | return protoimpl.X.MessageStringOf(x) 393 | } 394 | 395 | func (*FileNameAndOperateMode) ProtoMessage() {} 396 | 397 | func (x *FileNameAndOperateMode) ProtoReflect() protoreflect.Message { 398 | mi := &file_proto_faydfs_proto_msgTypes[3] 399 | if protoimpl.UnsafeEnabled && x != nil { 400 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 401 | if ms.LoadMessageInfo() == nil { 402 | ms.StoreMessageInfo(mi) 403 | } 404 | return ms 405 | } 406 | return mi.MessageOf(x) 407 | } 408 | 409 | // Deprecated: Use FileNameAndOperateMode.ProtoReflect.Descriptor instead. 410 | func (*FileNameAndOperateMode) Descriptor() ([]byte, []int) { 411 | return file_proto_faydfs_proto_rawDescGZIP(), []int{3} 412 | } 413 | 414 | func (x *FileNameAndOperateMode) GetFileName() string { 415 | if x != nil { 416 | return x.FileName 417 | } 418 | return "" 419 | } 420 | 421 | func (x *FileNameAndOperateMode) GetMode() FileNameAndOperateMode_OperateMetaMode { 422 | if x != nil { 423 | return x.Mode 424 | } 425 | return FileNameAndOperateMode_DELETE 426 | } 427 | 428 | type SrcAndDestPath struct { 429 | state protoimpl.MessageState 430 | sizeCache protoimpl.SizeCache 431 | unknownFields protoimpl.UnknownFields 432 | 433 | RenameSrcPath string `protobuf:"bytes,1,opt,name=renameSrcPath,proto3" json:"renameSrcPath,omitempty"` 434 | RenameDestPath string `protobuf:"bytes,2,opt,name=renameDestPath,proto3" json:"renameDestPath,omitempty"` 435 | } 436 | 437 | func (x *SrcAndDestPath) Reset() { 438 | *x = SrcAndDestPath{} 439 | if protoimpl.UnsafeEnabled { 440 | mi := &file_proto_faydfs_proto_msgTypes[4] 441 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 442 | ms.StoreMessageInfo(mi) 443 | } 444 | } 445 | 446 | func (x *SrcAndDestPath) String() string { 447 | return protoimpl.X.MessageStringOf(x) 448 | } 449 | 450 | func (*SrcAndDestPath) ProtoMessage() {} 451 | 452 | func (x *SrcAndDestPath) ProtoReflect() protoreflect.Message { 453 | mi := &file_proto_faydfs_proto_msgTypes[4] 454 | if protoimpl.UnsafeEnabled && x != nil { 455 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 456 | if ms.LoadMessageInfo() == nil { 457 | ms.StoreMessageInfo(mi) 458 | } 459 | return ms 460 | } 461 | return mi.MessageOf(x) 462 | } 463 | 464 | // Deprecated: Use SrcAndDestPath.ProtoReflect.Descriptor instead. 465 | func (*SrcAndDestPath) Descriptor() ([]byte, []int) { 466 | return file_proto_faydfs_proto_rawDescGZIP(), []int{4} 467 | } 468 | 469 | func (x *SrcAndDestPath) GetRenameSrcPath() string { 470 | if x != nil { 471 | return x.RenameSrcPath 472 | } 473 | return "" 474 | } 475 | 476 | func (x *SrcAndDestPath) GetRenameDestPath() string { 477 | if x != nil { 478 | return x.RenameDestPath 479 | } 480 | return "" 481 | } 482 | 483 | type PathName struct { 484 | state protoimpl.MessageState 485 | sizeCache protoimpl.SizeCache 486 | unknownFields protoimpl.UnknownFields 487 | 488 | PathName string `protobuf:"bytes,1,opt,name=pathName,proto3" json:"pathName,omitempty"` 489 | } 490 | 491 | func (x *PathName) Reset() { 492 | *x = PathName{} 493 | if protoimpl.UnsafeEnabled { 494 | mi := &file_proto_faydfs_proto_msgTypes[5] 495 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 496 | ms.StoreMessageInfo(mi) 497 | } 498 | } 499 | 500 | func (x *PathName) String() string { 501 | return protoimpl.X.MessageStringOf(x) 502 | } 503 | 504 | func (*PathName) ProtoMessage() {} 505 | 506 | func (x *PathName) ProtoReflect() protoreflect.Message { 507 | mi := &file_proto_faydfs_proto_msgTypes[5] 508 | if protoimpl.UnsafeEnabled && x != nil { 509 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 510 | if ms.LoadMessageInfo() == nil { 511 | ms.StoreMessageInfo(mi) 512 | } 513 | return ms 514 | } 515 | return mi.MessageOf(x) 516 | } 517 | 518 | // Deprecated: Use PathName.ProtoReflect.Descriptor instead. 519 | func (*PathName) Descriptor() ([]byte, []int) { 520 | return file_proto_faydfs_proto_rawDescGZIP(), []int{5} 521 | } 522 | 523 | func (x *PathName) GetPathName() string { 524 | if x != nil { 525 | return x.PathName 526 | } 527 | return "" 528 | } 529 | 530 | type FileLocationArr struct { 531 | state protoimpl.MessageState 532 | sizeCache protoimpl.SizeCache 533 | unknownFields protoimpl.UnknownFields 534 | 535 | FileBlocksList []*BlockReplicaList `protobuf:"bytes,1,rep,name=FileBlocksList,proto3" json:"FileBlocksList,omitempty"` 536 | } 537 | 538 | func (x *FileLocationArr) Reset() { 539 | *x = FileLocationArr{} 540 | if protoimpl.UnsafeEnabled { 541 | mi := &file_proto_faydfs_proto_msgTypes[6] 542 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 543 | ms.StoreMessageInfo(mi) 544 | } 545 | } 546 | 547 | func (x *FileLocationArr) String() string { 548 | return protoimpl.X.MessageStringOf(x) 549 | } 550 | 551 | func (*FileLocationArr) ProtoMessage() {} 552 | 553 | func (x *FileLocationArr) ProtoReflect() protoreflect.Message { 554 | mi := &file_proto_faydfs_proto_msgTypes[6] 555 | if protoimpl.UnsafeEnabled && x != nil { 556 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 557 | if ms.LoadMessageInfo() == nil { 558 | ms.StoreMessageInfo(mi) 559 | } 560 | return ms 561 | } 562 | return mi.MessageOf(x) 563 | } 564 | 565 | // Deprecated: Use FileLocationArr.ProtoReflect.Descriptor instead. 566 | func (*FileLocationArr) Descriptor() ([]byte, []int) { 567 | return file_proto_faydfs_proto_rawDescGZIP(), []int{6} 568 | } 569 | 570 | func (x *FileLocationArr) GetFileBlocksList() []*BlockReplicaList { 571 | if x != nil { 572 | return x.FileBlocksList 573 | } 574 | return nil 575 | } 576 | 577 | type BlockReplicaList struct { 578 | state protoimpl.MessageState 579 | sizeCache protoimpl.SizeCache 580 | unknownFields protoimpl.UnknownFields 581 | 582 | BlockReplicaList []*BlockLocation `protobuf:"bytes,1,rep,name=BlockReplicaList,proto3" json:"BlockReplicaList,omitempty"` 583 | } 584 | 585 | func (x *BlockReplicaList) Reset() { 586 | *x = BlockReplicaList{} 587 | if protoimpl.UnsafeEnabled { 588 | mi := &file_proto_faydfs_proto_msgTypes[7] 589 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 590 | ms.StoreMessageInfo(mi) 591 | } 592 | } 593 | 594 | func (x *BlockReplicaList) String() string { 595 | return protoimpl.X.MessageStringOf(x) 596 | } 597 | 598 | func (*BlockReplicaList) ProtoMessage() {} 599 | 600 | func (x *BlockReplicaList) ProtoReflect() protoreflect.Message { 601 | mi := &file_proto_faydfs_proto_msgTypes[7] 602 | if protoimpl.UnsafeEnabled && x != nil { 603 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 604 | if ms.LoadMessageInfo() == nil { 605 | ms.StoreMessageInfo(mi) 606 | } 607 | return ms 608 | } 609 | return mi.MessageOf(x) 610 | } 611 | 612 | // Deprecated: Use BlockReplicaList.ProtoReflect.Descriptor instead. 613 | func (*BlockReplicaList) Descriptor() ([]byte, []int) { 614 | return file_proto_faydfs_proto_rawDescGZIP(), []int{7} 615 | } 616 | 617 | func (x *BlockReplicaList) GetBlockReplicaList() []*BlockLocation { 618 | if x != nil { 619 | return x.BlockReplicaList 620 | } 621 | return nil 622 | } 623 | 624 | type BlockLocation struct { 625 | state protoimpl.MessageState 626 | sizeCache protoimpl.SizeCache 627 | unknownFields protoimpl.UnknownFields 628 | 629 | IpAddr string `protobuf:"bytes,1,opt,name=ipAddr,proto3" json:"ipAddr,omitempty"` 630 | BlockName string `protobuf:"bytes,2,opt,name=blockName,proto3" json:"blockName,omitempty"` 631 | BlockSize int64 `protobuf:"varint,3,opt,name=blockSize,proto3" json:"blockSize,omitempty"` 632 | ReplicaID int64 `protobuf:"varint,4,opt,name=replicaID,proto3" json:"replicaID,omitempty"` 633 | ReplicaState BlockLocation_ReplicaMetaState `protobuf:"varint,5,opt,name=replicaState,proto3,enum=proto.BlockLocation_ReplicaMetaState" json:"replicaState,omitempty"` 634 | } 635 | 636 | func (x *BlockLocation) Reset() { 637 | *x = BlockLocation{} 638 | if protoimpl.UnsafeEnabled { 639 | mi := &file_proto_faydfs_proto_msgTypes[8] 640 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 641 | ms.StoreMessageInfo(mi) 642 | } 643 | } 644 | 645 | func (x *BlockLocation) String() string { 646 | return protoimpl.X.MessageStringOf(x) 647 | } 648 | 649 | func (*BlockLocation) ProtoMessage() {} 650 | 651 | func (x *BlockLocation) ProtoReflect() protoreflect.Message { 652 | mi := &file_proto_faydfs_proto_msgTypes[8] 653 | if protoimpl.UnsafeEnabled && x != nil { 654 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 655 | if ms.LoadMessageInfo() == nil { 656 | ms.StoreMessageInfo(mi) 657 | } 658 | return ms 659 | } 660 | return mi.MessageOf(x) 661 | } 662 | 663 | // Deprecated: Use BlockLocation.ProtoReflect.Descriptor instead. 664 | func (*BlockLocation) Descriptor() ([]byte, []int) { 665 | return file_proto_faydfs_proto_rawDescGZIP(), []int{8} 666 | } 667 | 668 | func (x *BlockLocation) GetIpAddr() string { 669 | if x != nil { 670 | return x.IpAddr 671 | } 672 | return "" 673 | } 674 | 675 | func (x *BlockLocation) GetBlockName() string { 676 | if x != nil { 677 | return x.BlockName 678 | } 679 | return "" 680 | } 681 | 682 | func (x *BlockLocation) GetBlockSize() int64 { 683 | if x != nil { 684 | return x.BlockSize 685 | } 686 | return 0 687 | } 688 | 689 | func (x *BlockLocation) GetReplicaID() int64 { 690 | if x != nil { 691 | return x.ReplicaID 692 | } 693 | return 0 694 | } 695 | 696 | func (x *BlockLocation) GetReplicaState() BlockLocation_ReplicaMetaState { 697 | if x != nil { 698 | return x.ReplicaState 699 | } 700 | return BlockLocation_ReplicaPending 701 | } 702 | 703 | type OperateStatus struct { 704 | state protoimpl.MessageState 705 | sizeCache protoimpl.SizeCache 706 | unknownFields protoimpl.UnknownFields 707 | 708 | Success bool `protobuf:"varint,1,opt,name=success,proto3" json:"success,omitempty"` 709 | } 710 | 711 | func (x *OperateStatus) Reset() { 712 | *x = OperateStatus{} 713 | if protoimpl.UnsafeEnabled { 714 | mi := &file_proto_faydfs_proto_msgTypes[9] 715 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 716 | ms.StoreMessageInfo(mi) 717 | } 718 | } 719 | 720 | func (x *OperateStatus) String() string { 721 | return protoimpl.X.MessageStringOf(x) 722 | } 723 | 724 | func (*OperateStatus) ProtoMessage() {} 725 | 726 | func (x *OperateStatus) ProtoReflect() protoreflect.Message { 727 | mi := &file_proto_faydfs_proto_msgTypes[9] 728 | if protoimpl.UnsafeEnabled && x != nil { 729 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 730 | if ms.LoadMessageInfo() == nil { 731 | ms.StoreMessageInfo(mi) 732 | } 733 | return ms 734 | } 735 | return mi.MessageOf(x) 736 | } 737 | 738 | // Deprecated: Use OperateStatus.ProtoReflect.Descriptor instead. 739 | func (*OperateStatus) Descriptor() ([]byte, []int) { 740 | return file_proto_faydfs_proto_rawDescGZIP(), []int{9} 741 | } 742 | 743 | func (x *OperateStatus) GetSuccess() bool { 744 | if x != nil { 745 | return x.Success 746 | } 747 | return false 748 | } 749 | 750 | type FileMeta struct { 751 | state protoimpl.MessageState 752 | sizeCache protoimpl.SizeCache 753 | unknownFields protoimpl.UnknownFields 754 | 755 | FileName string `protobuf:"bytes,1,opt,name=fileName,proto3" json:"fileName,omitempty"` 756 | FileSize string `protobuf:"bytes,2,opt,name=fileSize,proto3" json:"fileSize,omitempty"` 757 | IsDir bool `protobuf:"varint,3,opt,name=isDir,proto3" json:"isDir,omitempty"` 758 | } 759 | 760 | func (x *FileMeta) Reset() { 761 | *x = FileMeta{} 762 | if protoimpl.UnsafeEnabled { 763 | mi := &file_proto_faydfs_proto_msgTypes[10] 764 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 765 | ms.StoreMessageInfo(mi) 766 | } 767 | } 768 | 769 | func (x *FileMeta) String() string { 770 | return protoimpl.X.MessageStringOf(x) 771 | } 772 | 773 | func (*FileMeta) ProtoMessage() {} 774 | 775 | func (x *FileMeta) ProtoReflect() protoreflect.Message { 776 | mi := &file_proto_faydfs_proto_msgTypes[10] 777 | if protoimpl.UnsafeEnabled && x != nil { 778 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 779 | if ms.LoadMessageInfo() == nil { 780 | ms.StoreMessageInfo(mi) 781 | } 782 | return ms 783 | } 784 | return mi.MessageOf(x) 785 | } 786 | 787 | // Deprecated: Use FileMeta.ProtoReflect.Descriptor instead. 788 | func (*FileMeta) Descriptor() ([]byte, []int) { 789 | return file_proto_faydfs_proto_rawDescGZIP(), []int{10} 790 | } 791 | 792 | func (x *FileMeta) GetFileName() string { 793 | if x != nil { 794 | return x.FileName 795 | } 796 | return "" 797 | } 798 | 799 | func (x *FileMeta) GetFileSize() string { 800 | if x != nil { 801 | return x.FileSize 802 | } 803 | return "" 804 | } 805 | 806 | func (x *FileMeta) GetIsDir() bool { 807 | if x != nil { 808 | return x.IsDir 809 | } 810 | return false 811 | } 812 | 813 | type DirMetaList struct { 814 | state protoimpl.MessageState 815 | sizeCache protoimpl.SizeCache 816 | unknownFields protoimpl.UnknownFields 817 | 818 | MetaList []*FileMeta `protobuf:"bytes,1,rep,name=metaList,proto3" json:"metaList,omitempty"` 819 | } 820 | 821 | func (x *DirMetaList) Reset() { 822 | *x = DirMetaList{} 823 | if protoimpl.UnsafeEnabled { 824 | mi := &file_proto_faydfs_proto_msgTypes[11] 825 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 826 | ms.StoreMessageInfo(mi) 827 | } 828 | } 829 | 830 | func (x *DirMetaList) String() string { 831 | return protoimpl.X.MessageStringOf(x) 832 | } 833 | 834 | func (*DirMetaList) ProtoMessage() {} 835 | 836 | func (x *DirMetaList) ProtoReflect() protoreflect.Message { 837 | mi := &file_proto_faydfs_proto_msgTypes[11] 838 | if protoimpl.UnsafeEnabled && x != nil { 839 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 840 | if ms.LoadMessageInfo() == nil { 841 | ms.StoreMessageInfo(mi) 842 | } 843 | return ms 844 | } 845 | return mi.MessageOf(x) 846 | } 847 | 848 | // Deprecated: Use DirMetaList.ProtoReflect.Descriptor instead. 849 | func (*DirMetaList) Descriptor() ([]byte, []int) { 850 | return file_proto_faydfs_proto_rawDescGZIP(), []int{11} 851 | } 852 | 853 | func (x *DirMetaList) GetMetaList() []*FileMeta { 854 | if x != nil { 855 | return x.MetaList 856 | } 857 | return nil 858 | } 859 | 860 | type Ping struct { 861 | state protoimpl.MessageState 862 | sizeCache protoimpl.SizeCache 863 | unknownFields protoimpl.UnknownFields 864 | 865 | Ping string `protobuf:"bytes,1,opt,name=ping,proto3" json:"ping,omitempty"` 866 | } 867 | 868 | func (x *Ping) Reset() { 869 | *x = Ping{} 870 | if protoimpl.UnsafeEnabled { 871 | mi := &file_proto_faydfs_proto_msgTypes[12] 872 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 873 | ms.StoreMessageInfo(mi) 874 | } 875 | } 876 | 877 | func (x *Ping) String() string { 878 | return protoimpl.X.MessageStringOf(x) 879 | } 880 | 881 | func (*Ping) ProtoMessage() {} 882 | 883 | func (x *Ping) ProtoReflect() protoreflect.Message { 884 | mi := &file_proto_faydfs_proto_msgTypes[12] 885 | if protoimpl.UnsafeEnabled && x != nil { 886 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 887 | if ms.LoadMessageInfo() == nil { 888 | ms.StoreMessageInfo(mi) 889 | } 890 | return ms 891 | } 892 | return mi.MessageOf(x) 893 | } 894 | 895 | // Deprecated: Use Ping.ProtoReflect.Descriptor instead. 896 | func (*Ping) Descriptor() ([]byte, []int) { 897 | return file_proto_faydfs_proto_rawDescGZIP(), []int{12} 898 | } 899 | 900 | func (x *Ping) GetPing() string { 901 | if x != nil { 902 | return x.Ping 903 | } 904 | return "" 905 | } 906 | 907 | type Heartbeat struct { 908 | state protoimpl.MessageState 909 | sizeCache protoimpl.SizeCache 910 | unknownFields protoimpl.UnknownFields 911 | 912 | IpAddr string `protobuf:"bytes,1,opt,name=ipAddr,proto3" json:"ipAddr,omitempty"` 913 | DiskUsage uint64 `protobuf:"varint,2,opt,name=DiskUsage,proto3" json:"DiskUsage,omitempty"` 914 | } 915 | 916 | func (x *Heartbeat) Reset() { 917 | *x = Heartbeat{} 918 | if protoimpl.UnsafeEnabled { 919 | mi := &file_proto_faydfs_proto_msgTypes[13] 920 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 921 | ms.StoreMessageInfo(mi) 922 | } 923 | } 924 | 925 | func (x *Heartbeat) String() string { 926 | return protoimpl.X.MessageStringOf(x) 927 | } 928 | 929 | func (*Heartbeat) ProtoMessage() {} 930 | 931 | func (x *Heartbeat) ProtoReflect() protoreflect.Message { 932 | mi := &file_proto_faydfs_proto_msgTypes[13] 933 | if protoimpl.UnsafeEnabled && x != nil { 934 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 935 | if ms.LoadMessageInfo() == nil { 936 | ms.StoreMessageInfo(mi) 937 | } 938 | return ms 939 | } 940 | return mi.MessageOf(x) 941 | } 942 | 943 | // Deprecated: Use Heartbeat.ProtoReflect.Descriptor instead. 944 | func (*Heartbeat) Descriptor() ([]byte, []int) { 945 | return file_proto_faydfs_proto_rawDescGZIP(), []int{13} 946 | } 947 | 948 | func (x *Heartbeat) GetIpAddr() string { 949 | if x != nil { 950 | return x.IpAddr 951 | } 952 | return "" 953 | } 954 | 955 | func (x *Heartbeat) GetDiskUsage() uint64 { 956 | if x != nil { 957 | return x.DiskUsage 958 | } 959 | return 0 960 | } 961 | 962 | type RegisterDataNodeReq struct { 963 | state protoimpl.MessageState 964 | sizeCache protoimpl.SizeCache 965 | unknownFields protoimpl.UnknownFields 966 | 967 | New bool `protobuf:"varint,1,opt,name=new,proto3" json:"new,omitempty"` 968 | DiskUsage uint64 `protobuf:"varint,2,opt,name=DiskUsage,proto3" json:"DiskUsage,omitempty"` 969 | IpAddr string `protobuf:"bytes,3,opt,name=ipAddr,proto3" json:"ipAddr,omitempty"` 970 | } 971 | 972 | func (x *RegisterDataNodeReq) Reset() { 973 | *x = RegisterDataNodeReq{} 974 | if protoimpl.UnsafeEnabled { 975 | mi := &file_proto_faydfs_proto_msgTypes[14] 976 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 977 | ms.StoreMessageInfo(mi) 978 | } 979 | } 980 | 981 | func (x *RegisterDataNodeReq) String() string { 982 | return protoimpl.X.MessageStringOf(x) 983 | } 984 | 985 | func (*RegisterDataNodeReq) ProtoMessage() {} 986 | 987 | func (x *RegisterDataNodeReq) ProtoReflect() protoreflect.Message { 988 | mi := &file_proto_faydfs_proto_msgTypes[14] 989 | if protoimpl.UnsafeEnabled && x != nil { 990 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 991 | if ms.LoadMessageInfo() == nil { 992 | ms.StoreMessageInfo(mi) 993 | } 994 | return ms 995 | } 996 | return mi.MessageOf(x) 997 | } 998 | 999 | // Deprecated: Use RegisterDataNodeReq.ProtoReflect.Descriptor instead. 1000 | func (*RegisterDataNodeReq) Descriptor() ([]byte, []int) { 1001 | return file_proto_faydfs_proto_rawDescGZIP(), []int{14} 1002 | } 1003 | 1004 | func (x *RegisterDataNodeReq) GetNew() bool { 1005 | if x != nil { 1006 | return x.New 1007 | } 1008 | return false 1009 | } 1010 | 1011 | func (x *RegisterDataNodeReq) GetDiskUsage() uint64 { 1012 | if x != nil { 1013 | return x.DiskUsage 1014 | } 1015 | return 0 1016 | } 1017 | 1018 | func (x *RegisterDataNodeReq) GetIpAddr() string { 1019 | if x != nil { 1020 | return x.IpAddr 1021 | } 1022 | return "" 1023 | } 1024 | 1025 | type DatanodeOperation struct { 1026 | state protoimpl.MessageState 1027 | sizeCache protoimpl.SizeCache 1028 | unknownFields protoimpl.UnknownFields 1029 | 1030 | Operation DatanodeOperation_Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=proto.DatanodeOperation_Operation" json:"operation,omitempty"` 1031 | IpAddr string `protobuf:"bytes,2,opt,name=ipAddr,proto3" json:"ipAddr,omitempty"` 1032 | } 1033 | 1034 | func (x *DatanodeOperation) Reset() { 1035 | *x = DatanodeOperation{} 1036 | if protoimpl.UnsafeEnabled { 1037 | mi := &file_proto_faydfs_proto_msgTypes[15] 1038 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 1039 | ms.StoreMessageInfo(mi) 1040 | } 1041 | } 1042 | 1043 | func (x *DatanodeOperation) String() string { 1044 | return protoimpl.X.MessageStringOf(x) 1045 | } 1046 | 1047 | func (*DatanodeOperation) ProtoMessage() {} 1048 | 1049 | func (x *DatanodeOperation) ProtoReflect() protoreflect.Message { 1050 | mi := &file_proto_faydfs_proto_msgTypes[15] 1051 | if protoimpl.UnsafeEnabled && x != nil { 1052 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 1053 | if ms.LoadMessageInfo() == nil { 1054 | ms.StoreMessageInfo(mi) 1055 | } 1056 | return ms 1057 | } 1058 | return mi.MessageOf(x) 1059 | } 1060 | 1061 | // Deprecated: Use DatanodeOperation.ProtoReflect.Descriptor instead. 1062 | func (*DatanodeOperation) Descriptor() ([]byte, []int) { 1063 | return file_proto_faydfs_proto_rawDescGZIP(), []int{15} 1064 | } 1065 | 1066 | func (x *DatanodeOperation) GetOperation() DatanodeOperation_Operation { 1067 | if x != nil { 1068 | return x.Operation 1069 | } 1070 | return DatanodeOperation_DELETE 1071 | } 1072 | 1073 | func (x *DatanodeOperation) GetIpAddr() string { 1074 | if x != nil { 1075 | return x.IpAddr 1076 | } 1077 | return "" 1078 | } 1079 | 1080 | type MetaStore struct { 1081 | state protoimpl.MessageState 1082 | sizeCache protoimpl.SizeCache 1083 | unknownFields protoimpl.UnknownFields 1084 | 1085 | FileLocationArr *FileLocationArr `protobuf:"bytes,1,opt,name=fileLocationArr,proto3" json:"fileLocationArr,omitempty"` 1086 | FilePath string `protobuf:"bytes,2,opt,name=filePath,proto3" json:"filePath,omitempty"` 1087 | FileSize uint64 `protobuf:"varint,3,opt,name=fileSize,proto3" json:"fileSize,omitempty"` 1088 | ClientName string `protobuf:"bytes,4,opt,name=clientName,proto3" json:"clientName,omitempty"` 1089 | } 1090 | 1091 | func (x *MetaStore) Reset() { 1092 | *x = MetaStore{} 1093 | if protoimpl.UnsafeEnabled { 1094 | mi := &file_proto_faydfs_proto_msgTypes[16] 1095 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 1096 | ms.StoreMessageInfo(mi) 1097 | } 1098 | } 1099 | 1100 | func (x *MetaStore) String() string { 1101 | return protoimpl.X.MessageStringOf(x) 1102 | } 1103 | 1104 | func (*MetaStore) ProtoMessage() {} 1105 | 1106 | func (x *MetaStore) ProtoReflect() protoreflect.Message { 1107 | mi := &file_proto_faydfs_proto_msgTypes[16] 1108 | if protoimpl.UnsafeEnabled && x != nil { 1109 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 1110 | if ms.LoadMessageInfo() == nil { 1111 | ms.StoreMessageInfo(mi) 1112 | } 1113 | return ms 1114 | } 1115 | return mi.MessageOf(x) 1116 | } 1117 | 1118 | // Deprecated: Use MetaStore.ProtoReflect.Descriptor instead. 1119 | func (*MetaStore) Descriptor() ([]byte, []int) { 1120 | return file_proto_faydfs_proto_rawDescGZIP(), []int{16} 1121 | } 1122 | 1123 | func (x *MetaStore) GetFileLocationArr() *FileLocationArr { 1124 | if x != nil { 1125 | return x.FileLocationArr 1126 | } 1127 | return nil 1128 | } 1129 | 1130 | func (x *MetaStore) GetFilePath() string { 1131 | if x != nil { 1132 | return x.FilePath 1133 | } 1134 | return "" 1135 | } 1136 | 1137 | func (x *MetaStore) GetFileSize() uint64 { 1138 | if x != nil { 1139 | return x.FileSize 1140 | } 1141 | return 0 1142 | } 1143 | 1144 | func (x *MetaStore) GetClientName() string { 1145 | if x != nil { 1146 | return x.ClientName 1147 | } 1148 | return "" 1149 | } 1150 | 1151 | type GetLease struct { 1152 | state protoimpl.MessageState 1153 | sizeCache protoimpl.SizeCache 1154 | unknownFields protoimpl.UnknownFields 1155 | 1156 | Pathname *PathName `protobuf:"bytes,1,opt,name=pathname,proto3" json:"pathname,omitempty"` 1157 | ClientName string `protobuf:"bytes,2,opt,name=clientName,proto3" json:"clientName,omitempty"` 1158 | } 1159 | 1160 | func (x *GetLease) Reset() { 1161 | *x = GetLease{} 1162 | if protoimpl.UnsafeEnabled { 1163 | mi := &file_proto_faydfs_proto_msgTypes[17] 1164 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 1165 | ms.StoreMessageInfo(mi) 1166 | } 1167 | } 1168 | 1169 | func (x *GetLease) String() string { 1170 | return protoimpl.X.MessageStringOf(x) 1171 | } 1172 | 1173 | func (*GetLease) ProtoMessage() {} 1174 | 1175 | func (x *GetLease) ProtoReflect() protoreflect.Message { 1176 | mi := &file_proto_faydfs_proto_msgTypes[17] 1177 | if protoimpl.UnsafeEnabled && x != nil { 1178 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 1179 | if ms.LoadMessageInfo() == nil { 1180 | ms.StoreMessageInfo(mi) 1181 | } 1182 | return ms 1183 | } 1184 | return mi.MessageOf(x) 1185 | } 1186 | 1187 | // Deprecated: Use GetLease.ProtoReflect.Descriptor instead. 1188 | func (*GetLease) Descriptor() ([]byte, []int) { 1189 | return file_proto_faydfs_proto_rawDescGZIP(), []int{17} 1190 | } 1191 | 1192 | func (x *GetLease) GetPathname() *PathName { 1193 | if x != nil { 1194 | return x.Pathname 1195 | } 1196 | return nil 1197 | } 1198 | 1199 | func (x *GetLease) GetClientName() string { 1200 | if x != nil { 1201 | return x.ClientName 1202 | } 1203 | return "" 1204 | } 1205 | 1206 | type CopyReplica2DN struct { 1207 | state protoimpl.MessageState 1208 | sizeCache protoimpl.SizeCache 1209 | unknownFields protoimpl.UnknownFields 1210 | 1211 | BlockName string `protobuf:"bytes,1,opt,name=blockName,proto3" json:"blockName,omitempty"` 1212 | NewIP string `protobuf:"bytes,2,opt,name=newIP,proto3" json:"newIP,omitempty"` 1213 | } 1214 | 1215 | func (x *CopyReplica2DN) Reset() { 1216 | *x = CopyReplica2DN{} 1217 | if protoimpl.UnsafeEnabled { 1218 | mi := &file_proto_faydfs_proto_msgTypes[18] 1219 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 1220 | ms.StoreMessageInfo(mi) 1221 | } 1222 | } 1223 | 1224 | func (x *CopyReplica2DN) String() string { 1225 | return protoimpl.X.MessageStringOf(x) 1226 | } 1227 | 1228 | func (*CopyReplica2DN) ProtoMessage() {} 1229 | 1230 | func (x *CopyReplica2DN) ProtoReflect() protoreflect.Message { 1231 | mi := &file_proto_faydfs_proto_msgTypes[18] 1232 | if protoimpl.UnsafeEnabled && x != nil { 1233 | ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) 1234 | if ms.LoadMessageInfo() == nil { 1235 | ms.StoreMessageInfo(mi) 1236 | } 1237 | return ms 1238 | } 1239 | return mi.MessageOf(x) 1240 | } 1241 | 1242 | // Deprecated: Use CopyReplica2DN.ProtoReflect.Descriptor instead. 1243 | func (*CopyReplica2DN) Descriptor() ([]byte, []int) { 1244 | return file_proto_faydfs_proto_rawDescGZIP(), []int{18} 1245 | } 1246 | 1247 | func (x *CopyReplica2DN) GetBlockName() string { 1248 | if x != nil { 1249 | return x.BlockName 1250 | } 1251 | return "" 1252 | } 1253 | 1254 | func (x *CopyReplica2DN) GetNewIP() string { 1255 | if x != nil { 1256 | return x.NewIP 1257 | } 1258 | return "" 1259 | } 1260 | 1261 | var File_proto_faydfs_proto protoreflect.FileDescriptor 1262 | 1263 | var file_proto_faydfs_proto_rawDesc = []byte{ 1264 | 0x0a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x66, 0x61, 0x79, 0x64, 0x66, 0x73, 0x2e, 0x70, 1265 | 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x77, 0x0a, 0x0f, 0x46, 1266 | 0x69, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1f, 1267 | 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 1268 | 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 1269 | 0x43, 0x0a, 0x10, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x4c, 1270 | 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 1271 | 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x4c, 0x69, 1272 | 0x73, 0x74, 0x52, 0x10, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 1273 | 0x4c, 0x69, 0x73, 0x74, 0x22, 0x20, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x18, 0x0a, 0x07, 1274 | 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x63, 1275 | 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x22, 0x97, 0x01, 0x0a, 0x0f, 0x46, 0x69, 0x6c, 0x65, 0x4e, 1276 | 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 1277 | 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 1278 | 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 1279 | 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 1280 | 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x2e, 0x4d, 0x6f, 0x64, 1281 | 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 1282 | 0x4e, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 1283 | 0x4e, 0x75, 0x6d, 0x22, 0x1b, 0x0a, 0x04, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x08, 0x0a, 0x04, 0x52, 1284 | 0x45, 0x41, 0x44, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x57, 0x52, 0x49, 0x54, 0x45, 0x10, 0x01, 1285 | 0x22, 0xa1, 0x01, 0x0a, 0x16, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 1286 | 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 1287 | 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 1288 | 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 1289 | 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 1290 | 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 1291 | 0x4d, 0x6f, 0x64, 0x65, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 1292 | 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x22, 0x28, 0x0a, 0x0f, 0x4f, 0x70, 1293 | 0x65, 0x72, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0a, 0x0a, 1294 | 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x4d, 0x4b, 0x44, 1295 | 0x49, 0x52, 0x10, 0x01, 0x22, 0x5e, 0x0a, 0x0e, 0x53, 0x72, 0x63, 0x41, 0x6e, 0x64, 0x44, 0x65, 1296 | 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 1297 | 0x53, 0x72, 0x63, 0x50, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 1298 | 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x53, 0x72, 0x63, 0x50, 0x61, 0x74, 0x68, 0x12, 0x26, 0x0a, 0x0e, 1299 | 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 1300 | 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x44, 0x65, 0x73, 0x74, 1301 | 0x50, 0x61, 0x74, 0x68, 0x22, 0x26, 0x0a, 0x08, 0x50, 0x61, 0x74, 0x68, 0x4e, 0x61, 0x6d, 0x65, 1302 | 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x74, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 1303 | 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x52, 0x0a, 0x0f, 1304 | 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x72, 0x12, 1305 | 0x3f, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4c, 0x69, 0x73, 1306 | 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 1307 | 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x4c, 0x69, 0x73, 0x74, 1308 | 0x52, 0x0e, 0x46, 0x69, 0x6c, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x4c, 0x69, 0x73, 0x74, 1309 | 0x22, 0x54, 0x0a, 0x10, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 1310 | 0x4c, 0x69, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x10, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 1311 | 0x6c, 0x69, 0x63, 0x61, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 1312 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f, 0x63, 0x61, 1313 | 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x69, 1314 | 0x63, 0x61, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x8a, 0x02, 0x0a, 0x0d, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 1315 | 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x41, 0x64, 1316 | 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 1317 | 0x12, 0x1c, 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 1318 | 0x01, 0x28, 0x09, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 1319 | 0x0a, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 1320 | 0x03, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1c, 0x0a, 0x09, 1321 | 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x49, 0x44, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 1322 | 0x09, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x49, 0x44, 0x12, 0x49, 0x0a, 0x0c, 0x72, 0x65, 1323 | 0x70, 0x6c, 0x69, 0x63, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 1324 | 0x32, 0x25, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x4c, 0x6f, 1325 | 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x4d, 0x65, 1326 | 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 1327 | 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x3c, 0x0a, 0x10, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 1328 | 0x4d, 0x65, 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x65, 0x70, 1329 | 0x6c, 0x69, 0x63, 0x61, 0x50, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x14, 0x0a, 1330 | 0x10, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x74, 0x65, 1331 | 0x64, 0x10, 0x01, 0x22, 0x29, 0x0a, 0x0d, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 1332 | 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 1333 | 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0x58, 1334 | 0x0a, 0x08, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 1335 | 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 1336 | 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 1337 | 0x7a, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 1338 | 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x73, 0x44, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 1339 | 0x08, 0x52, 0x05, 0x69, 0x73, 0x44, 0x69, 0x72, 0x22, 0x3a, 0x0a, 0x0b, 0x44, 0x69, 0x72, 0x4d, 1340 | 0x65, 0x74, 0x61, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x2b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x4c, 1341 | 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 1342 | 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 1343 | 0x4c, 0x69, 0x73, 0x74, 0x22, 0x1a, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x12, 0x0a, 0x04, 1344 | 0x70, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x69, 0x6e, 0x67, 1345 | 0x22, 0x41, 0x0a, 0x09, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x16, 0x0a, 1346 | 0x06, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 1347 | 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x44, 0x69, 0x73, 0x6b, 0x55, 0x73, 0x61, 1348 | 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x44, 0x69, 0x73, 0x6b, 0x55, 0x73, 1349 | 0x61, 0x67, 0x65, 0x22, 0x5d, 0x0a, 0x13, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 1350 | 0x61, 0x74, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x12, 0x10, 0x0a, 0x03, 0x6e, 0x65, 1351 | 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6e, 0x65, 0x77, 0x12, 0x1c, 0x0a, 0x09, 1352 | 0x44, 0x69, 0x73, 0x6b, 0x55, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 1353 | 0x09, 0x44, 0x69, 0x73, 0x6b, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 1354 | 0x41, 0x64, 0x64, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x41, 0x64, 1355 | 0x64, 0x72, 0x22, 0x95, 0x01, 0x0a, 0x11, 0x44, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x64, 0x65, 0x4f, 1356 | 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x40, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 1357 | 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x70, 0x72, 1358 | 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 1359 | 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 1360 | 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 1361 | 0x41, 0x64, 0x64, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x41, 0x64, 1362 | 0x64, 0x72, 0x22, 0x26, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 1363 | 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x52, 1364 | 0x45, 0x50, 0x4c, 0x49, 0x43, 0x41, 0x54, 0x45, 0x10, 0x01, 0x22, 0xa5, 0x01, 0x0a, 0x09, 0x4d, 1365 | 0x65, 0x74, 0x61, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x12, 0x40, 0x0a, 0x0f, 0x66, 0x69, 0x6c, 0x65, 1366 | 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 1367 | 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x6f, 1368 | 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x72, 0x52, 0x0f, 0x66, 0x69, 0x6c, 0x65, 0x4c, 1369 | 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 1370 | 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 1371 | 0x6c, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 1372 | 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x53, 0x69, 1373 | 0x7a, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 1374 | 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 1375 | 0x6d, 0x65, 0x22, 0x57, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x4c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x2b, 1376 | 0x0a, 0x08, 0x70, 0x61, 0x74, 0x68, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 1377 | 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4e, 0x61, 0x6d, 1378 | 0x65, 0x52, 0x08, 0x70, 0x61, 0x74, 0x68, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 1379 | 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 1380 | 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x22, 0x44, 0x0a, 0x0e, 0x43, 1381 | 0x6f, 0x70, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x32, 0x44, 0x4e, 0x12, 0x1c, 0x0a, 1382 | 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 1383 | 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 1384 | 0x65, 0x77, 0x49, 0x50, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, 0x65, 0x77, 0x49, 1385 | 0x50, 0x32, 0xe6, 0x03, 0x0a, 0x03, 0x43, 0x32, 0x4e, 0x12, 0x4e, 0x0a, 0x1c, 0x47, 0x65, 0x74, 1386 | 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x6e, 0x64, 0x4d, 1387 | 0x6f, 0x64, 0x69, 0x66, 0x79, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 1388 | 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 0x4d, 0x6f, 0x64, 1389 | 0x65, 0x1a, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x6f, 1390 | 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x72, 0x12, 0x3c, 0x0a, 0x0a, 0x43, 0x72, 0x65, 1391 | 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 1392 | 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x1a, 1393 | 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x61, 1394 | 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x72, 0x72, 0x12, 0x42, 0x0a, 0x0b, 0x4f, 0x70, 0x65, 0x72, 0x61, 1395 | 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 1396 | 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 0x64, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 1397 | 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x70, 1398 | 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3f, 0x0a, 0x10, 0x52, 1399 | 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x49, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x12, 1400 | 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x53, 0x72, 0x63, 0x41, 0x6e, 0x64, 0x44, 0x65, 1401 | 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 1402 | 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2f, 0x0a, 0x0b, 1403 | 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x0f, 0x2e, 0x70, 0x72, 1404 | 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x0f, 0x2e, 0x70, 1405 | 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x31, 0x0a, 1406 | 0x0a, 0x47, 0x65, 0x74, 0x44, 0x69, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x0f, 0x2e, 0x70, 0x72, 1407 | 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x61, 0x74, 0x68, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x12, 0x2e, 0x70, 1408 | 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x69, 0x72, 0x4d, 0x65, 0x74, 0x61, 0x4c, 0x69, 0x73, 0x74, 1409 | 0x12, 0x34, 0x0a, 0x0a, 0x50, 0x75, 0x74, 0x53, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x10, 1410 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x53, 0x74, 0x6f, 0x72, 0x65, 1411 | 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 1412 | 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x32, 0x0a, 0x09, 0x52, 0x65, 0x6e, 0x65, 0x77, 0x4c, 1413 | 0x6f, 0x63, 0x6b, 0x12, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x47, 0x65, 0x74, 0x4c, 1414 | 0x65, 0x61, 0x73, 0x65, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x70, 0x65, 1415 | 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x32, 0x7a, 0x0a, 0x03, 0x43, 0x32, 1416 | 0x44, 0x12, 0x33, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x2e, 1417 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x41, 0x6e, 1418 | 0x64, 0x4d, 0x6f, 0x64, 0x65, 0x1a, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 1419 | 0x6c, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x3e, 0x0a, 0x0a, 0x57, 0x72, 0x69, 0x74, 0x65, 0x42, 1420 | 0x6c, 0x6f, 0x63, 0x6b, 0x12, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x46, 0x69, 0x6c, 1421 | 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x1a, 0x14, 0x2e, 0x70, 1422 | 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 1423 | 0x75, 0x73, 0x22, 0x00, 0x28, 0x01, 0x32, 0x7b, 0x0a, 0x03, 0x4e, 0x32, 0x44, 0x12, 0x36, 0x0a, 1424 | 0x0e, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 1425 | 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x1a, 0x17, 0x2e, 0x70, 1426 | 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 1427 | 0x61, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0d, 0x52, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x52, 1428 | 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x12, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 1429 | 0x6f, 0x70, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x32, 0x44, 0x4e, 0x1a, 0x14, 0x2e, 1430 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 1431 | 0x74, 0x75, 0x73, 0x32, 0xca, 0x01, 0x0a, 0x03, 0x44, 0x32, 0x4e, 0x12, 0x3f, 0x0a, 0x11, 0x44, 1432 | 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x64, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 1433 | 0x12, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 1434 | 0x61, 0x74, 0x1a, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x6e, 1435 | 0x6f, 0x64, 0x65, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, 0x0b, 1436 | 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x70, 0x72, 1437 | 0x6f, 0x74, 0x6f, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x69, 0x63, 0x61, 1438 | 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4f, 0x70, 0x65, 1439 | 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x44, 0x0a, 0x10, 0x52, 0x65, 1440 | 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x1a, 1441 | 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x44, 1442 | 0x61, 0x74, 0x61, 0x4e, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x70, 0x72, 0x6f, 1443 | 0x74, 0x6f, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 1444 | 0x42, 0x0c, 0x5a, 0x0a, 0x2e, 0x2e, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 1445 | 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 1446 | } 1447 | 1448 | var ( 1449 | file_proto_faydfs_proto_rawDescOnce sync.Once 1450 | file_proto_faydfs_proto_rawDescData = file_proto_faydfs_proto_rawDesc 1451 | ) 1452 | 1453 | func file_proto_faydfs_proto_rawDescGZIP() []byte { 1454 | file_proto_faydfs_proto_rawDescOnce.Do(func() { 1455 | file_proto_faydfs_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_faydfs_proto_rawDescData) 1456 | }) 1457 | return file_proto_faydfs_proto_rawDescData 1458 | } 1459 | 1460 | var file_proto_faydfs_proto_enumTypes = make([]protoimpl.EnumInfo, 4) 1461 | var file_proto_faydfs_proto_msgTypes = make([]protoimpl.MessageInfo, 19) 1462 | var file_proto_faydfs_proto_goTypes = []interface{}{ 1463 | (FileNameAndMode_Mode)(0), // 0: proto.FileNameAndMode.Mode 1464 | (FileNameAndOperateMode_OperateMetaMode)(0), // 1: proto.FileNameAndOperateMode.OperateMetaMode 1465 | (BlockLocation_ReplicaMetaState)(0), // 2: proto.BlockLocation.ReplicaMetaState 1466 | (DatanodeOperation_Operation)(0), // 3: proto.DatanodeOperation.Operation 1467 | (*FileWriteStream)(nil), // 4: proto.FileWriteStream 1468 | (*File)(nil), // 5: proto.File 1469 | (*FileNameAndMode)(nil), // 6: proto.FileNameAndMode 1470 | (*FileNameAndOperateMode)(nil), // 7: proto.FileNameAndOperateMode 1471 | (*SrcAndDestPath)(nil), // 8: proto.SrcAndDestPath 1472 | (*PathName)(nil), // 9: proto.PathName 1473 | (*FileLocationArr)(nil), // 10: proto.FileLocationArr 1474 | (*BlockReplicaList)(nil), // 11: proto.BlockReplicaList 1475 | (*BlockLocation)(nil), // 12: proto.BlockLocation 1476 | (*OperateStatus)(nil), // 13: proto.OperateStatus 1477 | (*FileMeta)(nil), // 14: proto.FileMeta 1478 | (*DirMetaList)(nil), // 15: proto.DirMetaList 1479 | (*Ping)(nil), // 16: proto.Ping 1480 | (*Heartbeat)(nil), // 17: proto.Heartbeat 1481 | (*RegisterDataNodeReq)(nil), // 18: proto.RegisterDataNodeReq 1482 | (*DatanodeOperation)(nil), // 19: proto.DatanodeOperation 1483 | (*MetaStore)(nil), // 20: proto.MetaStore 1484 | (*GetLease)(nil), // 21: proto.GetLease 1485 | (*CopyReplica2DN)(nil), // 22: proto.CopyReplica2DN 1486 | } 1487 | var file_proto_faydfs_proto_depIdxs = []int32{ 1488 | 5, // 0: proto.FileWriteStream.file:type_name -> proto.File 1489 | 11, // 1: proto.FileWriteStream.BlockReplicaList:type_name -> proto.BlockReplicaList 1490 | 0, // 2: proto.FileNameAndMode.mode:type_name -> proto.FileNameAndMode.Mode 1491 | 1, // 3: proto.FileNameAndOperateMode.mode:type_name -> proto.FileNameAndOperateMode.OperateMetaMode 1492 | 11, // 4: proto.FileLocationArr.FileBlocksList:type_name -> proto.BlockReplicaList 1493 | 12, // 5: proto.BlockReplicaList.BlockReplicaList:type_name -> proto.BlockLocation 1494 | 2, // 6: proto.BlockLocation.replicaState:type_name -> proto.BlockLocation.ReplicaMetaState 1495 | 14, // 7: proto.DirMetaList.metaList:type_name -> proto.FileMeta 1496 | 3, // 8: proto.DatanodeOperation.operation:type_name -> proto.DatanodeOperation.Operation 1497 | 10, // 9: proto.MetaStore.fileLocationArr:type_name -> proto.FileLocationArr 1498 | 9, // 10: proto.GetLease.pathname:type_name -> proto.PathName 1499 | 6, // 11: proto.C2N.GetFileLocationAndModifyMeta:input_type -> proto.FileNameAndMode 1500 | 6, // 12: proto.C2N.CreateFile:input_type -> proto.FileNameAndMode 1501 | 7, // 13: proto.C2N.OperateMeta:input_type -> proto.FileNameAndOperateMode 1502 | 8, // 14: proto.C2N.RenameFileInMeta:input_type -> proto.SrcAndDestPath 1503 | 9, // 15: proto.C2N.GetFileMeta:input_type -> proto.PathName 1504 | 9, // 16: proto.C2N.GetDirMeta:input_type -> proto.PathName 1505 | 20, // 17: proto.C2N.PutSuccess:input_type -> proto.MetaStore 1506 | 21, // 18: proto.C2N.RenewLock:input_type -> proto.GetLease 1507 | 6, // 19: proto.C2D.GetBlock:input_type -> proto.FileNameAndMode 1508 | 4, // 20: proto.C2D.WriteBlock:input_type -> proto.FileWriteStream 1509 | 16, // 21: proto.N2D.GetBlockReport:input_type -> proto.Ping 1510 | 22, // 22: proto.N2D.ReloadReplica:input_type -> proto.CopyReplica2DN 1511 | 17, // 23: proto.D2N.DatanodeHeartbeat:input_type -> proto.Heartbeat 1512 | 11, // 24: proto.D2N.BlockReport:input_type -> proto.BlockReplicaList 1513 | 18, // 25: proto.D2N.RegisterDataNode:input_type -> proto.RegisterDataNodeReq 1514 | 10, // 26: proto.C2N.GetFileLocationAndModifyMeta:output_type -> proto.FileLocationArr 1515 | 10, // 27: proto.C2N.CreateFile:output_type -> proto.FileLocationArr 1516 | 13, // 28: proto.C2N.OperateMeta:output_type -> proto.OperateStatus 1517 | 13, // 29: proto.C2N.RenameFileInMeta:output_type -> proto.OperateStatus 1518 | 14, // 30: proto.C2N.GetFileMeta:output_type -> proto.FileMeta 1519 | 15, // 31: proto.C2N.GetDirMeta:output_type -> proto.DirMetaList 1520 | 13, // 32: proto.C2N.PutSuccess:output_type -> proto.OperateStatus 1521 | 13, // 33: proto.C2N.RenewLock:output_type -> proto.OperateStatus 1522 | 5, // 34: proto.C2D.GetBlock:output_type -> proto.File 1523 | 13, // 35: proto.C2D.WriteBlock:output_type -> proto.OperateStatus 1524 | 11, // 36: proto.N2D.GetBlockReport:output_type -> proto.BlockReplicaList 1525 | 13, // 37: proto.N2D.ReloadReplica:output_type -> proto.OperateStatus 1526 | 19, // 38: proto.D2N.DatanodeHeartbeat:output_type -> proto.DatanodeOperation 1527 | 13, // 39: proto.D2N.BlockReport:output_type -> proto.OperateStatus 1528 | 13, // 40: proto.D2N.RegisterDataNode:output_type -> proto.OperateStatus 1529 | 26, // [26:41] is the sub-list for method output_type 1530 | 11, // [11:26] is the sub-list for method input_type 1531 | 11, // [11:11] is the sub-list for extension type_name 1532 | 11, // [11:11] is the sub-list for extension extendee 1533 | 0, // [0:11] is the sub-list for field type_name 1534 | } 1535 | 1536 | func init() { file_proto_faydfs_proto_init() } 1537 | func file_proto_faydfs_proto_init() { 1538 | if File_proto_faydfs_proto != nil { 1539 | return 1540 | } 1541 | if !protoimpl.UnsafeEnabled { 1542 | file_proto_faydfs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { 1543 | switch v := v.(*FileWriteStream); i { 1544 | case 0: 1545 | return &v.state 1546 | case 1: 1547 | return &v.sizeCache 1548 | case 2: 1549 | return &v.unknownFields 1550 | default: 1551 | return nil 1552 | } 1553 | } 1554 | file_proto_faydfs_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { 1555 | switch v := v.(*File); i { 1556 | case 0: 1557 | return &v.state 1558 | case 1: 1559 | return &v.sizeCache 1560 | case 2: 1561 | return &v.unknownFields 1562 | default: 1563 | return nil 1564 | } 1565 | } 1566 | file_proto_faydfs_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { 1567 | switch v := v.(*FileNameAndMode); i { 1568 | case 0: 1569 | return &v.state 1570 | case 1: 1571 | return &v.sizeCache 1572 | case 2: 1573 | return &v.unknownFields 1574 | default: 1575 | return nil 1576 | } 1577 | } 1578 | file_proto_faydfs_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { 1579 | switch v := v.(*FileNameAndOperateMode); i { 1580 | case 0: 1581 | return &v.state 1582 | case 1: 1583 | return &v.sizeCache 1584 | case 2: 1585 | return &v.unknownFields 1586 | default: 1587 | return nil 1588 | } 1589 | } 1590 | file_proto_faydfs_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { 1591 | switch v := v.(*SrcAndDestPath); i { 1592 | case 0: 1593 | return &v.state 1594 | case 1: 1595 | return &v.sizeCache 1596 | case 2: 1597 | return &v.unknownFields 1598 | default: 1599 | return nil 1600 | } 1601 | } 1602 | file_proto_faydfs_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { 1603 | switch v := v.(*PathName); i { 1604 | case 0: 1605 | return &v.state 1606 | case 1: 1607 | return &v.sizeCache 1608 | case 2: 1609 | return &v.unknownFields 1610 | default: 1611 | return nil 1612 | } 1613 | } 1614 | file_proto_faydfs_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { 1615 | switch v := v.(*FileLocationArr); i { 1616 | case 0: 1617 | return &v.state 1618 | case 1: 1619 | return &v.sizeCache 1620 | case 2: 1621 | return &v.unknownFields 1622 | default: 1623 | return nil 1624 | } 1625 | } 1626 | file_proto_faydfs_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { 1627 | switch v := v.(*BlockReplicaList); i { 1628 | case 0: 1629 | return &v.state 1630 | case 1: 1631 | return &v.sizeCache 1632 | case 2: 1633 | return &v.unknownFields 1634 | default: 1635 | return nil 1636 | } 1637 | } 1638 | file_proto_faydfs_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { 1639 | switch v := v.(*BlockLocation); i { 1640 | case 0: 1641 | return &v.state 1642 | case 1: 1643 | return &v.sizeCache 1644 | case 2: 1645 | return &v.unknownFields 1646 | default: 1647 | return nil 1648 | } 1649 | } 1650 | file_proto_faydfs_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { 1651 | switch v := v.(*OperateStatus); i { 1652 | case 0: 1653 | return &v.state 1654 | case 1: 1655 | return &v.sizeCache 1656 | case 2: 1657 | return &v.unknownFields 1658 | default: 1659 | return nil 1660 | } 1661 | } 1662 | file_proto_faydfs_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { 1663 | switch v := v.(*FileMeta); i { 1664 | case 0: 1665 | return &v.state 1666 | case 1: 1667 | return &v.sizeCache 1668 | case 2: 1669 | return &v.unknownFields 1670 | default: 1671 | return nil 1672 | } 1673 | } 1674 | file_proto_faydfs_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { 1675 | switch v := v.(*DirMetaList); i { 1676 | case 0: 1677 | return &v.state 1678 | case 1: 1679 | return &v.sizeCache 1680 | case 2: 1681 | return &v.unknownFields 1682 | default: 1683 | return nil 1684 | } 1685 | } 1686 | file_proto_faydfs_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { 1687 | switch v := v.(*Ping); i { 1688 | case 0: 1689 | return &v.state 1690 | case 1: 1691 | return &v.sizeCache 1692 | case 2: 1693 | return &v.unknownFields 1694 | default: 1695 | return nil 1696 | } 1697 | } 1698 | file_proto_faydfs_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { 1699 | switch v := v.(*Heartbeat); i { 1700 | case 0: 1701 | return &v.state 1702 | case 1: 1703 | return &v.sizeCache 1704 | case 2: 1705 | return &v.unknownFields 1706 | default: 1707 | return nil 1708 | } 1709 | } 1710 | file_proto_faydfs_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { 1711 | switch v := v.(*RegisterDataNodeReq); i { 1712 | case 0: 1713 | return &v.state 1714 | case 1: 1715 | return &v.sizeCache 1716 | case 2: 1717 | return &v.unknownFields 1718 | default: 1719 | return nil 1720 | } 1721 | } 1722 | file_proto_faydfs_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { 1723 | switch v := v.(*DatanodeOperation); i { 1724 | case 0: 1725 | return &v.state 1726 | case 1: 1727 | return &v.sizeCache 1728 | case 2: 1729 | return &v.unknownFields 1730 | default: 1731 | return nil 1732 | } 1733 | } 1734 | file_proto_faydfs_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { 1735 | switch v := v.(*MetaStore); i { 1736 | case 0: 1737 | return &v.state 1738 | case 1: 1739 | return &v.sizeCache 1740 | case 2: 1741 | return &v.unknownFields 1742 | default: 1743 | return nil 1744 | } 1745 | } 1746 | file_proto_faydfs_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { 1747 | switch v := v.(*GetLease); i { 1748 | case 0: 1749 | return &v.state 1750 | case 1: 1751 | return &v.sizeCache 1752 | case 2: 1753 | return &v.unknownFields 1754 | default: 1755 | return nil 1756 | } 1757 | } 1758 | file_proto_faydfs_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { 1759 | switch v := v.(*CopyReplica2DN); i { 1760 | case 0: 1761 | return &v.state 1762 | case 1: 1763 | return &v.sizeCache 1764 | case 2: 1765 | return &v.unknownFields 1766 | default: 1767 | return nil 1768 | } 1769 | } 1770 | } 1771 | type x struct{} 1772 | out := protoimpl.TypeBuilder{ 1773 | File: protoimpl.DescBuilder{ 1774 | GoPackagePath: reflect.TypeOf(x{}).PkgPath(), 1775 | RawDescriptor: file_proto_faydfs_proto_rawDesc, 1776 | NumEnums: 4, 1777 | NumMessages: 19, 1778 | NumExtensions: 0, 1779 | NumServices: 4, 1780 | }, 1781 | GoTypes: file_proto_faydfs_proto_goTypes, 1782 | DependencyIndexes: file_proto_faydfs_proto_depIdxs, 1783 | EnumInfos: file_proto_faydfs_proto_enumTypes, 1784 | MessageInfos: file_proto_faydfs_proto_msgTypes, 1785 | }.Build() 1786 | File_proto_faydfs_proto = out.File 1787 | file_proto_faydfs_proto_rawDesc = nil 1788 | file_proto_faydfs_proto_goTypes = nil 1789 | file_proto_faydfs_proto_depIdxs = nil 1790 | } 1791 | -------------------------------------------------------------------------------- /proto/faydfs.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option go_package = "../service"; 4 | 5 | package proto; 6 | 7 | service C2N { 8 | // 获取文件位置并操作元数据 (应在datanode返回给client之前进行元数据修改) 9 | rpc GetFileLocationAndModifyMeta (FileNameAndMode) returns (FileLocationArr); 10 | // 创建文件 11 | rpc CreateFile (FileNameAndMode) returns (FileLocationArr); 12 | // Delete 和 Mkdir 13 | rpc OperateMeta (FileNameAndOperateMode) returns (OperateStatus); 14 | // Rename 15 | rpc RenameFileInMeta (SrcAndDestPath) returns (OperateStatus); 16 | // Stat 17 | rpc GetFileMeta (PathName) returns (FileMeta); 18 | // List 19 | rpc GetDirMeta (PathName) returns (DirMetaList); 20 | // 告知metanode,datanode数据传输完成 21 | rpc PutSuccess (MetaStore) returns (OperateStatus); 22 | // 更新租约 23 | rpc RenewLock(GetLease) returns (OperateStatus); 24 | } 25 | 26 | service C2D { 27 | // 从块中读取数据 28 | rpc GetBlock (FileNameAndMode) returns (stream File){}; 29 | // 向指定块写入数据 30 | rpc WriteBlock (stream FileWriteStream) returns (OperateStatus){}; 31 | } 32 | 33 | service N2D { 34 | // 从datanode中获取块的位置信息 35 | rpc GetBlockReport (Ping) returns (BlockReplicaList); 36 | // 向datanode发出请求复制转移block 37 | rpc ReloadReplica (CopyReplica2DN) returns (OperateStatus); 38 | } 39 | 40 | service D2N { 41 | // 每3s向namenode发送一次心跳 42 | rpc DatanodeHeartbeat(Heartbeat) returns (DatanodeOperation); 43 | // 每1h向namenode汇报一次block状态 44 | rpc BlockReport (BlockReplicaList) returns (OperateStatus); 45 | // 向namenode进行注册 46 | rpc RegisterDataNode (RegisterDataNodeReq) returns (OperateStatus); 47 | } 48 | 49 | message FileWriteStream { 50 | File file = 1; 51 | BlockReplicaList BlockReplicaList = 2; 52 | } 53 | 54 | message File { 55 | bytes content = 1; 56 | } 57 | 58 | // 文件路径名称与要做的操作 59 | message FileNameAndMode { 60 | enum Mode { 61 | READ = 0; 62 | WRITE = 1; 63 | } 64 | string fileName = 1; 65 | Mode mode = 2; 66 | int64 blockNum = 3; 67 | } 68 | 69 | message FileNameAndOperateMode { 70 | enum OperateMetaMode { 71 | DELETE = 0; 72 | MKDIR = 1; 73 | } 74 | string fileName = 1; 75 | OperateMetaMode mode = 2; 76 | } 77 | 78 | message SrcAndDestPath { 79 | string renameSrcPath = 1; 80 | string renameDestPath = 2; 81 | } 82 | 83 | 84 | message PathName { 85 | string pathName = 1; 86 | } 87 | 88 | message FileLocationArr { 89 | repeated BlockReplicaList FileBlocksList = 1; 90 | } 91 | 92 | message BlockReplicaList { 93 | repeated BlockLocation BlockReplicaList = 1; 94 | } 95 | 96 | message BlockLocation { 97 | enum ReplicaMetaState { 98 | ReplicaPending = 0; 99 | ReplicaCommitted = 1; 100 | } 101 | string ipAddr = 1; 102 | string blockName = 2; 103 | int64 blockSize = 3; 104 | int64 replicaID = 4; 105 | ReplicaMetaState replicaState = 5; 106 | } 107 | 108 | message OperateStatus { 109 | bool success = 1; 110 | } 111 | 112 | message FileMeta { 113 | string fileName = 1; 114 | string fileSize = 2; 115 | bool isDir = 3; 116 | } 117 | 118 | message DirMetaList { 119 | repeated FileMeta metaList = 1; 120 | } 121 | 122 | message Ping { 123 | string ping = 1; 124 | } 125 | 126 | message Heartbeat { 127 | string ipAddr = 1; 128 | uint64 DiskUsage = 2; 129 | } 130 | 131 | message RegisterDataNodeReq { 132 | bool new = 1; 133 | uint64 DiskUsage = 2; 134 | string ipAddr = 3; 135 | } 136 | 137 | message DatanodeOperation { 138 | enum Operation { 139 | DELETE = 0; 140 | REPLICATE = 1; 141 | } 142 | Operation operation = 1; 143 | string ipAddr = 2; 144 | } 145 | 146 | message MetaStore{ 147 | FileLocationArr fileLocationArr = 1; 148 | string filePath = 2; 149 | uint64 fileSize = 3; 150 | string clientName = 4; 151 | } 152 | 153 | message GetLease{ 154 | PathName pathname = 1; 155 | string clientName = 2; 156 | } 157 | 158 | message CopyReplica2DN{ 159 | string blockName = 1; 160 | string newIP = 2; 161 | } -------------------------------------------------------------------------------- /proto/faydfs_grpc.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go-grpc. DO NOT EDIT. 2 | // versions: 3 | // - protoc-gen-go-grpc v1.2.0 4 | // - protoc v3.20.1 5 | // source: proto/faydfs.proto 6 | 7 | package proto 8 | 9 | import ( 10 | context "context" 11 | grpc "google.golang.org/grpc" 12 | codes "google.golang.org/grpc/codes" 13 | status "google.golang.org/grpc/status" 14 | ) 15 | 16 | // This is a compile-time assertion to ensure that this generated file 17 | // is compatible with the grpc package it is being compiled against. 18 | // Requires gRPC-Go v1.32.0 or later. 19 | const _ = grpc.SupportPackageIsVersion7 20 | 21 | // C2NClient is the client API for C2N service. 22 | // 23 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 24 | type C2NClient interface { 25 | // 获取文件位置并操作元数据 (应在datanode返回给client之前进行元数据修改) 26 | GetFileLocationAndModifyMeta(ctx context.Context, in *FileNameAndMode, opts ...grpc.CallOption) (*FileLocationArr, error) 27 | // 创建文件 28 | CreateFile(ctx context.Context, in *FileNameAndMode, opts ...grpc.CallOption) (*FileLocationArr, error) 29 | // Delete 和 Mkdir 30 | OperateMeta(ctx context.Context, in *FileNameAndOperateMode, opts ...grpc.CallOption) (*OperateStatus, error) 31 | // Rename 32 | RenameFileInMeta(ctx context.Context, in *SrcAndDestPath, opts ...grpc.CallOption) (*OperateStatus, error) 33 | // Stat 34 | GetFileMeta(ctx context.Context, in *PathName, opts ...grpc.CallOption) (*FileMeta, error) 35 | // List 36 | GetDirMeta(ctx context.Context, in *PathName, opts ...grpc.CallOption) (*DirMetaList, error) 37 | // 告知metanode,datanode数据传输完成 38 | PutSuccess(ctx context.Context, in *MetaStore, opts ...grpc.CallOption) (*OperateStatus, error) 39 | // 更新租约 40 | RenewLock(ctx context.Context, in *GetLease, opts ...grpc.CallOption) (*OperateStatus, error) 41 | } 42 | 43 | type c2NClient struct { 44 | cc grpc.ClientConnInterface 45 | } 46 | 47 | func NewC2NClient(cc grpc.ClientConnInterface) C2NClient { 48 | return &c2NClient{cc} 49 | } 50 | 51 | func (c *c2NClient) GetFileLocationAndModifyMeta(ctx context.Context, in *FileNameAndMode, opts ...grpc.CallOption) (*FileLocationArr, error) { 52 | out := new(FileLocationArr) 53 | err := c.cc.Invoke(ctx, "/proto.C2N/GetFileLocationAndModifyMeta", in, out, opts...) 54 | if err != nil { 55 | return nil, err 56 | } 57 | return out, nil 58 | } 59 | 60 | func (c *c2NClient) CreateFile(ctx context.Context, in *FileNameAndMode, opts ...grpc.CallOption) (*FileLocationArr, error) { 61 | out := new(FileLocationArr) 62 | err := c.cc.Invoke(ctx, "/proto.C2N/CreateFile", in, out, opts...) 63 | if err != nil { 64 | return nil, err 65 | } 66 | return out, nil 67 | } 68 | 69 | func (c *c2NClient) OperateMeta(ctx context.Context, in *FileNameAndOperateMode, opts ...grpc.CallOption) (*OperateStatus, error) { 70 | out := new(OperateStatus) 71 | err := c.cc.Invoke(ctx, "/proto.C2N/OperateMeta", in, out, opts...) 72 | if err != nil { 73 | return nil, err 74 | } 75 | return out, nil 76 | } 77 | 78 | func (c *c2NClient) RenameFileInMeta(ctx context.Context, in *SrcAndDestPath, opts ...grpc.CallOption) (*OperateStatus, error) { 79 | out := new(OperateStatus) 80 | err := c.cc.Invoke(ctx, "/proto.C2N/RenameFileInMeta", in, out, opts...) 81 | if err != nil { 82 | return nil, err 83 | } 84 | return out, nil 85 | } 86 | 87 | func (c *c2NClient) GetFileMeta(ctx context.Context, in *PathName, opts ...grpc.CallOption) (*FileMeta, error) { 88 | out := new(FileMeta) 89 | err := c.cc.Invoke(ctx, "/proto.C2N/GetFileMeta", in, out, opts...) 90 | if err != nil { 91 | return nil, err 92 | } 93 | return out, nil 94 | } 95 | 96 | func (c *c2NClient) GetDirMeta(ctx context.Context, in *PathName, opts ...grpc.CallOption) (*DirMetaList, error) { 97 | out := new(DirMetaList) 98 | err := c.cc.Invoke(ctx, "/proto.C2N/GetDirMeta", in, out, opts...) 99 | if err != nil { 100 | return nil, err 101 | } 102 | return out, nil 103 | } 104 | 105 | func (c *c2NClient) PutSuccess(ctx context.Context, in *MetaStore, opts ...grpc.CallOption) (*OperateStatus, error) { 106 | out := new(OperateStatus) 107 | err := c.cc.Invoke(ctx, "/proto.C2N/PutSuccess", in, out, opts...) 108 | if err != nil { 109 | return nil, err 110 | } 111 | return out, nil 112 | } 113 | 114 | func (c *c2NClient) RenewLock(ctx context.Context, in *GetLease, opts ...grpc.CallOption) (*OperateStatus, error) { 115 | out := new(OperateStatus) 116 | err := c.cc.Invoke(ctx, "/proto.C2N/RenewLock", in, out, opts...) 117 | if err != nil { 118 | return nil, err 119 | } 120 | return out, nil 121 | } 122 | 123 | // C2NServer is the server API for C2N service. 124 | // All implementations must embed UnimplementedC2NServer 125 | // for forward compatibility 126 | type C2NServer interface { 127 | // 获取文件位置并操作元数据 (应在datanode返回给client之前进行元数据修改) 128 | GetFileLocationAndModifyMeta(context.Context, *FileNameAndMode) (*FileLocationArr, error) 129 | // 创建文件 130 | CreateFile(context.Context, *FileNameAndMode) (*FileLocationArr, error) 131 | // Delete 和 Mkdir 132 | OperateMeta(context.Context, *FileNameAndOperateMode) (*OperateStatus, error) 133 | // Rename 134 | RenameFileInMeta(context.Context, *SrcAndDestPath) (*OperateStatus, error) 135 | // Stat 136 | GetFileMeta(context.Context, *PathName) (*FileMeta, error) 137 | // List 138 | GetDirMeta(context.Context, *PathName) (*DirMetaList, error) 139 | // 告知metanode,datanode数据传输完成 140 | PutSuccess(context.Context, *MetaStore) (*OperateStatus, error) 141 | // 更新租约 142 | RenewLock(context.Context, *GetLease) (*OperateStatus, error) 143 | mustEmbedUnimplementedC2NServer() 144 | } 145 | 146 | // UnimplementedC2NServer must be embedded to have forward compatible implementations. 147 | type UnimplementedC2NServer struct { 148 | } 149 | 150 | func (UnimplementedC2NServer) GetFileLocationAndModifyMeta(context.Context, *FileNameAndMode) (*FileLocationArr, error) { 151 | return nil, status.Errorf(codes.Unimplemented, "method GetFileLocationAndModifyMeta not implemented") 152 | } 153 | func (UnimplementedC2NServer) CreateFile(context.Context, *FileNameAndMode) (*FileLocationArr, error) { 154 | return nil, status.Errorf(codes.Unimplemented, "method CreateFile not implemented") 155 | } 156 | func (UnimplementedC2NServer) OperateMeta(context.Context, *FileNameAndOperateMode) (*OperateStatus, error) { 157 | return nil, status.Errorf(codes.Unimplemented, "method OperateMeta not implemented") 158 | } 159 | func (UnimplementedC2NServer) RenameFileInMeta(context.Context, *SrcAndDestPath) (*OperateStatus, error) { 160 | return nil, status.Errorf(codes.Unimplemented, "method RenameFileInMeta not implemented") 161 | } 162 | func (UnimplementedC2NServer) GetFileMeta(context.Context, *PathName) (*FileMeta, error) { 163 | return nil, status.Errorf(codes.Unimplemented, "method GetFileMeta not implemented") 164 | } 165 | func (UnimplementedC2NServer) GetDirMeta(context.Context, *PathName) (*DirMetaList, error) { 166 | return nil, status.Errorf(codes.Unimplemented, "method GetDirMeta not implemented") 167 | } 168 | func (UnimplementedC2NServer) PutSuccess(context.Context, *MetaStore) (*OperateStatus, error) { 169 | return nil, status.Errorf(codes.Unimplemented, "method PutSuccess not implemented") 170 | } 171 | func (UnimplementedC2NServer) RenewLock(context.Context, *GetLease) (*OperateStatus, error) { 172 | return nil, status.Errorf(codes.Unimplemented, "method RenewLock not implemented") 173 | } 174 | func (UnimplementedC2NServer) mustEmbedUnimplementedC2NServer() {} 175 | 176 | // UnsafeC2NServer may be embedded to opt out of forward compatibility for this service. 177 | // Use of this interface is not recommended, as added methods to C2NServer will 178 | // result in compilation errors. 179 | type UnsafeC2NServer interface { 180 | mustEmbedUnimplementedC2NServer() 181 | } 182 | 183 | func RegisterC2NServer(s grpc.ServiceRegistrar, srv C2NServer) { 184 | s.RegisterService(&C2N_ServiceDesc, srv) 185 | } 186 | 187 | func _C2N_GetFileLocationAndModifyMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 188 | in := new(FileNameAndMode) 189 | if err := dec(in); err != nil { 190 | return nil, err 191 | } 192 | if interceptor == nil { 193 | return srv.(C2NServer).GetFileLocationAndModifyMeta(ctx, in) 194 | } 195 | info := &grpc.UnaryServerInfo{ 196 | Server: srv, 197 | FullMethod: "/proto.C2N/GetFileLocationAndModifyMeta", 198 | } 199 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 200 | return srv.(C2NServer).GetFileLocationAndModifyMeta(ctx, req.(*FileNameAndMode)) 201 | } 202 | return interceptor(ctx, in, info, handler) 203 | } 204 | 205 | func _C2N_CreateFile_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 206 | in := new(FileNameAndMode) 207 | if err := dec(in); err != nil { 208 | return nil, err 209 | } 210 | if interceptor == nil { 211 | return srv.(C2NServer).CreateFile(ctx, in) 212 | } 213 | info := &grpc.UnaryServerInfo{ 214 | Server: srv, 215 | FullMethod: "/proto.C2N/CreateFile", 216 | } 217 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 218 | return srv.(C2NServer).CreateFile(ctx, req.(*FileNameAndMode)) 219 | } 220 | return interceptor(ctx, in, info, handler) 221 | } 222 | 223 | func _C2N_OperateMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 224 | in := new(FileNameAndOperateMode) 225 | if err := dec(in); err != nil { 226 | return nil, err 227 | } 228 | if interceptor == nil { 229 | return srv.(C2NServer).OperateMeta(ctx, in) 230 | } 231 | info := &grpc.UnaryServerInfo{ 232 | Server: srv, 233 | FullMethod: "/proto.C2N/OperateMeta", 234 | } 235 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 236 | return srv.(C2NServer).OperateMeta(ctx, req.(*FileNameAndOperateMode)) 237 | } 238 | return interceptor(ctx, in, info, handler) 239 | } 240 | 241 | func _C2N_RenameFileInMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 242 | in := new(SrcAndDestPath) 243 | if err := dec(in); err != nil { 244 | return nil, err 245 | } 246 | if interceptor == nil { 247 | return srv.(C2NServer).RenameFileInMeta(ctx, in) 248 | } 249 | info := &grpc.UnaryServerInfo{ 250 | Server: srv, 251 | FullMethod: "/proto.C2N/RenameFileInMeta", 252 | } 253 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 254 | return srv.(C2NServer).RenameFileInMeta(ctx, req.(*SrcAndDestPath)) 255 | } 256 | return interceptor(ctx, in, info, handler) 257 | } 258 | 259 | func _C2N_GetFileMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 260 | in := new(PathName) 261 | if err := dec(in); err != nil { 262 | return nil, err 263 | } 264 | if interceptor == nil { 265 | return srv.(C2NServer).GetFileMeta(ctx, in) 266 | } 267 | info := &grpc.UnaryServerInfo{ 268 | Server: srv, 269 | FullMethod: "/proto.C2N/GetFileMeta", 270 | } 271 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 272 | return srv.(C2NServer).GetFileMeta(ctx, req.(*PathName)) 273 | } 274 | return interceptor(ctx, in, info, handler) 275 | } 276 | 277 | func _C2N_GetDirMeta_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 278 | in := new(PathName) 279 | if err := dec(in); err != nil { 280 | return nil, err 281 | } 282 | if interceptor == nil { 283 | return srv.(C2NServer).GetDirMeta(ctx, in) 284 | } 285 | info := &grpc.UnaryServerInfo{ 286 | Server: srv, 287 | FullMethod: "/proto.C2N/GetDirMeta", 288 | } 289 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 290 | return srv.(C2NServer).GetDirMeta(ctx, req.(*PathName)) 291 | } 292 | return interceptor(ctx, in, info, handler) 293 | } 294 | 295 | func _C2N_PutSuccess_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 296 | in := new(MetaStore) 297 | if err := dec(in); err != nil { 298 | return nil, err 299 | } 300 | if interceptor == nil { 301 | return srv.(C2NServer).PutSuccess(ctx, in) 302 | } 303 | info := &grpc.UnaryServerInfo{ 304 | Server: srv, 305 | FullMethod: "/proto.C2N/PutSuccess", 306 | } 307 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 308 | return srv.(C2NServer).PutSuccess(ctx, req.(*MetaStore)) 309 | } 310 | return interceptor(ctx, in, info, handler) 311 | } 312 | 313 | func _C2N_RenewLock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 314 | in := new(GetLease) 315 | if err := dec(in); err != nil { 316 | return nil, err 317 | } 318 | if interceptor == nil { 319 | return srv.(C2NServer).RenewLock(ctx, in) 320 | } 321 | info := &grpc.UnaryServerInfo{ 322 | Server: srv, 323 | FullMethod: "/proto.C2N/RenewLock", 324 | } 325 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 326 | return srv.(C2NServer).RenewLock(ctx, req.(*GetLease)) 327 | } 328 | return interceptor(ctx, in, info, handler) 329 | } 330 | 331 | // C2N_ServiceDesc is the grpc.ServiceDesc for C2N service. 332 | // It's only intended for direct use with grpc.RegisterService, 333 | // and not to be introspected or modified (even as a copy) 334 | var C2N_ServiceDesc = grpc.ServiceDesc{ 335 | ServiceName: "proto.C2N", 336 | HandlerType: (*C2NServer)(nil), 337 | Methods: []grpc.MethodDesc{ 338 | { 339 | MethodName: "GetFileLocationAndModifyMeta", 340 | Handler: _C2N_GetFileLocationAndModifyMeta_Handler, 341 | }, 342 | { 343 | MethodName: "CreateFile", 344 | Handler: _C2N_CreateFile_Handler, 345 | }, 346 | { 347 | MethodName: "OperateMeta", 348 | Handler: _C2N_OperateMeta_Handler, 349 | }, 350 | { 351 | MethodName: "RenameFileInMeta", 352 | Handler: _C2N_RenameFileInMeta_Handler, 353 | }, 354 | { 355 | MethodName: "GetFileMeta", 356 | Handler: _C2N_GetFileMeta_Handler, 357 | }, 358 | { 359 | MethodName: "GetDirMeta", 360 | Handler: _C2N_GetDirMeta_Handler, 361 | }, 362 | { 363 | MethodName: "PutSuccess", 364 | Handler: _C2N_PutSuccess_Handler, 365 | }, 366 | { 367 | MethodName: "RenewLock", 368 | Handler: _C2N_RenewLock_Handler, 369 | }, 370 | }, 371 | Streams: []grpc.StreamDesc{}, 372 | Metadata: "proto/faydfs.proto", 373 | } 374 | 375 | // C2DClient is the client API for C2D service. 376 | // 377 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 378 | type C2DClient interface { 379 | // 从块中读取数据 380 | GetBlock(ctx context.Context, in *FileNameAndMode, opts ...grpc.CallOption) (C2D_GetBlockClient, error) 381 | // 向指定块写入数据 382 | WriteBlock(ctx context.Context, opts ...grpc.CallOption) (C2D_WriteBlockClient, error) 383 | } 384 | 385 | type c2DClient struct { 386 | cc grpc.ClientConnInterface 387 | } 388 | 389 | func NewC2DClient(cc grpc.ClientConnInterface) C2DClient { 390 | return &c2DClient{cc} 391 | } 392 | 393 | func (c *c2DClient) GetBlock(ctx context.Context, in *FileNameAndMode, opts ...grpc.CallOption) (C2D_GetBlockClient, error) { 394 | stream, err := c.cc.NewStream(ctx, &C2D_ServiceDesc.Streams[0], "/proto.C2D/GetBlock", opts...) 395 | if err != nil { 396 | return nil, err 397 | } 398 | x := &c2DGetBlockClient{stream} 399 | if err := x.ClientStream.SendMsg(in); err != nil { 400 | return nil, err 401 | } 402 | if err := x.ClientStream.CloseSend(); err != nil { 403 | return nil, err 404 | } 405 | return x, nil 406 | } 407 | 408 | type C2D_GetBlockClient interface { 409 | Recv() (*File, error) 410 | grpc.ClientStream 411 | } 412 | 413 | type c2DGetBlockClient struct { 414 | grpc.ClientStream 415 | } 416 | 417 | func (x *c2DGetBlockClient) Recv() (*File, error) { 418 | m := new(File) 419 | if err := x.ClientStream.RecvMsg(m); err != nil { 420 | return nil, err 421 | } 422 | return m, nil 423 | } 424 | 425 | func (c *c2DClient) WriteBlock(ctx context.Context, opts ...grpc.CallOption) (C2D_WriteBlockClient, error) { 426 | stream, err := c.cc.NewStream(ctx, &C2D_ServiceDesc.Streams[1], "/proto.C2D/WriteBlock", opts...) 427 | if err != nil { 428 | return nil, err 429 | } 430 | x := &c2DWriteBlockClient{stream} 431 | return x, nil 432 | } 433 | 434 | type C2D_WriteBlockClient interface { 435 | Send(*FileWriteStream) error 436 | CloseAndRecv() (*OperateStatus, error) 437 | grpc.ClientStream 438 | } 439 | 440 | type c2DWriteBlockClient struct { 441 | grpc.ClientStream 442 | } 443 | 444 | func (x *c2DWriteBlockClient) Send(m *FileWriteStream) error { 445 | return x.ClientStream.SendMsg(m) 446 | } 447 | 448 | func (x *c2DWriteBlockClient) CloseAndRecv() (*OperateStatus, error) { 449 | if err := x.ClientStream.CloseSend(); err != nil { 450 | return nil, err 451 | } 452 | m := new(OperateStatus) 453 | if err := x.ClientStream.RecvMsg(m); err != nil { 454 | return nil, err 455 | } 456 | return m, nil 457 | } 458 | 459 | // C2DServer is the server API for C2D service. 460 | // All implementations must embed UnimplementedC2DServer 461 | // for forward compatibility 462 | type C2DServer interface { 463 | // 从块中读取数据 464 | GetBlock(*FileNameAndMode, C2D_GetBlockServer) error 465 | // 向指定块写入数据 466 | WriteBlock(C2D_WriteBlockServer) error 467 | mustEmbedUnimplementedC2DServer() 468 | } 469 | 470 | // UnimplementedC2DServer must be embedded to have forward compatible implementations. 471 | type UnimplementedC2DServer struct { 472 | } 473 | 474 | func (UnimplementedC2DServer) GetBlock(*FileNameAndMode, C2D_GetBlockServer) error { 475 | return status.Errorf(codes.Unimplemented, "method GetBlock not implemented") 476 | } 477 | func (UnimplementedC2DServer) WriteBlock(C2D_WriteBlockServer) error { 478 | return status.Errorf(codes.Unimplemented, "method WriteBlock not implemented") 479 | } 480 | func (UnimplementedC2DServer) mustEmbedUnimplementedC2DServer() {} 481 | 482 | // UnsafeC2DServer may be embedded to opt out of forward compatibility for this service. 483 | // Use of this interface is not recommended, as added methods to C2DServer will 484 | // result in compilation errors. 485 | type UnsafeC2DServer interface { 486 | mustEmbedUnimplementedC2DServer() 487 | } 488 | 489 | func RegisterC2DServer(s grpc.ServiceRegistrar, srv C2DServer) { 490 | s.RegisterService(&C2D_ServiceDesc, srv) 491 | } 492 | 493 | func _C2D_GetBlock_Handler(srv interface{}, stream grpc.ServerStream) error { 494 | m := new(FileNameAndMode) 495 | if err := stream.RecvMsg(m); err != nil { 496 | return err 497 | } 498 | return srv.(C2DServer).GetBlock(m, &c2DGetBlockServer{stream}) 499 | } 500 | 501 | type C2D_GetBlockServer interface { 502 | Send(*File) error 503 | grpc.ServerStream 504 | } 505 | 506 | type c2DGetBlockServer struct { 507 | grpc.ServerStream 508 | } 509 | 510 | func (x *c2DGetBlockServer) Send(m *File) error { 511 | return x.ServerStream.SendMsg(m) 512 | } 513 | 514 | func _C2D_WriteBlock_Handler(srv interface{}, stream grpc.ServerStream) error { 515 | return srv.(C2DServer).WriteBlock(&c2DWriteBlockServer{stream}) 516 | } 517 | 518 | type C2D_WriteBlockServer interface { 519 | SendAndClose(*OperateStatus) error 520 | Recv() (*FileWriteStream, error) 521 | grpc.ServerStream 522 | } 523 | 524 | type c2DWriteBlockServer struct { 525 | grpc.ServerStream 526 | } 527 | 528 | func (x *c2DWriteBlockServer) SendAndClose(m *OperateStatus) error { 529 | return x.ServerStream.SendMsg(m) 530 | } 531 | 532 | func (x *c2DWriteBlockServer) Recv() (*FileWriteStream, error) { 533 | m := new(FileWriteStream) 534 | if err := x.ServerStream.RecvMsg(m); err != nil { 535 | return nil, err 536 | } 537 | return m, nil 538 | } 539 | 540 | // C2D_ServiceDesc is the grpc.ServiceDesc for C2D service. 541 | // It's only intended for direct use with grpc.RegisterService, 542 | // and not to be introspected or modified (even as a copy) 543 | var C2D_ServiceDesc = grpc.ServiceDesc{ 544 | ServiceName: "proto.C2D", 545 | HandlerType: (*C2DServer)(nil), 546 | Methods: []grpc.MethodDesc{}, 547 | Streams: []grpc.StreamDesc{ 548 | { 549 | StreamName: "GetBlock", 550 | Handler: _C2D_GetBlock_Handler, 551 | ServerStreams: true, 552 | }, 553 | { 554 | StreamName: "WriteBlock", 555 | Handler: _C2D_WriteBlock_Handler, 556 | ClientStreams: true, 557 | }, 558 | }, 559 | Metadata: "proto/faydfs.proto", 560 | } 561 | 562 | // N2DClient is the client API for N2D service. 563 | // 564 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 565 | type N2DClient interface { 566 | // 从datanode中获取块的位置信息 567 | GetBlockReport(ctx context.Context, in *Ping, opts ...grpc.CallOption) (*BlockReplicaList, error) 568 | // 向datanode发出请求复制转移block 569 | ReloadReplica(ctx context.Context, in *CopyReplica2DN, opts ...grpc.CallOption) (*OperateStatus, error) 570 | } 571 | 572 | type n2DClient struct { 573 | cc grpc.ClientConnInterface 574 | } 575 | 576 | func NewN2DClient(cc grpc.ClientConnInterface) N2DClient { 577 | return &n2DClient{cc} 578 | } 579 | 580 | func (c *n2DClient) GetBlockReport(ctx context.Context, in *Ping, opts ...grpc.CallOption) (*BlockReplicaList, error) { 581 | out := new(BlockReplicaList) 582 | err := c.cc.Invoke(ctx, "/proto.N2D/GetBlockReport", in, out, opts...) 583 | if err != nil { 584 | return nil, err 585 | } 586 | return out, nil 587 | } 588 | 589 | func (c *n2DClient) ReloadReplica(ctx context.Context, in *CopyReplica2DN, opts ...grpc.CallOption) (*OperateStatus, error) { 590 | out := new(OperateStatus) 591 | err := c.cc.Invoke(ctx, "/proto.N2D/ReloadReplica", in, out, opts...) 592 | if err != nil { 593 | return nil, err 594 | } 595 | return out, nil 596 | } 597 | 598 | // N2DServer is the server API for N2D service. 599 | // All implementations must embed UnimplementedN2DServer 600 | // for forward compatibility 601 | type N2DServer interface { 602 | // 从datanode中获取块的位置信息 603 | GetBlockReport(context.Context, *Ping) (*BlockReplicaList, error) 604 | // 向datanode发出请求复制转移block 605 | ReloadReplica(context.Context, *CopyReplica2DN) (*OperateStatus, error) 606 | mustEmbedUnimplementedN2DServer() 607 | } 608 | 609 | // UnimplementedN2DServer must be embedded to have forward compatible implementations. 610 | type UnimplementedN2DServer struct { 611 | } 612 | 613 | func (UnimplementedN2DServer) GetBlockReport(context.Context, *Ping) (*BlockReplicaList, error) { 614 | return nil, status.Errorf(codes.Unimplemented, "method GetBlockReport not implemented") 615 | } 616 | func (UnimplementedN2DServer) ReloadReplica(context.Context, *CopyReplica2DN) (*OperateStatus, error) { 617 | return nil, status.Errorf(codes.Unimplemented, "method ReloadReplica not implemented") 618 | } 619 | func (UnimplementedN2DServer) mustEmbedUnimplementedN2DServer() {} 620 | 621 | // UnsafeN2DServer may be embedded to opt out of forward compatibility for this service. 622 | // Use of this interface is not recommended, as added methods to N2DServer will 623 | // result in compilation errors. 624 | type UnsafeN2DServer interface { 625 | mustEmbedUnimplementedN2DServer() 626 | } 627 | 628 | func RegisterN2DServer(s grpc.ServiceRegistrar, srv N2DServer) { 629 | s.RegisterService(&N2D_ServiceDesc, srv) 630 | } 631 | 632 | func _N2D_GetBlockReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 633 | in := new(Ping) 634 | if err := dec(in); err != nil { 635 | return nil, err 636 | } 637 | if interceptor == nil { 638 | return srv.(N2DServer).GetBlockReport(ctx, in) 639 | } 640 | info := &grpc.UnaryServerInfo{ 641 | Server: srv, 642 | FullMethod: "/proto.N2D/GetBlockReport", 643 | } 644 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 645 | return srv.(N2DServer).GetBlockReport(ctx, req.(*Ping)) 646 | } 647 | return interceptor(ctx, in, info, handler) 648 | } 649 | 650 | func _N2D_ReloadReplica_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 651 | in := new(CopyReplica2DN) 652 | if err := dec(in); err != nil { 653 | return nil, err 654 | } 655 | if interceptor == nil { 656 | return srv.(N2DServer).ReloadReplica(ctx, in) 657 | } 658 | info := &grpc.UnaryServerInfo{ 659 | Server: srv, 660 | FullMethod: "/proto.N2D/ReloadReplica", 661 | } 662 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 663 | return srv.(N2DServer).ReloadReplica(ctx, req.(*CopyReplica2DN)) 664 | } 665 | return interceptor(ctx, in, info, handler) 666 | } 667 | 668 | // N2D_ServiceDesc is the grpc.ServiceDesc for N2D service. 669 | // It's only intended for direct use with grpc.RegisterService, 670 | // and not to be introspected or modified (even as a copy) 671 | var N2D_ServiceDesc = grpc.ServiceDesc{ 672 | ServiceName: "proto.N2D", 673 | HandlerType: (*N2DServer)(nil), 674 | Methods: []grpc.MethodDesc{ 675 | { 676 | MethodName: "GetBlockReport", 677 | Handler: _N2D_GetBlockReport_Handler, 678 | }, 679 | { 680 | MethodName: "ReloadReplica", 681 | Handler: _N2D_ReloadReplica_Handler, 682 | }, 683 | }, 684 | Streams: []grpc.StreamDesc{}, 685 | Metadata: "proto/faydfs.proto", 686 | } 687 | 688 | // D2NClient is the client API for D2N service. 689 | // 690 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. 691 | type D2NClient interface { 692 | // 每3s向namenode发送一次心跳 693 | DatanodeHeartbeat(ctx context.Context, in *Heartbeat, opts ...grpc.CallOption) (*DatanodeOperation, error) 694 | // 每1h向namenode汇报一次block状态 695 | BlockReport(ctx context.Context, in *BlockReplicaList, opts ...grpc.CallOption) (*OperateStatus, error) 696 | // 向namenode进行注册 697 | RegisterDataNode(ctx context.Context, in *RegisterDataNodeReq, opts ...grpc.CallOption) (*OperateStatus, error) 698 | } 699 | 700 | type d2NClient struct { 701 | cc grpc.ClientConnInterface 702 | } 703 | 704 | func NewD2NClient(cc grpc.ClientConnInterface) D2NClient { 705 | return &d2NClient{cc} 706 | } 707 | 708 | func (c *d2NClient) DatanodeHeartbeat(ctx context.Context, in *Heartbeat, opts ...grpc.CallOption) (*DatanodeOperation, error) { 709 | out := new(DatanodeOperation) 710 | err := c.cc.Invoke(ctx, "/proto.D2N/DatanodeHeartbeat", in, out, opts...) 711 | if err != nil { 712 | return nil, err 713 | } 714 | return out, nil 715 | } 716 | 717 | func (c *d2NClient) BlockReport(ctx context.Context, in *BlockReplicaList, opts ...grpc.CallOption) (*OperateStatus, error) { 718 | out := new(OperateStatus) 719 | err := c.cc.Invoke(ctx, "/proto.D2N/BlockReport", in, out, opts...) 720 | if err != nil { 721 | return nil, err 722 | } 723 | return out, nil 724 | } 725 | 726 | func (c *d2NClient) RegisterDataNode(ctx context.Context, in *RegisterDataNodeReq, opts ...grpc.CallOption) (*OperateStatus, error) { 727 | out := new(OperateStatus) 728 | err := c.cc.Invoke(ctx, "/proto.D2N/RegisterDataNode", in, out, opts...) 729 | if err != nil { 730 | return nil, err 731 | } 732 | return out, nil 733 | } 734 | 735 | // D2NServer is the server API for D2N service. 736 | // All implementations must embed UnimplementedD2NServer 737 | // for forward compatibility 738 | type D2NServer interface { 739 | // 每3s向namenode发送一次心跳 740 | DatanodeHeartbeat(context.Context, *Heartbeat) (*DatanodeOperation, error) 741 | // 每1h向namenode汇报一次block状态 742 | BlockReport(context.Context, *BlockReplicaList) (*OperateStatus, error) 743 | // 向namenode进行注册 744 | RegisterDataNode(context.Context, *RegisterDataNodeReq) (*OperateStatus, error) 745 | mustEmbedUnimplementedD2NServer() 746 | } 747 | 748 | // UnimplementedD2NServer must be embedded to have forward compatible implementations. 749 | type UnimplementedD2NServer struct { 750 | } 751 | 752 | func (UnimplementedD2NServer) DatanodeHeartbeat(context.Context, *Heartbeat) (*DatanodeOperation, error) { 753 | return nil, status.Errorf(codes.Unimplemented, "method DatanodeHeartbeat not implemented") 754 | } 755 | func (UnimplementedD2NServer) BlockReport(context.Context, *BlockReplicaList) (*OperateStatus, error) { 756 | return nil, status.Errorf(codes.Unimplemented, "method BlockReport not implemented") 757 | } 758 | func (UnimplementedD2NServer) RegisterDataNode(context.Context, *RegisterDataNodeReq) (*OperateStatus, error) { 759 | return nil, status.Errorf(codes.Unimplemented, "method RegisterDataNode not implemented") 760 | } 761 | func (UnimplementedD2NServer) mustEmbedUnimplementedD2NServer() {} 762 | 763 | // UnsafeD2NServer may be embedded to opt out of forward compatibility for this service. 764 | // Use of this interface is not recommended, as added methods to D2NServer will 765 | // result in compilation errors. 766 | type UnsafeD2NServer interface { 767 | mustEmbedUnimplementedD2NServer() 768 | } 769 | 770 | func RegisterD2NServer(s grpc.ServiceRegistrar, srv D2NServer) { 771 | s.RegisterService(&D2N_ServiceDesc, srv) 772 | } 773 | 774 | func _D2N_DatanodeHeartbeat_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 775 | in := new(Heartbeat) 776 | if err := dec(in); err != nil { 777 | return nil, err 778 | } 779 | if interceptor == nil { 780 | return srv.(D2NServer).DatanodeHeartbeat(ctx, in) 781 | } 782 | info := &grpc.UnaryServerInfo{ 783 | Server: srv, 784 | FullMethod: "/proto.D2N/DatanodeHeartbeat", 785 | } 786 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 787 | return srv.(D2NServer).DatanodeHeartbeat(ctx, req.(*Heartbeat)) 788 | } 789 | return interceptor(ctx, in, info, handler) 790 | } 791 | 792 | func _D2N_BlockReport_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 793 | in := new(BlockReplicaList) 794 | if err := dec(in); err != nil { 795 | return nil, err 796 | } 797 | if interceptor == nil { 798 | return srv.(D2NServer).BlockReport(ctx, in) 799 | } 800 | info := &grpc.UnaryServerInfo{ 801 | Server: srv, 802 | FullMethod: "/proto.D2N/BlockReport", 803 | } 804 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 805 | return srv.(D2NServer).BlockReport(ctx, req.(*BlockReplicaList)) 806 | } 807 | return interceptor(ctx, in, info, handler) 808 | } 809 | 810 | func _D2N_RegisterDataNode_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 811 | in := new(RegisterDataNodeReq) 812 | if err := dec(in); err != nil { 813 | return nil, err 814 | } 815 | if interceptor == nil { 816 | return srv.(D2NServer).RegisterDataNode(ctx, in) 817 | } 818 | info := &grpc.UnaryServerInfo{ 819 | Server: srv, 820 | FullMethod: "/proto.D2N/RegisterDataNode", 821 | } 822 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 823 | return srv.(D2NServer).RegisterDataNode(ctx, req.(*RegisterDataNodeReq)) 824 | } 825 | return interceptor(ctx, in, info, handler) 826 | } 827 | 828 | // D2N_ServiceDesc is the grpc.ServiceDesc for D2N service. 829 | // It's only intended for direct use with grpc.RegisterService, 830 | // and not to be introspected or modified (even as a copy) 831 | var D2N_ServiceDesc = grpc.ServiceDesc{ 832 | ServiceName: "proto.D2N", 833 | HandlerType: (*D2NServer)(nil), 834 | Methods: []grpc.MethodDesc{ 835 | { 836 | MethodName: "DatanodeHeartbeat", 837 | Handler: _D2N_DatanodeHeartbeat_Handler, 838 | }, 839 | { 840 | MethodName: "BlockReport", 841 | Handler: _D2N_BlockReport_Handler, 842 | }, 843 | { 844 | MethodName: "RegisterDataNode", 845 | Handler: _D2N_RegisterDataNode_Handler, 846 | }, 847 | }, 848 | Streams: []grpc.StreamDesc{}, 849 | Metadata: "proto/faydfs.proto", 850 | } 851 | -------------------------------------------------------------------------------- /public/const.go: -------------------------------------------------------------------------------- 1 | package public 2 | -------------------------------------------------------------------------------- /public/errors.go: -------------------------------------------------------------------------------- 1 | package public 2 | 3 | import "errors" 4 | 5 | const ( 6 | CAN_NOT_FIND_REAL = 0 7 | ) 8 | 9 | var ErrRealIPNotFound = errors.New("IP not found") 10 | var ErrFileNotFound = errors.New("file not found") 11 | var ErrPathNotFind = errors.New("path not found") 12 | var ErrDirAlreadyExists = errors.New("the directory already exists") 13 | var ErrNotEmptyDir = errors.New("other files in directory") 14 | var ErrOnlySupportRenameEmptyDir = errors.New("only support rename empty directory") 15 | var ErrNotDir = errors.New("the files is not directory") 16 | var ErrNotEnoughStorageSpace = errors.New("not enough storage space ") 17 | var ErrLeaseOccupied = errors.New("the lease is being used") 18 | var ErrReplicaNotFound = errors.New("replica not found") 19 | var ErrCanNotChangeRootDir = errors.New("can not change root dir") 20 | -------------------------------------------------------------------------------- /public/util.go: -------------------------------------------------------------------------------- 1 | package public 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "fmt" 7 | "log" 8 | "os" 9 | ) 10 | 11 | // CreateDir creates a dir 12 | func CreateDir(path string) { 13 | if _, err := os.Stat(path); os.IsNotExist(err) { 14 | err = os.Mkdir(path, 0640) 15 | if err != nil { 16 | fmt.Println(err, "err creating file ", path) 17 | } 18 | } 19 | } 20 | 21 | // Int2Bytes 整形转换成字节 22 | func Int2Bytes(n int) []byte { 23 | x := int32(n) 24 | bytesBuffer := bytes.NewBuffer([]byte{}) 25 | err := binary.Write(bytesBuffer, binary.BigEndian, x) 26 | if err != nil { 27 | log.Fatal(err) 28 | } 29 | return bytesBuffer.Bytes() 30 | } 31 | 32 | // Bytes2Int 字节转换成整形 33 | func Bytes2Int(b []byte) int { 34 | bytesBuffer := bytes.NewBuffer(b) 35 | 36 | var x int32 37 | err := binary.Read(bytesBuffer, binary.BigEndian, &x) 38 | if err != nil { 39 | log.Fatal(err) 40 | } 41 | return int(x) 42 | } 43 | -------------------------------------------------------------------------------- /test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | fayClient "faydfs/client" 5 | "fmt" 6 | ) 7 | 8 | func main() { 9 | fmt.Println("start") 10 | client := fayClient.GetClient() 11 | fmt.Println("getClient") 12 | 13 | result := client.Put("D://testGPU.py", "/testGPU.py") 14 | fmt.Println("Put D://testGPU.py to /testGPU.py ", result.ResultExtraMsg) 15 | 16 | //result2 := client.Get("/testGPU.py", "D://testSuccess.py") 17 | //fmt.Println("Get /testGPU.py to D://testSuccess.py ", result2.ResultExtraMsg) 18 | // 19 | //result2 = client.Mkdir("/mydir") 20 | //fmt.Println("Mkdir /mydir ", result2.ResultExtraMsg) 21 | // 22 | //result2 = client.Put("D://testGPU.py", "/mydir/testGPU.py") 23 | //fmt.Println("Put D://testGPU.py to /mydir/testGPU.py ", result2.ResultExtraMsg) 24 | // 25 | //result2 = client.Stat("/mydir") 26 | //fmt.Println("GetStat /mydir", result2.ResultExtraMsg) 27 | //fmt.Println(result2.Data) 28 | // 29 | //result2 = client.List("/mydir") 30 | //fmt.Println("List /mydir ", result2.ResultExtraMsg) 31 | //fmt.Println(result2.Data) 32 | // 33 | //result2 = client.Get("/mydir/testGPU.py", "D://testGPU.py") 34 | //fmt.Println("Get /mydir/testGPU.py to D://testGPU.py ", result2.ResultExtraMsg) 35 | // 36 | //result2 = client.Rename("/mydir/testGPU.py", "/mydir/test.py") 37 | //fmt.Println("Rename /mydir/testGPU.py to /mydir/test.py", result2.ResultExtraMsg) 38 | // 39 | //result2 = client.Get("/mydir/test.py", "D://testRename.py") 40 | //fmt.Println("Get /mydir/test.py to D://testGet.py ", result2.ResultExtraMsg) 41 | // 42 | //result2 = client.List("/mydir") 43 | //fmt.Println("List /mydir ", result2.ResultExtraMsg) 44 | //fmt.Println(result2.Data) 45 | // 46 | //result2 = client.Delete("/mydir/test.py") 47 | //fmt.Println("Delete /mydir/test.py ", result2.ResultExtraMsg) 48 | // 49 | //result2 = client.Stat("/mydir") 50 | //fmt.Println("GetStat /mydir", result2.ResultExtraMsg) 51 | //fmt.Println(result2.Data) 52 | // 53 | //result2 = client.List("/mydir") 54 | //fmt.Println("GetStat /mydir", result2.ResultExtraMsg) 55 | //fmt.Println(result2.Data) 56 | 57 | } 58 | --------------------------------------------------------------------------------