| @@ -16,9 +16,12 @@ require ( | |||||
| github.com/baohan10/reedsolomon v0.0.0-20230406042632-43574cac9fa7 // indirect | github.com/baohan10/reedsolomon v0.0.0-20230406042632-43574cac9fa7 // indirect | ||||
| github.com/beevik/etree v1.2.0 // indirect | github.com/beevik/etree v1.2.0 // indirect | ||||
| github.com/benbjohnson/clock v1.3.0 // indirect | github.com/benbjohnson/clock v1.3.0 // indirect | ||||
| github.com/coreos/go-semver v0.3.0 // indirect | |||||
| github.com/coreos/go-systemd/v22 v22.5.0 // indirect | |||||
| github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect | github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 // indirect | ||||
| github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect | ||||
| github.com/go-ping/ping v1.1.0 // indirect | github.com/go-ping/ping v1.1.0 // indirect | ||||
| github.com/gogo/protobuf v1.3.2 // indirect | |||||
| github.com/golang/protobuf v1.5.3 // indirect | github.com/golang/protobuf v1.5.3 // indirect | ||||
| github.com/google/uuid v1.3.0 // indirect | github.com/google/uuid v1.3.0 // indirect | ||||
| github.com/hashicorp/errwrap v1.1.0 // indirect | github.com/hashicorp/errwrap v1.1.0 // indirect | ||||
| @@ -26,6 +29,7 @@ require ( | |||||
| github.com/imdario/mergo v0.3.15 // indirect | github.com/imdario/mergo v0.3.15 // indirect | ||||
| github.com/ipfs/boxo v0.8.0 // indirect | github.com/ipfs/boxo v0.8.0 // indirect | ||||
| github.com/ipfs/go-cid v0.4.1 // indirect | github.com/ipfs/go-cid v0.4.1 // indirect | ||||
| github.com/json-iterator/go v1.1.12 // indirect | |||||
| github.com/klauspost/cpuid/v2 v2.2.4 // indirect | github.com/klauspost/cpuid/v2 v2.2.4 // indirect | ||||
| github.com/libp2p/go-buffer-pool v0.1.0 // indirect | github.com/libp2p/go-buffer-pool v0.1.0 // indirect | ||||
| github.com/libp2p/go-flow-metrics v0.1.0 // indirect | github.com/libp2p/go-flow-metrics v0.1.0 // indirect | ||||
| @@ -34,6 +38,8 @@ require ( | |||||
| github.com/minio/sha256-simd v1.0.0 // indirect | github.com/minio/sha256-simd v1.0.0 // indirect | ||||
| github.com/mitchellh/go-homedir v1.1.0 // indirect | github.com/mitchellh/go-homedir v1.1.0 // indirect | ||||
| github.com/mitchellh/mapstructure v1.5.0 // indirect | github.com/mitchellh/mapstructure v1.5.0 // indirect | ||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect | |||||
| github.com/modern-go/reflect2 v1.0.2 // indirect | |||||
| github.com/mr-tron/base58 v1.2.0 // indirect | github.com/mr-tron/base58 v1.2.0 // indirect | ||||
| github.com/multiformats/go-base32 v0.1.0 // indirect | github.com/multiformats/go-base32 v0.1.0 // indirect | ||||
| github.com/multiformats/go-base36 v0.2.0 // indirect | github.com/multiformats/go-base36 v0.2.0 // indirect | ||||
| @@ -48,7 +54,14 @@ require ( | |||||
| github.com/spaolacci/murmur3 v1.1.0 // indirect | github.com/spaolacci/murmur3 v1.1.0 // indirect | ||||
| github.com/streadway/amqp v1.0.0 // indirect | github.com/streadway/amqp v1.0.0 // indirect | ||||
| github.com/whyrusleeping/tar-utils v0.0.0-20201201191210-20a61371de5b // indirect | github.com/whyrusleeping/tar-utils v0.0.0-20201201191210-20a61371de5b // indirect | ||||
| github.com/zyedidia/generic v1.2.1 // indirect | |||||
| gitlink.org.cn/cloudream/db v0.0.0 // indirect | gitlink.org.cn/cloudream/db v0.0.0 // indirect | ||||
| go.etcd.io/etcd/api/v3 v3.5.9 // indirect | |||||
| go.etcd.io/etcd/client/pkg/v3 v3.5.9 // indirect | |||||
| go.etcd.io/etcd/client/v3 v3.5.9 // indirect | |||||
| go.uber.org/atomic v1.10.0 // indirect | |||||
| go.uber.org/multierr v1.11.0 // indirect | |||||
| go.uber.org/zap v1.24.0 // indirect | |||||
| golang.org/x/crypto v0.8.0 // indirect | golang.org/x/crypto v0.8.0 // indirect | ||||
| golang.org/x/exp v0.0.0-20230519143937-03e91628a987 // indirect | golang.org/x/exp v0.0.0-20230519143937-03e91628a987 // indirect | ||||
| golang.org/x/net v0.9.0 // indirect | golang.org/x/net v0.9.0 // indirect | ||||
| @@ -7,6 +7,10 @@ github.com/beevik/etree v1.2.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zV | |||||
| github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= | github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= | ||||
| github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= | github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= | ||||
| github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= | github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 h1:SKI1/fuSdodxmNNyVBR8d7X/HuLnRpvvFO0AgyQk764= | ||||
| github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= | |||||
| github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= | |||||
| github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= | |||||
| github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= | |||||
| github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= | github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3 h1:HVTnpeuvF6Owjd5mniCL8DEXo7uYXdQEmOP4FJbV5tg= | ||||
| github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= | github.com/crackcomm/go-gitignore v0.0.0-20170627025303-887ab5e44cc3/go.mod h1:p1d6YEZWvFzEh4KLyvBcVSnrfNDDvK2zfK/4x2v/4pE= | ||||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| @@ -17,11 +21,15 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1 | |||||
| github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= | github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc= | ||||
| github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw= | github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw= | ||||
| github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= | github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk= | ||||
| github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= | |||||
| github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= | |||||
| github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= | |||||
| github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | ||||
| github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= | github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= | ||||
| github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= | github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= | ||||
| github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
| github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= | ||||
| github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= | |||||
| github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
| github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= | ||||
| github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
| @@ -39,7 +47,11 @@ github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s= | |||||
| github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= | github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk= | ||||
| github.com/ipfs/go-ipfs-api v0.6.0 h1:JARgG0VTbjyVhO5ZfesnbXv9wTcMvoKRBLF1SzJqzmg= | github.com/ipfs/go-ipfs-api v0.6.0 h1:JARgG0VTbjyVhO5ZfesnbXv9wTcMvoKRBLF1SzJqzmg= | ||||
| github.com/ipfs/go-ipfs-api v0.6.0/go.mod h1:iDC2VMwN9LUpQV/GzEeZ2zNqd8NUdRmWcFM+K/6odf0= | github.com/ipfs/go-ipfs-api v0.6.0/go.mod h1:iDC2VMwN9LUpQV/GzEeZ2zNqd8NUdRmWcFM+K/6odf0= | ||||
| github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= | |||||
| github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= | |||||
| github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= | github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= | ||||
| github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= | |||||
| github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | |||||
| github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | ||||
| github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | ||||
| github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= | github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= | ||||
| @@ -58,6 +70,10 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG | |||||
| github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= | ||||
| github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= | ||||
| github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= | ||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= | |||||
| github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= | |||||
| github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= | |||||
| github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= | |||||
| github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= | github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o= | ||||
| github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= | github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc= | ||||
| github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= | github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE= | ||||
| @@ -79,6 +95,7 @@ github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOEL | |||||
| github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= | github.com/otiai10/copy v1.12.0 h1:cLMgSQnXBs1eehF0Wy/FAGsgDTDmAqFR7rQylBb1nDY= | ||||
| github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= | github.com/otiai10/copy v1.12.0/go.mod h1:rSaLseMUsZFFbsFGc7wCJnnkTAvdc5L6VWxPE4308Ww= | ||||
| github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= | github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= | ||||
| github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | |||||
| github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||||
| github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
| github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= | github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= | ||||
| @@ -92,20 +109,53 @@ github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2 | |||||
| github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo= | github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo= | ||||
| github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= | github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= | ||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | |||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= | github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= | ||||
| github.com/whyrusleeping/tar-utils v0.0.0-20201201191210-20a61371de5b h1:wA3QeTsaAXybLL2kb2cKhCAQTHgYTMwuI8lBlJSv5V8= | github.com/whyrusleeping/tar-utils v0.0.0-20201201191210-20a61371de5b h1:wA3QeTsaAXybLL2kb2cKhCAQTHgYTMwuI8lBlJSv5V8= | ||||
| github.com/whyrusleeping/tar-utils v0.0.0-20201201191210-20a61371de5b/go.mod h1:xT1Y5p2JR2PfSZihE0s4mjdJaRGp1waCTf5JzhQLBck= | github.com/whyrusleeping/tar-utils v0.0.0-20201201191210-20a61371de5b/go.mod h1:xT1Y5p2JR2PfSZihE0s4mjdJaRGp1waCTf5JzhQLBck= | ||||
| github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||||
| github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||||
| github.com/zyedidia/generic v1.2.1 h1:Zv5KS/N2m0XZZiuLS82qheRG4X1o5gsWreGb0hR7XDc= | |||||
| github.com/zyedidia/generic v1.2.1/go.mod h1:ly2RBz4mnz1yeuVbQA/VFwGjK3mnHGRj1JuoG336Bis= | |||||
| go.etcd.io/etcd/api/v3 v3.5.9 h1:4wSsluwyTbGGmyjJktOf3wFQoTBIURXHnq9n/G/JQHs= | |||||
| go.etcd.io/etcd/api/v3 v3.5.9/go.mod h1:uyAal843mC8uUVSLWz6eHa/d971iDGnCRpmKd2Z+X8k= | |||||
| go.etcd.io/etcd/client/pkg/v3 v3.5.9 h1:oidDC4+YEuSIQbsR94rY9gur91UPL6DnxDCIYd2IGsE= | |||||
| go.etcd.io/etcd/client/pkg/v3 v3.5.9/go.mod h1:y+CzeSmkMpWN2Jyu1npecjB9BBnABxGM4pN8cGuJeL4= | |||||
| go.etcd.io/etcd/client/v3 v3.5.9 h1:r5xghnU7CwbUxD/fbUtRyJGaYNfDun8sp/gTr1hew6E= | |||||
| go.etcd.io/etcd/client/v3 v3.5.9/go.mod h1:i/Eo5LrZ5IKqpbtpPDuaUnDOUv471oDg8cjQaUr2MbA= | |||||
| go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= | |||||
| go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= | |||||
| go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= | |||||
| go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= | |||||
| go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= | |||||
| go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= | |||||
| go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= | |||||
| golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||||
| golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||||
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||||
| golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= | golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= | ||||
| golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= | golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= | ||||
| golang.org/x/exp v0.0.0-20230519143937-03e91628a987 h1:3xJIFvzUFbu4ls0BTBYcgbCGhA63eAOEMxIHugyXJqA= | golang.org/x/exp v0.0.0-20230519143937-03e91628a987 h1:3xJIFvzUFbu4ls0BTBYcgbCGhA63eAOEMxIHugyXJqA= | ||||
| golang.org/x/exp v0.0.0-20230519143937-03e91628a987/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= | golang.org/x/exp v0.0.0-20230519143937-03e91628a987/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= | ||||
| golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||||
| golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||||
| golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||||
| golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||||
| golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||||
| golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||||
| golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= | golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= | ||||
| golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= | golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= | ||||
| golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= | golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= | ||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
| golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
| golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
| golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= | golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= | ||||
| golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
| golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
| golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
| golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
| golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| @@ -113,11 +163,18 @@ golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBc | |||||
| golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= | golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= | ||||
| golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= | golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= | ||||
| golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= | ||||
| golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
| golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||||
| golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | |||||
| golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
| golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
| golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
| google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd h1:sLpv7bNL1AsX3fdnWh9WVh7ejIzXdOc1RRHGeAmeStU= | google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd h1:sLpv7bNL1AsX3fdnWh9WVh7ejIzXdOc1RRHGeAmeStU= | ||||
| google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= | google.golang.org/genproto v0.0.0-20230403163135-c38d8f061ccd/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= | ||||
| google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= | google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= | ||||
| @@ -127,6 +184,7 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ | |||||
| google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= | google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= | ||||
| google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | |||||
| gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| @@ -1,6 +1,7 @@ | |||||
| package config | package config | ||||
| import ( | import ( | ||||
| "gitlink.org.cn/cloudream/common/pkg/distlock" | |||||
| log "gitlink.org.cn/cloudream/common/pkg/logger" | log "gitlink.org.cn/cloudream/common/pkg/logger" | ||||
| c "gitlink.org.cn/cloudream/common/utils/config" | c "gitlink.org.cn/cloudream/common/utils/config" | ||||
| "gitlink.org.cn/cloudream/common/utils/ipfs" | "gitlink.org.cn/cloudream/common/utils/ipfs" | ||||
| @@ -8,14 +9,17 @@ import ( | |||||
| ) | ) | ||||
| type Config struct { | type Config struct { | ||||
| ID int64 `json:"id"` | |||||
| GRPCListenAddress string `json:"grpcListenAddress"` | |||||
| LocalIP string `json:"localIP"` | |||||
| StorageBaseDir string `json:"storageBaseDir"` | |||||
| TempFileLifetime int `json:"tempFileLifetime"` // temp状态的副本最多能保持多久时间,单位:秒 | |||||
| Logger log.Config `json:"logger"` | |||||
| RabbitMQ racfg.Config `json:"rabbitMQ"` | |||||
| IPFS ipfs.Config `json:"ipfs"` | |||||
| ID int64 `json:"id"` | |||||
| GRPCListenAddress string `json:"grpcListenAddress"` | |||||
| GRPCPort int `json:"grpcPort"` | |||||
| LocalIP string `json:"localIP"` | |||||
| ExternalIP string `json:"externalIP"` | |||||
| StorageBaseDir string `json:"storageBaseDir"` | |||||
| TempFileLifetime int `json:"tempFileLifetime"` // temp状态的副本最多能保持多久时间,单位:秒 | |||||
| Logger log.Config `json:"logger"` | |||||
| RabbitMQ racfg.Config `json:"rabbitMQ"` | |||||
| IPFS ipfs.Config `json:"ipfs"` | |||||
| DistLock distlock.Config `json:"distlock"` | |||||
| } | } | ||||
| var cfg Config | var cfg Config | ||||
| @@ -14,9 +14,7 @@ import ( | |||||
| "gitlink.org.cn/cloudream/agent/internal/task" | "gitlink.org.cn/cloudream/agent/internal/task" | ||||
| "gitlink.org.cn/cloudream/common/consts" | "gitlink.org.cn/cloudream/common/consts" | ||||
| "gitlink.org.cn/cloudream/common/pkg/logger" | "gitlink.org.cn/cloudream/common/pkg/logger" | ||||
| log "gitlink.org.cn/cloudream/common/pkg/logger" | |||||
| "gitlink.org.cn/cloudream/common/utils" | "gitlink.org.cn/cloudream/common/utils" | ||||
| "gitlink.org.cn/cloudream/common/utils/serder" | |||||
| "gitlink.org.cn/cloudream/ec" | "gitlink.org.cn/cloudream/ec" | ||||
| "gitlink.org.cn/cloudream/common/consts/errorcode" | "gitlink.org.cn/cloudream/common/consts/errorcode" | ||||
| @@ -24,43 +22,37 @@ import ( | |||||
| agtmsg "gitlink.org.cn/cloudream/rabbitmq/message/agent" | agtmsg "gitlink.org.cn/cloudream/rabbitmq/message/agent" | ||||
| ) | ) | ||||
| func (service *Service) StartMovingObjectToStorage(msg *agtmsg.StartMovingObjectToStorage) (*agtmsg.StartMovingObjectToStorageResp, *ramsg.CodeMessage) { | |||||
| func (service *Service) StartStorageMoveObject(msg *agtmsg.StartStorageMoveObject) (*agtmsg.StartStorageMoveObjectResp, *ramsg.CodeMessage) { | |||||
| outFileName := utils.MakeMoveOperationFileName(msg.ObjectID, msg.UserID) | outFileName := utils.MakeMoveOperationFileName(msg.ObjectID, msg.UserID) | ||||
| outFilePath := filepath.Join(config.Cfg().StorageBaseDir, msg.Directory, outFileName) | outFilePath := filepath.Join(config.Cfg().StorageBaseDir, msg.Directory, outFileName) | ||||
| if msg.Redundancy == consts.REDUNDANCY_REP { | |||||
| taskID, err := service.moveRepObject(msg, outFilePath) | |||||
| if repRed, ok := msg.Redundancy.(ramsg.RepRedundancyData); ok { | |||||
| taskID, err := service.moveRepObject(repRed, outFilePath) | |||||
| if err != nil { | if err != nil { | ||||
| logger.Warnf("move rep object as %s failed, err: %s", outFilePath, err.Error()) | logger.Warnf("move rep object as %s failed, err: %s", outFilePath, err.Error()) | ||||
| return ramsg.ReplyFailed[agtmsg.StartMovingObjectToStorageResp](errorcode.OPERATION_FAILED, "move rep object failed") | |||||
| return ramsg.ReplyFailed[agtmsg.StartStorageMoveObjectResp](errorcode.OPERATION_FAILED, "move rep object failed") | |||||
| } | } | ||||
| return ramsg.ReplyOK(agtmsg.NewStartMovingObjectToStorageResp(taskID)) | |||||
| return ramsg.ReplyOK(agtmsg.NewStartStorageMoveObjectResp(taskID)) | |||||
| } else { | } else { | ||||
| // TODO 处理其他备份类型 | // TODO 处理其他备份类型 | ||||
| return ramsg.ReplyFailed[agtmsg.StartMovingObjectToStorageResp](errorcode.OPERATION_FAILED, "not implement yet!") | |||||
| return ramsg.ReplyFailed[agtmsg.StartStorageMoveObjectResp](errorcode.OPERATION_FAILED, "not implement yet!") | |||||
| } | } | ||||
| } | } | ||||
| func (svc *Service) moveRepObject(msg *agtmsg.StartMovingObjectToStorage, outFilePath string) (string, error) { | |||||
| var repInfo ramsg.ObjectRepInfo | |||||
| err := serder.AnyToAny(msg.RedundancyData, &repInfo) | |||||
| if err != nil { | |||||
| return "", fmt.Errorf("redundancy data to rep info failed, err: %w", err) | |||||
| } | |||||
| tsk := svc.taskManager.StartComparable(task.NewIPFSRead(repInfo.FileHash, outFilePath)) | |||||
| func (svc *Service) moveRepObject(repData ramsg.RepRedundancyData, outFilePath string) (string, error) { | |||||
| tsk := svc.taskManager.StartComparable(task.NewIPFSRead(repData.FileHash, outFilePath)) | |||||
| return tsk.ID(), nil | return tsk.ID(), nil | ||||
| } | } | ||||
| func (svc *Service) WaitMovingObject(msg *agtmsg.WaitMovingObject) (*agtmsg.WaitMovingObjectResp, *ramsg.CodeMessage) { | |||||
| log.WithField("TaskID", msg.TaskID).Debugf("wait moving object") | |||||
| func (svc *Service) WaitStorageMoveObject(msg *agtmsg.WaitStorageMoveObject) (*agtmsg.WaitStorageMoveObjectResp, *ramsg.CodeMessage) { | |||||
| logger.WithField("TaskID", msg.TaskID).Debugf("wait moving object") | |||||
| tsk := svc.taskManager.FindByID(msg.TaskID) | tsk := svc.taskManager.FindByID(msg.TaskID) | ||||
| if tsk == nil { | if tsk == nil { | ||||
| return ramsg.ReplyFailed[agtmsg.WaitMovingObjectResp](errorcode.TASK_NOT_FOUND, "task not found") | |||||
| return ramsg.ReplyFailed[agtmsg.WaitStorageMoveObjectResp](errorcode.TASK_NOT_FOUND, "task not found") | |||||
| } | } | ||||
| if msg.WaitTimeoutMs == 0 { | if msg.WaitTimeoutMs == 0 { | ||||
| @@ -71,7 +63,7 @@ func (svc *Service) WaitMovingObject(msg *agtmsg.WaitMovingObject) (*agtmsg.Wait | |||||
| errMsg = tsk.Error().Error() | errMsg = tsk.Error().Error() | ||||
| } | } | ||||
| return ramsg.ReplyOK(agtmsg.NewWaitMovingObjectResp(true, errMsg)) | |||||
| return ramsg.ReplyOK(agtmsg.NewWaitStorageMoveObjectResp(true, errMsg)) | |||||
| } else { | } else { | ||||
| if tsk.WaitTimeout(time.Duration(msg.WaitTimeoutMs)) { | if tsk.WaitTimeout(time.Duration(msg.WaitTimeoutMs)) { | ||||
| @@ -81,20 +73,20 @@ func (svc *Service) WaitMovingObject(msg *agtmsg.WaitMovingObject) (*agtmsg.Wait | |||||
| errMsg = tsk.Error().Error() | errMsg = tsk.Error().Error() | ||||
| } | } | ||||
| return ramsg.ReplyOK(agtmsg.NewWaitMovingObjectResp(true, errMsg)) | |||||
| return ramsg.ReplyOK(agtmsg.NewWaitStorageMoveObjectResp(true, errMsg)) | |||||
| } | } | ||||
| return ramsg.ReplyOK(agtmsg.NewWaitMovingObjectResp(false, "")) | |||||
| return ramsg.ReplyOK(agtmsg.NewWaitStorageMoveObjectResp(false, "")) | |||||
| } | } | ||||
| } | } | ||||
| func (svc *Service) CheckStorage(msg *agtmsg.CheckStorage) (*agtmsg.CheckStorageResp, *ramsg.CodeMessage) { | |||||
| func (svc *Service) StorageCheck(msg *agtmsg.StorageCheck) (*agtmsg.StorageCheckResp, *ramsg.CodeMessage) { | |||||
| dirFullPath := filepath.Join(config.Cfg().StorageBaseDir, msg.Directory) | dirFullPath := filepath.Join(config.Cfg().StorageBaseDir, msg.Directory) | ||||
| infos, err := ioutil.ReadDir(dirFullPath) | infos, err := ioutil.ReadDir(dirFullPath) | ||||
| if err != nil { | if err != nil { | ||||
| logger.Warnf("list storage directory failed, err: %s", err.Error()) | logger.Warnf("list storage directory failed, err: %s", err.Error()) | ||||
| return ramsg.ReplyOK(agtmsg.NewCheckStorageResp( | |||||
| return ramsg.ReplyOK(agtmsg.NewStorageCheckResp( | |||||
| err.Error(), | err.Error(), | ||||
| nil, | nil, | ||||
| )) | )) | ||||
| @@ -109,13 +101,13 @@ func (svc *Service) CheckStorage(msg *agtmsg.CheckStorage) (*agtmsg.CheckStorage | |||||
| } | } | ||||
| } | } | ||||
| func (svc *Service) checkStorageIncrement(msg *agtmsg.CheckStorage, fileInfos []fs.FileInfo) (*agtmsg.CheckStorageResp, *ramsg.CodeMessage) { | |||||
| func (svc *Service) checkStorageIncrement(msg *agtmsg.StorageCheck, fileInfos []fs.FileInfo) (*agtmsg.StorageCheckResp, *ramsg.CodeMessage) { | |||||
| infosMap := make(map[string]fs.FileInfo) | infosMap := make(map[string]fs.FileInfo) | ||||
| for _, info := range fileInfos { | for _, info := range fileInfos { | ||||
| infosMap[info.Name()] = info | infosMap[info.Name()] = info | ||||
| } | } | ||||
| var entries []agtmsg.CheckStorageRespEntry | |||||
| var entries []agtmsg.StorageCheckRespEntry | |||||
| for _, obj := range msg.Objects { | for _, obj := range msg.Objects { | ||||
| fileName := utils.MakeMoveOperationFileName(obj.ObjectID, obj.UserID) | fileName := utils.MakeMoveOperationFileName(obj.ObjectID, obj.UserID) | ||||
| _, ok := infosMap[fileName] | _, ok := infosMap[fileName] | ||||
| @@ -127,23 +119,23 @@ func (svc *Service) checkStorageIncrement(msg *agtmsg.CheckStorage, fileInfos [] | |||||
| } else { | } else { | ||||
| // 只要文件不存在,就删除StorageObject表中的记录 | // 只要文件不存在,就删除StorageObject表中的记录 | ||||
| entries = append(entries, agtmsg.NewCheckStorageRespEntry(obj.ObjectID, obj.UserID, agtmsg.CHECK_STORAGE_RESP_OP_DELETE)) | |||||
| entries = append(entries, agtmsg.NewStorageCheckRespEntry(obj.ObjectID, obj.UserID, agtmsg.CHECK_STORAGE_RESP_OP_DELETE)) | |||||
| } | } | ||||
| } | } | ||||
| // 增量情况下,不需要对infosMap中没检查的记录进行处理 | // 增量情况下,不需要对infosMap中没检查的记录进行处理 | ||||
| return ramsg.ReplyOK(agtmsg.NewCheckStorageResp(consts.STORAGE_DIRECTORY_STATE_OK, entries)) | |||||
| return ramsg.ReplyOK(agtmsg.NewStorageCheckResp(consts.STORAGE_DIRECTORY_STATE_OK, entries)) | |||||
| } | } | ||||
| func (svc *Service) checkStorageComplete(msg *agtmsg.CheckStorage, fileInfos []fs.FileInfo) (*agtmsg.CheckStorageResp, *ramsg.CodeMessage) { | |||||
| func (svc *Service) checkStorageComplete(msg *agtmsg.StorageCheck, fileInfos []fs.FileInfo) (*agtmsg.StorageCheckResp, *ramsg.CodeMessage) { | |||||
| infosMap := make(map[string]fs.FileInfo) | infosMap := make(map[string]fs.FileInfo) | ||||
| for _, info := range fileInfos { | for _, info := range fileInfos { | ||||
| infosMap[info.Name()] = info | infosMap[info.Name()] = info | ||||
| } | } | ||||
| var entries []agtmsg.CheckStorageRespEntry | |||||
| var entries []agtmsg.StorageCheckRespEntry | |||||
| for _, obj := range msg.Objects { | for _, obj := range msg.Objects { | ||||
| fileName := utils.MakeMoveOperationFileName(obj.ObjectID, obj.UserID) | fileName := utils.MakeMoveOperationFileName(obj.ObjectID, obj.UserID) | ||||
| _, ok := infosMap[fileName] | _, ok := infosMap[fileName] | ||||
| @@ -155,17 +147,17 @@ func (svc *Service) checkStorageComplete(msg *agtmsg.CheckStorage, fileInfos []f | |||||
| } else { | } else { | ||||
| // 只要文件不存在,就删除StorageObject表中的记录 | // 只要文件不存在,就删除StorageObject表中的记录 | ||||
| entries = append(entries, agtmsg.NewCheckStorageRespEntry(obj.ObjectID, obj.UserID, agtmsg.CHECK_STORAGE_RESP_OP_DELETE)) | |||||
| entries = append(entries, agtmsg.NewStorageCheckRespEntry(obj.ObjectID, obj.UserID, agtmsg.CHECK_STORAGE_RESP_OP_DELETE)) | |||||
| } | } | ||||
| } | } | ||||
| // Storage中多出来的文件不做处理 | // Storage中多出来的文件不做处理 | ||||
| return ramsg.ReplyOK(agtmsg.NewCheckStorageResp(consts.STORAGE_DIRECTORY_STATE_OK, entries)) | |||||
| return ramsg.ReplyOK(agtmsg.NewStorageCheckResp(consts.STORAGE_DIRECTORY_STATE_OK, entries)) | |||||
| } | } | ||||
| /* | /* | ||||
| func (service *Service) ECMove(msg *agtmsg.ECMoveCommand) *agtmsg.StartMovingObjectToStorageResp { | |||||
| func (service *Service) ECMove(msg *agtmsg.ECMoveCommand) *agtmsg.StartStorageMoveObjectResp { | |||||
| panic("not implement yet!") | panic("not implement yet!") | ||||
| wg := sync.WaitGroup{} | wg := sync.WaitGroup{} | ||||
| fmt.Println("EcMove") | fmt.Println("EcMove") | ||||
| @@ -297,3 +289,59 @@ func persist(inBuf []chan []byte, numPacket int64, localFilePath string, wg *syn | |||||
| file.Close() | file.Close() | ||||
| wg.Done() | wg.Done() | ||||
| } | } | ||||
| func (svc *Service) StartStorageUploadRepObject(msg *agtmsg.StartStorageUploadRepObject) (*agtmsg.StartStorageUploadRepObjectResp, *ramsg.CodeMessage) { | |||||
| fullPath := filepath.Join(config.Cfg().StorageBaseDir, msg.StorageDirectory, msg.FilePath) | |||||
| file, err := os.Open(fullPath) | |||||
| if err != nil { | |||||
| logger.Warnf("opening file %s: %s", fullPath, err.Error()) | |||||
| return nil, ramsg.Failed(errorcode.OPERATION_FAILED, "open file failed") | |||||
| } | |||||
| fileInfo, err := file.Stat() | |||||
| if err != nil { | |||||
| file.Close() | |||||
| logger.Warnf("getting file %s state: %s", fullPath, err.Error()) | |||||
| return nil, ramsg.Failed(errorcode.OPERATION_FAILED, "get file info failed") | |||||
| } | |||||
| fileSize := fileInfo.Size() | |||||
| uploadObject := task.UploadObject{ | |||||
| ObjectName: msg.ObjectName, | |||||
| File: file, | |||||
| FileSize: fileSize, | |||||
| } | |||||
| uploadObjects := []task.UploadObject{uploadObject} | |||||
| // Task会关闭文件流 | |||||
| tsk := svc.taskManager.StartNew(task.NewUploadRepObjects(msg.UserID, msg.BucketID, uploadObjects, msg.RepCount)) | |||||
| return ramsg.ReplyOK(agtmsg.NewStartStorageUploadRepObjectResp(tsk.ID())) | |||||
| } | |||||
| func (svc *Service) WaitStorageUploadRepObject(msg *agtmsg.WaitStorageUploadRepObject) (*agtmsg.WaitStorageUploadRepObjectResp, *ramsg.CodeMessage) { | |||||
| tsk := svc.taskManager.FindByID(msg.TaskID) | |||||
| if tsk == nil { | |||||
| return nil, ramsg.Failed(errorcode.TASK_NOT_FOUND, "task not found") | |||||
| } | |||||
| if msg.WaitTimeoutMs == 0 { | |||||
| tsk.Wait() | |||||
| } else if !tsk.WaitTimeout(time.Duration(msg.WaitTimeoutMs)) { | |||||
| return ramsg.ReplyOK(agtmsg.NewWaitStorageUploadRepObjectResp(false, "", 0, "")) | |||||
| } | |||||
| uploadTask := tsk.Body().(*task.UploadRepObjects) | |||||
| uploadRet := uploadTask.Results[0] | |||||
| errMsg := "" | |||||
| if tsk.Error() != nil { | |||||
| errMsg = tsk.Error().Error() | |||||
| } | |||||
| if uploadRet.Error != nil { | |||||
| errMsg = uploadRet.Error.Error() | |||||
| } | |||||
| return ramsg.ReplyOK(agtmsg.NewWaitStorageUploadRepObjectResp(true, errMsg, uploadRet.ObjectID, uploadRet.FileHash)) | |||||
| } | |||||
| @@ -7,7 +7,6 @@ import ( | |||||
| "path/filepath" | "path/filepath" | ||||
| "time" | "time" | ||||
| "github.com/juju/ratelimit" | |||||
| "gitlink.org.cn/cloudream/common/pkg/logger" | "gitlink.org.cn/cloudream/common/pkg/logger" | ||||
| ) | ) | ||||
| @@ -73,8 +72,7 @@ func (t *IPFSRead) Execute(ctx TaskContext, complete CompleteFn) { | |||||
| return | return | ||||
| } | } | ||||
| bkt := ratelimit.NewBucketWithRate(10*1024, 10*1024) | |||||
| _, err = io.Copy(outputFile, ratelimit.Reader(rd, bkt)) | |||||
| _, err = io.Copy(outputFile, rd) | |||||
| if err != nil { | if err != nil { | ||||
| err := fmt.Errorf("copy ipfs file to local file failed, err: %w", err) | err := fmt.Errorf("copy ipfs file to local file failed, err: %w", err) | ||||
| log.WithField("LocalPath", t.LocalPath).Warn(err.Error()) | log.WithField("LocalPath", t.LocalPath).Warn(err.Error()) | ||||
| @@ -1,12 +1,16 @@ | |||||
| package task | package task | ||||
| import ( | import ( | ||||
| distsvc "gitlink.org.cn/cloudream/common/pkg/distlock/service" | |||||
| "gitlink.org.cn/cloudream/common/pkg/task" | "gitlink.org.cn/cloudream/common/pkg/task" | ||||
| "gitlink.org.cn/cloudream/common/utils/ipfs" | "gitlink.org.cn/cloudream/common/utils/ipfs" | ||||
| coorcli "gitlink.org.cn/cloudream/rabbitmq/client/coordinator" | |||||
| ) | ) | ||||
| type TaskContext struct { | type TaskContext struct { | ||||
| IPFS *ipfs.IPFS | |||||
| IPFS *ipfs.IPFS | |||||
| Coordinator *coorcli.Client | |||||
| DistLock *distsvc.Service | |||||
| } | } | ||||
| // 需要在Task结束后主动调用,completing函数将在Manager加锁期间被调用, | // 需要在Task结束后主动调用,completing函数将在Manager加锁期间被调用, | ||||
| @@ -21,8 +25,10 @@ type Task = task.Task[TaskContext] | |||||
| type CompleteOption = task.CompleteOption | type CompleteOption = task.CompleteOption | ||||
| func NewManager(ipfs *ipfs.IPFS) Manager { | |||||
| func NewManager(ipfs *ipfs.IPFS, coorCli *coorcli.Client, distLock *distsvc.Service) Manager { | |||||
| return task.NewManager(TaskContext{ | return task.NewManager(TaskContext{ | ||||
| IPFS: ipfs, | |||||
| IPFS: ipfs, | |||||
| Coordinator: coorCli, | |||||
| DistLock: distLock, | |||||
| }) | }) | ||||
| } | } | ||||
| @@ -0,0 +1,282 @@ | |||||
| package task | |||||
| import ( | |||||
| "fmt" | |||||
| "io" | |||||
| "math/rand" | |||||
| "time" | |||||
| "github.com/samber/lo" | |||||
| "gitlink.org.cn/cloudream/agent/internal/config" | |||||
| "gitlink.org.cn/cloudream/common/pkg/distlock/reqbuilder" | |||||
| "gitlink.org.cn/cloudream/common/pkg/logger" | |||||
| mygrpc "gitlink.org.cn/cloudream/common/utils/grpc" | |||||
| "gitlink.org.cn/cloudream/common/utils/ipfs" | |||||
| agentcaller "gitlink.org.cn/cloudream/proto" | |||||
| ramsg "gitlink.org.cn/cloudream/rabbitmq/message" | |||||
| coormsg "gitlink.org.cn/cloudream/rabbitmq/message/coordinator" | |||||
| "google.golang.org/grpc" | |||||
| "google.golang.org/grpc/credentials/insecure" | |||||
| ) | |||||
| // UploadObjects和UploadRepResults为一一对应关系 | |||||
| type UploadRepObjects struct { | |||||
| userID int64 | |||||
| bucketID int64 | |||||
| repCount int | |||||
| Objects []UploadObject | |||||
| Results []UploadSingleRepObjectResult | |||||
| IsUploading bool | |||||
| } | |||||
| type UploadRepObjectsResult struct { | |||||
| Objects []UploadObject | |||||
| Results []UploadSingleRepObjectResult | |||||
| IsUploading bool | |||||
| } | |||||
| type UploadObject struct { | |||||
| ObjectName string | |||||
| File io.ReadCloser | |||||
| FileSize int64 | |||||
| } | |||||
| type UploadSingleRepObjectResult struct { | |||||
| Error error | |||||
| FileHash string | |||||
| ObjectID int64 | |||||
| } | |||||
| func NewUploadRepObjects(userID int64, bucketID int64, uploadObjects []UploadObject, repCount int) *UploadRepObjects { | |||||
| return &UploadRepObjects{ | |||||
| userID: userID, | |||||
| bucketID: bucketID, | |||||
| Objects: uploadObjects, | |||||
| repCount: repCount, | |||||
| } | |||||
| } | |||||
| func (t *UploadRepObjects) Execute(ctx TaskContext, complete CompleteFn) { | |||||
| log := logger.WithType[UploadRepObjects]("Task") | |||||
| log.Debugf("begin with %v", logger.FormatStruct(t)) | |||||
| defer log.Debugf("end") | |||||
| err := t.do(ctx) | |||||
| complete(err, CompleteOption{ | |||||
| RemovingDelay: time.Minute, | |||||
| }) | |||||
| for _, obj := range t.Objects { | |||||
| obj.File.Close() | |||||
| } | |||||
| } | |||||
| func (t *UploadRepObjects) do(ctx TaskContext) error { | |||||
| reqBlder := reqbuilder.NewBuilder() | |||||
| for _, uploadObject := range t.Objects { | |||||
| reqBlder.Metadata(). | |||||
| // 用于防止创建了多个同名对象 | |||||
| Object().CreateOne(t.bucketID, uploadObject.ObjectName) | |||||
| } | |||||
| mutex, err := reqBlder. | |||||
| Metadata(). | |||||
| // 用于判断用户是否有桶的权限 | |||||
| UserBucket().ReadOne(t.userID, t.bucketID). | |||||
| // 用于查询可用的上传节点 | |||||
| Node().ReadAny(). | |||||
| // 用于设置Rep配置 | |||||
| ObjectRep().CreateAny(). | |||||
| // 用于创建Cache记录 | |||||
| Cache().CreateAny(). | |||||
| MutexLock(ctx.DistLock) | |||||
| if err != nil { | |||||
| return fmt.Errorf("acquire locks failed, err: %w", err) | |||||
| } | |||||
| defer mutex.Unlock() | |||||
| var repWriteResps []*coormsg.PreUploadResp | |||||
| //判断是否所有文件都符合上传条件 | |||||
| hasFailure := true | |||||
| for i := 0; i < len(t.Objects); i++ { | |||||
| repWriteResp, err := t.preUploadSingleObject(ctx, t.Objects[i]) | |||||
| if err != nil { | |||||
| hasFailure = false | |||||
| t.Results = append(t.Results, | |||||
| UploadSingleRepObjectResult{ | |||||
| Error: err, | |||||
| FileHash: "", | |||||
| ObjectID: 0, | |||||
| }) | |||||
| continue | |||||
| } | |||||
| t.Results = append(t.Results, UploadSingleRepObjectResult{}) | |||||
| repWriteResps = append(repWriteResps, repWriteResp) | |||||
| } | |||||
| // 不满足上传条件,返回各文件检查结果 | |||||
| if !hasFailure { | |||||
| return nil | |||||
| } | |||||
| //上传文件夹 | |||||
| t.IsUploading = true | |||||
| for i := 0; i < len(repWriteResps); i++ { | |||||
| objectID, fileHash, err := t.uploadSingleObject(ctx, t.Objects[i], repWriteResps[i]) | |||||
| // 记录文件上传结果 | |||||
| t.Results[i] = UploadSingleRepObjectResult{ | |||||
| Error: err, | |||||
| FileHash: fileHash, | |||||
| ObjectID: objectID, | |||||
| } | |||||
| } | |||||
| return nil | |||||
| } | |||||
| // 检查单个文件是否能够上传 | |||||
| func (t *UploadRepObjects) preUploadSingleObject(ctx TaskContext, uploadObject UploadObject) (*coormsg.PreUploadResp, error) { | |||||
| //发送写请求,请求Coor分配写入节点Ip | |||||
| repWriteResp, err := ctx.Coordinator.PreUploadRepObject(coormsg.NewPreUploadRepObjectBody(t.bucketID, uploadObject.ObjectName, uploadObject.FileSize, t.userID, config.Cfg().ExternalIP)) | |||||
| if err != nil { | |||||
| return nil, fmt.Errorf("pre upload rep object: %w", err) | |||||
| } | |||||
| if len(repWriteResp.Nodes) == 0 { | |||||
| return nil, fmt.Errorf("no node to upload file") | |||||
| } | |||||
| return repWriteResp, nil | |||||
| } | |||||
| // 上传文件 | |||||
| func (t *UploadRepObjects) uploadSingleObject(ctx TaskContext, uploadObject UploadObject, preResp *coormsg.PreUploadResp) (int64, string, error) { | |||||
| var fileHash string | |||||
| uploadedNodeIDs := []int64{} | |||||
| willUploadToNode := true | |||||
| // 因为本地的IPFS属于调度系统的一部分,所以需要加锁 | |||||
| mutex, err := reqbuilder.NewBuilder(). | |||||
| IPFS().CreateAnyRep(config.Cfg().ID). | |||||
| MutexLock(ctx.DistLock) | |||||
| if err != nil { | |||||
| return 0, "", fmt.Errorf("acquiring locks: %w", err) | |||||
| } | |||||
| fileHash, err = uploadToLocalIPFS(ctx.IPFS, uploadObject.File) | |||||
| if err != nil { | |||||
| // 上传失败,则立刻解锁 | |||||
| mutex.Unlock() | |||||
| logger.Warnf("uploading to local IPFS: %s, will select a node to upload", err.Error()) | |||||
| } else { | |||||
| willUploadToNode = false | |||||
| uploadedNodeIDs = append(uploadedNodeIDs, config.Cfg().ID) | |||||
| // 上传成功,则等到所有操作结束后才能解锁 | |||||
| defer mutex.Unlock() | |||||
| } | |||||
| // 本地IPFS失败,则发送到agent上传 | |||||
| if willUploadToNode { | |||||
| // 本地IPFS已经失败,所以不要再选择当前节点了 | |||||
| uploadNode := t.chooseUploadNode(lo.Reject(preResp.Nodes, func(item ramsg.RespNode, index int) bool { return item.ID == config.Cfg().ID })) | |||||
| // 如果客户端与节点在同一个地域,则使用内网地址连接节点 | |||||
| nodeIP := uploadNode.ExternalIP | |||||
| if uploadNode.IsSameLocation { | |||||
| nodeIP = uploadNode.LocalIP | |||||
| logger.Infof("client and node %d are at the same location, use local ip\n", uploadNode.ID) | |||||
| } | |||||
| mutex, err := reqbuilder.NewBuilder(). | |||||
| // 防止上传的副本被清除 | |||||
| IPFS().CreateAnyRep(uploadNode.ID). | |||||
| MutexLock(ctx.DistLock) | |||||
| if err != nil { | |||||
| return 0, "", fmt.Errorf("acquire locks failed, err: %w", err) | |||||
| } | |||||
| defer mutex.Unlock() | |||||
| fileHash, err = uploadToNode(uploadObject.File, nodeIP) | |||||
| if err != nil { | |||||
| return 0, "", fmt.Errorf("upload to node %s failed, err: %w", nodeIP, err) | |||||
| } | |||||
| uploadedNodeIDs = append(uploadedNodeIDs, uploadNode.ID) | |||||
| } | |||||
| // 记录写入的文件的Hash | |||||
| createResp, err := ctx.Coordinator.CreateRepObject(coormsg.NewCreateRepObject(t.bucketID, uploadObject.ObjectName, uploadObject.FileSize, t.repCount, t.userID, uploadedNodeIDs, fileHash)) | |||||
| if err != nil { | |||||
| return 0, "", fmt.Errorf("creating rep object: %w", err) | |||||
| } | |||||
| return createResp.ObjectID, fileHash, nil | |||||
| } | |||||
| // chooseUploadNode 选择一个上传文件的节点 | |||||
| // 1. 从与当前客户端相同地域的节点中随机选一个 | |||||
| // 2. 没有用的话从所有节点中随机选一个 | |||||
| func (t *UploadRepObjects) chooseUploadNode(nodes []ramsg.RespNode) ramsg.RespNode { | |||||
| sameLocationNodes := lo.Filter(nodes, func(e ramsg.RespNode, i int) bool { return e.IsSameLocation }) | |||||
| if len(sameLocationNodes) > 0 { | |||||
| return sameLocationNodes[rand.Intn(len(sameLocationNodes))] | |||||
| } | |||||
| return nodes[rand.Intn(len(nodes))] | |||||
| } | |||||
| func uploadToNode(file io.ReadCloser, nodeIP string) (string, error) { | |||||
| // 建立grpc连接,发送请求 | |||||
| grpcAddr := fmt.Sprintf("%s:%d", nodeIP, config.Cfg().GRPCPort) | |||||
| grpcCon, err := grpc.Dial(grpcAddr, grpc.WithTransportCredentials(insecure.NewCredentials())) | |||||
| if err != nil { | |||||
| return "", fmt.Errorf("connect to grpc server at %s failed, err: %w", grpcAddr, err) | |||||
| } | |||||
| defer grpcCon.Close() | |||||
| client := agentcaller.NewFileTransportClient(grpcCon) | |||||
| upload, err := mygrpc.SendFileAsStream(client) | |||||
| if err != nil { | |||||
| return "", fmt.Errorf("request to send file failed, err: %w", err) | |||||
| } | |||||
| // 发送文件数据 | |||||
| _, err = io.Copy(upload, file) | |||||
| if err != nil { | |||||
| // 发生错误则关闭连接 | |||||
| upload.Abort(io.ErrClosedPipe) | |||||
| return "", fmt.Errorf("copy file date to upload stream failed, err: %w", err) | |||||
| } | |||||
| // 发送EOF消息,并获得FileHash | |||||
| fileHash, err := upload.Finish() | |||||
| if err != nil { | |||||
| upload.Abort(io.ErrClosedPipe) | |||||
| return "", fmt.Errorf("send EOF failed, err: %w", err) | |||||
| } | |||||
| return fileHash, nil | |||||
| } | |||||
| func uploadToLocalIPFS(ipfs *ipfs.IPFS, file io.ReadCloser) (string, error) { | |||||
| // 从本地IPFS上传文件 | |||||
| writer, err := ipfs.CreateFile() | |||||
| if err != nil { | |||||
| return "", fmt.Errorf("create IPFS file failed, err: %w", err) | |||||
| } | |||||
| _, err = io.Copy(writer, file) | |||||
| if err != nil { | |||||
| return "", fmt.Errorf("copy file data to IPFS failed, err: %w", err) | |||||
| } | |||||
| fileHash, err := writer.Finish() | |||||
| if err != nil { | |||||
| return "", fmt.Errorf("finish writing IPFS failed, err: %w", err) | |||||
| } | |||||
| return fileHash, nil | |||||
| } | |||||
| @@ -8,12 +8,14 @@ import ( | |||||
| "gitlink.org.cn/cloudream/agent/internal/config" | "gitlink.org.cn/cloudream/agent/internal/config" | ||||
| "gitlink.org.cn/cloudream/agent/internal/task" | "gitlink.org.cn/cloudream/agent/internal/task" | ||||
| distsvc "gitlink.org.cn/cloudream/common/pkg/distlock/service" | |||||
| log "gitlink.org.cn/cloudream/common/pkg/logger" | log "gitlink.org.cn/cloudream/common/pkg/logger" | ||||
| "gitlink.org.cn/cloudream/common/utils/ipfs" | "gitlink.org.cn/cloudream/common/utils/ipfs" | ||||
| agentserver "gitlink.org.cn/cloudream/proto" | agentserver "gitlink.org.cn/cloudream/proto" | ||||
| "google.golang.org/grpc" | "google.golang.org/grpc" | ||||
| "gitlink.org.cn/cloudream/rabbitmq/client/coordinator" | |||||
| rasvr "gitlink.org.cn/cloudream/rabbitmq/server/agent" | rasvr "gitlink.org.cn/cloudream/rabbitmq/server/agent" | ||||
| cmdsvc "gitlink.org.cn/cloudream/agent/internal/services/cmd" | cmdsvc "gitlink.org.cn/cloudream/agent/internal/services/cmd" | ||||
| @@ -44,11 +46,21 @@ func main() { | |||||
| log.Fatalf("new ipfs failed, err: %s", err.Error()) | log.Fatalf("new ipfs failed, err: %s", err.Error()) | ||||
| } | } | ||||
| coor, err := coordinator.NewClient(&config.Cfg().RabbitMQ) | |||||
| if err != nil { | |||||
| log.Fatalf("new ipfs failed, err: %s", err.Error()) | |||||
| } | |||||
| distlock, err := distsvc.NewService(&config.Cfg().DistLock) | |||||
| if err != nil { | |||||
| log.Fatalf("new ipfs failed, err: %s", err.Error()) | |||||
| } | |||||
| //处置协调端、客户端命令(可多建几个) | //处置协调端、客户端命令(可多建几个) | ||||
| wg := sync.WaitGroup{} | wg := sync.WaitGroup{} | ||||
| wg.Add(4) | |||||
| wg.Add(5) | |||||
| taskMgr := task.NewManager(ipfs) | |||||
| taskMgr := task.NewManager(ipfs, coor, distlock) | |||||
| // 启动命令服务器 | // 启动命令服务器 | ||||
| // TODO 需要设计AgentID持久化机制 | // TODO 需要设计AgentID持久化机制 | ||||
| @@ -74,6 +86,8 @@ func main() { | |||||
| agentserver.RegisterFileTransportServer(s, grpcsvc.NewService(ipfs)) | agentserver.RegisterFileTransportServer(s, grpcsvc.NewService(ipfs)) | ||||
| go serveGRPC(s, lis, &wg) | go serveGRPC(s, lis, &wg) | ||||
| go serveDistLock(distlock) | |||||
| wg.Wait() | wg.Wait() | ||||
| } | } | ||||
| @@ -104,3 +118,15 @@ func serveGRPC(s *grpc.Server, lis net.Listener, wg *sync.WaitGroup) { | |||||
| wg.Done() | wg.Done() | ||||
| } | } | ||||
| func serveDistLock(svc *distsvc.Service) { | |||||
| log.Info("start serving distlock") | |||||
| err := svc.Serve() | |||||
| if err != nil { | |||||
| log.Errorf("distlock stopped with error: %s", err.Error()) | |||||
| } | |||||
| log.Info("distlock stopped") | |||||
| } | |||||