Compare commits

..

2630 Commits

Author SHA1 Message Date
slasher
6b2e7926be fix(access): limit writer in pipe
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2026-06-22 11:11:24 +08:00
xiejian
e286733d88 fix(shardnode): clean up prometheus labels on shard/disk removal
with: #1000420047

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-05-25 10:40:13 +08:00
JasonHu520
9f669c9dcc fix(proxy): use route item version instread of volume
with: #1000987849
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-05-21 11:27:33 +08:00
JasonHu520
3f66f4673b feat(cli): when migrate node check volume unit unavailable
with: #1000420094
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-05-20 19:10:42 +08:00
xiejian
bb7e06259b fix(clustermgr): use actual range count for shard init done check
with: #1000979225

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-05-18 19:10:24 +08:00
xiejian
612b656595 refactor(shardnode): improve tracing and volume cache consistency
with: #1000420040

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-05-15 11:02:25 +08:00
tangdeyi
5819c292a8 fix(clustermgr): fix the volume and shard route field persistence
with #1000431984

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-05-14 09:35:07 +08:00
xiejian
9dba0f1a9f feat(access): support gradual repair message routing to shardnode
with: #1000959605

Signed-off-by: xiejian <xiejian3@oppo.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-12 17:51:53 +08:00
tangdeyi
22accdacd7 fix(clustermgr): fix route overflow causing abnormal cleanup process
with #1000431984

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-05-12 15:45:40 +08:00
JasonHu520
736b07427b fix(scheduler): fixup repair task lock failed
with: #1000941756
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-05-07 16:23:59 +08:00
slasher
05433024c1 fix(clustermgr): fixup repaired disk's node id
. #1000431984

Signed-off-by: slasher <shenjie1@oppo.com>
2026-05-07 10:23:09 +08:00
xiejian
7ac5d2eb6d fix(clustermgr): skip Repaired/Dropped disks in hostPathFilter on node host update
with: #1000453093

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-05-06 19:30:46 +08:00
JasonHu520
16b5d3e6f1 fix(blobnode): fix disk meta info crc not match for fallback last version
with: #1000887229

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
32fa5e55b1 fix(clustermgr): minus reserved space once on replica node
. #1000192943

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
9bff191118 chore(clustermgr): fixup logging format of disk id
. #1000431984

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
2c1a8821b3 docs(blobstore): update documentation for new version
. #1000431984

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
c2d0d7992e fix(clustermgr): skip not enabled codemode when getWeightedDataUnitCount
with #1000518879

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
7acad970e0 feat(proxy): print codemode config when start serve
with: #1000420053

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
ec7940db5c fix(proxy): check volume routeversion before update to cache
with: #1000419929

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
193bfb416b feat(clustermgr): create volume route for admin interface
. #1000431984

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
ad09ec279d chore(cli): move args of clustermgr volume list to flags
. #1000657118

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
3269ca5906 fix(blobnode): fixup blobnode write trace of net reader
. #1000657118

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
JasonHu520
c73f38b2f4 fix(scheduler): manual migrate task also should fresh disk info
with: #1000744290

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
JasonHu520
0c7f1fbb42 fix(scheduler): follower also should load normal disk
with: #1000744290
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
JasonHu520
48e9013b93 fix(scheduler): update disk info for inspect task
with: #1000744290
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
407a763600 fix(proxy): set the correct number of volumes to buffer upon restart
with: #1000705228 #1000420053

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
df7cec5ad0 feat(cli): add filter rack for choosing nodes
. #1000645443

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
dec013044a style(common): using generic version of functions
. #1000657118

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
a07809fc95 refactor(shardnode): reorganize shardnode cli tools
with: #1000685347

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
6272fa3d38 fix(shardnode): encode blob task stats in correct way
with: #1000420040

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
94da88c382 fix(shardnode): set default retry times for slice repair config
with: #1000420040

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
ae2107cc6c feat(cli): show blocking volume of migrate node, create task auto
. #1000645443

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
ac1f02e5c9 feat(cli): greedy find safe nodes to move
. #1000645443

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
9c76be3c6a fix(shardnode): fix sliceRepiarMgr components not initialized
with: #1000420040

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
mawei029
ac7ac4b7bb fix(blobnode): blobnode start up change ip, add node with local node id
with: #1000464074

Signed-off-by: mawei029 <mawei2@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
8d37f14b22 fix(clustermgr): fix update node info
with #1000596325

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
44ff52987e feat(shardnode): support ip change for blob delete and slice repair process
with: #1000567432

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
c2c9db173b feature(shardnode): init shardnode metrics report
with: #1000503826

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
c0a5c67060 feature(shardnode): metadata statistics implementation
with: #1000464391

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
6dcf03ab41 refactor(shardnode): rename del_blob.go
with: #1000420040

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
4d5b05ec0d feat(shardnode): init execute repair message process
with: #1000420040

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
073b7aee84 refactor(shardnode): rename blobdeleter package to message
with: #1000420040

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
43248c2656 refactor(shardnode): 1.extract public blob message process components
2.update punish message process

with: #1000420040

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
mawei029
2294b13288 fix(blobnode): read format json backward compatible, check crc with old version
with: #1000464074

Signed-off-by: mawei029 <mawei2@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
e122cb60f3 feat(clustermgr): add cluster readonly manager api
with #1000596325

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
412fa7a48d fix(clustermgr): total free chunk only stats normal disk
#1000518879

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
6518595f6e feat(access): no distance for crossing idc getting
. #1000573599

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
8e85d22aee feat(proxy): changeable expiration config for volume and disk
. #1000570314

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
c047eecb51 feat(access): disk info expire in access memory
. #1000558473

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
e93202c7c9 refactor(proxy): replace VersionVolume with VolumeInfo
with: #1000419929

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
00919b446f feat(proxy): update volume cache by apply route update from clustermgr
with: #1000419929

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
ac43310e84 feat(cli): using disk host for command
. #1000557660

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
0be8a2d820 feat(access): using disk host for put and get
. #1000557660

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
54a61cea8c feat(clustermgr): multi create volume optimization
1. volume creation is limited by idc/disk free chunk
2. volume creation count can be configured by codemode ratio
3. volume creation can be triggered by volume writable space

with #1000518879

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
48d2dfdf6c feat(clustermgr): update disk lastupdate when disk status changes
with #1000518879

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
6499ead6d5 feat(clustermgr): raft filewal cleans trash log by itself
with #1000543617

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
8b085fbac6 feat(clustermgr): clustermgr support blobnode ip change
with #1000453093

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
JasonHu520
28c5590b25 feat(scheduler): support ip change for delete and shard repair process
with: #1000426729
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
JasonHu520
df1a79c29d feat(scheduler): support ip change for blobnode
with: #1000426729
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
3ffb090df4 feat(clustermgr): volume route add volume base info
with #1000431984

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
mawei029
db13083205 feat(blobnode): support blobnode ip change with nodeID
with: #1000464074

Signed-off-by: mawei029 <mawei2@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
be22aad2b7 feat(clustermgr): create and update volume route
with #1000431984

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
mawei029
2b2efeb073 fix(blobnode): we need check old disk status
when hot register disk; and check cluster id when add disk

with: #1000528521

Signed-off-by: mawei029 <mawei2@oppo.com>
2026-04-21 09:23:09 +08:00
JasonHu520
0e08c6e443 feat(scheduler): balance task access new alloc interface of cm
with: #1000527051
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
mawei029
f66d9bd2ae chore(blobnode): optimize stop blobnode, add some print log
with: #1000486493

Signed-off-by: mawei029 <mawei2@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
e0c1414bba feat(proxy): supports independent config of volume cache for different codemode
with: #1000420053

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
06f8fb00cf feat(log): apply async logger to app and api
. #1000453008

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
b5fc5b8a23 feat(log): drop logging if aync queque is full
. #1000453008

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
3771f8a0be feat(log): add async logger in util
. #1000453008

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
tangdeyi
e5e1848ef0 feat(clustermgr): alloc chunk at disk level in balance case
with #1000479337

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
142434da6e fix(access): return 499 if alloc canceled
. #1000508589

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
mawei029
b572bb6be4 feat(blobnode): we can hot query, qos current statistic
with: #1000415457

Signed-off-by: mawei029 <mawei2@oppo.com>
2026-04-21 09:23:09 +08:00
zhangjianwei2
00fa06c716 feat(bssdk): support specify code_mode and cluster_id for access sdk put api
fixes: https://github.com/cubefs/cubefs/issues/3954

@formatter:off

Signed-off-by: zhangjianwei2 <zhangjianwei2@cmss.chinamobile.com>
2026-04-21 09:23:09 +08:00
yuzhiqiang
ed09c33f3b feat(blobnode): supports mounting meta directories separately for each disk
@formatter:off

Signed-off-by: yuzhiqiang <yuzhiqiang_yewu@cmss.chinamobile.com>
2026-04-21 09:23:09 +08:00
JasonHu520
199a945da0 perf(scheduler): optimize volume lock and disk limiting conflicts
with: #1000414417
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
mawei029
67e82011b3 fix(blobnode): fix clean lost disk metric when startup
fix fatal when lost disk has already marked broken disk

with: #1000389434 , #1000389466

Signed-off-by: mawei029 <mawei2@oppo.com>
2026-04-21 09:23:09 +08:00
slasher
5a588bb032 feat(access): retry uniqe proxy service in access
. #1000403229

Signed-off-by: slasher <shenjie1@oppo.com>
2026-04-21 09:23:09 +08:00
xiejian
b6ee58a15f feat(shardnode): synchronize the latest volume alloc process of proxy
with: #1000389284

Signed-off-by: xiejian <xiejian3@oppo.com>
2026-04-21 09:23:09 +08:00
JasonHu520
c7188afc2a feat(scheduler): acquire task no more aware task switch status
with: #1000380867

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2026-04-21 09:23:09 +08:00
yanghonggang
e3bc840a4e refactor(blobstore): reuse stream mempool and lazy init in access
* blobstore/sdk/sdk_client.go: sdkHandler now reuses the memory pool from
  the underlying stream handler instead of relying on a separate init()
* blobstore/api/access/client.go: Delay memory pool allocation until
  New() is called, removing the forced init() allocation

close #3918

@formatter:off

Signed-off-by: yanghonggang <yanghonggang_yewu@cmss.chinamobile.com>
Signed-off-by: zhangjianwei2 <zhangjianwei2_yewu@cmss.chinamobile.com>
2026-04-21 09:23:09 +08:00
Cloudstriff
ec4630026b feat(blobstore): init cpp version package directory
with #1000382944

Signed-off-by: Cloudstriff <chenjiong@oppo.com>
2026-04-21 09:23:09 +08:00
leonrayang
4d6c55a9ab feat(doc): 2026 Roadmap Update
Signed-off-by: leonrayang <changliang@oppo.com>
2026-04-20 17:13:00 +08:00
chihe
80a062bf2c fix(doc): modify change log
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
2025-12-26 14:59:44 +08:00
clinx
0bcdcee745 fix(flash): fix codeQL issue
@formatter:off

Signed-off-by: clinx <chenlin1@oppo.com>
2025-12-26 11:30:38 +08:00
leonrayang
0b02c44208 fix(client): Disable xattr security.capability to avoid useless request to backend
close:#1000519910

@formatter:off

Signed-off-by: leonrayang <changliang@oppo.com>
2025-12-25 14:43:17 +08:00
leonrayang
2b6173f7e6 fix(doc): Delete and update the usage of some outdated project names
@formatter:off

Signed-off-by: leonrayang <changliang@oppo.com>
2025-12-25 14:42:34 +08:00
clinx
43c448a75b fix(flash): change the reserved space of flashnode
with: #1000568547

Signed-off-by: clinx <chenlin1@oppo.com>
2025-12-25 14:42:00 +08:00
Victor1319
0424ada0fc fix(fuse): revert maxWrite constant to 128kB.
close:#1000511705

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-12-25 14:41:44 +08:00
chihe
81643df8cb fix(master): add triggerCondition for dataNode balance
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
2025-12-24 19:31:51 +08:00
chihe
aa70981991 feat(doc): update docs for v3.5.3
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
2025-12-24 17:01:37 +08:00
clinx
68177b7812 fix(client): prevent directory and parent inode from referencing each other
with: #1000568547

Signed-off-by: clinx <chenlin1@oppo.com>
2025-12-24 17:01:37 +08:00
chihe
2816bd85d9 enhance(client): change default value for aheadReadMem
close:#1000517044

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 95cef5547c)
2025-12-24 17:01:37 +08:00
chihe
85d119ca04 fix(client): add minAheadReadSize
close:#1000517044

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 6abbbe772e)
2025-12-24 17:01:37 +08:00
clinx
a02b6e578b fix(client): avoid errors being suppressed
with: #1000551797

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit f21efa70db)
2025-12-24 17:01:37 +08:00
clinx
8bc35a2abe fix(client): On successful tiny extent write, return connection to pool
with: #1000551797

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit fd5065ca36)
2025-12-24 17:01:36 +08:00
clinx
22b8f7d086 fix(client): only read req data
with: #1000412030

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit d64ae846e0)
2025-12-24 17:01:36 +08:00
chihe
fec6c03fe4 fix(client): sync flush when new ek is created
close:#1000511680

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 43724a4d6d)
2025-12-24 17:01:36 +08:00
Victor1319
d8638e22b5 refactor(master): use IsDeleted for volume status checks.
close:#1000542120

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 0ad5c80c05)
2025-12-24 17:01:36 +08:00
chihe
57321ed6b5 fix(client): wait for all asynchronous flush requests to complete
close:#1000511680

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit e3acdb7c1f)
2025-12-24 17:01:36 +08:00
Victor1319
5cf66705de fix(meta): enhance txRename_ll.
close:#1000527746

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit d766464509)
2025-12-24 17:01:35 +08:00
chihe
b47bc52042 fix(client): fix putAheadReadBlock Blocking issue
close:#1000412030

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit ccb7de44bb)
2025-12-24 17:01:35 +08:00
clinx
a21a0b6b4c fix(client): update client first
with: #1000412030

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit c406e88c58)
2025-12-24 17:01:35 +08:00
shuqiang-zheng
846adfbad5 fix(master): adjust shutdown order of disk/DP decommission goroutines on leader change.
close: #1000520724

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 31aaaf00ad)
2025-12-24 17:01:34 +08:00
Victor1319
e22d16caeb fix(client): set FuseServeThreads default to 0
close:#1000451308

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 268e113f7b)
2025-12-24 17:01:34 +08:00
chihe
fdf9862387 fix(client): check remain size for cache block
close:#1000516353

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit a45ba8a82a)
2025-12-24 17:01:34 +08:00
chihe
393e6b4e4c fix(client): if directIO is enabled, wait for flush before write
close:#1000511680

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 109e4f1998)
2025-12-24 17:01:34 +08:00
shuqiang-zheng
34bdb46979 fix(master): check diskErr only for markDecommission DPs.
close: #1000511821

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit e485333226)
2025-12-24 17:01:34 +08:00
clinx
d5ae6348ce fix(client): close call debug.stack
with: #1000451308

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit ad09488065)
2025-12-24 17:01:33 +08:00
clinx
bf75d08969 fix(client): write meta conflict
with: #1000451308

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 2f6568e81c)
2025-12-24 17:01:33 +08:00
zhumingze
a1c14cbcb3 fix(master): logic adapts for decommission parts of the dp on the node. #1000441588
Signed-off-by: zhumingze <zhumingze@oppo.com>
(cherry picked from commit 09adcf3912)
2025-12-24 17:01:33 +08:00
clinx
17a4db2642 fix(client): change update extents by inodecache
with:#1000451308

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 09e2646fac)
2025-12-24 17:01:32 +08:00
clinx
08895b35ab fix(client): set FuseServeThreads default value to 64
with: #1000451308

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 37bce4a424)
2025-12-24 17:01:32 +08:00
shuqiang-zheng
606dd18675 fix(master): set decommissionFail only after removing all failed DPs from queue
close: #1000479261

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 54d63c4424)
2025-12-24 17:01:32 +08:00
clinx
3572394cf8 fix(client): clear resource base on sdk init remote client
with: #1000451308

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 0782d0ec50)
2025-12-24 17:01:32 +08:00
clinx
d35a07e841 fix(flash): update read metric
with: #1000451308

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 1581da2e1c)
2025-12-24 17:01:31 +08:00
shuqiang-zheng
5bea69cd67 feat(master): the dp decommission progress will not exceed 100%.
close: #1000471110

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit c171ba1a1c)
2025-12-24 17:01:31 +08:00
chihe
7a618a44ad fix(client): use sync flush if open file as directIO
close:#1000464581

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 34fb8cdeb2)
2025-12-24 17:01:31 +08:00
Victor1319
cbbead5859 fix(master): avoid to invoke partition lock in dpmap func.
close:#1000459767

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 03cb604303)
2025-12-24 17:01:31 +08:00
chihe
698b727acb fix(client): quit asyncFluashManager when streamer is closed
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 27a5ac6e57)
2025-12-24 17:01:31 +08:00
clinx
3b2ffbcf7a fix(flash): for legacy OpFlashNodeHeartbeat
with: #1000451308

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 40f13d22db)
2025-12-24 17:01:30 +08:00
chihe
903c2eede2 fix(client): delete inode cache when write streamer is timeout
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 428066c973)
2025-12-24 17:01:30 +08:00
clinx
76e0ae04a8 fix(flash): select availbale disk by real left space
with: #1000444307

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 86f06bc00f)
2025-12-24 17:01:30 +08:00
chihe
70dcb4f740 fix(client): clear all blockCache when truncating file
close:#1000310987

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 3c7771df51)
2025-12-24 17:01:30 +08:00
chihe
39ee65f326 fix(client): fix some bugs for metaCacheAcceleration
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit ad947942d1)
2025-12-24 17:01:29 +08:00
Victor1319
80eb869ebe feat(stream): enhance connection pool management with cost tracking. #1000402826
- Add cost tracking to connection pool objects
- Implement SetUseCostPool method for connection pool
- Update connection handling to utilize cost in PutConnectV2
- Introduce PoolInterface for improved pool management
- Create PoolWithCost for managing connections based on cost

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 767f5e9ae2)
2025-12-24 17:01:29 +08:00
chihe
1d422c8bc0 fix(client): enhance the logic of looking up for directory
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 36f1e4569f)
2025-12-24 17:01:29 +08:00
Victor1319
b6103ad53f feat(client): enhance directory lookup with lazy loading of child directories. #1000402826
- Add sync.Once to Dir struct for lazy initialization
- Implement lazy loading of child directories in Lookup method
- Update InodeGet to use InodeGetExt_ll for better performance
- Modify extents handling logic in InodeGet method
- Rename getExtetnsPool to GetExtetnsPool for consistency

Signed-off-by: [Your Name] <your.email@example.com>
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 8f1b4a54be)
2025-12-24 17:01:28 +08:00
chihe
84d84f5a08 feat(client): support metaCacheAcceleration
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit d88c999c35)
2025-12-24 17:01:28 +08:00
Victor1319
360f72e9db fix(client): update inode expiration time and enhance logging for extents. #1000402826
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-12-24 17:01:28 +08:00
clinx
4ae784e64b fix(flash): compatibility for historical opcodes
with: #1000412152

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit ce34ed7fdd)
2025-12-24 17:01:27 +08:00
clinx
9cd6c92dd3 fix(flash): check mount point and add metrics
with: #1000414729

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit a9c84eca6b)
2025-12-24 17:01:25 +08:00
chihe
4958298824 fixc(client): fix bug with evictCacheBlock
close:#1000412030

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 59142af7e0)
2025-12-24 17:01:25 +08:00
clinx
e8239124a6 fix(client): fix ut fail
close: #1000412030

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit dc49d7a695)
2025-12-24 17:01:25 +08:00
chihe
e5ba5d31c9 fix(client): use extentOffset to create block key for aheadRead
close:#1000412030

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 0e84a32213)
2025-12-24 17:01:25 +08:00
chihe
110bdf5a17 fix(client): update rightOffset to make window for aheadRead move forward
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit dcaeee8970)
2025-12-24 17:01:25 +08:00
shuqiang-zheng
61ff222b32 fix(master): fixed an issue where disks successfully decommissioned were re-marked .
close: #1000412387

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit d4ecea0527)
2025-12-24 17:01:25 +08:00
clinx
63c1e7d8d7 fix(client): Fix the issue of the client refreshing metadata unexpectedly
with:  #1000409494

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 26bcf93666)
2025-12-24 17:01:25 +08:00
zhumingze
7b39125377 fix(master): Modify the display information of lostDisk status. #1000409772
Signed-off-by: zhumingze <zhumingze@oppo.com>
(cherry picked from commit f384d50b27)
2025-12-24 17:01:25 +08:00
clinx
9903d1f151 fix(flash): avoid application startup failure due to errors in a single disk
with:#1000409494

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 694d52120c)
2025-12-24 17:01:24 +08:00
chihe
e1b02e33b4 fix(client): check dp when creating or excuting task for aheadRead
close;#1000406278

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 6ec3410805)
2025-12-24 17:01:24 +08:00
chihe
e60f814e64 fix(client): reset offset for aheadReading tinyExtent
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit dc5d876568)
2025-12-24 17:01:24 +08:00
Victor1319
5f9412e03d feat(client): add TCP keep-alive time configuration for connection pools. #1000402826
- Implement TcpAliveTime option in mount options
- Set TCP keep-alive time for stream and ahead read connection pools
- Update connection pool to accept timeout and minimum capacity parameters

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit d96c5db9a3)
2025-12-24 17:01:24 +08:00
clinx
6a0f7b8cd1 feat(flashnode): client warm up meta data with path
with: #1000150848

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 6e6373b1d6)
2025-12-24 17:01:23 +08:00
clinx
c02f9bc031 fix(flash): check for a stop event when receiving a pause command
with: #1000394421

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 7f484f126f)
2025-12-24 17:01:23 +08:00
chihe
be579d8c22 fix(client): fix s3test CI test issue
close:#1000363069

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 18d5d20b71)
2025-12-24 17:01:23 +08:00
clinx
cd086fcb46 fix(flash): warm up task set force remote cache true
with: #1000390069

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 272660d7cb)
2025-12-24 17:01:22 +08:00
chihe
9f3548653a refactor(client): new sliding algorithm for readAhead
close:#1000048465

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit c2d6947a71)
2025-12-24 17:01:22 +08:00
chihe
407b49211d feat(client): support defining the size of cacheBlockSize
close:#1000261380

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit d2031e685c)
2025-12-24 17:01:22 +08:00
clinx
8ab32b038a fix(flash): increase reserve space for flash node
with: #1000386811

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 2881c1ce33)
2025-12-24 17:01:22 +08:00
clinx
144674ee30 feat(falsh): check file size limits for warm up task
with: #1000383519

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 03ae1861c7)
2025-12-24 17:01:22 +08:00
clinx
15f85f11a7 fix(flash): Double-check to prevent deleting newly created data
with: #1000379203

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 97365b5b2e)
2025-12-24 17:01:22 +08:00
clinx
7d6f427942 fix(flash): Avoid printing garbled characters
with: #1000371716

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 31e326f36d)
2025-12-24 17:01:22 +08:00
shuqiang-zheng
5251e6a78f feat(master): Record the decommission term when the dataNode is decommissioned.
close: #1000362788

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 8a0b0e5b67)
2025-12-24 17:01:21 +08:00
clinx
2a9b335268 fix(client): put interface uses custom errors to avoid obtaining pointer errors
with: #1000371716

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 578c7abb49)
2025-12-24 17:01:21 +08:00
chihe
7b045f2004 fix(client): flush as sequnce
close:#1000363069

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit d7ee0324af)
2025-12-24 17:01:21 +08:00
chihe
127bdc8899 fix(client): calculate remainsize in doMultiAheadRead
close:#1000367076

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit bea4dd6439)
2025-12-24 17:01:21 +08:00
shuqiang-zheng
2b3734bdad fix(master): fix the issue about dp marked decommission state.
close: #1000365149

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit e17f460bd2)
2025-12-24 17:01:21 +08:00
shuqiang-zheng
1c580ae8ab fix(master): display the weight and decommission type.
close: #1000362788

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit ef8d06e97e)
2025-12-24 17:01:20 +08:00
clinx
5554fe1e05 fix(flash): free allocated size after write data completed
with: #1000360870

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 61e58f7098)
2025-12-24 17:01:20 +08:00
clinx
e226b5cd07 fix(client): Remove unused time statistics fields
with: #1000359075

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 6f96108973)
2025-12-24 17:01:20 +08:00
clinx
36480cc4eb fix(client): update client dp info by master
with: #1000359075

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 5ea3b0ced5)
2025-12-24 17:01:20 +08:00
chihe
1f27e9bd37 fix(client): fix errMsg for aheadRead
close:#1000367076

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit b2498aabf3)
2025-12-24 17:01:19 +08:00
clinx
6ee91cd64c fix(flash): avoid returning network EOF
with: #1000360870

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 086034cb92)
2025-12-24 17:01:19 +08:00
clinx
b586dcd2a9 fix(flash): change the write packet size to 64K to avoid timeout
with:#1000360870

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 6e73ed2cd0)
2025-12-24 17:01:19 +08:00
chihe
49bbf008be fix(client): do not wait for async flush if stream is error
close:#1000363069

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit b5b2d3644c)
2025-12-24 17:01:19 +08:00
clinx
02f98822d1 fix(flash): set connection deadline with ctx for put
with: #1000360870

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit b07e38d8b1)
2025-12-24 17:01:18 +08:00
clinx
207f7b859a fix(flash): do not put cache miss error to warn
with: #1000360870

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 6503c0d7cc)
2025-12-24 17:01:18 +08:00
shuqiang-zheng
a721af2489 fix(master): fix issue about querying the decommissioning progress of a disk.
close: #1000362788

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 45d91e1387)
2025-12-24 17:01:18 +08:00
clinx
ed1f826956 fix(flash): print cache miss error to debug log file
with: #1000360870

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit e306c6f6fb)
2025-12-24 17:01:18 +08:00
shuqiang-zheng
f4ff24068e fix(master): fix an issue about maximum rollback count.
close: #1000359057

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 53ef100852)
2025-12-24 17:01:18 +08:00
shuqiang-zheng
8042b39daa fix(master): fix panic caused by lack of locking during concurrent access to the rafts map.
close: #1000356742

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 5635b02677)
2025-12-24 17:01:17 +08:00
shuqiang-zheng
97855da728 fix(master): fix the issue of inaccurate disk and node decommission progress due to leader changes.
close: #1000349627

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 65ac8ca7b2)
2025-12-24 17:01:17 +08:00
clinx
29052a66e7 fix(flash): free pre-allocated space after file creation
with:#1000360870

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 77eb7c264c)
2025-12-24 17:01:17 +08:00
chihe
1ce947de7b fix(clinet): shuffle the order of hosts for aheadread
close:#1000340945

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit f49728b4be)
2025-12-24 17:01:16 +08:00
clinx
02f6ab6370 fix(flash): change keyToDiskMap type
with: #1000356686

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 750ea762d1)
2025-12-24 17:01:16 +08:00
clinx
e9e4a82869 fix(flash): the master distributes the flashkeylimit value
with: #1000356686

Signed-off-by: clinx <chenlin1@oppo.com>
2025-12-24 17:01:16 +08:00
clinx
c38343e211 fix(flash): the read and write rate limit sizes using master config
with: #1000356820

Signed-off-by: clinx <chenlin1@oppo.com>

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 76dd0886b5)
2025-12-24 17:01:16 +08:00
chihe
a83b7d2678 fix(client): fix the issue with the timing of triggering the addNextTask task
close:#1000354285

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit de243a2a87)
2025-12-24 17:01:15 +08:00
Victor1319
d1291ff9f0 fix(cluster): update infos to handle discard partitions.
close:#1000355377

- Modify function signature to include ignoreDiscard parameter
- Update logic to skip discarded data partitions when requested
- Ensure compatibility with existing data node retrieval logic

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit d24e646004)
2025-12-24 17:01:15 +08:00
clinx
5561a1d3a6 fix(flash): check key limit with no wait
with: #1000355286

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit b6771c282a)
2025-12-24 17:01:15 +08:00
chihe
220d470ac2 fix(client): fixing the prefetching sliding window logic
close:#1000354285

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 5657874b3f)
2025-12-24 17:01:15 +08:00
chihe
663d97f009 fix(client): add unit test for aheadread
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 9d45588a13)
2025-12-24 17:01:14 +08:00
clinx
41aa1cf2c1 feat(flash): atomic update request result
with: #1000347719

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 52a3674321)
2025-12-24 17:01:14 +08:00
clinx
d10274f4a4 fix(flash): config client flow limit by master
with: #1000347719

Signed-off-by: clinx <chenlin1@oppo.com>
2025-12-24 17:01:14 +08:00
clinx
3aa98d5fae fix(flash): pull handleReadTimeout when flashnode start
with: #1000347719

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit dfa3e22413)
2025-12-24 17:01:14 +08:00
clinx
ea4f49f026 fix(flash): change log level to warn
with: #1000347719

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 53edbd9d19)
2025-12-24 17:01:14 +08:00
chihe
01dfa9f09e fix(client): fix bugs in partly hit scenarios of the prefetch function
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 19ea486af1)
2025-12-24 17:01:13 +08:00
dengxiaochao
d794dc4647 fix(sdk): incorrect offset when aheadread copy cacheBlock to req data buffer
@formatter:off

Signed-off-by: dengxiaochao <dengxiaochao@bilibili.com>
(cherry picked from commit a5f9ecd148)
2025-12-24 17:01:13 +08:00
clinx
6125ac66b7 fix(flash): to load blockv2 need to init key limieter
with: #1000347719

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 6685b34b2e)
2025-12-24 17:01:13 +08:00
clinx
cd4078e069 fix(client): add flow limit for object operation
with: #1000343199

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit d4c2520e8f)
2025-12-24 17:01:13 +08:00
clinx
bebe48c0ca feat(flash): add key limiter for cache read
with: #1000274394

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 951e600424)
2025-12-24 17:01:12 +08:00
shuqiang-zheng
4b3a8708ce fix(master): Optimize the reporting metrics for bad disks that fail to decommission promptly.
close: #1000336199

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit dfcc603a03)
2025-12-24 17:01:12 +08:00
shuqiang-zheng
08b78954ca fix(master): fix an issue where token might consume twice.
close: #1000336199

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 654d5bfcf2)
2025-12-24 17:01:12 +08:00
chihe
5c83c917a1 fix(client): read from leader when excuting ahead read
close:#1000340945

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit a59c4c71ed)
2025-12-24 17:01:11 +08:00
zhumingze
8960c9388e fix(master): Don't show disk decommissionSuccess alerts triggered by node decommission.
.#1000336575

Signed-off-by: zhumingze <zhumingze@oppo.com>
(cherry picked from commit 2f64db405b)
2025-12-24 17:01:11 +08:00
clinx
5f948db14a fix(cache): modify the retry logic to adapt to the first packet timeout duration
with: #1000343199

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 9808c33d84)
2025-12-24 17:01:10 +08:00
clinx
358058c74a fix(cache): improve read concurrency
with: #1000326585

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit e2b5003956)
2025-12-24 17:01:10 +08:00
Victor1319
c68437384a fix(master): enhance error handling in getVolSimpleInfo
close:#1000337685

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit f47bc8ba9e)
2025-12-24 17:01:10 +08:00
shuqiang-zheng
0663e062b8 feat(master): check vol deletion when traversing dp decommission queue.
close: #1000329496

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 37db5cf3b1)
2025-12-24 17:01:10 +08:00
shuqiang-zheng
17b991b351 feat(master): add status update records to dp decommission process for querying.
close: #1000329528

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-12-24 17:01:10 +08:00
shuqiang-zheng
eab8a04023 feat(master): add retries for ignore dataPartitions during disk decommission.
close: #1000329518

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit e1165a242e)
2025-12-24 17:01:09 +08:00
shuqiang-zheng
1c0a800f93 fix(master): add display of remainingDpCnt when querying disk or dataNode decommission progress.
close: #1000329505

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
(cherry picked from commit 83748a2a03)
2025-12-24 17:01:09 +08:00
chihe
99b040a620 fix(client): cleanup eh when flush is completed
close:#1000310987

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit d1e7e412e0)
2025-12-24 17:01:09 +08:00
chihe
1cf8acde1c fix(client): fix error for ltp
close:#1000310987

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 65c1b4a878)
2025-12-24 17:01:09 +08:00
chihe
14266c2d3e fix(client): cache blocks will not be evicted when they are not read.
close:#1000310987

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 428255293e)
2025-12-24 17:01:08 +08:00
clinx
d2d6db8824 fix(flash): set file lru size to 100000
with: #1000311735

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit f2454cab0c)
2025-12-24 17:01:08 +08:00
clinx
e4eaed9441 fix(cli): configure sameZoneTimeout via VOL for file cluster
with: #1000311735

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 19bcefeb45)
2025-12-24 17:01:08 +08:00
Victor1319
e2ef7066d7 fix(master): reset leader node stat when leader change. #1000317232
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 2b7fe94f49)
2025-12-24 17:01:07 +08:00
clinx
83b5714dc8 fix(flashnode): enhance LRU retrieval speed
with: #1000303671

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit fd5060d2ad)
2025-12-24 17:01:07 +08:00
clinx
b6b085c356 fix(client): right aligned for reading block
close: #1000303671

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 049da98617)
2025-12-24 17:01:07 +08:00
Victor1319
99e41928dd feat(cmd): add healthy and ready check url. #1000296298
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 2802e5e486)
2025-12-24 17:01:07 +08:00
Victor1319
6283610ad4 fix(meta): fix meta panic when log extent info. #1000286609
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit aae1646931)
2025-12-24 17:01:07 +08:00
clinx
57bea86ae0 fix(flash): print hanging size
with: #1000307099

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 7a249e1d99)
2025-12-24 17:01:07 +08:00
chihe
7f9177766d fix(client): do not clean extent handler if flush is async
close:#1000306048

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 70c41c1f85)
2025-12-24 17:01:06 +08:00
clinx
d9b73e6990 fix(master): set right ReducingSlots status
with: #1000307099

Signed-off-by: clinx <chenlin1@oppo.com>

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit d0410e887d)
2025-12-24 17:01:06 +08:00
clinx
7dcd384f53 fix(client): set DefaultRemoteCacheSameRegionTimeout to 20 ms
with: #1000303671

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 862c7f1171)
2025-12-24 17:01:06 +08:00
clinx
55609e0f8b fix(flash): set block allocate size equal to request length
with: #1000292905

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 91bb7d441d)
2025-12-24 17:01:06 +08:00
clinx
82d52a297d fix(master): long-term unused slot activation employs a gradual addition approach.
with: #1000292905

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit bdf08f93a5)
2025-12-24 17:01:06 +08:00
clinx
7b773fbebb fix(flash): store fg slots when slots changed
with: #1000292546

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit bdf1f207bd)
2025-12-24 17:01:06 +08:00
clinx
850bfb9305 fix(flash): record evict count on delete element
with: #1000150848

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit f10253c7a3)
2025-12-24 17:01:05 +08:00
clinx
2ce4af6a64 fix(flashnode): clean streamer resource at consumer finish
with: #1000150848

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit c3737e9b38)
2025-12-24 17:01:05 +08:00
clinx
0270edc70e fix(flashnode): cache expired data
close:#1000150848

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 2fc64021af)
2025-12-24 17:01:05 +08:00
chihe
c1638c3c16 fix(flashnode): evict stream when file is warmed
close:#1000150848

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 1f0a1dbfc3)
2025-12-24 17:01:04 +08:00
clinx
16dd2c30e0 fix(client): close conn when aysnc write failed
with: #1000293406

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 497c4cb4c2)
2025-12-24 17:01:04 +08:00
zhumingze
ff1f157f20 fix(master): add some log to locate migrate mp problem. #1000295064
Signed-off-by: zhumingze <zhumingze@oppo.com>
(cherry picked from commit f6359bf1e8)
2025-12-24 17:01:04 +08:00
chihe
1803b18700 fix(client): reduce the memory usage of the aheadRead
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
2025-12-24 17:01:04 +08:00
Victor1319
eaf52bfdaa refactor(data): refactor the usage of the buffer pool during the prefetch process. #1000048465
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 693f7e4996)
2025-12-24 17:01:03 +08:00
Victor1319
3214ae5787 refactor(fuse): refactor fuse read performance. #1000261380
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
(cherry picked from commit 6dee04aa85)
2025-12-24 17:01:03 +08:00
chihe
2c4f7630c1 fix(client): fix ltp error for async fluash
@formatter:off

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 9153aec096)
2025-12-24 17:01:03 +08:00
leonrayang
2ad10f37f0 feat(client): Add async flush, reduce the close handler time cost @formatter:off
Signed-off-by: leonrayang <changliang@oppo.com>
(cherry picked from commit 0aaead993e)
2025-12-24 17:01:03 +08:00
chihe
789acc67c5 feat(master): call sdk of flashgroupmanager
close:#1000151163

Signed-off-by: chihe <chihe@oppo.com>
2025-12-24 17:01:03 +08:00
clinx
a7acee10ec fix(flash): config init remote client timeout
with: #1000285575

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit e11e67210d)
2025-12-24 17:01:02 +08:00
clinx
763517e3c1 fix(flash): set read and write flow by master
with: #1000285575

Signed-off-by: clinx <chenlin1@oppo.com>
2025-12-24 17:01:02 +08:00
clinx
042d9a15ab fix(client): check whether the data has been fully read before reading
with: #1000286146

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit e05a97fbb1)
2025-12-24 17:01:02 +08:00
clinx
d513c94cd8 fix(flash): correct the log information
with: #1000275887

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 25b958ca13)
2025-12-24 17:01:02 +08:00
clinx
984f3daf11 fix(client): Add retry logic when an error occurs while fetching remote configuration information
with: #1000275887

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit dff1e3525b)
2025-12-24 17:01:02 +08:00
clinx
b52dc796cf fix(tool): print stat log for remote cache test tool
with:#1000275887

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 32641daf6d)
2025-12-24 17:01:01 +08:00
clinx
62eece5dc5 fix(flashnode): change the flashnode report time during leader chang #1000275887
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 94a90af9ae)
2025-12-24 17:01:01 +08:00
clinx
3f8d101613 fix(flash): adjust some log descriptions and default values
close:#1000257468

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit d7e6e6ccb1)
2025-12-24 17:01:01 +08:00
clinx
f8de40fc15 fix(flashnode): use disk path to stat capacity#1000272437
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit ff5732f1ec)
2025-12-24 17:01:01 +08:00
clinx
288ad296c7 fix(flash): print statfs error
close:#1000271802

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 880b56b124)
2025-12-24 17:01:01 +08:00
clinx
49b81bf67f fix(client): wait for caching data for read operation #1000267457
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit eb9e348047)
2025-12-24 17:01:01 +08:00
clinx
a6025f3b42 fix(client): restore connection addresses removed after network disconnection #1000267457
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 45347dee6b)
2025-12-24 17:01:00 +08:00
clinx
184b6a1535 feat(tool): remove specific key #1000250043
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 6fe627bd87)
2025-12-24 17:01:00 +08:00
clinx
abd4b9c722 fix(flashenode): Be compatible with both FUSE and SDK method invocations
close:#1000250043

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 15d6d1d3f1)
2025-12-24 17:01:00 +08:00
clinx
e49098d7a7 fix(flashnode): fix the log filename and request parameters in the URL #1000257468
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 969c554f78)
2025-12-24 17:01:00 +08:00
clinx
4cafd415d7 feat(sdk): skip processing when single Put loads insufficient data.
close:#1000151053

Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 0f3b1f8c1b)
2025-12-24 17:00:59 +08:00
clinx
b284a10680 client(sdk): read data with random#1000151053
Signed-off-by: clinx <chenlin1@oppo.com>

(cherry picked from commit 3e175326ac)
2025-12-24 17:00:59 +08:00
clinx
04243536dc client(sdk): optimize the read process #1000151053
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit 66a10d3e38)
2025-12-24 17:00:59 +08:00
baihailong
b3c5db3eee fix(sdk): conn SetReadDeadline and reader specify ctx. #1000151163
Signed-off-by: baihailong <baihailong@oppo.com>
(cherry picked from commit 8fb8ae389c)
2025-12-24 17:00:59 +08:00
chihe
625b6f1f36 fix(tools): close reader when read is completed
close:#1000151163

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit c3b0722c7a)
2025-12-24 17:00:59 +08:00
clinx
bab0f6d6a3 fix(flashnode): use the CLI to set the hot key miss count.
close:#1000150848

Signed-off-by: clinx <chenlin1@oppo.com>
2025-12-24 17:00:59 +08:00
chihe
45dcc10e6a fix(flashnode): fixed the infinite loop issue in GetObject.
close:#1000151055

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit c5e2315c7d)
2025-12-24 17:00:59 +08:00
chihe
58771c8dc2 feat(remotecache): add config tool
close:#1000151163

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 037348725c)
2025-12-24 17:00:58 +08:00
clinx
54da526123 feat(flashnode): print client reqid in server log #1000150848
Signed-off-by: clinx <chenlin1@oppo.com>

(cherry picked from commit 52142b16c2)
2025-12-24 17:00:58 +08:00
baihailong
f567742019 fix(cli): cluster info show remotecache config. #1000151055
Signed-off-by: baihailong <baihailong@oppo.com>
(cherry picked from commit f414efe63e)
2025-12-24 17:00:58 +08:00
chihe
48f600d419 feat(flashnode): add benchmark tool
close:#1000151163

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 7dee432348)
2025-12-24 17:00:58 +08:00
chihe
56b5d8960b feat(sdk): client send heartbeat to flashnode.#1000151055
Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 9c1263aa86)
2025-12-24 17:00:37 +08:00
baihailong
6e84aad323 fix(sdk): excute updateRemoteCacheConfig before UpdateFlashGroups.
close:#1000151055

Signed-off-by: baihailong <baihailong@oppo.com>
(cherry picked from commit 7e2db85306)
2025-12-24 17:00:37 +08:00
baihailong
0a5aa265de feat(flashgroupmanager): enable set remotecache config.#1000181329
Signed-off-by: baihailong <baihailong@oppo.com>
(cherry picked from commit 84192cb594)
2025-12-24 17:00:36 +08:00
chihe
3c7fb3cbec fix(sdk): enable remoteCacheClient init log.#1000151055
Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit bf87156ac3)
2025-12-24 17:00:14 +08:00
baihailong
f658776889 fix(sdk): modify get and put packet size to 32k.#1000151055
Signed-off-by: baihailong <baihailong@oppo.com>
(cherry picked from commit ff74a2a190)
2025-12-24 17:00:13 +08:00
clinx
d760b25ce1 fix(flashnode): rate limiting based on actual written data flow
close:#1000150848

Signed-off-by: clinx <chenlin1@oppo.com>

(cherry picked from commit 4320c3fc7c)
2025-12-24 17:00:13 +08:00
baihailong
23763d4219 fix(sdk): When the required read length is exceeded, reader returns EOF. #1000151055
Signed-off-by: baihailong <baihailong@oppo.com>
(cherry picked from commit bfb1440bbb)
2025-12-24 17:00:12 +08:00
clinx
72158dbc22 feat(flashnode): add metric info for put block #1000150848
Signed-off-by: clinx <chenlin1@oppo.com>
(cherry picked from commit bcb1482c32)
2025-12-24 17:00:12 +08:00
baihailong
169152fb41 feat(flashnode): support read block.#1000151055
Signed-off-by: baihailong <baihailong@oppo.com>
(cherry picked from commit c7aac8a558)
2025-12-24 17:00:12 +08:00
clinx
64b8dbf0c6 fix(flashnode): check file length using allocated size #1000150848
Signed-off-by: clinx <chenlin1@oppo.com>

(cherry picked from commit c094de085f)
2025-12-24 17:00:11 +08:00
clinx
7a02e89572 feat(flashnode): write data with 4KB alignment #1000150848
Signed-off-by: clinx <chenlin1@oppo.com>

(cherry picked from commit 24336a6bbb)
2025-12-24 17:00:11 +08:00
chihe
9e5daafdb8 feat(flashnode): support put block to flashnode #1000150848
Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 0929e28a07)
2025-12-24 16:59:50 +08:00
baihailong
e95b3c523e fix(flashgroupmanager): cluster info list all master nodes.
close#1000181329

Signed-off-by: baihailong <baihailong@oppo.com>
(cherry picked from commit 5074b878b1)
2025-12-24 16:59:49 +08:00
chihe
695d57db88 feat(flashgroupmanager): support reverse proxy
close:#1000170146

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 1334c95a9c)
2025-12-24 16:59:49 +08:00
chihe
9c561ac9e3 feat(flashgroupmaster): support raft
close:#1000167427

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit b7af94e2a4)
2025-12-24 16:59:49 +08:00
chihe
d95c94d0e8 feat(flashgroupmanager): support api for flashnode management
close:#1000154569

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 7d37d86f47)
2025-12-24 16:59:49 +08:00
chihe
7db7d4ddfc feat(flashgroupmanager): support api for flashgroup management
close:#1000153351

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 0f02785f81)
2025-12-24 16:59:49 +08:00
chihe
4497d7de7a feat(flashgroupmanager): support api service
close:#1000151163

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit e40e6c0597)
2025-12-24 16:59:49 +08:00
chihe
f538ba0612 fix(sdk): rename RemoteCacheBase to RemoteCacheClient.#1000151055
Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit c98b7cbd7e)
2025-12-24 16:59:10 +08:00
chihe
a0415ef82d enhance(sdk): refactor sdk for remotecache.#1000151055
Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit a63ec1abb6)
2025-12-24 16:58:18 +08:00
chihe
d2c12c4813 enhance(flashnode): restruct the dirctory for code
close:#1000149211

Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 22f7c23bee)
2025-12-23 16:15:17 +08:00
tan changzhi
6915dfd4b6 fix(master): expand quota id range to support more quota settings
Signed-off-by: tan changzhi <544463199@qq.com>
2025-12-16 14:30:56 +08:00
yuzhiqiang
2912760ee5 fix(blobstore): avoid unnecessary work for disabled codemodes
Signed-off-by: yuzhiqiang <yuzhiqiang_yewu@cmss.chinamobile.com>
2025-11-19 09:56:58 +08:00
yuzhiqiang
b4a41d9007 fix(blobstore): still sleeps and waits when configured to delete immediately
Signed-off-by: yuzhiqiang <yuzhiqiang_yewu@cmss.chinamobile.com>
2025-11-13 16:32:05 +08:00
Victor1319
070b82370d style(api): improve code comments for clarity and consistency. #3942
- Add spaces after comment slashes for better readability
- Standardize comment formatting across multiple files
- Enhance clarity of comments in data partition handling

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-11-11 20:23:43 +08:00
RpLi
655dfbf4d9 feature(master): Automated data distribution balance of datanode
Signed-off-by: RpLi <vsian_v@outlook.com>
2025-10-31 23:38:50 +08:00
tangdeyi
e21194a9db fix(clustermgr): fix bn oversold freechunk use in allocator
with #1000255629

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-10-30 22:30:42 +08:00
yuzhiqiang
a1bf7cc1c7 fix(blobstore): adjust the log level for specific error types
adjust the log level to reduce unnecessary log output

Signed-off-by: yuzhiqiang <yuzhiqiang_yewu@cmss.chinamobile.com>
2025-10-22 15:22:43 +08:00
slasher
e502bbbc0b fix(cli): proxy erase ALL with interval
. #21966006

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-22 14:19:26 +08:00
slasher
b758e6ae43 chore(docs): update document of access and rpc
update to blobstore v1.5.1

@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-15 10:58:51 +08:00
xiejian
8960fc7232 feat(shardnode): no need to wait apply member change when delete shards of broken disk
with #1000176986

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:49:59 +08:00
xiejian
5a0a424edb fix(shardnode): avoid concurrent map iteration and map write
when deleteSlice() failed in blob delete process

with: #1000357684

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:49:52 +08:00
xiejian
b19837d3b5 fix(shardnode): update clear trash shard task process
with: #1000362906

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:47:54 +08:00
xiejian
d936cd4284 fix(shardnode): when disk broken and volume not updated should not delete blob success
with: #1000357684

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:47:54 +08:00
mawei029
71124329b4 fix(bssdk): handle shard node client timeout error, punish with threshold
with: #1000355280

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:47:54 +08:00
mawei029
e4d5e0f8c3 fix(blobnode): update leader from new host, may need exclucde multiple disk
with: #1000348559

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:47:54 +08:00
slasher
7d153130f0 chore(testing): move mock qos file to mockblobnode
. #1000145567

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:47:54 +08:00
slasher
26f9bb3669 feat(access): update shard leader when delete message failed
. #1000306808

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:47:54 +08:00
xiejian
6ac6e515a2 fix(shardnode): blobdeleter: when no more delete msg created and then punish a msg
punish operation can't take effect

with: #1000346246

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:47:54 +08:00
mawei029
d45a599ef8 fix(blobnode): we should remove old broken disk when show progess at next round inspction
with: #1000348559

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:47:54 +08:00
mawei029
9bde9f9467 chore(blobnode): data inspect clean metric api, inspect print log
with: #1000343886

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:47:54 +08:00
slasher
29eb157da0 feat(rpc2): reuse stream of definded errors
. #1000347649

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:47:54 +08:00
mawei029
0e239bbda4 fix(bssdk): update shard node leader, need change next shard node host
with: #1000347594

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:47:54 +08:00
xiejian
43780a871a fix(shardnode): blobdeleter: 1 fix deleteStage abnormal reset
2 avoid repeated list delete messages from storage

with: #1000346246

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:47:54 +08:00
slasher
42ebc216ca fix(rpc): atomic error with all type
. #1000341010

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:47:54 +08:00
xiejian
f4b8b362ac fix(shardnode): fix not record delete stage when delete shard failed in blobdeleter
with: #1000335110

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:47:19 +08:00
xiejian
a1b9bbb10c feat(shardnode): 1.add delete log for blobdeleter, add some trace log
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
0cbe1e276b feat(shardnode): support http rpc service
with: #1000324330

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
slasher
44d2151d55 fix(trace): thread safe in trace span logging
. #1000320592

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
c998151d88 chore(blobnode): optimize unstable io pool ut tests
with: #1000334360

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
c93391332d fix(blobnode): fix data inspect mistakenly flagged bid
with: #1000322051

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
a587a62b53 feat(shardnode): support show delete blob stats
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
slasher
76310260ee feat(access): write delete message to shardnode
. #1000306808

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:35 +08:00
slasher
5a0e61dbbd chore(util): parse size in json configuration
. #1000334184

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:35 +08:00
slasher
81136e138e chore(util): alignment adds full size and blocks
. #1000334184

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
3dafd80165 feat(shardnode): support set config to kinds of time unit in json string
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
c58a38222a refactor(api): rename parse.go to proto.go
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
0b116a1097 feat(shardnode): support function for building blob name or item id with shardkeys
change shardkeys type from [][]byte to []string

with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
0d5c51eca8 fix(blobnode): when task call io pool submit, but ctx is cancel, fix return error
with: #1000309518

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
cdfce1c0ab tools(blobnode): disk drop stat check tool, support get blobnode ip from net_card
with: #1000334360

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
JasonHu520
daa85f973b fix(scheduler): update blob delete process for updating volume strategy
with: #1000304421

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
186cca127a fix(bssdk): change blob name type from bytes to string
with: #1000181642

Signed-off-by: mawei029 <mawei2@oppo.com>
Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
8704c5b061 fix(shardnode): change blob name and item id data type from bytes to string
with: #1000181642

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
75fec3ce29 chroe(blobnode): qos dynamic print log with disk id, the same target does not change
with: #1000334360

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
ac218c0fbb fix(blobnode): qos config hot modify, qos dynamic update limiter
with: #1000291897

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
bb4b64cc13 chroe(blobnode): increase the speed of ut, blobnode/core saving 30 seconds time
with:#1000334360

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
slasher
5f9600d088 chore(cli): show oversold free chunks
. #1000334184

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:35 +08:00
slasher
ad13597835 fix(proxy): proxy erase success if cache file not exist
. #21966006

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:35 +08:00
slasher
72cb5e8a87 feat(util): add Any2String and String2Any
. #1000334184

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
ed90619ed6 fix(blobnode): fix data inspect concurrent write or read map
with: #1000287722

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
3ae408e632 feat(blobnode): optimize log print, query inspect progress, record local log
with: #1000276667, #1000276672

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
39622270c8 fix(scheduler): record DiskDrop and ManualMigrate task in cache
with: #1000088302

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
JasonHu520
05c3635ff4 perf(blobnode): batch read support config timeout independently
with: #1000285347

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
9caef0e93d refactor(shardnode): rename delete_stage.go to extent_msg.go
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
59ec91cf3c refactor(shardnode): replace msg.go from base to blobdeleter
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
xiejian
a851e43681 fix(shardnode): fix bugs of delete blob process
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:35 +08:00
mawei029
d9d494ef80 feat(blobnode): dynamic update qos limiter
with: #1000260946, #1000213241

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:35 +08:00
JasonHu520
dcc95a03af fix(scheduler): fix stats interface for not response delete
and repair process with follower

with: #1000262678

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:35 +08:00
Cloudstriff
861046913b feat(util): use multi queue and thread pool to read or write data in large file
with #1000262058

Signed-off-by: Cloudstriff <chenjiong@oppo.com>
2025-10-13 15:29:35 +08:00
Cloudstriff
fece963da4 feat(util): add lightly operation IsClosed for closer
with #1000262058

Signed-off-by: Cloudstriff <chenjiong@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
06b43cac9a fix(blobnode): both woker and blobnode, need load code mode
with: #1000271469

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
4cd5060660 fix(blobnode): crc failed while repairing via batch read, should set data not ok in memory
with: #1000262678

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
e9ef158574 fix(raft): limit entries size when call storage.Entries
with: #23065907

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
4b74e874b0 feat(shardnode): support DeleteBlobRaw api, generate delete blob msg when DeleteBlob
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
84cbec67e9 feat(shardnode): init blob delete manager to support delete blob process
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
7e826ee36c feat(shardnode): add basic functions required to support the delete blob process
with: #1000042472

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
432e1bfb58 refactor(blobnode): io qos mgr refactor, bandwidth dynamic limit, refactor qos type
with: #1000150059, #1000213238, #1000213241, #1000213265, #1000150059, #1000223627

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
a4a171a966 chroe(blobnode): meta db, disk broken EIO error
with: #1000334364

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
bde4cfedda refactor(blobnode): move util iopool to blobnode base
with: #1000250443

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
tangdeyi
ae044299b3 fix(clustermgr): set volume epoch when loadData
with #1000255629

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
315a833194 refactor(blobnode): refacotr blobnode api iostat io type
with: #1000150059

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
d2eabe608c fix(blobnode): support batch download for repair in local
with: #1000247932

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
2378992e7b chroe(blobnode): disk broken EIO error, cannot allocate memory
with: #1000249055

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
b346da9385 fix(access): new span for background task
. #1000247577

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
tangdeyi
5e452b92f9 fix(clustermgr): disk cannot set broken when dropping
with #1000245746

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
5a47e79981 perf(scheduler): optimize the punish time for failed deletion
with: #1000241330

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
b32fb71320 style(proxy): add trackLog when missing cache
. #23135507

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
b959f64536 feat(cli): erase proxy cache by filter
. #1000225268

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
3c7f0b429f feat(shardnode): remove shardkeys variable in ShardOpHeader struct
with: #1000181642

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
03368f9b69 feat(bssdk): remove ShardKeys field of the structure, set shardKeys in blob name
use '{}' to mark

with: #1000181642

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
cd4bd09ff3 feat(bssdk): encode shardKeys to blob name, use '{}' to mark
with: #1000181642

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
dfd14751b1 fix(blobnode): use the core disk config after the fix InitConfig
with: #1000233594

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
a548e93f81 feat(shardnode): set shardKeys in blob name or item id, use '{}' to mark
with: #1000181642

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
tangdeyi
8a5429cb4e fix(clustermgr): fix cluster concurrent apply panic issue
with #1000223876

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
f6c563d8a5 fix(blobnode): there may be remain chunk files, when restart during compacting
with: #1000223631

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
80d64c053b chore(blobnode): adjust code of compact process , structural adjustment
with: #1000223631

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
2de4f09154 feat(rpc2): close recv and send if error in stream client
. #1000219604

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
cab906aff9 feat(trace): new span and context to run in background
. #1000201519

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
5cf9f2aa4c fix(blobnode): happen EIO when handle chunk api, return broken disk
with: #1000196614

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
c113ecfa69 refactor(blobnode): added multiple startup of disk ut individual tests
with: #1000212202

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
f12c6f5acf fix(blobnode): fix blobnode is a new disk, and cm is a old repaired disk
with: #1000197168

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
abd803d026 fix(blobnode): fix disk status broken when start up, fix close at only blobnode close
with: #1000197168

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
91b5c28222 fix(blobnode): batch read interface support read 0 bids
with: #1000211245

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
b394e82e42 fix(scheduler): init clusterID for shard disk repair mgr
with: #1000197824

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
cd4a5d8a72 fix(blobnode): disk broken, rocksdb sst file corruption
with: #1000334360

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
ad264f1da5 fix(scheduler): set kafka offset retention time to 720 hours
with #1000169074

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
9155235dcd feat(scheduler): report chunk miss migrate
with #1000088302

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
xiejian
fc8a867216 refactor(scheduler): rename volume_update.go to task.go
with #1000088302

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
c2eae16c72 feat(blobnode): add config to enable iopool feature
with: #1000194242

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
04717ce338 fix(blobnode): use config of disk instead of service
with: #1000197824

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
ed72aa7146 fix(blobnode): happen EIO when handle shard/chunk io, return broken disk
with: #1000196614

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
af2989efdf chore(blobnode): optimize trace log detail, when occur error in io
with: #1000195617

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
f42229bf27 feat(clustermgr): add configuration reserved space
. #1000192943

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
83f0b7c140 feat(blobnode): start mode split blobnode service
with: #1000159741

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
3197d47f54 feat(blobnode): put nopdata in worker repair
. #1000180877

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
ed1b827156 feat(common): add zero buffer checker
cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
BenchmarkIsZeroBuffer
BenchmarkIsZeroBuffer/1M-zero-all
BenchmarkIsZeroBuffer/1M-zero-all-4        50384       23927   ns/op  0 B/op  0 allocs/op
BenchmarkIsZeroBuffer/1M-not-zero-first
BenchmarkIsZeroBuffer/1M-not-zero-first-4  1000000000      0.4 ns/op  0 B/op  0 allocs/op
BenchmarkIsZeroBuffer/1M-not-zero-mid
BenchmarkIsZeroBuffer/1M-not-zero-mid-4    108770      10617   ns/op  0 B/op  0 allocs/op
BenchmarkIsZeroBuffer/1M-not-zero-last
BenchmarkIsZeroBuffer/1M-not-zero-last-4   48726       22504   ns/op  0 B/op  0 allocs/op

. #1000180877

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
22bb533794 chore(test): change erroris target and err
. #1000042638

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
49d847fec5 refactor(blobnode): rename worker model file
with: #1000159720

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
tangdeyi
03cebe99f1 fix(clustermgr): volume allocation optimization
1. sort vid by health when diskload is not enabled
2. sort vid by health and diskload when diskload is enabled

with #1000151206

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
408938ae13 refactor(blobnode): split shard encode process from storage to api
with: #1000135108

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
4f4da7c09d refactor(blobnode): update get shards interface
with: #1000135108

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
2f0b2b163b feat(blobnode): chunk data support batch read
with: #1000135108

Signed-off-by: slasher <shenjie1@oppo.com>
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
ab621790d8 feat(blobnode): chunk migrate and disk repair support download data in batch
with: #1000119221

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
8037070a38 feat(blobnode): add batch shard read interface for blobnode client
with: #1000118252

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
JasonHu520
349d757d79 feat(blobnode): add offset to shard info for ListShard and ShardStat interface
with: #1000118065

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
ab2bb21e70 feat(cli): force write to readonly cluster
. #1000172452

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
2352cfd075 feat(cli): support sdk in access cli
. #1000172452

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
a808adf213 test(cli): pretty print access addresses
. #1000334184

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
0fc7265d79 feat(blobnode): data inspect clean old disk metric
because already replace a new disk and use another disk id

with: #1000166344

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
cb6818c4d0 refactor(blobnode): data inspect record local incorrect bids log
with: #1000165799

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
6a9607f583 fix(blobnode): fix false positives data inspect
with: #1000025911

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
mawei029
80b069d508 refactor(blobnode): optimize io context cancel, and it has become simpler
with: #1000146037

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
390b3554b4 feat(access): add nopdata in access
. #1000117047

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
7772b9ee6b feat(blobnode): add nopdata in blobnode
. #1000117014

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
2300b0f382 feat(util): add generic math max and min
. #1000153033

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:34 +08:00
tangdeyi
44b3ab643b feat(clustermgr): report broken unit num in volume shard
with #1000151206

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-10-13 15:29:34 +08:00
slasher
bc69c2abeb perf(trace): use range function instead copy of slice
. #23135507

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
0dc16bcc09 perf(trace): cache span start options and id
Benchmark_Span_Pool
Benchmark_Span_Pool/cached
Benchmark_Span_Pool/cached-4  1656540 724.6 ns/op   48 B/op   1 allocs/op
Benchmark_Span_Pool/nocache
Benchmark_Span_Pool/nocache-4  906054  4233 ns/op 1224 B/op  17 allocs/op

. #23135507

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
ec6ee4a793 perf(trace): cache span to reduce allocation in span tracking
Benchmark_Span_Pool
Benchmark_Span_Pool/nocache
Benchmark_Span_Pool/nocache-4  506971  6923 ns/op  1520 B/op  32 allocs/op
-->
Benchmark_Span_Pool
Benchmark_Span_Pool/cached
Benchmark_Span_Pool/cached-4   732175  1585 ns/op  654 B/op  16 allocs/op
Benchmark_Span_Pool/nocache
Benchmark_Span_Pool/nocache-4  688984  3551 ns/op 1582 B/op  23 allocs/op

Benchmark_Span_TrackLog
Benchmark_Span_TrackLog/duration-any
Benchmark_Span_TrackLog/duration-any-4    16785505  70.35 ns/op  0 B/op  0 allocs/op
Benchmark_Span_TrackLog/duration-second
Benchmark_Span_TrackLog/duration-second-4 18425104  64.40 ns/op  0 B/op  0 allocs/op
Benchmark_Span_TrackLog/duration-error
Benchmark_Span_TrackLog/duration-error-4  17530114  65.82 ns/op  0 B/op  0 allocs/op

. #23135507

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
ac1e84bf0b perf(trace): avoid to allocate option struct in span tracking
from:
Benchmark_Span_TrackLog
Benchmark_Span_TrackLog/duration-any
Benchmark_Span_TrackLog/duration-any-4      7892170  457.1 ns/op  40 B/op  3 allocs/op
Benchmark_Span_TrackLog/duration-second
Benchmark_Span_TrackLog/duration-second-4  10384854  113.5 ns/op  28 B/op  3 allocs/op
Benchmark_Span_TrackLog/duration-error
Benchmark_Span_TrackLog/duration-error-4    5301676  500.1 ns/op  80 B/op  6 allocs/op

to:
Benchmark_Span_TrackLog
Benchmark_Span_TrackLog/duration-any
Benchmark_Span_TrackLog/duration-any-4     11378097  97.32 ns/op  16 B/op  1 allocs/op
Benchmark_Span_TrackLog/duration-second
Benchmark_Span_TrackLog/duration-second-4  17787051  211.9 ns/op  24 B/op  3 allocs/op
Benchmark_Span_TrackLog/duration-error
Benchmark_Span_TrackLog/duration-error-4    9427880  189.0 ns/op  40 B/op  3 allocs/op

. #23135507

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
ad4e8b0f9f perf(util): format int to string with function outlining
BenchmarkUtilFormatInt
BenchmarkUtilFormatInt/format
BenchmarkUtilFormatInt/format-4   100000000  13.48 ns/op  0 B/op  0 allocs/op
BenchmarkUtilFormatInt/strconv
BenchmarkUtilFormatInt/strconv-4   21880332  92.22 ns/op  7 B/op  1 allocs/op

. #23135507

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
mawei029
076de2685d refactor(blobnode): remove unused switch reAddDisk
with: #1000025913

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
823d3f3a0c pref(rpc2): _gc_ reuse objects in rpc2
. #23113571

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
e5125b59c4 pref(rpc2): _gc_ reuse objects in transport frames
. #23113571

cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
BenchmarkAcceptClose
BenchmarkAcceptClose  276475   5393 ns/op  904 B/op  7 allocs/op
BenchmarkConnSmux
BenchmarkConnSmux      39103  31170 ns/op  121 B/op  0 allocs/op
BenchmarkPipeSmux
BenchmarkPipeSmux      90400  13771 ns/op    6 B/op  0 allocs/op
BenchmarkConnTCP
BenchmarkConnTCP       61194  18310 ns/op    0 B/op  0 allocs/op
BenchmarkRangedWrite
BenchmarkRangedWrite  242226   5230 ns/op   24 B/op  0 allocs/op

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
a793d19ce0 pref(rpc2): _gc_ reuse objects in transport allocator
. #23113571

cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
BenchmarkMSB
BenchmarkMSB         172919274   6.938 ns/op  0 B/op  0 allocs/op
BenchmarkAllocator
BenchmarkAllocator    38689362  31.63  ns/op  1 B/op  0 allocs/op
BenchmarkBufferRing
BenchmarkBufferRing     278162    4190 ns/op  0 B/op  0 allocs/op

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
50c3e4b4e8 fix(rpc2): write limited body to reader
. #1000334184

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
7fcb5c327a feat(blobnode): ranged read with aligned buffer
. #22951605

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
7f8a4916d8 feat(util): alignment size's head and padding tail
. #22984144

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
d00703a458 feat(transport): add ranged writer of frame
. #22922156

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
a2c0dfbadc feat(transport): add flag error for writing to next frame
. #22922145

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
7fcee0e46f feat(rpc2): aligned checksum buffer in request and response body
saving bytes in small en-decode body

. #22922123 #22922136

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
d54ac862f5 feat(transport): allocated buffer with frame header and aligned address
. #22922112

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
8c156972a8 chore(testing): move mock files to testing all
. #1000145567

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
ad3442a467 chore(testing): move mock files to testing shardnode
. #1000145567

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
61c2e882fb chore(testing): move mock files to testing clustermgr
. #1000145567

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
0ab1c039a0 chore(testing): move mock files to testing proxy
. #1000145567

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
JasonHu520
e0f47a5037 feat(scheduler): unlock volume support volume epoch
with: #1000131117

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:33 +08:00
tangdeyi
3cebf9fdbf feat(clustermgr): lock unlock volume support epoch
with #1000102800

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-10-13 15:29:33 +08:00
JasonHu520
f2bd5dc417 fix(raft): should check header of snapshot request
with: #1000100262

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
6506cab835 feat(common): add extend codemode
. #1000111154

close .3773 .3767

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
slasher
3d00ed9baf feat(rpc2): add wait queue in client
. #1000106546

Signed-off-by: slasher <shenjie1@oppo.com>
2025-10-13 15:29:33 +08:00
JasonHu520
9d8ec7c880 feat(raft): multi-raft build transport based on rpc2 stream mode
with: #1000100262

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-10-13 15:29:33 +08:00
linfangrong
eba36c1d01 fix(client): Fixed issues #3935 readdir offset
Signed-off-by: linfangrong <linfangrong.liuxin@qq.com>
2025-09-28 11:15:52 +08:00
linfangrong
785e55476c fix(client): Fixed issues #3935 readdir offset
Signed-off-by: linfangrong <linfangrong.liuxin@qq.com>
2025-09-28 11:15:52 +08:00
linfangrong
77940d0e53 fix(client): Fixed issues #3935 readdir offset
Signed-off-by: linfangrong <linfangrong.liuxin@qq.com>
2025-09-28 11:15:52 +08:00
linfangrong
b8c65c199c fix(client): Fixed issues #3935 readdir offset
Signed-off-by: linfangrong <linfangrong.liuxin@qq.com>
2025-09-28 11:15:52 +08:00
zhangjianwei2
b6c48c5a4e fix(common): correct kafka monitor error log for blobstore
Signed-off-by: zhangjianwei2 <zhangjianwei2_yewu@cmss.chinamobile.com>
2025-09-19 15:22:05 +08:00
Zhaohu Xing
69fae6c622 docs(cache): add cluster and vol parameters to config table
Signed-off-by: Zhaohu Xing <x.zhaohu@gmail.com>
2025-09-18 14:15:53 +08:00
steve.wei
e55a6b71d1 refactor(sdk): rename the variable parentMp to mp in the function getMembersFromMp
Signed-off-by: steve.wei <coderushing@gmail.com>
refactor: Rename the variable parentMp to mp in the function getMembersFromMp

Signed-off-by: steve.wei <coderushing@gmail.com>
2025-09-15 10:26:34 +08:00
JasonHu520
b4309236a2 fix(rpc): timeout with response in rpc client for timer reset
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-09-11 10:06:55 +08:00
slasher
d076024883 fix(rpc): timeout with response in rpc client
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-09-05 12:15:07 +08:00
mawei029
34663a6fd7 fix(blobnode): fix data inspect goroutine leak
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-09-04 15:54:03 +08:00
zhangjianwei2
4ddfc37d3f fix(bssdk): stream parameter hierarchy of sdk is inconsistent with access
fixes: https://github.com/cubefs/cubefs/issues/3920

Signed-off-by: zhangjianwei2 <zhangjianwei2_yewu@cmss.chinamobile.com>
2025-09-01 17:20:17 +08:00
yuzhiqiang
e578ed054d fix(blobstore): fix typo
Signed-off-by: yuzhiqiang <yuzhiqiang_yewu@cmss.chinamobile.com>
2025-09-01 17:03:40 +08:00
mawei029
7a18c4c20d fix(blobnode): need check write n at datafile, may be ctx is cancel
with: #1000309518

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-09-01 10:17:05 +08:00
mawei029
b7c1606fa2 fix(blobnode): qos limit read io concurrence overload
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-09-01 10:17:05 +08:00
dengxiaochao
0ef70c8d48 fix(sdk): incorrect offset when aheadread copy cacheBlock to req data buffer
Signed-off-by: dengxiaochao <dengxiaochao@bilibili.com>
2025-09-01 08:55:55 +08:00
linfangrong
0da75080fe fix(client): Fixed issues #3586 readdir offset
Signed-off-by: linfangrong <linfangrong.liuxin@qq.com>
2025-08-22 11:17:07 +08:00
yuzhiqiang
66d45dba3b fix(blobstore): remove the minimum value limit
In some specific scenarios, a smaller alloc_retry_interval_ms value
needs to be set, so the minimum value limit is removed.

Signed-off-by: yuzhiqiang <yuzhiqiang_yewu@cmss.chinamobile.com>
2025-08-22 10:05:28 +08:00
NaturezzZ
0a9673f266 fix(master): add retry to syncSendAdminTask to handle transient error
Signed-off-by: NaturezzZ <naturezzz@outlook.com>
2025-08-15 10:39:58 +08:00
aaronwu2010
310badc752 docs(docs): Add 7 FAQ cases.
Signed-off-by: aaronwu2010 <huochengwu@qq.com>
2025-08-14 14:19:50 +08:00
yuzhiqiang
2e4c46a4fb feat(blobstore): add compress option to log configuration
Since the lumberjack package has a compression option,
this option is also added to the log configuration.
The default value is false, and it is up to the user to decide whether to enable it.

Signed-off-by: yuzhiqiang <yuzhiqiang_yewu@cmss.chinamobile.com>
2025-08-14 11:36:51 +08:00
zhumingze1108
2f8f2f92a7 fix(sdk): gofmt v3.5.2 for mege to master
Signed-off-by: zhumingze1108 <zhumingze@oppo.com>
2025-08-11 20:21:42 +08:00
zhumingze
6d7ed87406 docs(docs): update yum.md for v3.5.2
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:20 +08:00
zhumingze
65cb06469f docs(docs): update changelog for v3.5.2
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:20 +08:00
clinx
432ae228b6 feat(docs): add docs about 3.5.1
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 17:21:20 +08:00
zhumingze
4f0935dccb docs(docs): Modify the docs according to v3.5.2
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:20 +08:00
shuqiang-zheng
c2120b249a fix(master): reported bad disk not complete decommission timely metric.
close:#1000242504

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:20 +08:00
zhumingze
77156bdb08 fix(master): Fixed the problem of repeated execution of disk decommission. #1000247984
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:20 +08:00
zhumingze
ea04e20415 fix(data): Determine the disk lost based on master and locally loaded Dp information
. #1000244723

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:20 +08:00
shuqiang-zheng
5229b942f0 fix(master): ignore dp that has the same srcAddr but are in the autoAddReplica status.
close:#1000242504

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:20 +08:00
shuqiang-zheng
5f458b8ff5 fix(master): remove the interface that resets the decommission state of the disk to avoid misuse.
close:#1000242504

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:20 +08:00
zhumingze
4f0b89ebb6 fix(data): Fix autoComputeCRC log issue. #1000232936
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:20 +08:00
zhumingze
69c99eb657 fix(master): Optimize fileStats related interfaces. #1000240718
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:19 +08:00
shuqiang-zheng
d22301841b fix(master): support adjusting the weight of the previous decommission.
close:#1000234137

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:19 +08:00
clinx
fb36f0f98b feat(flashnode): submit warm up task by http interface#1000150848
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 17:21:19 +08:00
clinx
24baf89ef5 feat(flashnode): specify the number of origin-fetching goroutines
. #1000150848

Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 17:21:19 +08:00
clinx
bb950063e8 fix(client): use heartbeat ping flashnode #1000151053
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 17:21:19 +08:00
chihe
76cb9a6742 feat(client): add the forceRemoteCache configuration
close:#22957483

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:19 +08:00
chihe
59016a67cb fix(client): do not remove context when dir is released
close:#21990545

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:19 +08:00
chihe
e0aa65f740 fix(flashnode): modify mem_stat for reading from dataNode
close:#23109728

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:19 +08:00
chihe
17165dc792 fix(client): do not remove node cache when dir is released
close:#21990545

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:19 +08:00
Victor1319
8b0aeef378 refactor(master): limit the interval between deleteing mp replica to 5 minutes. #1000230481
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:19 +08:00
Wu Huocheng
6fb8c5c280 chore(master): delete unsave count and calculate freeze count realtime.#1000230160
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:19 +08:00
shuqiang-zheng
8f8d7d6f5a fix(master): fix possible deadlocks during dp decommission.
close:#1000231787

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:19 +08:00
shuqiang-zheng
44cd11860e fix(master): modify dp decommission failure retry interval to 5 minutes.
close:#1000219034

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:19 +08:00
Wu Huocheng
503a930226 fix(metanode): replace runtime.GC with debug.OsFreeMemory.#1000228535
The runtime.GC may cause metanode lose heartbeat.

Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:19 +08:00
zhumingze
3264a846e5 fix(master): fix log and interface display issues. #1000230771
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:19 +08:00
Victor1319
ff65346f7b fix(master): check raft leader before handle leader change. #1000228487
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:19 +08:00
Victor1319
4dc8da9159 fix(master): set max limit as one year for trash interval. #1000227134
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:19 +08:00
leonrayang
91f6884901 revert(client): Add a log that records information about unsupported requests #23059813
This reverts commit ae352f498a.

Signed-off-by: leonrayang <changliang@oppo.com>
2025-08-11 17:21:19 +08:00
leonrayang
a84e88d7f9 feat(cli): Add tool to obtain partition information that not distributed in the same failure domain
. #1000227252

Signed-off-by: leonrayang <changliang@oppo.com>
2025-08-11 17:21:19 +08:00
shuqiang-zheng
58e8451fbe fix(master): modify the period of checking dp repairing status of background goroutine to 5 minutes.
close:#1000158166

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:19 +08:00
shuqiang-zheng
03112ff534 fix(master): fix the issue that newly created dp may falsely report dp no same peer.
close:#1000155538

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:19 +08:00
shuqiang-zheng
62a30aa9af fix(master): fix decommission target nodeSet problem.
close:#1000219643

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:19 +08:00
Victor1319
9b3023e788 refactor(master): classify DP anomaly alerts by media type. #1000196022
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:19 +08:00
Victor1319
d6f98b4fe6 refactor(master): support report zone, set info for node metrics. #1000138242
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:19 +08:00
Victor1319
76ea9434ea fix(client): avoid client nil point panic. #1000225195
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:19 +08:00
zhumingze
d2c97826a1 fix(meta): fix log problem. #1000223743
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:19 +08:00
zhumingze
50177fae9f fix(master): Optimize the judgment conditions when the bad disk is automatically decommission
. #1000223743

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:19 +08:00
Wu Huocheng
ff730e220a fix(master): check the migrate plan destination not in mp hosts.#1000222192
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:18 +08:00
zhumingze
e91577b8b8 fix(cli): Skip non-existent mp when printing. #1000217026
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:18 +08:00
zhumingze
18e49cd01d fix(master): Optimize TestStrawNodeSelector test case. #1000217026
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:18 +08:00
zhumingze
72d8e176af fix(master): Optimize disk decommission command and add boundary conditions. #1000217026
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:18 +08:00
Wu Huocheng
1be6fb6283 fix(master): add the new free list size.#1000221718
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:18 +08:00
wu huocheng
9d7e341a8b chore(master): update the unit test codes.#1000218883
Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:18 +08:00
Wu Huocheng
8df607c853 fix(master): select another meta node as leader.#1000218883
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:18 +08:00
Wu Huocheng
22a6f7928a fix(master): avoid to migrate meta partition to no writable node.#1000218883
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:18 +08:00
shuqiang-zheng
9bdd8580a9 fix(master): retry counts on dp decommission rollback should be after the judgment retry interval.
close:#1000219034

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:18 +08:00
shuqiang-zheng
e39e185356 fix(master): show dp of missing tiny extent when cli performs data partition checking.
close:#1000059418

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:18 +08:00
shuqiang-zheng
1ed3393568 fix(master): decommissionFailed dp may rejoin the decommission queue after changing the leader.
close:#1000215464

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:18 +08:00
Victor1319
464d7c5d1b fix(master): return rdonly status for metanode get api. #1000218177
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:18 +08:00
Victor1319
7b7dacb066 fix(master): check nil poniter when load flash task. #1000218177
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:18 +08:00
Victor1319
0a6b6b0804 fix(meta): Compatible with cache read scenarios. #1000218172
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:18 +08:00
zhumingze
e63be46cc0 fix(util): Optimizing dataNode oplog test case. #1000216688
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:18 +08:00
zhumingze
0aabac43db fix(all): Downgrade some log levels from error to warn. #1000202936
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:18 +08:00
leonrayang
811e0fbd70 feat(client): Add a log that records information about unsupported requests #23059813
Signed-off-by: leonrayang <changliang@oppo.com>
2025-08-11 17:21:18 +08:00
leonrayang
ef98cb989c fix(master): Reduce the warning logs generated by the UID process.#23059813
Signed-off-by: leonrayang <changliang@oppo.com>
2025-08-11 17:21:18 +08:00
Wu Huocheng
2145fa9ec4 fix(master): Add freeze meta partition stage two.#1000208370
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:18 +08:00
shuqiang-zheng
8fcdae734f fix(master): optimize log output for failed cancellation of decommission.
close:# 1000167790

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:18 +08:00
shuqiang-zheng
cec0f97a76 fix(master): fix that canceling decommission will block the subsequent automatic decommission.
close:#1000191419

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:18 +08:00
shuqiang-zheng
175ee90983 feat(master): the dp decommission supports specifying the target nodeSet.
close:#1000211002

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:18 +08:00
shuqiang-zheng
9b3f91b475 fix(master): remove the number limit of retries to ensure dp canceling decommission successful.
close:#1000209481

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:18 +08:00
zhumingze
f41ab87b0b fix(cli): skip not exist mp in check abnomral raft mps in cli. #1000203274
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:18 +08:00
Victor1319
ddde96c5f6 refactor(data): modify punch hole sync size to 128M for tiny extent. #1000212704
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:18 +08:00
Victor1319
640613aa7e refactor(master): add log when check mp status. #1000207169
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:18 +08:00
zhumingze
74385744ef fix(master): skip decommissionSuccessDisk in Autodecommision. #1000209481
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
d63f4fb662 fix(master): skip discard dp in checkDataReplicaMeta. #1000210172
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
0d4899662e fix(meta): Fix meta panic caused by fileStats. #1000183416
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
Wu Huocheng
265ad9774d fix(master): set metanode readonly before offline.#1000207388
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:17 +08:00
Victor1319
71a40e5874 fix(client): exit ahead read goroutine once stream is closed. #1000207169
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
108b69cd68 fix(master): Fix badPartition judgment problem. #1000207367
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
shuqiang-zheng
052bc84df8 fix(master): fix dp restore failure due to datanode not found.
close:#1000155538

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:17 +08:00
shuqiang-zheng
a5dc2d3abe fix(master): add a lock ensures that dp's DecommissionDiskRetryMap is thread-safe..
close:#1000188341

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:17 +08:00
shuqiang-zheng
3cd03545ef fix(master): DecommissionFirstHostDiskParallelLimit default value set to 10.
close:#1000041775

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:17 +08:00
shuqiang-zheng
fd7976866c fix(master): fix decommission priority problems.
close:#1000197987

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
bde40fb283 fix(master): Fix log print problem. #1000205234
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
dcedbe6397 fix(cli): Fix cli Incomplete printing problem. #1000203274
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
30f81f1575 fix(data): Fix data log problem. #1000202936
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
de8d81a807 fix(master): Fix dp decommission rollback issue. #1000203360
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
Victor1319
a77a5cce01 fix(smux): use stop chan to sync request fail status. #1000193713
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
b2f54cfa25 fix(data): print repairing error when reading a repairing dp copy encounter error. #1000196321
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
zhumingze
bf417dadce fix(client): Fix log related issues. #1000200359
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:17 +08:00
Victor1319
d7610f1f1d fix(flashnode): check reply size and data cap. #1000200376
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:17 +08:00
Victor1319
6dabb8774c fix(client): refactor client eio monitor reporter. #1000182431
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:17 +08:00
clinx
8bc784762a feat(client): added newline characters#23068759
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 17:21:17 +08:00
clinx
854a40f92c feat(client): print cache size in stat file #23068759
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 17:21:17 +08:00
Victor1319
6dcbb1a8c1 refactor(client): not report eio when write file not exist. #1000159871
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:17 +08:00
baihailong
f707cf9ac0 fix(client): no need to report metric when read size less than expect.#22186923
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:17 +08:00
baihailong
b3bfa2d127 fix(sdk): enable limit frequency,readDirLimit,batchInodeSize when RefreshSummary_ll.#23042874
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:17 +08:00
baihailong
7cdf8c0f62 fix(sdk): optimize getsummary timeout and batch set xattr
. #23042874

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:17 +08:00
baihailong
ebbc9c35a5 fix(clientmeta): remove client enableSummary and meta not support UpdateXAttr.#23129966
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:17 +08:00
baihailong
c954437422 fix(sdk): adapt old summary info.#23077560
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:17 +08:00
baihailong
dada328d8f fix(sdk): quotacache goroutime not exited when metawapper closed.#23077560
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:17 +08:00
baihailong
1c288fe4e5 fix(sdk): add some log.#23042874
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:17 +08:00
baihailong
c261a8cfcf fix(tool): optimize tool get access files info.#23042874
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:16 +08:00
baihailong
c3fccbccae fix(sdk): Adapt summaryinfo compatibility.#22890657
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:16 +08:00
baihailong
9df70e795e fix(sdk): optimize refresh summary for tool.#22890657
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-11 17:21:16 +08:00
Victor1319
4c38eabeb8 refactor(client): support config stream reqChan Size. #23114335
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:16 +08:00
chihe
7b79861165 fix(client): Do not delete cache when released for trash rebuilding
close:#21990545

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:16 +08:00
zhumingze
87eaebb8c2 feat(client): Improve the penalty mechanism for near read failure. #1000150366
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:16 +08:00
zhumingze
83cad776a7 fix(master): Fix the issue of noleader rollback retry time being very short. #1000198013
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:16 +08:00
Victor1319
b069b5f51b fix(smux): check frame state before write data to session. #1000193713
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:16 +08:00
Victor1319
809d023e9e refactor(vendor): user smux in depends to replace pkg in vendor. #1000193713
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
83c019a1a0 fix(master): fix the problem that weight can be less than 0 when perform decommission.
close:#1000196526

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
3caa52827a fix(master): fix the problem that totalDpCnt shows -1 when querying decommission status of disk
close:#1000194870

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
d9a2e6dc7e fix(master): add a map to save decommission retries for dp on different disks.
close:#1000188341

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
c631fb5325 fix(master): fix that FirstHostDiskParallelLimit may be set to 0 during first upgrade of cluster.
close:#1000041775

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
Victor1319
5ea53eb575 fix(data): update extent size after load from disk. #1000182163
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
999f2989ac fix(master): fix panic caused in build heartbeat response after loading broken disk.
close:#1000191783

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
zhumingze
7cc6f6f361 fix(meta): Add logs to troubleshoot meta panic. #1000183416
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:16 +08:00
zhumingze
b13b4ec849 fix(cli): Add separate display dpCnt according to mediaType for cli volume. #1000177017
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:16 +08:00
chihe
179bbe3bd5 fix(client): if it exceeds the quota, delete it directly
close:#1000153130

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:16 +08:00
chihe
990579e3cf fix(client): revert node cache
close:#1000123511

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
c819f23f33 fix(master): fix thread safety issue caused by unused locks in canceling decommission.
close:#1000167790

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
zhumingze
1c2acad05a fix(client): Adjust some log levels to warn. #1000187434
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:16 +08:00
zhumingze
12895d975f feat(meta): Add readDir iops limiter. #1000187434
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:16 +08:00
Wu Huocheng
b5b43f7ea3 chore(master): add meta partition and replica migrating plan message.#1000182330
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
b258e285f2 fix(master): fix the problem of disk not found when using cli to query disk information.
close:#1000188189

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
916b91977f fix(master): add displaying totalDpCnt in queryAllDecommissionDisk.
close:#1000187922

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
465976624b fix(master): fix the problem that bad disk may not be able to be recovered due to a non-existent dp.
close:#1000186419

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:16 +08:00
shuqiang-zheng
cfef0e0d5c fix(master): fix decommission problems
close:#1000183623

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:15 +08:00
shuqiang-zheng
a9d4ceafca fix(master): fix issues related to canceling disk decommission.
close:#1000167790 #1000156518 #1000160979

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
2aa2dace82 refactor(sdk): user readdir limit to implement readdir only api.#1000187177
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
2d622c907d fix(meta): msg sent back to the master process async to prevent blocking the connection
. #1000187177

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
886c93c180 fix(meta): check and rename old raft dir if exist. #1000187608
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
c3ad0e837a fix(master): skip empty addr when remote dp raft member. #1000186190
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
9e9eb0e753 fix(data): bad disk judgment logic fix. #1000184384
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
33c6e2d96d fix(data): limitIO ​​logic fix. #1000158099
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
41e6934a4c fix(master): limit the last dp replica can't be deleted. #1000182796
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
6702a0240a fix(cli): Add raftForceDel parameter for disk decommission. #1000181775
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
b7cc2f2b8a fix(cli): Add logs for loacting problem. #1000158099
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
9bb5598edf fix(data): retry repair directly for tiny empty recover offset check. #1000173499
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
cc29b3c706 refactor(meta): add warn log for mp create . #1000182796
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
e4b0d9a4ea fix(data): check extent store whether closed before tiny extent recover. #1000182163
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
d624108ddc fix(data): fix panic while create datapartition. #1000173883
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
d0fa18a24e fix(cli): cli adds the function of displaying the number of DPs of different media
. #1000177017

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
fafbd6c86b fix(master): Add deleting decommisionDisk records function for reloadDisk and deleteLostDisk
. #1000172911

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
chihe
6533102b0d fix(client): fix log error
close:#1000160727

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:15 +08:00
chihe
f0fc00932e fix(client): readdir call readirLimit
close:#1000150030

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 17:21:15 +08:00
Victor1319
dce30cb1c5 refactor(data): refactor extent has been deleted log. #1000133844
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
4034350ab6 fix(data): selectDisk skip lost disk. #1000173883
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
zhumingze
111956c970 fix(cli): Fix cli datapartition check display issue. #1000171648
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:15 +08:00
Wu Huocheng
6397233158 fix(master): offline metanode with correct mp count.#1000176933
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:15 +08:00
shuqiang-zheng
26cb520f37 fix(master): remove the logic of directly deleting diskErr replicas in dp metadata restore.
close:#1000164568

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:15 +08:00
shuqiang-zheng
d38270ebc9 fix(master): clear the repairingStatus when removing the raft member.
close:#1000164568

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:15 +08:00
shuqiang-zheng
ed53a80882 fix(master): fix repairingStatus problem.
close:#1000164568

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:15 +08:00
shuqiang-zheng
9120e071f5 fix(master): fix decommission problems
close:#1000161678

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:14 +08:00
shuqiang-zheng
ffb1ffed1b fix(master): fix panic that occurs during master execution of dp decommission.
close:#1000163454

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:14 +08:00
shuqiang-zheng
45b30b14ca fix(master): fix that dp decommission traversal process cannot exit in time.
close:#1000162591

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 17:21:14 +08:00
leonrayang
c7026c1af3 fix(master): Forbid unInited uidSpaceManager be used in testCase #1000112797
Signed-off-by: leonrayang <changliang@oppo.com>
2025-08-11 17:21:14 +08:00
leonrayang
901614ae0b feat(metanode): Add interface of reloadMp to enable online reload metapartition #1000171136
Signed-off-by: leonrayang <changliang@oppo.com>
2025-08-11 17:21:14 +08:00
leonrayang
7d5ad3adf4 feat(metanode): Add raft members consistent check with master hosts in metanode member check
. #1000165698

Signed-off-by: leonrayang <changliang@oppo.com>
2025-08-11 17:21:14 +08:00
Wu Huocheng
e944cecec5 chore(master): remove unnecessary message.#1000173254
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:14 +08:00
Wu Huocheng
b24b2afd46 fix(master): create part plan for cross zone mp.#1000169625
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:14 +08:00
Wu Huocheng
443770c908 fix(metanode): skip the deleted inodes.#1000172889
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:14 +08:00
zhumingze
1bc5ce41a5 docs(docs): Modify the documentation description of the recommission command. #1000155113
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:14 +08:00
zhumingze
db66d12cca fix(cli): Display DP of different decommission types separately. #1000169635
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:14 +08:00
Wu Huocheng
055123bce7 fix(master): allow to create part of migrate plan.#1000169625
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:14 +08:00
zhumingze
f04b0218c4 fix(master): Added error message when datanode does not exist during addReplica. #1000165052
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:14 +08:00
zhumingze
24390e05c6 fix(client): Fix the panic when the read process prints string. #1000163463
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:14 +08:00
zhumingze
b73b063598 fix(data): Limit asynchronous read and write iocc to 100. #1000167799
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:14 +08:00
Wu Huocheng
f5be071244 fix(master): loopback checking mp status and add error message.#1000160843
1. Skip the no leader status and continue the loop back checking mp status.
2. Add plan msg to display error information.

Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-11 17:21:14 +08:00
zhumingze
e3a4a71afa fix(master): Add error handling when the decommissionSuccess or decommissioned record not exist
. #1000162948

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-11 17:21:14 +08:00
Victor1319
2729a407c7 fix(meta): start freelist after init objMetaWrapper. #1000161320
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:14 +08:00
Victor1319
733768afef refactor(lcnode): skip extent not found error when migrate. #1000112446
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:14 +08:00
Victor1319
5b2d09c4d3 refactor(fmt): use gofumpt to format code. #1000063488
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-11 17:21:14 +08:00
slasher
add196d0cf chore(util): using newest bytespool
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-08-11 12:49:58 +08:00
clinx
c4124a35fa fix(client): add audit log for unknown region host #1000075110
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 12:49:58 +08:00
clinx
5ee4050950 fix(client): add audit log for cross region host #1000075110
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 12:49:58 +08:00
clinx
7cae3a1114 fix(flashnode): show empty stat #1000021930
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 12:49:58 +08:00
clinx
a8de2526c7 fix(flashnode): show empty stat #1000021930
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 12:49:58 +08:00
shuqiang-zheng
33935843d9 feat(meta): Support for dynamic adjustment of gogc.
close:#1000011090

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-11 12:49:58 +08:00
clinx
372eb7c979 fix(master): prevent reentrant locking #22935828
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-11 12:49:58 +08:00
chihe
d904281f22 fix(bcache): reduce memory consumption for bcache-service
close:#22775703

Signed-off-by: chihe <chihe@oppo.com>
2025-08-11 12:49:58 +08:00
slasher
525e70cdf5 feat(flashnode): add service of flashnode
. #22115361 #22200518 of #21957840

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-11 12:49:57 +08:00
zhumingze1108
07b6632686 fix(master): gofmt v3.5.2 for merge to master
Signed-off-by: zhumingze1108 <zhumingze@oppo.com>
2025-08-08 15:03:51 +08:00
Victor1319
8385bf3e0c refactor(client): Limit prefetching to use at most one-third of the memory. #1000160740
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:32 +08:00
Victor1319
fc05b1d503 refactor(all): remove cache rule and cache threshold. #1000142823
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:31 +08:00
Victor1319
bb22d0d0c9 refactor(meta): not output error log for not exist error. #1000139297
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:31 +08:00
Victor1319
e490c4c890 refactor(master): not empty when lc MinSize is zero. #1000144582
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:31 +08:00
Victor1319
fbec0bf690 fix(sdk): rafactor error msg when get partition 0 failed. #1000150298
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:31 +08:00
Victor1319
3b09c5205d fix(meta): getExtents func not update inode self. #1000152321
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:31 +08:00
Victor1319
a20e91c651 refactor(client): not report eio for extent not found error. #1000123658
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:31 +08:00
Victor1319
71002fbcf0 refactor(client): report not support error for notsup error code. #1000121097
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:31 +08:00
zhumingze
8f6bc07b66 fix(cli): Add logs for locating problem. #1000158099
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:31 +08:00
shuqiang-zheng
c8176fc7fc fix(master): add upper and lower limit judgment when setting gogc value
overwrite is been allowed when dp decommission.

close:#1000011090 #1000161090

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:31 +08:00
shuqiang-zheng
94ff433984 fix(master): set the repairingStatus of dp via raft.
close:#1000158166 #1000158134

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:31 +08:00
Wu Huocheng
40ddcaafe0 fix(master): correct the final array content.#1000148697
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:31 +08:00
zhumingze
818b47eb85 fix(cli): Add description of the use of the cli recommission command. #1000155113
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:31 +08:00
zhumingze
cadef3627a fix(data): Change the log level of dp not exist in repl_protocol from error to warn. #1000157333
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:31 +08:00
shuqiang-zheng
1ca22fc68c fix(master): clear the cache of recorded firstHostToken when master leader changes.
close:#1000157935

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:31 +08:00
Wu Huocheng
78e8d449d9 chore(master): Change paramters name.#1000148697
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:31 +08:00
Wu Huocheng
11fcaabaa0 fix(master): the value of final host is the same as mp.Hosts.#1000148697
The final hosts should be copied with new array.

Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:31 +08:00
Wu Huocheng
897470893e fix(master): change the leader before migrate meta partition.#1000147101
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:31 +08:00
shuqiang-zheng
a35f51ba73 fix(master): extent deletion and business writes are forbidden when dp is repair.
close:#1000121688

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:31 +08:00
shuqiang-zheng
67fd938f90 fix(master): set all replicas of dp to repairingStatus during dp decommission repair.
close:#1000121688

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:31 +08:00
shuqiang-zheng
36118447cd fix(master): modify alignment logic for new replica decommission progress to improve accuracy.
close:#1000121688

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:31 +08:00
shuqiang-zheng
72089c6f0c fix(master): fix issue caused by resetting decommissionRunning state.
close:#1000144597

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:31 +08:00
zhumingze
a144b60824 fix(master): Fix the garbled problem of printing logs #1000152748
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
68eb8fe774 fix(master): Fix request access information distortion caused by master switching leader.
. #1000152794

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
b74b3fa74e fix(objectnode): fix incorrect statusCode when creating volume in objectnode. #1000146602
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
15b24c6d0e fix(master): fix create dp timeout problem when create vol. #1000145610
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
chihe
4373c0ae18 fix(client): remove random wait for trash
close:#1000150030

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
71dee686ef feat(data): limitIO strategy for separating repair io from business io. #1000095860
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
Wu Huocheng
f4bcdc21c6 fix(master): Set tobeOffline flag before create migrate plan.#1000138733
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
37d1816f4f fix(master): fix decommissionSuccessDisk issue where it reappears after being deleted #1000131939
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
e252c16a44 fix(cli): Add decommissionType parameter in cli recommission #1000131203
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
1cf0bafea2 fix(data): fix null pointer panic When CreateDataPartition. #1000131492
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
c260b7db0c fix(meta): fix fileStats bug. #1000140349
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
zhumingze
9a571a7f35 fix(master): No additional display of discard dp. #1000128244
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:30 +08:00
shuqiang-zheng
4e6943fae5 fix(master): fix host0 decommission problem.
close:#1000111048

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:30 +08:00
shuqiang-zheng
b519bf1223 fix(master): fix raft member additions not taking effect during dp decommission.
close:#1000136087

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:30 +08:00
Wu Huocheng
ae8ccc5d58 feat(master): add freeze status into metapartition status.#1000090632
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:30 +08:00
Victor1319
dff6a87438 fix(master): add ignoreDiscard param for datanode get. #1000135139
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:30 +08:00
Victor1319
60baf1ff40 fix(master): not return discard dp for datanode get api. #1000135139
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:30 +08:00
Victor1319
e7edd63446 fix(data): avoid replicas empty when buildDataPartitionRepairTask. #1000134827
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:30 +08:00
Victor1319
8f0590bc1a feat(lc): support config file size for lifecycle rule. #1000135253
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:30 +08:00
shuqiang-zheng
cbacf08980 fix(master): add decommission statistics related functionality to cli.
close:#1000104677

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:30 +08:00
shuqiang-zheng
55c0331c14 fix(master): add some logs to locate raft member additions and removals that didn't take effect.
close:#1000105813

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:30 +08:00
shuqiang-zheng
9b4ba1dd9a fix(master): discard dp will be marked as successful during the decommission.
close:#1000129633

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:29 +08:00
shuqiang-zheng
6a687a21ae fix(master): remove the default concurrency limit for disk offline.
close:#1000063905

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:29 +08:00
shuqiang-zheng
339f112008 fix(master): update log level.
close:#1000111048

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:29 +08:00
shuqiang-zheng
89c1915676 fix(master): fix for dp no leader due to failure to add raft member during decommission.
close:#1000105754

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:29 +08:00
shuqiang-zheng
a3cf843526 feat(master): supports statistics of repair information in disk and node dimensions.
close:#1000104677

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:29 +08:00
Victor1319
e5abe1b66c refactor(meta): add audit log for append operation. #1000132254
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:29 +08:00
Wu Huocheng
a76fae0fad fix(master): use default media type before checking dp number.#1000131511
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:29 +08:00
Victor1319
317a47f1d3 fix(meta): fix old inode delete file remove failed bug. #1000125136
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:29 +08:00
Wu Huocheng
2ed1812744 feat(master): offline metanode which has no meta partition.#1000090632
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:29 +08:00
Wu Huocheng
488f730374 chore(master): enable offline active status metanode.#1000090632
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:29 +08:00
Wu Huocheng
043731dabc chore(master): Add meta node name into balance task.#1000090632
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:29 +08:00
Wu Huocheng
e2da451daa feat(master): Kick Out metanode at the end of background task.#1000090632
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:29 +08:00
Wu Huocheng
04991b6b80 feat(master): Set multiple config values.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:29 +08:00
Wu Huocheng
ad075f1559 feat(master): Add kick out metanode api.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:29 +08:00
Wu Huocheng
00c6a9b420 fix(master): remove the un-readable words in response.#1000129081
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:29 +08:00
leonrayang
4d7a690690 fix(metanode): Remove the logic of real-time calculation of the incremental data of the Quota
. #1000112797

Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:59:29 +08:00
leonrayang
0b58792d6d fix(metanode): Remove the logic of real-time calculation of the incremental data of the UID.
.  #1000112797

Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:59:29 +08:00
zhumingze
f6a2781590 fix(master): Fixed the abnormal display of repairStartTime. #1000117639
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:29 +08:00
zhumingze
f39493a9b4 fix(data): change ActionBatchMarkDelete limitIOError log level to info. #1000124626
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:29 +08:00
Victor1319
5ea1d37f21 refactor(meta): refactor inode and dentry muti version code. #1000114612
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:29 +08:00
Victor1319
72dc99de1f refactor(meta): refactor code and testcases. #1000114612
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:29 +08:00
Victor1319
388b1cb7cf refactor(meta): add bench testcase for inode marshal. #1000114612
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:29 +08:00
Victor1319
6f209ae5e9 feat(meta): Optimize the memory alignment of inode and dentry fields. #1000114802
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:28 +08:00
Victor1319
c296a62206 feat(meta): add testcase for inode and dentry marshal. #1000114612
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:28 +08:00
Victor1319
cd12bd7e6b feat(meta): use buf pool to refactor load snapshot. #1000105253
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:28 +08:00
Victor1319
3059c4c9b7 feat(meta): use buf pool to refactor dentry marshal func. #1000100705
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:28 +08:00
Victor1319
3ad0f3d01f feat(meta): use buf pool to refactor inode marshal func. #1000094350
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:28 +08:00
zhumingze
5390dbd59e fix(master): After a DecommissionRetry fails, wait ten minutes for next try.
.  #1000107357

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:28 +08:00
Wu Huocheng
ddbff60e9c feat(master): forbidden to create data partition when the writable number reach config value
. #1000100007

Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:28 +08:00
leonrayang
b1e4f5038a fix(client): Drop the unused forbidden process of volume capacity #1000112797
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:59:28 +08:00
zhumingze
86aa5c6a06 fix(meta): Perform fileStat once during mp load and config change. #1000102780
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:28 +08:00
zhumingze
314edb9bce fix(cli): Do not display dp with empty disk err replica. #1000113950
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:28 +08:00
zhumingze
0018b8dd38 fix(master): return isMannualDecommission parameter When calling the decommission query interface
. #1000112230

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:28 +08:00
zhumingze
a1baa5af24 fix(master): Adjust the dp timeout to 5 minutes. #1000112052
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:28 +08:00
Wu Huocheng
3baf29fdad chore(master): Add audit log for modification api.#1000099738
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:28 +08:00
zhumingze
02fda728d7 feat(master): Add disk decommission success metric. #1000012562
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:28 +08:00
shuqiang-zheng
3cbb46bd80 fix(master): fix some issues found during decommission testing.
close:#1000059418

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:28 +08:00
shuqiang-zheng
c0e6d5f0af fix(master): support for canceling decommission.
close:#1000059418

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:28 +08:00
shuqiang-zheng
7e21ea26f0 feat(master): support for dp decommission prioritization.
close:#1000059507

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:28 +08:00
shuqiang-zheng
fdf97e54ad fix(master): fix new replica repair blocking due to host0 unavailability during dp decommission.
close:#1000059565

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:28 +08:00
shuqiang-zheng
40d975d7a9 fix(master): fix host0 problem for dp repair.
close:#1000041775

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:59:28 +08:00
zhumingze
a18cf5072e feat(cli): Badpartition check display modified to dp number. #1000101191
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:28 +08:00
zhumingze
c2611b2459 feat(data): Check dp availability at random times. #1000022788
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:28 +08:00
leonrayang
069a4a63a2 feat(cli): Output the QoS information of the volume #1000101348
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:59:27 +08:00
Wu Huocheng
df6a12c5d6 chore(datanode): change checking interval from hour to minute.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:27 +08:00
Victor1319
ae766477e7 fix(meta): fix file stats init issue. #1000094081
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:27 +08:00
Victor1319
631baaf14d feat(master): add switch to control whether ignore tiny extent recover. #1000094081
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:27 +08:00
Victor1319
36936cafd8 feat(data): refactor tiny extent delete logic. #1000089221
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:27 +08:00
Wu Huocheng
a5467a3d58 fix(datanode): replace ExtentInfo with RepairExentInfo.#1000005968
This reverts commit e9d5ce73902aa196f89c5545ede7ca808e494bb3.

Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:27 +08:00
Victor1319
62b28d0626 refactor(fmt): use gofumpt to format code. #1000063488
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:27 +08:00
Victor1319
c3ccdfc7e2 refactor(sdk): remove dp cache code from sdk, client, cli. #1000063488
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:27 +08:00
Victor1319
a6197cd99a refactor(master): remove dp cache code from master. #1000063482
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:27 +08:00
Victor1319
0ebe0b874f refactor(data): remove dp cache code from datanode. #1000062928
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:27 +08:00
Victor1319
d66cd51bec refactor(meta): remove dp cache code from metanode. #1000063486
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:27 +08:00
zhumingze
ff102a00da feat(cli): Add display of repair start time in datapartition check. #1000081755
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:27 +08:00
Wu Huocheng
a87a847eb0 feat(raft): remove raft log rotate in start up.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:27 +08:00
Wu Huocheng
ad22bed634 fix(raft): rotate the logs.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:26 +08:00
Wu Huocheng
c577f3877c feat(datanode): rotate all data partition raft log.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:26 +08:00
Wu Huocheng
74f2a66968 feat(raft): remove raft log rotate in start up.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:26 +08:00
Wu Huocheng
6dc6d74d26 fix(raft): rotate the logs.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:26 +08:00
Wu Huocheng
57d0b95284 feat(datanode): rotate all data partition raft log.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:26 +08:00
Wu Huocheng
22ca01df2f perf(datanode): reduce the extent info struct size.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:26 +08:00
Wu Huocheng
30b29217a1 feat(datanode): evict the extent cache by ttl.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:26 +08:00
Wu Huocheng
167e4c488a perf(datanode): replace make with bytespool.#1000005968
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
75af3848b0 feat(cli): Add parameters to datapartition check to simplify display. #1000068067
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:26 +08:00
slasher
86e9ca1edc chore(util): using newest bytespool
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
47e9e94f1d feat(cli): Cli tool data partition check optimization. #1000057001
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
e5b45c21c9 feat(master): Dp no leader adds audit logs. #1000060037
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
d7182d70bd feat(datameta): Record the read-only reason for dp&mp replicas. #1000060034
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:26 +08:00
Victor1319
6e05be7156 refactor(data): refactor the usage of the buffer pool during the prefetch process. #1000048465
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
24cb92350d feat(data): Mark the disks that encounter disk errors during startup as bad disks. #1000004886
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
8986320af9 feat(mastermeta): support set fileStats thresholds. #1000047869
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
aafa2f3f87 feat(meta): Statistics of inode and dentry numbers by volume. #1000048141
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
4e54422a61 feat(meta): support volume file statistics. #1000047865
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:26 +08:00
zhumingze
6a39456dae feat(master): Add master replica missing warning. #1000044346
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
c8d253aa39 feat(master): mp&dp replica missing check time can be adjusted. #1000044373
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
bfe93e050c feat(datamaster): Supplement test cases related to lost and bad disks. #1000004886
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
1964c60240 feat(datamaster): Optimize the check disk lost logic. #1000004886
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
d1763ac873 feat(data): persist datanode allDisks. #1000004886
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
f1ad286a21 feat(data): Adjust some parameters and initialize. #1000004886
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
bf6d4f062f feat(masterdatacli): Add alerts for the completion of disk repair and improve cli display.
. #1000004886

Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
e0a1ff8c0f feat(data): Regularly check dp availability. #1000004886
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
1c794069a1 feat(masterdatacli): lost disks detection and reporting. #1000004886
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:25 +08:00
wu huocheng
4dddd2d05f fix(metric): fix the bug that value and label don't match.#1000005968
Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:25 +08:00
wu huocheng
7e991c4514 perf(client): simplify the client request monitor.#1000005952
Improve the performance by buffer.

Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:25 +08:00
wu huocheng
1456d3c239 feat(client): add request monitor for client
Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-08 14:59:25 +08:00
Victor1319
1a2947218f fix(all): fix conflicts when pick branch 3.5.0. #1000124254
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:59:25 +08:00
chihe
675c8618a4 fix(flashnode): simplifiy err msg for audit log
close:#23025850

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:59:25 +08:00
baihailong
4581cbd979 feat(flashnode): add metrics MetricCacheBytes,MetricHandleReadLatency,MetricSourceDataLatency
. #1000092826

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:59:25 +08:00
chihe
12f68e47b0 fix(client): update gen first when doing overwrite
close:#23025850

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:59:25 +08:00
clinx
d178a1fe51 fix(cli): show handle and read timeout unit#1000100585
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:59:25 +08:00
clinx
3b9696b8d6 fix(cli): set handle and read timeout by cli #1000100585
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:59:25 +08:00
zhumingze
608b59ee91 fix(client): FollowerRead retry after read request failed. #1000107530
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:59:24 +08:00
baihailong
6662617ce1 fix(sdk): sendToDataPartition return error msg when failed.#1000106708
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:59:24 +08:00
baihailong
9253644113 fix(sdk): add warn log print extents when processReply get ArgUnmatchErr error.#1000091570
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:59:24 +08:00
clinx
6af47faed0 fix(datanode): change warn message log level #1000091570
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:59:24 +08:00
leonrayang
1ab568cfc1 fix(datanode): Reducing the sync process to enhance the speed of creating extent #23118077
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:59:24 +08:00
chihe
94fd8c6618 fix(client): remove debug log
close:#1000101999

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:59:24 +08:00
chihe
206937fd96 fix(client): do not update the meta if remote cache is not enabled
close:#1000101999

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:59:24 +08:00
chihe
fb7b1ea7dc fix(client): add debug log for parameter error
close:#1000080725

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:59:24 +08:00
baihailong
8056986b3e fix(libsdk): NewEbsClient support config loglevel.
@formatter:off

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:59:24 +08:00
clinx
c20fb87a05 fix(cli): show remove all inactive nodes with node address #1000100585
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:59:24 +08:00
clinx
2083fbb8f1 fix(client): print error to console #1000099011
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:59:24 +08:00
baihailong
2ec055bc81 fix(master): if dp is discard does not print the warn log when getReplica.#1000092826
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:59:24 +08:00
baihailong
6566e91c9f fix(sdk): add warn log print extents when processReply get processReply error.1000091570
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:59:24 +08:00
baihailong
30f483b8a5 fix(flashnode): optimize computeAllocSize when there is a hole in dataSources.#1000080725
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:59:24 +08:00
leonrayang
efeeea3dcd fix(datanode): Fix the enhance the persistence process of extentId #23118077
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:59:24 +08:00
clinx
8c35095b29 fix(metanode): change inode out of range message to warn #1000082017
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:59:24 +08:00
baihailong
dea4a5ecb6 fix(sdk): check whether StorageClass allowed when remoteCacheAutoPrepare is opened.
. #1000083859

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:59:01 +08:00
clinx
a1fe50c7be fix(datanode): change write with return try other addr message to warn #1000082414
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
clinx
818e4834b0 fix(datanode): opstreamfollowerread change timeout message to warn #1000082031
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
clinx
261d6068d9 fix(metanode): change over quota message to warn #1000082017
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
leonrayang
5bd3da5846 feat(datanode): Enhance the persistence process of extentId #23118077
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:52:12 +08:00
clinx
07d2ba0be6 fix(flashnode): wait for the cache to start successfully before providing HTTP service #1000082949
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
clinx
487e4801f0 fix(client): set default value for async update fg information #1000080369
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
leonrayang
29ac3c29b7 fix(client): Enhance singals register work on client side #1000073719
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:52:12 +08:00
clinx
cea9567b1e fix(client): set default value for read timeout#1000075110
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
chihe
42e6bd21da fix(client): if follower read is enabled, try other hosts when triggering OpNotExistErr
close:#1000078338

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:52:12 +08:00
clinx
4a38fa1418 fix(client): add audit log for cross region host #1000075110
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
clinx
c296c6ff54 fix(client): distinguish between regions or zones based on the time issued by the master #1000075110
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
baihailong
35a97d6de8 fix(master): Assign default values to remoteCache parameters when upgrade master.#1000077514
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:12 +08:00
clinx
5cf2716bed fix(client): check if rc.mc is nil avoid async update panic #1000076960
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:12 +08:00
baihailong
967338d137 feat(master): Optimize the client to remove flashnode logic when flashnode returns timeout
. #1000074429

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:03 +08:00
clinx
f934c5726c fix(datanode): print memory-related data with added newline characters#1000068627
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:03 +08:00
clinx
3641507fbb fix(datanode): change the log level from error to warn for doStreamFixTinyDeleteRecord #1000068627
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:03 +08:00
chihe
964a6be097 fix(metanode): if vol is deleted, do not try to get the view of vol
close:#1000018506

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:52:03 +08:00
baihailong
6dec8982b4 fix(master): when client getFlashGroupView not exclude flashnode which is inactive.#1000068406
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:03 +08:00
clinx
56bbb851b0 feat(client): only add the directory inode to the dircache#23068759
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:03 +08:00
clinx
79562f9cd0 feat(client): print cache size in stat file #23068759
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:03 +08:00
baihailong
19b1bf9319 fix(client): not move flashnoe to unknownRank if returned LimitedIoError.#1000065874
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:03 +08:00
baihailong
f5c02acd5e fix(flashnode): add stat statistic for each datanode.#1000063595
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:03 +08:00
chihe
6bb14d523a bugfix(datanode): set IOLimitTicket to 3 second
close:#1000063103

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:52:02 +08:00
chihe
78c727cda3 fix(datanode): adjust log level for no leader
close:#1000001079

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
30d76f57df fix(meta): change log level when inode is delete #1000038153
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
273ddea5a1 fix(cli): print error msg to console #1000060043
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
0011472417 fix(lcnode): change log level when inode is delete #1000038153
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
6af8dea263 fix(master): change log level from error to waring when leader have changed #1000028939
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
baihailong
c71ca1570d fix(sdk): if get temporary ek when getDataSource return false and read from dn.#1000060859
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
812388b33a fix(cli): print error msg to console #1000060043
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
baihailong
02cf5d2343 fix(sdk): if get temporary ek when getDataSource return false and read from dn.#1000060859
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:02 +08:00
baihailong
fd2d45ea5a fix(flashnode): modify timeout uint from second to Millisecond when read datanode. #1000061026
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:02 +08:00
baihailong
f2365c1319 fix(master): modify master error log and add some log for TryRun.#1000044182
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
a0cf5a13f1 fix(client): asynchronously check if config is empty to avoid uninitialized panic #1000056931
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
f7b20d6d9f fix(flashnode): can't set 0 to RemoteCacheReadTimeout#1000021930
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
3889dba14a fix(flashnode): set default remote cache timeout to 100ms#1000021930
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
be196f9b6f fix(flashnode): show empty stat #1000021930
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
baihailong
603d6b5377 fix(util): use time.Now to check whether task is timeout.#1000048131
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
8fbab026ff fix(meta): adjust concurrent conflict errors to warnings #1000028960
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
Victor1319
940d72659d refactor(lcnode): try to check whether inode deleted when dst md5 changed. #1000044251
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
72f6196ba6 fix(flashnodeb): asynchronously send flashnode heartbeat message#1000044633
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
zhumingze
5faeca7fd9 fix(sdk): Optimize printing information in read process. #1000044633
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:52:02 +08:00
zhumingze
b22ef23cc0 fix(meta): Adjust the level of some logs in updateVolumes. #1000044602
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:52:02 +08:00
chihe
31585bd930 fix(flashnode): adjust log level
close:#1000014246

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:52:02 +08:00
baihailong
97612b6b20 feat(flashnode): enable statistic slot hit rate.#1000037792
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:52:02 +08:00
chihe
b67b08df90 fix(client): do not close conn if encountering limit error
close:#1000023889

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
143b073232 feat(cli): Remove delay-related monitoring information for flashnode#1000021930
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
b677abc848 feat(cli): idle not show group stats#1000021930
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
clinx
2176a61e7e feat(cli): print group status for flashnode #1000021930
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:02 +08:00
chihe
f5783cd728 fix(flashnode): add write limit for flashnode
close:#1000023889

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:52:02 +08:00
chihe
6a89226dc5 feat(flashnode): supports return to client directly if data is not cached
close:#1000014246

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:52:01 +08:00
clinx
a17a165baf fix(client): maintain consistency in the disable logic for remote cache #1000026048
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:52:01 +08:00
baihailong
c1ee0a0053 fix(sdkmaster): volume remoteCacheReadTimeout parameter changed from seconds to milliseconds.
. #1000024513

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:51:45 +08:00
baihailong
5eef58052b feat(master): enable master config flashnode read timeout dynamically.#1000020016
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:51:45 +08:00
clinx
3c67ab500b fix(flashnode): valid args for fla flashnode list#1000020535
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:51:45 +08:00
clinx
5584dfe034 fix(flashnode): valid args for fla flashnode list#1000020535
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:51:45 +08:00
clinx
0c5da8ea36 fix(flashnode): check the deletion operation of the flashnode #1000020535
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:51:45 +08:00
chihe
82a11e620c fix(client): ignore limit and context timeout error
close:#1000014246i,#1000017781

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:51:45 +08:00
chihe
99a71d0cd7 fix(datanode): do not print log if diskBaseFileID equals to 0
close:#1000012686

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:51:45 +08:00
baihailong
2faa29f3fa fix(master): if master loading meta not ready when client get flashgroups, return error.#1000006070
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:51:45 +08:00
shuqiang-zheng
9ce6bbcd43 fix(meta): fix the problem of high cpu caused by constantly requesting small memory during reading.
close:#1000016022

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:51:44 +08:00
chihe
baa7412321 fix(flashnode): do not close channel twice
close:#1000016077

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:51:44 +08:00
clinx
2b80a78b76 fix(flashnode): if the flashnode of the group is empty or unavailable, do not update the slot
. #1000014547

Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:51:35 +08:00
shuqiang-zheng
57fefaa661 feat(meta): perform security checks when configuring gogc, set upper and lower limits.
close:#1000011090

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:42:25 +08:00
shuqiang-zheng
324e23d2da feat(meta): free memory when deleting meta partitions.
close:#1000013477

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:42:25 +08:00
shuqiang-zheng
501dc61922 feat(meta): Support for dynamic adjustment of gogc.
close:#1000011090

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-08 14:42:25 +08:00
chihe
7c026a4daf fix(flashnode): delete pre-allocated size when return from InitForCacheRead
close:#1000012153

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:42:25 +08:00
clinx
1118f934ee feat(warmup): code check#22883846
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:42:25 +08:00
clinx
238bfdc555 feat(warmup): create flash manual task #22883846
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:42:10 +08:00
baihailong
7800234d56 fix(sdk): client not update local flashgroups when get empty flashgroups from master.#1000006070
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:39:41 +08:00
chihe
ca90d3bac8 feat(master): add setRead/WriteLimits for flashnode
close:#1000004942

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:39:41 +08:00
zhumingze
487641d0f9 feat(master): Skip the discard dp periodic check. #23132815
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:39:41 +08:00
zhumingze
b7759e42c5 feat(data): Solve the panic problem when deleting inode. #1000002511
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-08 14:39:41 +08:00
chihe
380b8dde52 fix(flashnode): reply to client as soon as possible
close:#23109728

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:39:41 +08:00
wu huocheng
9ad005fbdd feat(master): single node mode.#22834621
Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-08 14:39:41 +08:00
Victor1319
3f7942ea1d fix(master): use listen port as register consul port for master. #23119229
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:39:41 +08:00
Victor1319
a6fc8be1fc refactor(client): support config stream reqChan Size. #23114335
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:39:41 +08:00
Victor1319
8a4d89f936 fix(sdk): force update extent cache after trunc. #22962095
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:39:41 +08:00
Wu Huocheng
016d14fe17 fix(master): fix the nil pointer when master leader changed.#23070942
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-08 14:39:41 +08:00
Victor1319
efd90371e1 fix(client): fix client push commit failed. #22962095
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:39:41 +08:00
baihailong
0daae3b9c9 fix(metanode): fix metanode UpdateXAttr incompatibility problem.#22993674
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-08 14:39:41 +08:00
leonrayang
d182ede7c7 fix(sdk): The refCnt of the streamer may become inaccurate due to the counting conflicts
close:#22962095

Signed-off-by: leonrayang <chl696@sina.com>
2025-08-08 14:39:41 +08:00
Victor1319
8bb3f3a0bc refactor(master): add crossZone hint message when addAllowedStorageClass failed. #22962157
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:39:41 +08:00
Victor1319
2ccbea7e15 refactor(master): support report datanode status count for different media. #22960364
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:39:41 +08:00
Victor1319
9bac4d6e8f refactor(fsck): reduce debug log for fsck gc comand. #22958547
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-08 14:39:41 +08:00
clinx
800d34e444 fix(flashnode): record disk dimension to file read and write operations #23131609
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:39:36 +08:00
clinx
326f7611ca fix(objectnode): create reader or writer with corrected volume's type #23077454
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:39:32 +08:00
clinx
e50f6a23f4 fix(objectnode): create reader or writer with corrected volume's type #23077454
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:39:05 +08:00
clinx
37a5824998 fix(master): prevent reentrant locking #22935828
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-08 14:39:05 +08:00
tangdeyi
767d922713 fix(clustermgr): fix unlock ut
@formatter:off

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-08-08 14:39:05 +08:00
chihe
e9f0bf8c30 fix(bcache): reduce memory consumption for bcache-service
close:#22775703

Signed-off-by: chihe <chihe@oppo.com>
2025-08-08 14:39:01 +08:00
slasher
74a7c62171 chore(util): using newest bytespool
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-08-07 16:20:27 +08:00
zhumingze1108
d936fb90cc fix(master): fix Possible overflow issue.
Signed-off-by: zhumingze1108 <zhumingze@oppo.com>
2025-08-07 16:00:30 +08:00
zhumingze1108
b0fd043df1 fix(all): gofmt code for ci-test
Signed-off-by: zhumingze1108 <zhumingze@oppo.com>
2025-08-07 16:00:30 +08:00
zhumingze1108
ca20eb11f3 fix(client): fix conflict in v3.5.2 merge to master.
Signed-off-by: zhumingze1108 <zhumingze@oppo.com>
2025-08-07 16:00:30 +08:00
Victor1319
4ed781a41a fix(data): fix gc clear data failed bug. #22957485
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-07 16:00:30 +08:00
zhumingze
d6ad6681dd refactor(fsck): avoid panic when vol not exists #22911241
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:30 +08:00
zhaochenyang
3e3204cabe refactor(lcnode): lcnode response ack to master after save data #22941195
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2025-08-07 16:00:30 +08:00
Victor1319
df827a9909 fix(meta): Resolve the issue where log level settings for the EC are ineffective #22921293
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-07 16:00:30 +08:00
Victor1319
7c8d9b0c9a refactor(master): add vol used stats for monitor metrics. #22930922
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-07 16:00:30 +08:00
Victor1319
dec11132ba refactor(master): support report monitor stats for cluster different media datanode. #22929430
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-07 16:00:30 +08:00
Victor1319
76b8d7a946 refactor(all): refactor code for code scan warn info. #22929123
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-07 16:00:30 +08:00
clinx
a6939d0981 fix(flashnode): close cached files concurrently#23092015
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:30 +08:00
clinx
a1a2add9d9 fix(flashnode): confirm the default value is no #23079599
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:30 +08:00
clinx
c3b9145631 fix(flashnode): code check#23131609
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:30 +08:00
clinx
19e4fdc075 fix(flashnode): record disk dimension to file read and write operations #23131609
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:30 +08:00
clinx
cfa8134cc7 feat(flashnode): add read and write latency metrics for cache #1000002444
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:30 +08:00
chihe
91965b0b44 fix(flashnode): use limitRead for read cache
close:#23123752

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:30 +08:00
chihe
9a1adf8212 fix(flashnode): use limitWrite for flashnode instead of disk
close:#23123752

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:30 +08:00
chihe
be79605ea0 fix(flashnode): read data source one by one
close:#23095482

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:30 +08:00
clinx
c27769e9f0 fix(flashnode): wait group for woker goroutine #23092015
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:29 +08:00
clinx
1e5dd165c6 fix(flashnode): simplify the logic for deleting a directory #23092015
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:29 +08:00
clinx
28d975ce10 feat(flashnode): init load files using a separate coroutine for handling #23092015
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:29 +08:00
Wu Huocheng
1801c729a3 chore(master): fix the mistake of unit test codes.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:29 +08:00
Victor1319
d031b8f62c refactor(meta): not return error when lease time not expire. #23131784
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-07 16:00:29 +08:00
Victor1319
eae24a92f9 fix(meta): check whether sortEks empty when fsmUpdateExtentKeyAfterMigration. #23126054
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-08-07 16:00:29 +08:00
zhumingze
11e446b191 feat(master): Discard partition does not print the log of missing Replica. #23132815
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:29 +08:00
Wu Huocheng
5af9e23abf fix(master): Calculate the mp memory size by used value.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:29 +08:00
Wu Huocheng
2074d059c3 fix(master): Checking the whole pc memory usage.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:29 +08:00
shuqiang-zheng
4b9f564cdf feat(flashnode): enhancement of flashGroup information display.
close:#23070174

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:29 +08:00
shuqiang-zheng
808b831224 feat(flashnode): support for gradually creation and deletion of flashGroup.
close:#23070174

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:29 +08:00
zhumingze
e0b861423d fix(util): Avoid label conflicts during the version metric pushing process. #23104396
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:29 +08:00
clinx
a12abc9dcc fix(flashndoe): add user confirmation when the user attempts to remove flash group by id#23079599
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:29 +08:00
clinx
afadcde635 fix(flashndoe): add user confirmation when the user attempts to delete a flashnode. #23079599
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:29 +08:00
leonrayang
27ff3d3280 fix(master): Leader mismatch during volume cache synchoronize #23117176
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:29 +08:00
leonrayang
8d897d1289 feat(datanode): Enable crc check for BaseExtentID information #23118077
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:29 +08:00
leonrayang
7d9c971da5 fix(master): The limit fields in Quota should be stored to rocksdb if it is updated #23117980
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:29 +08:00
leonrayang
549128cf1a fix(datanode): Stop the tiny extent markdelete process while store stopped #23115007
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:29 +08:00
leonrayang
8d3fe7499c fix(datanode): Temporarily disable the crc read due to the wrong extentid in meta EXTENT_META
close: #23118077

Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:29 +08:00
zhumingze
175e6f4ee7 fix(datamaster): Adjust some error logs. #23101965
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:29 +08:00
zhumingze
bea1253769 fix(master): Optimize the display of checkDiskError logs. #23115792
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:29 +08:00
clinx
8b4b6ca311 fix(flashndoe): Evict cache by each disk using a separate coroutine for each disk #23091754
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:29 +08:00
shuqiang-zheng
c61e0a0896 feat(flashnode): fix the problem that lru is not eliminated in time due to insufficient disk space.
close:#23105469

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:28 +08:00
shuqiang-zheng
6c5f62ba89 feat(flashnode): load each disk's cacheBlock concurrently
close:#23103621

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:28 +08:00
shuqiang-zheng
4253b68c83 fix(flashnode): fix a possible no space left problem during concurrent cacheBlock creation.
close:#23105469

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:28 +08:00
shuqiang-zheng
e3f33db578 feat(flashnode): add bad disk alerts for flashnode on master.
close:#23057658

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:28 +08:00
shuqiang-zheng
24d656446f fix(flashnode): fix eof issues that could be caused by concurrent creation of cacheBlock.
close:#23100234

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:28 +08:00
shuqiang-zheng
b36e228468 feat(flashnode): after all cacheBlock loads completed, print the load completion information.
close:#23103621

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:28 +08:00
shuqiang-zheng
b2a4b1a478 fix(flashnode): determine disk actual leftspace before creating a cacheBlock to open the file.
close:#23105469

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:28 +08:00
clinx
99b6c2142d fix(flashnode): print audit log when read data from remote source#23112585
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:28 +08:00
clinx
41ad2fdc7d fix(flashnode): avoid unnecessary audit log printing #23112585
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:28 +08:00
zhumingze
e9b9b9250c fix(fsck): Improve the printing information of fsck. #23109752
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:28 +08:00
zhumingze
ef9ceeb8e3 fix(master): Decommission interface returns specific error information. #23117907
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:28 +08:00
zhumingze
fe8906f897 fix(master): No longer allow single replica dp raftForce deletion. #23115830
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:28 +08:00
zhumingze
3c91dcbf84 fix(data): Add dp information to cache in advance to avoid start raft error. #23113653
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:28 +08:00
Wu Huocheng
54c4f04c52 chore(raft): Add debug logs to track the raft peers changing.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:28 +08:00
clinx
03b21f5bd6 fix(flashnode): rename the field remoteCacheFollowerRead to remoteCacheMultiRead #23065717
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:28 +08:00
chihe
e32d901fb6 fix(flashnode): delete expired file for block cache before unlock
close:#23062373

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:28 +08:00
chihe
1e8032b24e fix(client): add gen for extent cache when doing overwrite
close:#23025850

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:28 +08:00
chihe
d7c377e5d3 fix(client): support 3.5.0 java sdk #23068759
Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:27 +08:00
wu huocheng
c41f9f2041 chore(master): clean the meta partition from smallest inode.#22834621
The smallest inode meta partition is exhausted. So remove such mp.

Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
wu huocheng
8d0c652b85 fix(master): unlock the mutex before return.#22834621
Rewrite the freeze function.

Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
wu huocheng
10d378fb19 chore(master): skip useless logs.#22834621
Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
Wu Huocheng
a2f6f97dfc feat(master): configure memory ratio percent and control mp migrate.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
Wu Huocheng
266c9a7ba4 fix(cli): report error when no migrate plan created.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
Wu Huocheng
ce8f310bb4 feat(master): Auto clear task that status is done.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
wu huocheng
6372209d12 fix(master): skip the meta partition that is recover or has no leader.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
Wu Huocheng
e27923fa1c chore(master): rerange the codes.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
Wu Huocheng
f13cc3a1b6 feat(master): Add migrate request meta partition apis.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:27 +08:00
zhumingze
55e0a1cade feat(master): Keep discard dp information in master and avoid panic when dp is nil. #23036742
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:27 +08:00
shuqiang-zheng
72358a9bc0 feat(flashnode): Add a configurable item to control the number of cache loading goroutines.
close:#22831482

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:27 +08:00
shuqiang-zheng
3cdea7d89f feat(flashnode): modify the upper limit of cachePercent and the defaultMaxUseRatio of lru.
close:#23080181

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:27 +08:00
shuqiang-zheng
f2d2a663a6 fix(flashnode): fix the problem of not being able to select readWrite disks.
close:#23078913

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:27 +08:00
shuqiang-zheng
1ebe5b6dfd feat(flashnode): if the disk is umounted, the cacheblock can be detected and stopped timely.
close:#23021760

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:27 +08:00
shuqiang-zheng
c3a505fb1e fix(flashnode): avoid the cache not being cleaned up when the flashnode is removed.
close:#23003554

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:27 +08:00
shuqiang-zheng
96f8c21399 fix(flashnode): fix empty volume directories not cleaned up when cacheBlock is deleted.
close:#23057658

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:27 +08:00
shuqiang-zheng
815fb21cde feat(flashnode): add error cacheBlock number count during restart loading process.
close:#23021760

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:27 +08:00
chihe
630b48ed2f fix(flashnode): add cacheItem into lru after file is inited
close:#23062373

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:27 +08:00
chihe
1d5213c43b fix(master): add default value for ttl and readTimeout for remoete cache
close:#23081308

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:26 +08:00
chihe
bc66f9ae66 fix(client): add some debug log
close:#23062373

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:26 +08:00
chihe
f212b4b113 fix(client): only read operation execute sendReadToDP
close:#23069988

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:26 +08:00
clinx
7de202b317 fix(objectnode): create ebs reader by sv#23077454
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:26 +08:00
leonrayang
72bf18cdff fix(data): Temporily modifying the test case has a high ratio of failure out #23059813
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:26 +08:00
leonrayang
2e8bf80543 fix(testcase): comment the test case has high ratio of failure out #23059813
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:26 +08:00
leonrayang
88ca620bf8 fix(datanode): Optimize io limiter exit process. #23059813
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:26 +08:00
leonrayang
e0b6ed4060 feat(client): Reducing the log output of flow limiter #23059813
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:26 +08:00
clinx
9df10b2063 fix(flashnode): reset test limiter#23061931
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:26 +08:00
clinx
f3b98b69b1 fix(flashnode): open readlimiter for OpFlashNodeCachePrepare. #23061931
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:26 +08:00
baihailong
58e68d9ef3 fix(flashnode): OpFlashNodeCachePrepare operation with flow control.#23061931
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 16:00:26 +08:00
clinx
0152d00450 fix(objectnode): create reader or writer with corrected volume's type #23077454
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:26 +08:00
clinx
ed5c20840b fix(master): prevent reentrant locking #22935828
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:26 +08:00
clinx
9c29ebadac fix(client): add default value #23062821
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:26 +08:00
chihe
279817ca50 fix(client): modify default value for remoteCacheReadTimeoutSec
close:#23047275

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:26 +08:00
clinx
2de99277d2 fix(client): show client remote cache flag when call master client info #23062821
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 16:00:26 +08:00
zhumingze
c4f524a52f feat(master): Add state transition for fail status when deleting excess copie. #23036843
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:26 +08:00
chihe
07a308a7de fix(flashnode): change the type of metric for ReadBytes and ReadCount
close:#22200531

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:26 +08:00
Wu Huocheng
45afc5aee0 fix(raft): use raftfsm.replicas instead of get peers.@formatter:off
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:26 +08:00
Wu Huocheng
ed61daa568 feat(raft): display raft peers.@formatter:off
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 16:00:26 +08:00
leonrayang
30b221b2af feat(datanode): Return error if request is hung by io limiter and exceeds maximum wait time
. #23057829

Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 16:00:26 +08:00
zhumingze
da9e00409d fix(sdk): Cancel the check whether leaderAddr is empty when getting dataPartition. #23046693
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:26 +08:00
zhumingze
bb15923446 fix(sdk): Before quorum read, read requests to the leader are no longer retried. #23046791
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:26 +08:00
zhumingze
86f3053ed8 fix(sdk): Fix bug in quorum read. #23045300
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 16:00:25 +08:00
chihe
596b79c286 fix(flashnode): check the type of error returned by flashnode
close:#23047275

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:25 +08:00
shuqiang-zheng
b4a9c85ae6 feat(flashnode): add interfaces for manual inactive disk.
@formatter:off

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:25 +08:00
shuqiang-zheng
fc3cddfc20 feat(flashnode): modify the name of the disk statistics in heartbeat reporting.
@formatter:off

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:25 +08:00
shuqiang-zheng
ca7739bb6a feat(flashnode): fix possible eof issues when reading cacheBlock files.
close:#23037080

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:25 +08:00
shuqiang-zheng
e0880fa4d0 feat(flashnode): clears the cache on flashNode when removing it.
close:#23003554

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:25 +08:00
shuqiang-zheng
08639d8b52 feat(flashnode): add multi disk support.
close:#23021760

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:25 +08:00
shuqiang-zheng
e90a0e933e feat(flashnode): clears the cache on flashNodes when removing them from the flashGroup.
close: #23003554

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:25 +08:00
shuqiang-zheng
0054b8e5d4 fix(datanode): fix opening file error caused by not limiting the number of file handles.
close: #23013594

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:25 +08:00
shuqiang-zheng
75d6aca05e fix(datanode): fixes for 1.read/write requests still being processed
2.log files not being found after service stopped.

close: #23013195

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 16:00:25 +08:00
baihailong
077d35fc53 fix(sdk): client not update fg even if flashgroup turn true after turn false last time.#23026799
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 16:00:25 +08:00
baihailong
fa1ce7515c fix(cli): if parameter remoteCacheMaxFileSizeGB not changed when update volume, stay the same.
. #23047778

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 16:00:25 +08:00
chihe
9a5d48ca84 fix(client): folder renamed or moved out of the cache directory will no longer be cached.
close:#23022505

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:25 +08:00
chihe
f36f62b80c fix(client): update fullpath and pinos when excuting rename opration
close:#21990545

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:25 +08:00
tangdeyi
77979034f5 fix(objectnode): add range get check
with #23042024

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-08-07 16:00:25 +08:00
baihailong
fe6e5acf47 fix(cubefs): fix some code format.
@formatter:off

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 16:00:25 +08:00
baihailong
45b7ffdf60 feat(flashnode): Querying flashnode status prints the expiration time of the key value.#23040431
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 16:00:25 +08:00
baihailong
4d7e0c1997 fix(cli): when create or update volume, remoteCacheMaxFileSizeGB must greater than 0.#23034629
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 16:00:25 +08:00
chihe
c999baf001 fix(client): try read from flashnode if dp is not avaliable
close:#23034648

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 16:00:25 +08:00
baihailong
6d04ae146c fix(cli): fix remotecache params when create volume.#23030205
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 16:00:25 +08:00
baihailong
e19232f374 feat(mastersdkcli): enable config remoteCache parameter by volume.
. #23020464

Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 16:00:11 +08:00
clinx
0d875b0a33 fix(object): stop update volume meta info when vol is deleted #22861848
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 15:57:57 +08:00
clinx
82ffd69b6b fix(object): stop update volume meta info when vol is deleted #22861848
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 15:57:57 +08:00
baihailong
a111204db9 fix(sdk): lcnode not register to master.#23017532
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:57 +08:00
baihailong
7bcd569001 fix(flashnode): add volume, clientIp, inode for DataSource.#23013250
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:57 +08:00
zhumingze
eb88697dac feat(sdk): for inner req, only support request dp leader. #22931456
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 15:57:57 +08:00
chihe
7e294e7f00 fix(master): deduplicate and remove contained for remote cache path
close:#23011064

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:57 +08:00
chihe
6e662d30d9 fix(client): add full path for Dir and File
close:##21990545

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:57 +08:00
chihe
3fa7ba4482 fix(clinet): remove node for dir when released
close:#21990545

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:57 +08:00
chihe
c147758ca1 fix(client): remove node cache when file is released
close:#21990545

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:57 +08:00
baihailong
5c7dfe077f feat(flashnode): enable flashnode read timeout configured by the master.#22965528
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:57 +08:00
baihailong
eff580aea8 fix(flashnode): optimize flashnode log level.#22985948
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:57 +08:00
baihailong
f5d59a2eaa fix(sdk): not initial remotecache when NewExtentClient for lcnode and objectNode.#23010877
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:57 +08:00
clinx
56fc4fa9b1 fix(data): outofslice error #22883846
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 15:57:57 +08:00
clinx
2b0f857d01 feat(data): compatible json serialization for old datanode. #22883846
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 15:57:56 +08:00
clinx
0eb05bd9f7 feat(data): compatible json serialization for old datanode. #22883846
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 15:57:56 +08:00
clinx
e3ae2ea3f1 feat(data): change extentinfo serialize for getting remote extend info#22883846
Signed-off-by: clinx <chenlin1@oppo.com>
2025-08-07 15:57:56 +08:00
chihe
b0807770c3 fix(objectnode): return error message when encountering internal err
close:#22997834

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:56 +08:00
chihe
c65d6c19df fix(lcnode): init ExtentConfig with metaWrapper
close:#23007284

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:56 +08:00
chihe
621017b3b3 fix(client): cache all files if remoteCachePath is empty.
close:#23002423

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:56 +08:00
chihe
639a696545 fix(bcache): reduce memory consumption for bcache-service
close:#22775703

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:56 +08:00
zhumingze
1a20920be2 feat(datameta): Modify gcRecyclePercent to be configurable. #22995150
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 15:57:56 +08:00
baihailong
8d81c6d2f0 fix(cli): Restrict cli only execute httpStat and httpEvict on the flashnode of the cluster.#22983845
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:56 +08:00
chihe
12917180d4 fix(master): fix dead lock for flashnode
close:#22985995

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:56 +08:00
zhumingze
5e57eb1ecd feat(master): Add maximally-read config in master for better management. #22931456
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 15:57:56 +08:00
zhumingze
cbdcb01411 feat(sdk): support read quorum when dp no leader. #22931456
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 15:57:56 +08:00
chihe
dcc1b828ab refactor(client): Increase the timeout period for blobstore client
close:#22897285

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:56 +08:00
shuqiang-zheng
745261d31a fix(flashnode): modify log level for cacheBlock load failures.
close:#22985948

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 15:57:56 +08:00
baihailong
3d7c4917c2 fix(flashnode): optimize flashnode list cost time.#22989953
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:56 +08:00
baihailong
836108a02c fix(flashnode): optimize log level when cachePrepareTaskCh has been full.#22985948
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:56 +08:00
baihailong
46c323c25e fix(sdk): if not enable followerread, flashnode only read from dp leader.#22972336
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:56 +08:00
baihailong
969df96cb7 fix(cli): fix flashgroup info too many blank line and limit max weight of flashgroup.#22981269
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:56 +08:00
baihailong
fbc5634f63 fix(master): when master not find flashnode zone leadto panic.#22983373
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:56 +08:00
baihailong
f6a8a544c2 feat(flashnode): supplement flashnode info for http interface flashnode/get.#22975706
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:57:56 +08:00
chihe
94253b719d feat(client): remote cache supports specify dir
close:#22897285

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:57:56 +08:00
shuqiang-zheng
ca2eb33605 fix(flashnode): modify the name of the cache size and ratio configuration item.
close:#22963423

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 15:57:56 +08:00
shuqiang-zheng
f883980012 fix(flashnode): fix slow source return in case of concurrent cache reads.
@formatter:off

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 15:57:56 +08:00
shuqiang-zheng
76007c2d8d fix(flashnode): same cacheBlock may be created multiple times.
close:#22922141

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 15:57:40 +08:00
shuqiang-zheng
110075c431 feat(flashnode): data cache supports persistence and caching limit the number of file handle.
close:#22886884 #22886873

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 15:45:54 +08:00
shuqiang-zheng
101f0e0099 fix(flashnode): fix the problem of high cpu due to frequent gc on flashnode.
close:#22872898

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 15:45:54 +08:00
shuqiang-zheng
1cfd66ec91 fix(flashnode): fix low performance due to traversing keys in fetch status.
close:#22838790

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 15:45:37 +08:00
shuqiang-zheng
cf338f6fa5 feat(flashnode): supports configurable lru capacity.
close:#22834016

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-08-07 15:45:37 +08:00
baihailong
e9d9a447fd feat(client): support configuring enableRemoteCacheOnlyForNotSSD.#22957483
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:37 +08:00
baihailong
19dd3a225a feat(client): support configuring the maximum file size of remotecache.#22897285
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:37 +08:00
zhumingze
a2a73616ca feat(fsck): Add force clean function for fsck. #22944717
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 15:45:37 +08:00
baihailong
090e94bab8 feat(flashcache): Support to specify the weight parameter when creating flashgroup.#22931494
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:37 +08:00
Wu Huocheng
2752860e9e chore(metanode): Add debug logs and meta partition empty checking.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 15:45:37 +08:00
Wu Huocheng
d8bdc8d44f feat(master): Add getting clean task for empty meta partition.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 15:45:37 +08:00
Wu Huocheng
799173432e feat(master): Wait for 10 minites before setting meta replica forbidden.#22834621
Run the clean command in the background. It may takes several hours.

Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 15:45:37 +08:00
Wu Huocheng
f00702a0d0 feat(metanode): add set meta partition freeze raft command.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 15:45:37 +08:00
Wu Huocheng
1565adf97d fix(metanode): backup the raft dir of meta partition.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 15:45:37 +08:00
Wu Huocheng
46bb136ee8 chore(master): update the codes according to review comments.#22834621
Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 15:45:37 +08:00
Wu Huocheng
242eedf13d chore(client): restore the client codes.#22834621
Delete the codes that removing empty meta partitions.

Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2025-08-07 15:45:37 +08:00
Wu Huocheng
6d881229b4 feat(master): Add freeze and clean empty meta partitions apis.#22834621
Signed-off-by: wu huocheng <wuhuocheng@oppo.com>
2025-08-07 15:45:37 +08:00
baihailong
4a30d7164c fix(master): Optimizing some http registration function of remotecache.#22913153
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:37 +08:00
zhumingze
410e4545e1 feat(master): Support setting dp and mp cnt limit for different machines #22883514
Signed-off-by: zhumingze <zhumingze@oppo.com>
2025-08-07 15:45:37 +08:00
baihailong
6d18b6251e fix(flashnode): parent directory permission wrong cause block file creation failure.#22906620
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:37 +08:00
baihailong
057d9605da fix(cli): Restrict the valid and default values of the volume's remoteCache parameter.#22897624
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:26 +08:00
baihailong
a04d110270 fix(flashnode): when removing a flashnode it adds an idle one.#22890663
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:25 +08:00
baihailong
db3099e619 fix(flashnode): fix unit test error.#22876448
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:25 +08:00
baihailong
607b49d953 fix(flashnode): optimize metrics of flashnode.#22876448
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:25 +08:00
baihailong
00b082d8d3 fix(flashnode): format some code and fix some test case error.#22692038
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:25 +08:00
baihailong
5083a406f0 fix(flashnode): add some metric for flashnode.#22837445
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:25 +08:00
baihailong
b550c3f4d8 fix(sdk): client can only select one flashnode in the same fg.#22802475
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:25 +08:00
baihailong
4a373f4b23 fix(flashcache): format some code and remove unsued code.#22692038
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:25 +08:00
baihailong
e56db1be36 fix(flashnode): enable config dataPath for flashnode. #22780994
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:25 +08:00
baihailong
027f3aa40c fix(flashcache): use NewExtentRequestV2 instead of NewExtentRequest.#22696653
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
90798863ca fix(flashcache): format some code of flashcache.#22692038
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
bc5a500a5d fix(sdk): Optimize the delay of client obtaining flashnode connection.#22707944
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
bc7c769457 fix(flashnode): flashnode enable config enableTmpfs.#22664221
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
7f31888f79 fix(flashnode): add block createtime and print it when expired.#22692038
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
e99b6e1af5 fix(master): add some debug log for flashnode.#22692038
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
18ca290acb fix(master): fix some bug after rebase 3.4.0 #22665391
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
0290520f25 fix(sdk): client remotecache connection pool capacity too small.#22687920
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
46d19b3182 fix(flashnode): fix some bug after rebase 3.4.0 #22665391
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
3d7896fc65 fix(client): client not release connection of flashnode immediately.#22653259
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
9025274e8e fix(flashnode): open file for block failed.#22642538
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
df36c10f1e fix(flashnode): flashnode hit count is not accurate.#22634423
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:45:09 +08:00
baihailong
034d6d36d5 fix(sdk): The client no longer updates the fg.#22636239
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:42:38 +08:00
baihailong
e0db394306 feat(flashnode): alerting when the hit rate is lower.#22633499
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:33 +08:00
baihailong
2dbcda285b fix(client): client support configure remoteCacheFollowerRead.#22588611
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:31 +08:00
baihailong
1998c55397 fix(flashnode): add statistical metrics for flashnode.#22559602
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:30 +08:00
baihailong
4a6527d101 fix(master): The remotecache parameter is supported when creating a volume.#22575809
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:27 +08:00
baihailong
ecaa92b1be fix(flashcache): remoteCache update flashgroug twice one time.#22559610
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:26 +08:00
baihailong
5a6d4a70d9 fix(flashcache): volume remotecache configuration is invalid after restart leader master.#22550872
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:25 +08:00
baihailong
6f6d29a493 fix(flashcache): volume remotecache configuration is invalid after restart leader master.#22550872
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:24 +08:00
baihailong
d6b862922d fix(flash_cache): optimize get inode meta info when prepareCacheRequests.#22240020
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:23 +08:00
baihailong
3cbf7153ea fix(flash_cache): cache expires randomly in the 10% expiration time range.#22240020
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:20 +08:00
baihailong
7d186c8d52 fix(cache): overwrite or truncate leadto flashcache inconsistent.#22240020
Signed-off-by: baihailong <baihailong@oppo.com>
2025-08-07 15:19:18 +08:00
leonrayang
96bb7b66ef feat(doc): Add pic for introduction of flash cache
Signed-off-by: leonrayang <chl696@sina.com>

@formatter:off
2025-08-07 15:19:17 +08:00
leonrayang
30659caa84 enhance(client): enhance the check of slots for flashGroup create
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 15:19:15 +08:00
leonrayang
3f6243d8b4 update(client): debug and pass remote read process
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 15:19:14 +08:00
slasher
bf26b4bc3d feat(sdk): add common headers in sdk http client
. #22115371

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:13 +08:00
slasher
ecb0b49016 feat(util): add go ping for flash sdk
. #22200563

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:12 +08:00
slasher
c98e438814 feat(flash): enable volume config in master
. #22200580

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:11 +08:00
leonrayang
2e497bcd73 update(flashsdk): enable remote cache
Signed-off-by: leonrayang <chl696@sina.com>
2025-08-07 15:19:08 +08:00
slasher
d8396639d5 chore(cli): return errors to root of cmd
. #22200600

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:08 +08:00
slasher
a53b757e6d fix(flashnode): run testing in docker with no tmpfs
. #22200600

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:07 +08:00
slasher
2742e1ddb7 feat(master): add http args parser in master
. #22200600

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:06 +08:00
slasher
1877c03de8 feat(flashnode): turn on off client cache in master
. #22115371

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:05 +08:00
slasher
fccb8d1947 feat(flashnode): update client cache when status changed
. #22115371

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:04 +08:00
slasher
beee1f4c55 feat(flashnode): load flash ring in master
. #22200580

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:03 +08:00
slasher
459ec2f5e5 test(flashnode): add test case of flash node
. #22200518

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:03 +08:00
slasher
015776b952 test(master): add test case of flash cache
. #22115371 of 21940685

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:02 +08:00
slasher
44e56bb610 feat(flashnode): make slot with user defined
. #22200518

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:01 +08:00
slasher
d30f8cae5b feat(flashnode): run flashnode in docker
. #22115361

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:19:00 +08:00
slasher
a3e89bcfaf feat(flashnode): refinement flashnode
. #22200504 #22200509

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:18:59 +08:00
slasher
4a11077864 feat(flashnode): add cli of flashnode and flashgroup
. #22200531 #22200571 #22200580

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:18:58 +08:00
slasher
df73ec05fc feat(flashnode): add sdk stream of flashnode
. #22115361

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:18:57 +08:00
slasher
297477a2ed chore(util): add util of bloom fliter
. #22200490

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:18:56 +08:00
slasher
9101dc2fe8 feat(flashnode): add sdk of flashnode
. #22200490

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:18:55 +08:00
slasher
c4aaa43205 feat(flashnode): add flash node service in master
. #22200531 #22115371 #22200563

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:18:53 +08:00
slasher
b150a10a36 feat(flashnode): add service of flashnode
. #22115361 #22200518 of #21957840

Signed-off-by: slasher <mcq.sejust@gmail.com>
2025-08-07 15:18:46 +08:00
chihe
b1521e5a45 fix(master): fix CancelDecommissionDataNode for getApiList
close:#22922055

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:18:43 +08:00
chihe
625289c6cd fix(cli): do not enable trash when excuting operation for quota
close:#22922055

Signed-off-by: chihe <chihe@oppo.com>
2025-08-07 15:17:53 +08:00
yanghonggang
d00e08cc2d fix(blobstore): include cap check in alloc tests and reject size <= 0
close #3868

Signed-off-by: yanghonggang <yanghonggang_yewu@cmss.chinamobile.com>
2025-07-28 14:16:36 +08:00
slasher
ad376ea9a2 fix(access): update repairing volume cache
CodeDiskBroken
put: update cache cos put needs N+M-1 written shards
get: ignore cos get just need N+1 shards

. #1000242605

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-23 10:08:41 +08:00
yanghonggang
40f67d570b feat(blobstore): add blobstore bench tool
The bench tool is used to evaluate the performance of blobstore.
It supports performance evaluation for put, get, and del operations.

Fixes: #3795

Signed-off-by: yanghonggang <yanghonggang_yewu@cmss.chinamobile.com>
Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-22 10:07:55 +08:00
yanghonggang
513c04c21f feat(bssdk): support log file configuration for sdk client
This commit adds support for logging to a file in the blobstore sdk client,
allowing configuration of log file path, level, and size.

close: #3862

Signed-off-by: yanghonggang <yanghonggang_yewu@cmss.chinamobile.com>
Signed-off-by: zhangjianwei2 <zhangjianwei2_yewu@cmss.chinamobile.com>
2025-07-21 16:57:35 +08:00
slasher
131b332136 chore(ci): split run test for cubefs and blobstore
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-09 10:05:10 +08:00
xiejian
b363b75d99 fix(proxy): avoid alloc 0 volume from clustermgr
with: #1000217440

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:32:17 +08:00
Cloudstriff
ebb82972f6 fix(clustermgr): skip disk not found error when disk is dropping, avoid disk drop task blocking
with #1000200308

Signed-off-by: Cloudstriff <chenjiong@oppo.com>
2025-07-08 11:32:12 +08:00
slasher
514f9ac3b7 feat(access): add ordered configration of codemode to order reading shards
EC24P8 in 1AZ
Matrix: C(32, 8) = 10518300
Memory: (24 + 24*24 + 24*24*8) * 10518300 ~= 51 GB

EC12P9 in 3AZ, 7 constant shards in local AZ
Matrix: C(14, 5) = 18018
Memory: (24 + 24*12 + 12*12*8) * 18018 ~= 25 MB

. #1000199588

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:32:07 +08:00
slasher
e56f5ccd96 fix(access): using last token in client
. #1000203638

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:16 +08:00
xiejian
8ede90565d fix(shardnode): skip readIndex in shard.Stats() when service start
with: #1000176274

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:16 +08:00
xiejian
dcdb7fb681 fix(shardnode): do not compare idc and rack info with clustermgr when init
with: #1000176986

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:16 +08:00
xiejian
03cb728729 fix(shardnode): prevent seal part slices of local
with: #1000183861

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:16 +08:00
xiejian
0c6d15042d fix(shardnode): 1.remove raft group when apply remove member
avoid removed member still leader and clear raft data after all raft log applied
2. skip load disk which status is not normal in clustermgr
3.import gomonkey package

with: #1000176986

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:16 +08:00
mawei029
b99da2112f fix(bssdk): fix list blob count uint overstep the boundary, modify panic to span error
with: #1000179782

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:16 +08:00
xiejian
24f9066d35 feat(raft): print runtime stack when raft worker handle error
with: #1000167662

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:16 +08:00
xiejian
413c1de3c2 fix(shardnode): check readIndexFunc loaded in shard when preRWCheck
with: #1000167662

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:16 +08:00
slasher
daf016636f fix(access): return origin error if context cancel
. #1000042638

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:16 +08:00
slasher
2ebab23f6c fix(access): remove token if last slice only has one blob
. #1000155215

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:16 +08:00
slasher
d4288318de feat(ci): add docker for go 1.18
@formatter:off

close: #3782

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:16 +08:00
slasher
9ea30f5ac5 chore(docs): add rpc2 configuration
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:16 +08:00
Cloudstriff
21ef7c2a21 refactor(clustermgr): do refactor for v1.4.4 change
with #1000138128

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:16 +08:00
mawei029
fdf69e2596 fix(blobnode): fix the unstable test case
with: #1000102964

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:16 +08:00
tangdeyi
78df429486 fix(clustermgr): drop node/disk apply err return
with #1000102800

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:16 +08:00
tangdeyi
ca68b3f33f fix(clustermgr): rename ak and sk
with #1000095073

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:16 +08:00
tangdeyi
d48ca7debc fix(clustermgr): fix snapshot member nodehost store
with #1000095073

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:16 +08:00
mawei029
d29e116edc fix(bssdk): support multiple clusters can be configured when consul is empty
with: #1000045453

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:16 +08:00
xiejian
836738b7e1 feat(shardnode): distinguish item and blob key in storage
with: #22989410

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:16 +08:00
JasonHu520
ed2e209b9c perf(raft): entry cache supports quickly get
with: #23065907
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:16 +08:00
JasonHu520
41bf952511 fix(raft): the entry cache supports overwriting by index
with: #23065907
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:16 +08:00
mawei029
4867b6ca6d fix(bssdk): old leader disk is broken, choose new leader from the old units
with: #1000022240

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:16 +08:00
mawei029
c577b51612 fix(bssdk): old leader disk is broken, change leader disk
with: #1000014262, #1000010625

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:16 +08:00
JasonHu520
ff9a307699 fix(blobnode): remove bad unit which update id failed with cm
with: #1000010625

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:16 +08:00
xiejian
27327ab3ce fix(shardnode): replay raft log by ReadIndex() before start serve, remove load shard asynchronous
with: #1000004366

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
slasher
1ca6fc0554 feat(util): add util statistic for time delay
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
858895b18e fix(cli): cli support local file path as request body when PutBlob
with: #23109197

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
b6a2be88ec refactor(bssdk): not support GetBlob data when not sealed blob
modify alloc slice args count is real success count

with: #23109197

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
8274a65907 fix(shardnode): record slice count when SealBlob
with #23109197

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
fd185ed965 test(shardnode): optimize shardnode ut
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
74c69ccd41 fix(shardnode): remove failedSlice.Count check of AllocSlice api
full check of SealBlob args, update location when SealBlob

with #23109197

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
slasher
f7664eec0f feat(rpc2): cache server request and response in pool
. #23076156

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
e0a59713ff chore(bssdk): update code comment
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
f83500da17 feat(shardnode): clear shardnode list blob log, print blob when seal failed
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
a7ffe01736 feat(raft): clear raft log
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
fe107d3304 feat(shardnode): sync route version from clustermgr before start serve
with #23092404

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
42d0bbfa37 fix(bssdk): prevent route version rollback
with: #23031244

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
4b75603a06 fix(bssdk): fix location size after alloc slices
with: #23053900

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
slasher
f7472eeb2d fix(access): remove marker of listing broken disk
. #23065780

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:15 +08:00
tangdeyi
6ad085725c fix(clustermgr): loadroute when apply snapshot
with #23075869

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:15 +08:00
tangdeyi
89219627e3 tools(clustermgr): get inconsistent volume between leader and follower
with #23074437

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:15 +08:00
JasonHu520
cdb9a30565 fix(scheduler): if get dest disk shard info failed, task should be redo
with:#23080463

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
6acfc1ad4b feat(tools): cli disk drop stat, support specify some disk, use cmd context, find vuid not in cm
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
a05df55013 fix(shardnode): prevent reopen broken disk as normal cause raft panic
with #23075546

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
4bd8cfe927 fix(bssdk): update catalog route, leader disk is 0
and old broken disk was the primary node.
update route version when update shard stat

with: #23058322

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
9768679d98 refactor(bssdk): get catalog route, leader disk is not in disk units
with: #23058322

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
ed7e566648 fix(shardnode): 1.close rocksdb iterator in shard.
List which may cause memory leak
2.ensure the idempotence of the createBlob api

with #23045889 #23045869

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
0269a61764 fix(shardnode): optimize shard do checkpoint
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
ad2ace90d8 fix(shardnode): asynchronous execute handleRaftError to avoid deadlock
with #23025534 #23031244

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
717792ff45 fix(bssdk): check valid catalog when get from cm, fix acquire leader disk id is zero
with: #23031244

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
37557274e3 refactor(bssdk): specific delete error message, when not proxy service controller
with: #23031244

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
tangdeyi
4135173df1 fix(clustermgr): complete routeVersion field in full route fetch
with #23013508

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:15 +08:00
slasher
4094d85642 fix(rpc2): mutex client new session
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
f90f00efa6 fix(bssdk): fix update shard catalog suid info, when catalog change item is not leader
with: #23028809

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
c9ab48ba83 refactor(bssdk): optimize the delete process to reduce once get blob to shardnode
with: #23021397

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
6a35374908 feat(shardnode): add FindAndDeleteBlob api
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
eeb2bc9761 fix(shardnode): combine handle eio and remove disk raft group
with #23025534

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
tangdeyi
634cb93113 fix(clustermgr): fix nested lock
#23013508

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
4397e20b3e style(shardnode): add blobname as trace tag
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
ac919b9128 style(raft): remove unnecessary log
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
tangdeyi
c48913bc24 fix(clustermgr): fix chunk report err return
with #23020436

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
1cdfd8f95a feat(shardnode): inspect and clean up trash shards
with #22963391

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
828a7be5ac fix(bssdk): fix put at size is 0 because valid size is 0
alloc slice count dont change, update some log

with: #23012656

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
76b2a6e6e3 fix(shardnode): record Slice.ValidSize when alloc or seal
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
70f6955e1e fix(shardnode): 1. reject insert item with empty ID 2.fix ListItem
with #22989681 #22989410

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
81e6fb4310 fix(bssdk): use location crc when get blob from shardnode, seal blob send size; fix leader suid
with: #22959393

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
tangdeyi
eefca95507 fix(clustermgr): fix the deadlock problem caused by nested metalock and nodelock
with #23004457

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
a0f2790899 fix(raft): prevent removed raft group try process message
with #22953685

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
815a9cffda fix(shardnode): avoid disk instance cannot gc cause repaired disk can not reopen
with #22953685

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
83b87cb839 fix(rpc2): prevent unmarshal initialized proto struct cause EOF
with #22985316

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
19f006b1f4 fix(shardnode): 1.transfer leader return err with code 2.add update shard args check
with #22982347 #22982342 #22980415

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
986bb6c830 fix(shardnode): 1.prevent create blob with empty name
2.fix some error msg
3.fix seal and delete blob return nil when get space failed

with #22977114 #22981300 #22982188

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
35140e84ff feat(kvstorev2): fix rocksdb readLoop maybe panic when deliver rets
with #22953685

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
aded3ec020 feat(shardnode): handle raft panic by disk
with #22953685 #22963391

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
dd020f772a fix(bssdk): leader broken disk, wait new leader node
remove redundant get blob when delete blob

with: #22959393

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
18755e1113 fix(bssdk): switch leader node or update shard, we need to discard leaner units
with: #22959393, #22959050, #22952828

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
JasonHu520
d02d5ad0a9 fix(raft): manager no more create transport
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:15 +08:00
JasonHu520
7295732597 fix(raft): in the data synchronization process, persist the data first and then respond
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
6c5d75abde fix(bssdk): fix put blob all fail, seal slices is zero, put blob ok but seal fail
with: #22933065

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
a743a2a74b fix(bssdk): fix update shard when put fail at restart shardnode
with: #22941519

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
slasher
5c385715ff fix(cli): add log level setting for cli
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:15 +08:00
JasonHu520
0e0474bb64 feat(raft): handle raft group panic error
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:15 +08:00
JasonHu520
db3df98398 feat(scheduler): use err code replace detail
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
28c197a0e2 feat(shardnode): transfer leader when handleEIO
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
JasonHu520
759217aeab fix(raft): leader can not be leaner, need leader transfer
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
b1c8321beb fix(bssdk): add print log, wait shard node return no leader
default shard node retry time

with: #22918200

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
ecd4101463 fix(shardnode): prevent alloc slice for sealed Blob
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
ce75c10929 refactor(rpc): Solving serious problems in code scanning
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
0de3986825 refactor(shardnode): Solving serious problems in code scanning
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
82b7c61fbd refactor(raft): Solving serious problems in code scanning
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
slasher
587b825bc0 feat(cli): encode and decode json bytes in cli
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
7b57e9d894 fix(bssdk): convert error code 5xx key not found
with: #22912998

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
94e068fa65 fix(bssdk): private createBlob and sealBlob
with: #22918200

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
e20adade26 fix(bssdk): fix get leader shardnode with new diskID when connect refuse
with: #22918200

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
eb0499a6c9 fix(shardnode): convert kvstore key not found err to err with code
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
ba801c5c77 fix(shardnode): check request blob name length
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
slasher
80e0ac3b81 fix(rpc2): parse codec args in multi frames
. #22922602

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
ea3d9f9d38 fix(shardnode): excludes failed vid when AllocSlice
with #22916378

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
5b39560fa8 fix(bssdk): transform the error message in more detail, when list blob
with: #22905178

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
f97631d8eb fix(bssdk): sum body hashes and return it when put blob, modify print log
with: #22901344

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
mawei029
9d84c73c17 fix(bssdk): fix panic, modify get the disk punished status from cache
with: #22893213

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
1eef24a5dd refactor(kvstorev2): optimize SeekForPrev of kvstorev2
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
4c99c2a735 fix(shardnode): handle situations of failedSlice is empty of AllocSlice api
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
JasonHu520
aef6b4efc7 feat(blobnode): request new leader to update source unit
with #22812331

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
c20c28b17f fix(shardnode): prevent shard delete get leader which is itself cause dead lock
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
JasonHu520
fcd249e20a feat(blobnode): update source shard unit to learner
with #22812331

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
71d680d91c fix(shardnode): 1.load disk shard concurrency
2.remove trash shard
3.update listShard api
4.optimize lock nesting to avoid lock conflicts, stats api return node host
5.kvstorev2 add optimized default config
6.support about recover shard cli
7.optimize trace log time cost record

with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
xiejian
35df8a3f09 fix(raft): 1.remove entry cache put verify, fix get and get from
2.fix duplicated heartbeat request and MsgAppResp response
3.remove snapshot meta when storage close
4.fix outgoingSnapshot repeat close
5.add some log and fix log level and format

with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:15 +08:00
Cloudstriff
7fbc45344b perf(raft): optimized raft storage Entries and Term interface performance
with #22792157

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:14 +08:00
xiejian
bb272a12a5 feat(shardnode): add time cost detail of blob api in span
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
26086a3208 feat(shardnode): add padding when encode space key to avoid out of order
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
9d8d1c1996 fix(raft): 1.do not return error when process proposal msg failed because of not leader
2.storage keep both snapshot meta and hard state
3.fix applyUpdateRaw panic when found not value but do close
4.fix apply snapshot in statemachine while appy commited entries concurrently

with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
fbb8d2ca1d feat(shardnode): support tcmalloc and rocksdb stats api
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
6546e56e54 feat(shardnode): support tcmalloc
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
38f382d808 fix(shardnode): with member ctx when createRaftGroup to fix suid is 0 after apply snapshot
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
2d8a920fd1 feat(shardnode): support addShard cli tool
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
4b73769f5d fix(shardnode): fix restart panic after apply snapshot and tickElection
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
24edbfdbb1 fix(shardnode): encode kv storage data key with shardID
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
173a1cd157 fix(shardnode): fix panic problem when restart service with apply snapshot
supplement kvstore interface

with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
d0e5f634e1 fix(shardnode): fix fatal when shard is deleting but apply member change
flush when delete shard info, read/write check when do snapshot, do checkpoint

with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
JasonHu520
0d4321d8c1 fix(scheduler): fix cancel shard task failed
with #22812331

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:14 +08:00
tangdeyi
89d49fbe1d fix(clustermgr): put refresh into loadData cause of snapshot
with #22842525

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:14 +08:00
tangdeyi
da172ccb9d fix(clustermgr): validate arg when chunk is reported
with #22815976

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:14 +08:00
mawei029
92668d0b96 fix(access): need get twice shard stats from shardnode
with: #22751713 of #22751546

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:14 +08:00
mawei029
c2b33079e6 fix(access): need update shard route when connection refused, catalog skip leader disk 0
with: #22751713 of #22751546

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:14 +08:00
mawei029
6034ad9e03 feat(bssdk): tool sdk cli support perf tools to put,get,delete
with: #22751704 of #22751546

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:14 +08:00
mawei029
7dbdcb859a refactor(bssdk): sdk cli convert blobname byte to string, suid readable
with: #22751573 of #22751546

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:14 +08:00
mawei029
26a9fd2ac7 refactor(tools): drop disk stat, open rocksdb read only without depend on LOCK
remove duplicate disk path

@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:14 +08:00
slasher
9dad1ee7cf feat(access): punish volume disk and service with own value
. #22762717

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:14 +08:00
slasher
bed91e7765 feat(access): report metric of read and write
. #22762725

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:14 +08:00
tangdeyi
f7859160de fix(clustermgr): remove shardUnitInfo in shardItem
. #22711921

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:14 +08:00
tangdeyi
ddbc6f37ac feat(clustermgr): persistent raft members when applying snapshot
. #22711921

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:14 +08:00
mawei029
7e016da2a3 fix(bssdk): get blob fill crc, shard keys fix panic, shard not
leader update, get next end shard, cli readable

with: #22639120

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:14 +08:00
mawei029
6357ce9b75 feat(bssdk): blobstore cli support sdk cmd
with: #22639120

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:14 +08:00
slasher
c6b2152692 feat(rpc2): unmarshal none if response length is zero
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
30789df40d fix(shardnode): fix the bugs found with sdk test, and add unit test
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
slasher
e26e3ab749 fix(access): force flush proxy volume if context canceled
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:14 +08:00
JasonHu520
d7abb27eac refactor(scheduler): update log level for kafka message
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:14 +08:00
Cloudstriff
d6c6a775e0 feat(raft): fix query log term by index in raft storage
with #22656329

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:14 +08:00
Cloudstriff
6a3d90ca93 fix(kvstorev2): fix kv list without handleError function
with #22656329

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:14 +08:00
mawei029
84d6df46af feat(access): sdk put blob, delete blob from shard node
with: #22549147 of #22357707

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
7706c4b4b3 fix(shardnode): calculate crc when persist Location, update AllocSlice api
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
ae3626ac38 fix(shardnode): return err if repeat create blob, fix alloc slice check
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
tangdeyi
26fffe9b21 feat(clustermgr): optimize the judgment of shard init done
. #22672295

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:14 +08:00
slasher
2a98715983 feat(rpc2): bad request if parse parameter failed
. #22617142

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
3f0f1d2b31 refactor(raft): remove raft config resolver, only keep transport resolver
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
5a93938026 refactor(access): move location crc calculate func to common package
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
5a07148126 refactor(raft): fix ut, and some ticker config
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
Cloudstriff
c724be4931 feat(shardnode): add snapshot header support on apply snapshot progress
with #22656329

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:14 +08:00
xiejian
9f9cb91540 refactor(raft): simplify SealBlob api args
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
JasonHu520
596e12a83c refactor(blobnode): some changes for code style
with: #22481824 #22481829

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:14 +08:00
Cloudstriff
6bfdb3547c fix(blobnode): fix transfer leader without update shard member type
with #22615053

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:14 +08:00
JasonHu520
56bfb25102 feat(blobnode): access the client of clustermgr and shardnode
with: #22481824 #22481829

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:14 +08:00
JasonHu520
d5e206e18f feat(blobnode): add shard task for worker
1. add some ut shard disk repair task

with: #22481824 #22481829

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:14 +08:00
JasonHu520
67277bdf0e feat(scheduler): add shard disk repair manager
1. finish shard task process and shard disk repair

with: #22452167

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:14 +08:00
JasonHu520
19e3ec09e4 feat(scheduler): add shard node task
1. Update the scheduler and worker interaction protocols to support new
task types

with: #22417838

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:14 +08:00
JasonHu520
afaef8a55c fix(scheduler): fix task update volume failed and task retry duplicated in finish stage
with: #22481824 #22481829

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
6b1a33c26a fix(raft): fix raft transport panic when disk not finish load
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
6a0842c17c fix(shardnode): fix base transport singleflight key conflict
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
d2facf68d9 fix(raft): fix raft manager interface convert problem
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
2a57182e15 feat(shardnode): add shardnode related cli tools
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
ea7e25f25f feat(shardnode): support AllocSlice api, update SealBlob api args
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
4e563e095e refactor(shardnode): replace shardnode.Blob with commom.Blob
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
0e5d3eb8a1 fix(shardnode): fix the problem of incorrect assignment of unit learner
field in addShard process
fix rpc auditlog missing traceID problem, add shardnode log
fix update shard without suid
fix shard task routeVersion check

with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
xiejian
899fb14003 fix(clustermgr): fix cm AllocChunks failure causes concurrency issues
with #22565373

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:14 +08:00
slasher
e270e33102 chore(rpc2): add test server and client
tcp, transport, rpc, rpc2

@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:14 +08:00
slasher
d5e816db40 feat(rpc2): client retry on codec parameter
. #22637531

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:14 +08:00
slasher
fc32992b0b feat(rpc2): audit log on error handler
. #22617142

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:14 +08:00
tangdeyi
0612bfc8ff feat(clustermgr): blobstore cli add catalog cmd
. #22631156

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:14 +08:00
tangdeyi
aa952305d5 fix(clustermgr): remove shard compatibile mode code and record version
. #22416534

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
b5b77a1c97 fix(shardnode): fix test founded problems
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
20176fe835 fix(access): report punished service with threshold
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
f79491f781 feat(rpc2): add any codec for any value
. #22573386

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
ce3acc2279 fix(common): rename Location and Slice's json tag
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
c6c97d78b6 fix(shardnode): fix kvstorev2 problems
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
c697fc85dd fix(shardnode): fix raft related problems
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
241781a646 test(shardnode): complete unit test
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
c96e84040c feat(clustermgr): add space management
. #22416534

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
85e6c02538 feat(clustermgr): add route management
. #22477961

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
533caf5fcd feat(clustermgr): add shard management and catalog module
. #22477946

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
f20a06c956 feat(clustermgr): add shardnode disk and node management
. #22432395

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
Cloudstriff
6c8ece4ba6 feat(raft): add multi manager support at one transport only
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:13 +08:00
Cloudstriff
1d5cf15406 fix(raft): fix raft transport return nil connection when dial failed
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:13 +08:00
tangdeyi
b780eebda6 fix(clustermgr): add leader diskID of shard
. #22556044

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
7d1f94c043 feat(util): defaulter generic with float and integer
. #22575353

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
acc5db3371 feat(rpc2): add cli for simple request
. #22573386

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
ead8eda3c5 feat(rpc2): fixup some code of rpc2
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
fe1543e18e feat(shardnode): adapt rpc2 protocol
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
7a935eb42d feat(rpc): metrics of auditlog with struct
. #22566070

Benchmark_ParserRow
Benchmark_ParserRow-4         199876    5903 ns/op   2264 B/op    30 allocs/op
Benchmark_ParserAuditlog
Benchmark_ParserAuditlog-4   1000000    1053 ns/op    389 B/op     9 allocs/op

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
08ffaad88d feat(rpc2): transport with rdma connection and writev
. #22550097 #22551076

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
946ec8516f feat(rpc2): transport with context cancel
. #22548427

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
e41f7a497b feat(rpc2): add rpc2 server and client with json
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
ac953debb5 feat(rpc2): add intercepor of auditlog
. #22537366

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
12dd967d35 feat(rpc2): add intercepor of auth
. #22537366

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
fb6f396b3e feat(rpc2): change gogo proto stringer
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
fc2b033216 feat(rpc2): add checksum algorithm xxh3
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
917a57b2fd feat(rpc2): add package xxh3
. github.com/zeebo/xxh3

@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
d795ac793b feat(rpc2): router add interceptor
. #22520668

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
760e326b62 feat(rpc2): add lb in client
. #22517396

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
3a3572c456 feat(rpc2): add connection buffer io
. #22510825

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
07dcc69dff feat(rpc2): add testing of example
. #22505814

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
b7ea90c5b6 feat(rpc2): put parameter and result in body
. #22502053

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
cd0452cd51 feat(rpc2): add dialer and listener
. #22495341

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
27b2588bde feat(rpc2): request and response with checksum
. #22495324

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
d3e06e797a feat(rpc2): router add middlewares
. #22358085

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
bcec11314d feat(rpc2): make header stable if sent
. #22358085

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
7c6f4031fe feat(rpc2): request and response with crc checker
. #22358085

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
5b64ccee13 feat(rpc2): transport keepalive with ping pong
. #22478859

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
a554531ac6 feat(rpc2): add client connector and router
. #22358085

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
2ccf906337 feat(rpc2): add server stream
. #22358085

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
f4a5af920b feat(rpc2): add client stream
. #22358085

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
ece7650dea feat(rpc2): add client request
. #22358085

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
09d20443e9 feat(rpc2): add rpc2 transport with smux
. #22439641

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
79323f8623 perf(util): add mutex with run function safely and try lock
. #22309205

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
mawei029
4cfbf9e6d7 feat(access): sdk get blob, punish shard node
with: #22433440 of #22357707

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:13 +08:00
mawei029
7615877923 feat(bssdk): route shard manage, find shard. punish shard host
with: #22433410 of #22357707

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
5811746f43 feat(shardnode): support TransferShardLeader api, use suid index as ShardStats leaderIndex
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
d7e049fb2e fix(clustermgr): refresh skips unavailable disks when building alloctor
. #22532584

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
mawei029
0747a90254 feat(bssdk): init sdk, support shard node cluster. basic interface
with: #22433403 of #22357707

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:13 +08:00
slasher
576162ae21 fix(access): try to update volume in access request to blobnode
. #22411498

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
1b7b582fd1 feat(shardnode): define ShardStats with proto
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
64dbd0d4eb feat(raft): group Stat() api support peer detail
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
1be349ac62 feat(shardnode): complete shardserver transport and support raft stat api
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
bca402c128 fix(clustermgr): shard report not use pointer
with #22433442

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
d235fccfec feat(clustermgr): add get space by spaceID
. #22433442

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
809d081d09 feat(shardnode): add shard route version check and update
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
4dc732792f feat(shardnode): modify the naming of api parameters
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
3ddbdba340 feat(shardnode): volume manager and shardnode service
1.init volume and bid manager for allocate blob slices
2.complete shardnode service init
3. init shardnode client

with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
d9d0d004bc feat(clustermgr): rename shard epoch to routeVersion
. #22416534

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
xiejian
9107c71b36 fix(clustermgr): fix cm alloc chunks retry one more time
with: #22488148

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
3b348fa52c feat(clustermgr): add shardnode space and route api
. #22433442

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
tangdeyi
552cb2fd9f feat(clustermgr): optimize drop node process
1. dropping node triggers dropping disk
2. node is set to dropped as all disks are either dropped or repaired
3. add disk is banned if node is dropping

with #22358259

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:13 +08:00
mawei029
5d2d90e9b9 refactor(blobnode): limit disk concurrency, ctx cancel read write
with: #22358329 of #22357713

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-07-08 11:30:12 +08:00
xiejian
1626e0f9fc feat(api): init blob api proto, add missing license
with #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
6b84ed7f32 feat(shardnode): fulfill shard node broken disk process and disk reopen process
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
f3a83ecb47 style(shardnode): code static check and style refactor
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
94a53b6b97 feat(shardnode): shards report implements
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
e7b3be5195 feat(api): shards report proto definition
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
c06fdb8b3c feat(shardnode): update shard and remove shard implements
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
38fd15c74c feat(raft): add clear raft data support on remove raft group progress
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
xiejian
d6415c38f8 refactor(shardnode): fix code review problems
with: #22409856 of #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
xiejian
eb1a280bc0 refactor(shardnode): update grpc version
with: #22409856 of #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
xiejian
6627d67fd5 fix(shardnode): add item interface implementation, fix code merge problems
with: #22409856 of #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
xiejian
917cc5efb9 fix(shardnode): fix catalog module code error
with: #22409856 of #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
xiejian
725f4ec9e4 fix(shardnode): fix disk module code error
with: #22409856 of #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
xiejian
52a7ca1efc fix(shardnode): fix shard module code error
with: #22409856 of #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
b065cdfde2 refactor(shardnode): do code refactor for shard request proto change
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
29677b09be feat(api): replace shard id with suid on shard request api proto
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
a4562e5b8d feat(shardnode): initial shardnode module code framework
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
db9ffe9d1c feat(util): add util function implements
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
562c16fc63 feat(common): add multi raft implements
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
xiejian
75bc515d0b fix(common): update kvstorev2
with: #22409822 of #22357426

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-07-08 11:30:12 +08:00
tangdeyi
b7cade30e6 fix(clustermgr): basic clustermgr dev-branch for shardnode management
1. fix refactor code and test problem
2. add clustermgr api about shardnode and space

. #22360410

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
792f3654eb feat(api): add shard and shard constant definition
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
c032cfa902 feat(api): fulfill clustermgr api proto
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
Cloudstriff
a090a877d1 feat(all): add shard node role support on cluster manager
with #22357426

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-07-08 11:30:12 +08:00
slasher
c7d6b31fba build(build): remove blobstore path in blobstore binary
. #22361741

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:11 +08:00
slasher
1d1efefa15 perf(util): add mutex with run function safely
. #22309205

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:11 +08:00
slasher
c65a4aa48b perf(common): span assertion in object not interface
. #22361471

Benchmark_Span_Assertion
Benchmark_Span_Assertion/SpanImplement
Benchmark_Span_Assertion/SpanImplement-4    1000000000    0.5911 ns/op
Benchmark_Span_Assertion/SpanOperation
Benchmark_Span_Assertion/SpanOperation-4    1000000000    0.7124 ns/op
Benchmark_Span_Assertion/SpanInterface
Benchmark_Span_Assertion/SpanInterface-4     245477289    4.905  ns/op

Signed-off-by: slasher <shenjie1@oppo.com>
2025-07-08 11:30:11 +08:00
songguoliang
1c84e9503b fix(master): fix master node data partition check dead lock problem
Signed-off-by: songguoliang <songguoliang@kuaishou.com>
2025-07-07 19:35:31 +08:00
NaturalSelect
627118cd8b feat(cli): support change master leader by cmd
Signed-off-by: NaturalSelect <huangzhibin@xiaomi.com>
2025-06-27 14:49:32 +08:00
yanghonggang
7a116351bf fix(blobstore): ensure Delete returns correct failed locations on error
Previously, the Delete method did not fully comply with its interface contract,
which states that it should return the list of locations that have not yet been
deleted when an error occurs.

This change ensures:
- When args are invalid (e.g., illegal Locations), returns (nil, ErrIllegalArguments),
  as no deletion was attempted.
- For other errors, returns the list of failed or pending locations to allow proper
  handling by the caller.

This improves consistency and helps callers handle partial failures correctly.

close #3851

Signed-off-by: yanghonggang <yanghonggang_yewu@cmss.chinamobile.com>
2025-06-25 15:17:55 +08:00
clinx
ab38b43203 fix(doc): cli Change flashGroup to flashgroup for en doc
Signed-off-by: clinx <chenlin1@oppo.com>
2025-06-17 19:32:59 +08:00
xiaojunxiang
d3ec3ba9d3 fix(flashgroup): doc, Change flashGroup to flashgroup, otherwise it will cause an error.
Signed-off-by: xiaojunxiang <xiaojunxiang@kingsoft.com>
2025-06-17 19:32:59 +08:00
slasher
cc45cc7270 test(crc32block): fix testing of range to next block
close: #3844

Signed-off-by: slasher <shenjie1@oppo.com>
2025-06-11 17:17:46 +08:00
slasher
7069ce0a84 chore(ci): check commit has consecutive spaces
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-06-03 14:38:33 +08:00
slasher
89e599d7be chore(docs): remove unusefull files
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-06-03 14:08:15 +08:00
clinx
f36148c745 docs(docs): add title for flash document
Signed-off-by: clinx <chenlin1@oppo.com>
2025-06-03 09:54:07 +08:00
clinx
0bb17f21de docs(docs): update change log for v3.5.1
Signed-off-by: clinx <chenlin1@oppo.com>
2025-05-28 20:12:16 +08:00
clinx
1a7cfcab37 docs(docs): update yum rpm to 3.5.1
Signed-off-by: clinx <chenlin1@oppo.com>
2025-05-28 11:22:36 +08:00
clinx
19db2687fc fix(docs): Remove the description of redundant flash nodes
Signed-off-by: clinx <chenlin1@oppo.com>
2025-05-27 16:29:58 +08:00
Cloudstriff
3df63b1a3b feat(all): add EC24P8 codemode for ocs archive
with #1000145875

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-27 15:00:15 +08:00
clinx
155f6e11e0 fix(docs): An error occurred while loading images in the 'File Pre-read' document
Signed-off-by: clinx <chenlin1@oppo.com>
2025-05-27 11:15:31 +08:00
clinx
4808a0dc5e feat(docs): add docs about 3.5.1
Signed-off-by: clinx <chenlin1@oppo.com>
2025-05-27 09:53:51 +08:00
mawei029
44c168d562 fix(blobnode): fix the unstable test case, limit rate io
with: #1000102964

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-05-23 17:10:05 +08:00
Cloudstriff
235ecdd073 fix(clustermgr): set oversold_free_chunk_cnt into 0 when reset oversold_chunk_ratio into 0
with #1000138128

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-23 15:03:02 +08:00
Cloudstriff
fa335af66d fix(clustermgr): chunk ratio validation modify and increase report chunks num limit
with #1000088261

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-21 15:14:06 +08:00
xiejian
21d99fb9e8 fix(proxy): avoid no volumes in backup when first time switch
with: #1000128497

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-05-21 15:14:06 +08:00
Cloudstriff
1570264b3e feat(blobnode): reset chunk dirty into 1 when blobnode restart to report all chunks
with #1000112253

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-21 15:14:06 +08:00
slasher
d521e6f3e3 feat(cli): load clusters from consul in cli, change config clusters to slice
. #1000118768

Signed-off-by: slasher <shenjie1@oppo.com>
2025-05-21 15:14:06 +08:00
xiejian
45796304f5 fix(proxy): avoid proxy request 0 volume from clustermgr
with: #1000118387

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-05-21 15:14:06 +08:00
slasher
f12bf4ab8b docs(access): change access stream shard crc configs
. #1000114187

Signed-off-by: slasher <shenjie1@oppo.com>
2025-05-21 15:14:06 +08:00
slasher
0dd5cc376f feat(access): check shard get crc in access
. #1000114187

Signed-off-by: slasher <shenjie1@oppo.com>
2025-05-21 15:14:06 +08:00
slasher
b6e0936257 feat(blobnode): do not return crc in range shard get
. #1000114180

Signed-off-by: slasher <shenjie1@oppo.com>
2025-05-21 15:14:06 +08:00
Cloudstriff
bc0af29d84 fix(clustermgr): fix list disk api return zero when chunk_oversold_ratio is set
with #1000112253

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-21 15:13:51 +08:00
xiejian
912efc5139 feat(proxy): alloc volume according to both volume space and volume num
with: #1000100021

Signed-off-by: xiejian <xiejian3@oppo.com>
2025-05-21 15:13:51 +08:00
zhangjianwei
1700359efe feat(blobnode): add config to avoid hdd read iops when shard delete
with: #1000101801

Signed-off-by: zhangjianwei <jianwei1216@qq.com>
2025-05-21 15:13:32 +08:00
Cloudstriff
a28e1a56bc fix(clustermgr): fix ChunkOversoldRatio and VolumeOverboughtRatio validation
add sys config swith case

with #1000088261

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-21 15:13:17 +08:00
Cloudstriff
20c3de884c feat(blobnode): enable exceed the max chunk num in chunk create progress
with #1000088261

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-21 15:12:06 +08:00
Cloudstriff
14d37c87db feat(blobnode): add global config getter for blobnode
with #1000088261

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-21 15:12:06 +08:00
Cloudstriff
319953c846 feat(clustermgr): add ChunkOversoldRatio and VolumeOverBoughtRatio support
with #1000088261

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2025-05-21 15:12:06 +08:00
baihailong
92360e00a7 feat(docs): add FAQ
@formatter:off

Signed-off-by: baihailong <baihailong@oppo.com>
2025-05-21 14:44:31 +08:00
slasher
b7692def89 chore(ci): list all commits and json to local file
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-05-20 19:24:41 +08:00
heymingwei
ec6ca0af10 fix(blobstore): waiting apply snapshot finish when save new raft log
Signed-off-by: heymingwei <gongwilliam@163.com>
2025-05-20 11:38:58 +08:00
slasher
c5389d27ad chore(.git_hub-2): check commit message with letters
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-05-14 15:38:40 +08:00
zhangjianwei
6365c76349 fix(scheduler): adjust log levels to reduce unnecessary log output for blob_deleter
case-1: during period blobnode chunk compact, delete ops are not allowed,
        so scheduler bloc_deleter will receive a large number of
        `chunk is compacting` error logs when MarkDelete/Delete.
case-2: during period blobnode chunk migrating, delete ops are not allowed,
        so scheduler blob_deleter will receive a large number of
        `vuid readonly` error logs when MarkDelete/Delete.
Solution:
to reduce log pressure,
set ErrChunkInCompact/ErrReadonlyVUID to warning level

close #3794

Signed-off-by: zhangjianwei <jianwei1216@qq.com>
2025-05-13 15:36:04 +08:00
yanghonggang
d821466a1f fix(blobstore): rename CodeNoAvaliableVolume to CodeNoCodemodeVolume
The previous error code 'CodeNoAvaliableVolume' (801) contained a typo
and was semantically ambiguous. To avoid confusion with the similarly
named 'CodeNoAvailableVolume' (917) from Clustermgr, it has been renamed
to 'CodeNoCodemodeVolume'.

Fixes: #3790

Signed-off-by: yanghonggang <yanghonggang_yewu@cmss.chinamobile.com>
2025-05-13 14:50:05 +08:00
slasher
59df85ac57 feat(dial): add dial testing for blobstore
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-05-09 10:02:20 +08:00
slasher
be56f5aa66 perf(util): store pointer of bytes in bytespool
pkg: github.com/cubefs/cubefs/blobstore/util/bytespool
cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
BenchmarkBytespoolSlice
BenchmarkBytespoolSlice-4      23023845    50.60 ns/op   29 B/op    1 allocs/op
BenchmarkBytespoolPointer
BenchmarkBytespoolPointer-4    60203656    18.60 ns/op    0 B/op    0 allocs/op

@formatter:off

close #3786

Signed-off-by: slasher <shenjie1@oppo.com>
2025-05-06 17:19:47 +08:00
JasonHu520
ecff057179 docs(docs): update docs for scheduler of blobstore
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-04-28 16:46:43 +08:00
mawei029
34e6122824 docs(blobnode): update blobnode config qos docs
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 16:46:43 +08:00
mawei029
0aeb9e0adb refactor(blobnode): first wait token, and then read/write io
with: #1000064393

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
b1fa364a84 fix(blobnode): return user code for writing less body
. #1000076490

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
8f7c5f1a09 chore(cli): list all broken chunks
. #23065780

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
640cb1e6ed chore(blobnode): parse shard header at position
with: #1000070129

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
9b25f1aeb4 refactor(blobnode): config reload dont return json args, only return ok
with: #1000073970

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
47de7947f4 refactor(blobnode): limit the maximum depth value of qos config
with: #1000074167

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
d56977c8ca refactor(blobnode): datafile Read return io.ReadCloser, shard body io.ReadCloser
with: #1000064393

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
9492b9d139 fix(blobnode): fix release bytespool buffer when return reader, add ut concurrence read and write
with: #1000064393

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
2bd3104251 chore(blobnode): add cost time statistics when datafile delete shard
with: #23146103

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
82ddae18d4 feat(access): logging slow disk in get and put
. #1000037209

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
fc8d7649dc feat(blobnode): qos io hot change max concurrence limit count
with: #23146103

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
5d949cc7d7 docs(blobstore): add document of access directly read shard data
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
413a35c2c6 refactor(blobnode): qos io delete concurrency, hot change delete max wait count
with: #23079658

close #3720

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
tangdeyi
543a0b993e fix(clustermgr): fix heartbeat disk err return
with #23092315

close #3699

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
512e717991 feat(blobnode): write big/small io payload with header and footer
with: #23079652

close #3719

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
JasonHu520
a1fb8c24f8 feat(scheduler): add rate limit for delete
with: #23065620

+ #3720

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
dd35b8f085 refactor(blobnode): optimize merge multi small io into single write, optimize read alloc memory
with: #23079652, #23080447

+ #3719

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
70b557d945 chore(common): sized crc32 with go 1.17
Add back transport later for TODO

@formatter:off

close #3718

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
9059184293 feat(common): add crc32 sized block coder
. #23096104

+ #3718

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
9085a00da3 feat(common): avoid crc32 sized coder allocation
. #23074869

+ #3718

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
b4ed23d627 feat(common): crc32 encoder with append mode
. #22922161

+ #3718

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
ac2ac1549a feat(common): crc32 checker with fix mode
return fixed decodable crc body

. #22922161

+ #3718

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
f2cfda4126 feat(common): crc32 decoder with load mode
return head and data

. #22922161

+ #3718

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
427d0ae09c feat(common): add zero copy and partial content crc32 en-decoder
. #22922161

+ #3718

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
tangdeyi
3cb3892be7 fix(clustermgr): some minor bug fixes
1. put diskmgr refresh into loadData
2. fix check inconsistent vid
3. raft http server timeout can be configured
4. applyExpireVolume not double check volume expiration
5. applyAllocVolume not double check volume free size or health

with #23092315

close #3722

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
b31e484c9b fix(access): remove marker of listing broken disk
. #23065780

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
JasonHu520
42f85990a5 perf(scheduler): optimize delete process
with: #23065620

close #3721

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2025-04-28 11:30:09 +08:00
mawei029
a95dde77bf fix(blobnode): delete local disk after it is repaired, fix access DiskNotFound
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2025-04-28 11:30:09 +08:00
slasher
0d3ac68d65 feat(access): with other timeout in read only data shard
. #22782275

close #3717

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-28 11:30:09 +08:00
zhangjianwei
f4c9dac980 docs(cm): fix volume_inspect switch key
Signed-off-by: zhangjianwei <jianwei1216@qq.com>
2025-04-16 09:56:26 +08:00
liubingxing
3d51f7b6ba fix(cli): migrate metanode cmd cannot work with default limit mp count
Signed-off-by: liubingxing <liubbingxing@gmail.com>
2025-04-15 17:12:55 +08:00
liubingxing
e0ca16e6ad fix(cli): migrate metanode cmd cannot work with default limit mp count
Signed-off-by: liubingxing <liubbingxing@gmail.com>
2025-04-15 17:12:55 +08:00
liubingxing
ec394572c8 fix(master): fix chooseZoneNormal when multi zones and each one only has a node
Signed-off-by: liubingxing <liubbingxing@gmail.com>
2025-04-11 14:47:42 +08:00
liubingxing
cde83bd84f fix(client): dp near read do not work because NearHosts was replaced by Hosts
Signed-off-by: liubingxing <liubbingxing@gmail.com>
2025-04-10 15:28:04 +08:00
FourSpaces
b7635952e0 fix(objectnode): When S3 deletes an object, the empty folder is not recursively deleted
Signed-off-by: FourSpaces <cheng1483x@gmail.com>
2025-04-10 11:16:02 +08:00
FourSpaces
9cc87735fe fix(objectnode): S3 Folder not recursively deleted
Signed-off-by: FourSpaces <cheng1483x@gmail.com>
2025-04-10 11:16:02 +08:00
slasher
e8adeff5fa chore(build): try to use the newest command docker compose
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-09 16:41:55 +08:00
slasher
65889a5213 feat(util): try to wait with context in retry
cpu: Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz
BenchmarkWait
BenchmarkWait/success
BenchmarkWait/success-4     432140625    2.793 ns/op    0 B/op  0 allocs/op
BenchmarkWait/retry-3
BenchmarkWait/retry-3-4      97395789   12.27 ns/op     0 B/op  0 allocs/op
BenchmarkContext
BenchmarkContext/success
BenchmarkContext/success-4  449174043    2.641 ns/op    0 B/op  0 allocs/op
BenchmarkContext/retry-3
BenchmarkContext/retry-3-4    3177039  380.2 ns/op    232 B/op  3 allocs/op

@formatter:off

Closes #3758

Signed-off-by: slasher <shenjie1@oppo.com>
2025-04-09 16:41:55 +08:00
baihailong
11983f9888 feat(docs): add sdk user manual.
Signed-off-by: baihailong <baihailong@oppo.com>
2025-04-04 11:32:40 +08:00
baihailong
3e737aaf98 feat(docs): add sdk user manual.
Signed-off-by: baihailong <baihailong@oppo.com>
2025-04-02 09:54:27 +08:00
StevenLeiZhang
7a1921817a fix(build): grafana container can not start
close #3746

Signed-off-by: StevenLeiZhang <zhangleiic@163.com>
2025-03-31 10:15:06 +08:00
StevenLeiZhang
fbdd016bbb fix(build): run_docker.sh raises error
close #3743

Signed-off-by: StevenLeiZhang <zhangleiic@163.com>
2025-03-31 10:01:43 +08:00
slasher
fbca71d06c perf(util): scale the capacity of buffer in o1
BenchmarkBytespool
BenchmarkBytespool-4  21887019  67.65 ns/op  28 B/op  1 allocs/op

@formatter:off

close #3740

Signed-off-by: slasher <shenjie1@oppo.com>
2025-03-24 14:16:30 +08:00
leonrayang
a92c8452cf fix(revert): align and reuse the Packet struct to reduce allocated memory
This reverts commit f4c3f8aa40.

Signed-off-by: leonrayang <chl696@sina.com>
2025-03-21 15:37:39 +08:00
daimaishusheng
f4c3f8aa40 perf(metanode): align and reuse the Packet struct to reduce allocated memory
Signed-off-by: daimaishusheng <tangjiankun1226@gmail.com>
2025-03-21 14:59:11 +08:00
zhaoguangbao
5e22523086 fix(raft): fix readIndex not set index.
Signed-off-by: zhaoguangbao <zhaoguangbao@xiaomi.com>
2025-03-20 17:12:07 +08:00
FourSpaces
18a63b6a17 fix(lcnode): The randomness of goroutine scheduling sequence may lead to errors
Signed-off-by: FourSpaces <cheng1483x@gmail.com>
2025-03-20 16:44:56 +08:00
yanbin027
f25c5b9cc7 feat(client): "client support aheadread"
Signed-off-by: yanbin027 <yanbin027@ke.com>
2025-03-20 14:18:21 +08:00
jrchyang
c918d5cfce fix(build): enable multi-thread compilation in rocksdb
Signed-off-by: jrchyang <yujrchyang@gmail.com>
2025-03-19 11:12:34 +08:00
Victor1319
ee92370d58 docs(docs): update yum rpm to 3.5.0.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-03-19 09:47:13 +08:00
aaronwu2010
7d941bab3c docs(docs): Add one new single mode setup method.
Signed-off-by: aaronwu2010 <huochengwu@qq.com>
2025-03-18 17:36:02 +08:00
slasher
67a3eb55b9 fix(blobstore): unpacking imports in clustermgr api
@formatter:off

close #3725

Signed-off-by: slasher <shenjie1@oppo.com>
2025-03-18 11:18:23 +08:00
slasher
5c6586357c chore(testing): move mocks of iopool to testing
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2025-03-18 11:18:23 +08:00
leonrayang
7653850560 feat(doc): Update the ROADMAP of 2025
Signed-off-by: leonrayang <chl696@sina.com>
2025-03-18 10:16:56 +08:00
Victor1319
99bd130e53 docs(docs): add version 3.5.0 to change log.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-03-14 14:41:24 +08:00
Victor1319
bd38497923 docs(docs): remove upgrade 3.5 faq from docs.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-03-14 14:41:24 +08:00
yuxiaobo
45e4e5868d fix(blobstore): Entries returns a slice of log entries in the range [lo,hi)
Signed-off-by: yuxiaobo <yxbstorm@gmail.com>
2025-03-13 09:14:38 +08:00
Victor1319
67ef38bd41 docs(docs): update upgrade 3.5.0 title level.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-03-12 19:45:58 +08:00
Victor1319
2c13743c59 docs(docs): add faq upgrade file to sidbar.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-03-12 17:08:24 +08:00
Victor1319
1355cddd80 docs(docs): add feature hybridcloud file to sidbar.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-03-12 15:00:30 +08:00
Victor1319
e1b0c89706 docs(docs): correct some issuse abount docs. #23131054
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-03-11 18:42:50 +08:00
Victor1319
df9ff5fd79 docs(docs): add docs abount 3.5.0. #23131054
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-03-11 18:42:50 +08:00
zhaochenyang
13b9510a31 docs(doc): add cubefs lcnode config
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2025-03-11 18:42:50 +08:00
zhaochenyang
96b0587ca5 docs(doc): add cubefs lcnode design introduction
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2025-03-11 18:42:50 +08:00
Reliey
c2d9c0c31c feat(docs): update FAQ cases.
Signed-off-by: Reliey <616318745@qq.com>
2025-03-06 20:13:39 +08:00
slasher
7f1e02e668 chore(style): fix semgrep of ip v6 in document
Signed-off-by: slasher <shenjie1@oppo.com>
2025-03-03 11:07:46 +08:00
zjregee
1e55506ba3 docs(doc): Update the maturity level of cubefs to graduated
Signed-off-by: zjregee <zjregee@gmail.com>
2025-03-03 10:39:47 +08:00
shuqiang-zheng
3ae088f641 docs(doc): modify the csi driver image.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2025-02-28 21:03:22 +08:00
slasher
c713d78265 chore(style): fix up semgrep for ip v4 and v6
Signed-off-by: slasher <shenjie1@oppo.com>
2025-02-19 10:05:11 +08:00
slasher
1f851540ac chore(test): add semgrep ignore paths
Signed-off-by: slasher <shenjie1@oppo.com>
2025-02-18 17:53:24 +08:00
leonrayang
2e2250256c fix(docker): The filed version is obsolete due to the updated version of Docker Composeweq
Signed-off-by: leonrayang <chl696@sina.com>
2025-02-18 15:19:32 +08:00
Haifeng
5f9ccb2ccc update haifeng's email 2025-02-15 01:12:20 +08:00
yuxiaobo
2ba145511f feat(raftserver): the raft log is stored in rocksdb
Signed-off-by: yuxiaobo <yxbstorm@gmail.com>
2025-02-13 10:37:58 +08:00
aaronwu2010
f091672537 docs(doc): Fix some document mistake.
Signed-off-by: aaronwu2010 <huochengwu@qq.com>
2025-02-12 17:45:40 +08:00
slasher
f4d63c379c chore(github): upgrade codeql to v3
version: v3.28.9

Signed-off-by: slasher <shenjie1@oppo.com>
2025-02-12 10:03:23 +08:00
aaronwu2010
5c2e4153c7 docs(all): Add FAQ pages.
Signed-off-by: aaronwu2010 <huochengwu@qq.com>
2025-02-11 19:57:15 +08:00
Victor1319
23731ab7f5 fix(meta): fix metanode panic when append empty extents. #3648
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2025-02-10 09:45:16 +08:00
slasher
8e76523249 chore(github): upgrade action of upload-artifact
see more: https://github.blog/changelog/2024-04-16-deprecation-notice-v3-of-the-artifact-actions/

Signed-off-by: slasher <shenjie1@oppo.com>
2025-02-08 15:27:14 +08:00
Haifeng Liu
8b116fb918
Update README.md
graduated + can be run in the cloud
2025-01-17 22:31:40 +08:00
FourSpaces
121b2c87e1 fix(othertools): java libcubefs compilation failure caused by path errors
Signed-off-by: FourSpaces <cheng1483x@gmail.com>
2025-01-17 11:15:18 +08:00
tangdeyi
c255d8f92f fix(clustermgr): fix abnormal hardState commit
with #22897498

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2025-01-13 14:17:27 +08:00
morphes1995
4a96eeb26e fix(object): buffer optimization when calculate md5sum
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2025-01-10 15:56:35 +08:00
Reliey
b0cd15e1c4 docs(doc): Modify fsck clean instructions.
Signed-off-by: Reliey <616318745@qq.com>
2025-01-09 19:12:02 +08:00
gukaifeng
2e24163a51 fix(metanode): fsync the crc file after wirte
Signed-off-by: gukaifeng <gukaifeng@xiaomi.com>
Signed-off-by: slasher <shenjie1@oppo.com>
2025-01-08 18:01:42 +08:00
chihe
02b037cdc1 fix(doc): modify png path for blobstore
Signed-off-by: chihe <chihe@oppo.com>
2025-01-07 09:50:09 +08:00
baihailong
9a3794274c feat(docs): add cubefs compiles arm version instructions.
Signed-off-by: baihailong <baihailong@oppo.com>
2025-01-03 10:10:34 +08:00
morphes1995
fb4f541413 feat(master): conf persist in rocksdb; if raft use diverse port, old version nodes can't register
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-12-31 17:36:32 +08:00
morphes1995
ab398d669d fix(master): RaftPartitionCanUsingDifferentPort make effective after and all dn/mn upgraded
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-12-31 17:36:32 +08:00
morphes1995
bc08a804cb feat(master): add param to limit replica location;once raft use diverse port, can't be changed
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-12-31 17:36:32 +08:00
morphes1995
9a334cd7e8 feat(master): add param to control whether raft partition can use different port
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-12-31 17:36:32 +08:00
morphes1995
00a3ee193f fix(master): fix port inconsistent when create dp/mp during upgrading process
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-12-31 17:36:32 +08:00
morphes1995
848384c2a2 feat(master): node selector try to select nodes locate on distinct machine
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-12-31 17:36:32 +08:00
morphes1995
f4c7755316 feat(metanode): support multi metanode process using different port on single node
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-12-31 17:36:32 +08:00
morphes1995
b23df49eca feat(datanode): support multi datanode process using different port on single node
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-12-31 17:36:32 +08:00
zhaoguangbao
2beb480989 fix(raft): fix apply not return pool.
Signed-off-by: zbb <zbb9528@gmail.com>
2024-12-30 10:43:50 +08:00
Victor1319
d07fb451f4 refactor(master): refactor go code with golint. #22906448
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
8bb0c20885 refactor(all): rename java code dir for codeql check . #22906448
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
8bb1131500 refactor(all): refactor go code with golint. #22906448
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
0c406f55d9 refactor(master): resolve conflicts when picking to master branch. #22906448
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
7c0e8fa470 fix(meta): use a read-write lock to prevent concurrent access to clustername. #22915506
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
173dc9dbe1 fix(datanode): datanode can be removed with discard dp
close:#22771554

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
dac1a12d0a refactor(master): resolve conflicts when picking to master branch. #22906448
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
3396accd80 feat(projectstructure): reorganize the module directory in the root to a suitable subdirectory
close:#22458839

Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
Victor1319
c384557efe fix(meta): avoid panic when new export point. #22911241
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
041f312c6d refactor(fsck): ignore timestamp validation and support compatibility with older versions. #22911241
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
67d5dab1db fix(master): ignore abnormal dp when addVolStorageClass. #22908260
enable to skip check mp & dp forbidden status.

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
4c62f60ef1 fix(datanode): trigger disk error when read data from tiny extent
close:#22771554

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
911db95789 fix(datacmd): modify the alarm level of logLeftSpaceLimitRatio parameter parsing errors #22904699
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
9df314bceb fix(client): if Current is renanmed, create it again
close:#22900926

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
2963ffff6f fix(data): fix deadlock when load extent header from disk. #22900702
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
634e1abea3 fix(meta): add lock when range metapartitions. #22899488
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
154e7ba0d5 refactor(sdk): to avoid int range overflow in sdk retry logic. #22858505
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
77c2df26db refactor(meta): avoid load mp failed when get vol info error. #22858505
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
89efec9e52 refactor(util): support delete audit log in log module. #22858505
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
ba48924d95 refactor(master): remove useless code. #22890822
eliminate security vulnerabilities in the code.

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
edaf7b6f93 feat(cli): support cli to view inode detail information by inode id. #22867405
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
f57815426a fix(util): change clean internal of audit log to 10s #22858505
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
1b15a549bc fix(meta): update storage class as blobstore when file empty. #22883730
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
c9685d9713 fix(meta): execute sync func only when error is nil. #22883730
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
684ca7787f fix(meta): use local reserved variable to replace var in inode. #22883730
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
tangdeyi
b7cf39a0c3 fix(objectnode): optimize the logic of createBucket
with #22863348

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
b6ba24d842 refactor(meta): simplify calculation process of Quota for accuracy and performance
Close:#22788628

Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
Victor1319
b78bc6ac2e fix(sdk): fix client trash concurrent delete bug. #22862286
adjust trash dir lock lease time to 1 hour.

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
86e50fd1f5 refactor(meta): record error when RenewalForbiddenMigration failed.
#22871509

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
46fc3600aa fix(trash) if rebuild dir failed ,retry next time
close:#22867890

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
18d79eb33c fix(client): do not return when parent dir is created by other routinues
close:#22867890

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
1fdd359f56 fix(client): start schedule task for trash after metawrapper is initilized
close:#22867890

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
f9c00bb5c8 fix(meta): adjust the call order of the RegistConsul func to prevent concurrent modify to clustername.
#22873788

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
645076645a feat(metanode): optimize the extend memory allocate process in storeExtend, marshal and unmarshal
close:#22788628

Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
Victor1319
877954e167 refactor(meta): add txId in audit log for dentryOp. #22871509
refactor tx retry default cfg when tx is conflicted to over default timeout cfg.

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
ecc4444490 fix(master): modify logic for reporting metric for diskError
close:#22771554

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
498260102c feat(util): set the default rotate size for audit logs to 1G #22858505
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
72e458fb73 fix(metanode): not close syncAtime chan. #22871509
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
23bf2cd91f fix(bcache): no cubefscache directory causes an error when starting bcache.#22870633
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
3b6905a825 fix(sdk): support refresh dir log automatically. #22862286
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
2cf7602bda refactor(meta): refactor delete migration eks log. #22869219
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
d6630cb0e9 feat(sdk): use dir lock to prevent multiple trash from running concurrently. #22862286
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
edcad2d620 refactor(lcnode): rename variable name writeGen to leaseExpire. #22855673
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
306132d83d fix(util): modify clean logic of audit log and add test case #22858505
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
eec42fcec6 feat(cli): support cli to display vol used size based on dp media type #22853006
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
0b81daa151 refactor(meta): refactor client lease logic. #22855673
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
tangdeyi
3461b0873d fix(objectnode): close volume loadOSSMeta task when volume is deleted
with #22861848

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
1f5145a4a2 feat(fsck): add CheckMP command to detect inconsistency among mp copies #22779997
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
18ae97d850 feat(cmd): enable pprof configuration for signle-node deployment #22779997
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
0a7b6fda95 fix(meta): to avoid write EXTENT_DEL_V2_xx header twice. #22860885
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
14a53f9143 fix(libsdk): when start client NewStatistic one time.#22784741
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
78a4d47548 fix(sdk): optimize refreshSummary code.#22854234
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
791f044a45 fix(sdk): if not find inode of dentry when refreshSummary, skip it.#22828321
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
bc661949db fix(skd): add total access file size.#22826411
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
97583eba3c fix(skd): add directory access file info statistics of storage type.#22789777
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
d07f5c4fd0 fix(skd): add directory access file capacity statistics.#22784741
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
42b068c4e6 fix(sdk): optimize tool, use ReadDirLimit_ll instead of ReadDir_ll when get dentry.#22724074
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
43e1e007b7 fix(sdk): according to the access time statistics directory files.#22724074
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
498f7ecbbc feat(metanode): disable the process related to snapshots if snapshots are switched off
close:#22404072

Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
Victor1319
b99f674824 feat(meta): support return real atime for batchIget api. #22853172
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
f9c2f49204 fix(meta): don't block extent delete req when no success exts. #22852635
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
e3abe5fc97 fix(master): update bcache report info. #22845037
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
02c720959b fix(meta): when no error break for loop. #22832968
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
fa2e7a4cdf feat(master): support report whether enable bcache for client. #22845037
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
a5be7f5c7b fix(sdk): add panic log when invoke getRetryIntervalTimeOut.
#22840499

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
3a8f5eb3f8 feat(master): support query all client ip from master. #22834669
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
824098f801 refactor(lcnode): hybrid cloud lifecycle rule prefix check #22726594
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
d15462b427 fix(master): check zone type when add datanode node. #22832968
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
2030e66068 fix(meta): ignore get dp partitions error when create mp. #22832968
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Cloudstriff
c822f9de20 feat(rpc): add metrics filter config for auditlog
with #22357724

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2024-12-26 09:24:22 +08:00
Victor1319
ced8ca0978 feat(masterdata): add config to control whether vol read direct disk. #22818122
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
ab8217379e refactor(datanode): refactor data read and write performance. #22504692
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
6e9caa9131 refactor(meta): refactor dir lock and unlock logic. #22659556
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
8a7a949f96 refactor(master): set forbidWriteOfProtoVer0 as true for new vol. #22825400
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
a3a34e787f fix(master): fix RUnlock failed when invoke AllPartitionForbidVer0. #22822061
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
b894dfa082 fix(bcache): fixed bcache server can start multiple processes.#22808275
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
1fa202e06d refactor(sdk): for inner req, only support request mp leader . #22818553
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
2015d02b78 fix(client): optimize bcache switch names and debug logs.#22814877
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
7b8801af4e test(docker): support run in hybrid way for docker mod. #22816675
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
fba5a5d6f3 refactor(master): check vol forbidden write type when add vol storage class. #22814514
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
7c9e2aa7f9 fix(master): not show Unspecified storage class in allowed storage class. #22812125
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
3825cad310 refactor(sdk): support limit tiny extent buf size. #22811542
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
d6c575eff4 fix(sdk): when enable bcache maybe leadto bad file descriptor.#22812246
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
ad04648370 refactor(lcnode): hybrid cloud lc scanner skip trash dir #22797969
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
07762e229e refactor(meta): use bufio to write sanpshot data. #22785311
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
d66aa8a296 refactor(meta): delete migrate extent key when delete inode. #22785311
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
45ff2bf46e feat(metanode): optimize quota infomation storage to reduce usage of memory
close:#22788628

Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
dd3fd9616c feat(metanode): optimize memory usage of metanode, fields be allocted as needed in multi snapshot
close:#22785952

Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
Victor1319
244eeee62b refactor(meta): refactor migrate extent delete performance. #22785311
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
3c4c7ea65b refactor(meta): refactor variable name. #22785311
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
e922b4336c refactor(meta): reduce cpu cost for mp delete worker. #22785311
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
152d9b08f5 refactor(lcnode): hybrid cloud add auditlog for lc start stop and heartbeat #22771832
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
644508479e feat(metasdkmaster): support read quoram when mp no leader. #22782472
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
447fcc1d61 fix(master): support meta follower read. #22782680
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
44d1d95161 fix(meta): fix some issue about compatiable. #22780321
1. remove useless code.
2. fix compatiable bug abount dataMediatType.

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
60401d3e87 refactor(meta): remove useless code. #22716915
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
8209e99634 feat(client): trash can be disabled by sdk
close:#22775703

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
5c43034c5f fix(master): when performing meta-restoring, it is essential to check this action need to be executed.
close:#22771554

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
4ab0642da0 fix(sdk): enable config bcache only for clod data.#22770439
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
531fe6abec fix(client): enableBcache is invalid even if it was specified.#22770449
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
zhumingze
830781858e refactor(autofs): update default log and client path logic #22227137
Signed-off-by: zhumingze <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
40f7d2fc5c fix(meta): return opErr when append migrate extent key. #22771173
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
c36d41d8a5 refactor(master): add log for master raft op. #22766129
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
0c09436c98 fix(metanode): remove invalid filed for repsonese of getInode
close:#22768285

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
2f5ba609e5 refactor(lcnode): hybrid cloud avoid heatbeat timeout during adding lcnode #22768923
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
a69ba6978f fix(meta): fix unmarshal append inode bug. #22764528
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Reliey
96f4b0101b feat(datanode): add endpoint for setting enablePid in exporter and handle response building #22257509
Signed-off-by: Reliey <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Reliey
ddfc4c29b8 feat(master): add http interface getOpLog for data processing #22257509
Signed-off-by: Reliey <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Reliey
5f3c6e2d4a feat(cli): support reporting and viewing of cluster and vol dimension disk data #22257509
Signed-off-by: Reliey <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Reliey
3986329ed7 feat(mastercli): support datanode report dpOpLog and diskOpLog infomation. #22257509
Signed-off-by: Reliey <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Reliey
9ef9459cb3 test(stat): add testcase for statistic log when disk is full. #22637219
Signed-off-by: Reliey <zhumingze@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
a32476c9c5 fix(meta): fix unmarshal append inode bug. #22764528
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
bcf36ab04f fix(metanode): modify log level for fsmInternalBatchFreeMigrationExtentKey
close:#22757889

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
0eecc1fd85 fix(cli): fix some tiny issues. #22727537
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
abc2ab5912 refactor(master): support double check master media cfg type. #22727537
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
6fee55eb98 fix(meta): process extent list req as cache for blobstore ino. #22726594
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
ad404e752f feat(meta): hybrid cloud metanode quit starting if master not support the API getUpgradeCompatibleSettings
close:#22727537
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
7d22d9d451 feat(master): no allowed to start if config legacyDataMediaType not set correctly
close:#22716686
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
shuqiang-zheng
754d983c36 fix(meta): fix an unlocked error when getting the leader address and master address from the masterclient.
close:#22709182
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
2bfd708dcf refactor(metanode): submit inode to free forbidden migration by batch
close:#22701675

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
623a671184 fix(meta): empty file not check storage class. #22735527
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
7ba5908e16 fix(ci): set master config enableDirectDeleteVol as true
close:#22716686
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
2bced8d337 refactor(datameta): hybrid cloud optimize some logs related to upgrade compatibility
close:#22716686
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
67ef6faefc fix(raft): make the apply and apply snapshot processes mutually exclusive. #22720099
not truncate raft log before raft apply snapshot success.

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
692fa3e567 fix(meta): only file check storage class when unmarshal inode. #22735527
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
9f5fbba63b refactor(master): refactor variable name from cap to quota. #22731703
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
1eca4bf9bc fix(meta): avoid modify inode info in btree.#22575226
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
ce3439d199 feat(master): support replica storage quota limit.#22731703
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
2fc987ad17 refactor(meta): refactor metanode inodeGetWithAtime code. #22726594
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
5ca27c4483 refactor(master): suppor stat blob storage used. #22623271
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
168fa0418c feat(mastermeta): add LegacyDataMediaType in master cluster values, and metaNode fetch it from master.
close:#22716686
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
716aa7970a feat(masterdata): datanode quit starting if master returns mediaType not match when register
close:#22727852
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
87f06d51bb refactor(master): support show vol used space group by media type. #22718093
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
07a9e70386 refactor(meta): support concurrent delete extent. #22716917
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
f134d2699c fix(metanode): delete extent_del file when reach end of the file. #22706828
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
c6f2c51277 fix(metanode): recover panic when marshal inode failed. #22720099
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
97af707e01 refactor(meta): support compatible with v3.4.0. #22711062
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
1f704d8eea fix(master): hybrid cloud correctly set legacy zone's dataMediaType by config legacyDataMediaType
#22699128
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
99beb68c32 fix(master): when create replica volume and replica-num is less than 3, auto set follower-read as true
close:#22701504
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
46b540ac7c fix(master): avoid the Apply and Snapshot processes at the same time. #22660472
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
17b4921396 fix(fsck): fix nil pointer when get partition info
close:#22709584
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
d09a0d21e4 refactor(lcnode): hybrid cloud avoid panic if rule in doing is nil #22706069
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
c824423199 refactor(meta): pass atime when batch sync inodes atime. #22701675
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
c666468043 refactor(meta): support batch persist inode atime. #22701675
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d59f4e0b84 fix(cli): if create replica volume and replica-num is assigned 1 or 2, set follower-read as true
close:#22701504
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
a4dd4dfa92 refactor(lcnode): hybrid cloud config lc start time and disable expiration #22653422
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
658b89a4d5 fix(meta): increase the timeout when fetch info from master in register and mp start procedure
close:#22677404
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
3706792e52 fix(master): add log for persisting apply index
close:#22660472

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
3e060881ca test[java]: improve the operation types provided by TestCfsClient.java
close:#22687828
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
0a3f53cdfa fix(client): client data modification is prohibited if renewal failed
close:#22676203

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
0eb8f4127d refactor(lcnode): hybrid cloud admin lcnode auditlog #22675357 #22680253
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
18cbae3922 refactor(lcnode): hybrid cloud check vol delete before lifecycle task start #22666520
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
90de1d5705 fix(master): interface AdminVolAddAllowedStorageClass correctly returns success
clsoe:#22665897
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
83580e76df fix(sdk): avoid write on tiny extent handler again. #22657199
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d9ae754e15 feat(master): if mediaType is 0 in /dataNode/add, set the mediaType as conf item legacyDataMediaType
close:#22395995
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
883b15189d feat(metamastercli): hybrid cloud migration data usage statistics.
close:#22658297
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
c8de84516c refactor(sdk): log print dataPartition count of mediaType when refresh and select dataPartition.
close:#22600758
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
f25aa0734d feat(master): not allow a volume supports both replica storageClass and blobstore
close:#22395995
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
1452d45a88 feat(meta): put them into extent delete channel when deleting migration extents of type replica
close:#22605815
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
3677494108 refactor(sdk): support sleep before retry when write datanode failed. #22602256
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
f7a7ed66ee refactor(lcnode): hybrid cloud lifecycle validity check #22653422
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
532d35a5f1 fix(sdk): set innerReq when init metawrapper. #22645132
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
53d939fad6 fix(datameta): use default value if master not support the API AdminGetVolListForbidWriteOpOfProtoVer0.
close:#22644059
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
fecf14f159 feat(lcnode): set inner req true when init lc scanner meta wrapper. #22639641
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
d4d65ab8a0 feat(meta): not modify atime when get extent list for inner req. #22639641
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
2694a71d5d feat(meta): return real accessTime for lcnode get req. #22639636
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
63d0b94f57 feat(master): add an API to get volumes those set forbidden write op codes of protocaol version-0
close#22531837
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
f56ef231a1 fix(sdk): classifiy statistic file size and count for refresher tool.#22490031
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
e9fb2da0b1 fix(libsdk): libsdk support interface for cubefs tools.#22490031
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
9f7ffeb194 feat(masterdatameta): support volume to forbidden write operate codes of lower packet protocol version
close#22531837

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
9d23e1660f refactor(lcnode): hybrid cloud stop task if vol delete #22520059
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
a43f96d403 feat(dataclientmaster): support configuring datanode and metanode to forbidden
write operate codes of lower packet protocol version.
       	 close#22531837
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
7fa4bb8992 refactor(lcnode): hybrid cloud memory optimization #22401401
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
4939fa8f63 refactor(lcnode): hybrid cloud config use create time and log optimization #22616040
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
b65e2b7ca6 fix(meta): hybrid cloud not allow truncate if inode's actual storageClass is blob
close:#22571994
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
ca137d7c0d fix(meta): hybrid cloud fix panic when print log in function UpdateExtentKeyAfterMigration
close:#22568588
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
ade3d22670 refactor(meta): hybrid cloud add storageClass validation check when inode.storageClass changes
##22542807
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
282bb4bde2 feat(master): if crossZone true, support degrade to create partitions when only one zone available
close:#22548189
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
aa716d9fc0 refactor(lcnode): hybrid cloud stop scan retry and log optimization #22515436 #22538171 #22543543
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
8c7acf9714 refactor(sdk): updateExtentKeyAfterMigration print only warn log if inode's lease is occupied
close:#22543543
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
71a04cd570 fix(master): reset mp replica's usage stat of storageClass if the metanode is not alive.
close:#22490158
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
0d12d07d03 fix(client): to access the right storageClass when inode has migrated to blobstore
close:#22506168
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
7a1c28fc85 fix(SDK): in function ExtentClient.Read, return if get extents failed.
#22476752
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
e21dbd7a0a fix(metanode): if storage class is already the same with request, return directly
close:#22517222

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
037df5f5f9 fix(sdkclient): client compatible with older version server modules
#22400600
	@formatter:off
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
56b4c27f7a fix(lcnode): hybrid cloud support start one task and stop one task
#22423763
	#22502668
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
f385a3b49d fix(lcnode): hybrid cloud delete vol done result when start vol task #22496315
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
eca0d782fb fix(lcnode): hybrid cloud support start vol task and stop vol task #22326199
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
daf4dd9d51 fix(lcNode): hybrid cloud set followerRead as false when create ExtentClient
#22481972
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
4e3e4752e0 fix(lcnode): hybrid cloud fix panic in setLcMetrics #22466527
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
c496672d81 fix(lcnode): hybrid cloud task restart everyday and sync lc results #22449953 #22438986 #22454917
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
cc025affe3 refactor(client): hybrid cloud print warn log when OpMetaExtentsList returns proto.OpMismatchStorageClass
#22004328
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
57c8f26829 refactor(cli): hybrid cloud add storageClass tips in help messages
#22395995
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
42aaa6d19a refactor(meta): hybrid cloud optimize meta log in UpdateExtentKeyAfterMigration()
#22395995
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
7346d24e74 fix(lcnode): hybrid cloud task continue if lcnode or master restart #22326221 #22322540
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
f9d8d69a29 fix(meta): after deletion migrate extents of an inode
push it back info free list if it is marked delete.
	#22313098
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
e05a7c063e refactor(meta): hybrid cloud optimize some error logging
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
744b001d5c fix(lcnode): hybrid cloud new blobstore client only when migrating to blobstore #22404848
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
af298477f3 fix(master): check if volume's zoneName list has the resource when add allowed storageClass
#22395995
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
7ddd35e9ee fix(lcnode): hybrid cloud optimize lcnode scanning #22347010 #22401484
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
00b4ccdbce fix(meta): hybrid cloud if raft not leader when submit opFSMUpdateExtentKeyAfterMigration
response proto.OpAgain
	#22332725
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
6e06157948 feat(metalcnode): meta API OpMetaUpdateExtentKeyAfterMigration replies err details to lcNode
lcNode will print it to audit log
	#22327519
	#22385058
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
e2e9943f47 feat(cli): while creating volume, auto set crossZone as true if assigned more than one zone.
#22376966

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d1cbcb3d5e fix(master): hybrid cloud while creating volume, check datapartiton count of specific meidaType.
#22377936
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
4d6ee74eb2 feat(meta): hybrid cloud metapartition can start when failed to create blobStore client
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
5c20dc2109 feat(client): hybrid cloud only create blobStore client when volume's storageClass is blobStore.
close #22338879
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
acbe17f966 feat(master): if crossZone is set but there is only one candidate zone
still create volume in the zone.

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
3c3874b238 fix(meta): hybrid cloud Optimize the error message in audit log of lcNode when OpMetaUpdateExtentKeyAfterMigration failed
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
131bdc4ae8 fix(master): fixed usage of lock dpMissingReplicaMutex in struct warningMetrics
#22295296
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
114fa4f0d6 fix(master): close chan stopc only once, to avoid panic
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
bfc9130b8e fix(master): hybrid cloud when zoneName in datanode's conf file changed, make adjustments of topology.
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
0fe9b02796 fix(lcnode): hybrid cloud optimize lcnode auditlog #22295845
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
da6467830a fix(lcnode): hybrid cloud optimize conflict rule prefix #22311091
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
bc8ef471bd fix(lcnode): hybrid cloud optimize lcnodeInfo #22316398 #22326972
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
be1e6ba732 feat(master): hybrid cloud support assigning mediaType when manually create datapartiton.
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d7503fb7b5 feat(master): hybrid cloud support cross zone when creating volume
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
3b9ef65dbe chore(all): format code
@formatter:off

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
7a63703de6 feat(master): hybrid cloud support query cluster storage class info
close: #22310366
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
f029d45f6a feat(cli): hybrid cloud support query vol hybrid storage info
close: #22304812 #22304800
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
014396bdf9 fix(gosdk): hybrid cloud modify gosdk to be compatible with hybrid cloud
#22196087
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
f0b73c1e48 feat(meta): hybrid cloud check if sortedExtents is the same when inode's storageClass
it the same with UpdateExtentKeyAfterMigrationRequest
	@formatter:off
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
bf9e425de6 feat(master): hybrid cloud check destination datanode's media type must be the same
with the source node's when migration and decommission

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
9fd51b5119 fix(lcnode): hybrid cloud remove multiple registrations for /metrics
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
1d3fc46209 fix(lcnode): hybrid cloud fix panic in lcmgr scanning
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
c37b33479c fix(master): hybrid cloud when manually migrate a datanode, target node's mediaType
must be the same with the source node's.

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
90a667e789 fix(master): hybrid cloud when adding a replica, target datanode's mediaType
must be the same with the datapartition's mediaType

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
0c57fa34a9 fix(client): if volume is cold and no datapartition, not print log in updateDataPartition
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
09259d999d fix(sdk): hybrid cloud set VolCacheDpStorageClass when invoking NewExtentClient
#22196488
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
c57484daca refactor(master): hybrid cloud refactor the check of createVolReq
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
36393590a2 fix(ci): hybrid cloud fix test case TestCreateVolWithDpCount
#22196488
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
0ec2d1c2b6 fix(cli): hybrid cloud show if the node is set as read-only when get node information
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
a137f68eb5 fix(meta): hybrid cloud when create root inode, set its storageClass as the volume's VolstorageClass
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
0173aa7e48 fix(master): hybrid cloud fix test cases of creating datapartitions
#22196488
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
ae18253359 fix(meta): hybrid cloud reduce debug log in function (*metaPartition).deleteWorker()
#22171638
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
3561f231ba fix(cli): fix the display of the 'metapartition check' command of the cfs-cli tool
clsoe:#22152841

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
84b095887a fix(metanode): hybrid cloud operation for CreateInfo should check storage class for client request
close:#22151482

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
ed9545c7a7 feat(lcnode): hybrid cloud add lcnode auditlog (#22067931)
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
cb588b1d42 fix(metanode): hybrid cloud if storage class for inode is already the same
with request for UpdateExtentKeyAfterMigration, return nil

close:#22112938

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
309d89f1a3 fix(meta): hybrid cloud check err when invoking (*Inode).UnmarshalInodeValue
close:#22112817
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
23d03a0592 fix(sdk): revert some modify for sdk.#22148104
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
31ed67cb5e fix(sdk): closeStream leadto panic. #22148104
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
7414081277 fix(sdk): hybrid cloud revert modify for streamer's multi server and fix in other way
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
283c22f717 fix(lcnode): hybrid cloud 1. fix LcNodeInfoResponse panic; 2. set snapshot idleNodeCh
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
3a0c807faf fix(lcnode): hybrid cloud snapshot apply on lcnode
1. add firstDentry may cause panic if channel close
	2. reset snapshot verinfos before add verinfo
	3. add TaskResults in GetOneTask to avoid adding tasks repeatedly
	4. support notify multi snapshot tasks
	5. delete snapshot failed retry

Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
e62a84fb95 fix(metanode): hybrid cloud when ek is nil but mek is not nil, no replacement occurs.
close:#22037699

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
d87bb469d4 fix(metanode): hybrid cloud reset the flag of inode when migration ek is deleted
close:#21959956

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
0fc7a908e0 fix(sdk): hybrid cloud waitForFlush blocked leadto deadlock.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
d33fc14119 fix(sdk): hybrid cloud add sdk debug log
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
b701abdf6a fix(meta): if inode is dir, not allowed to set migrate extents in UpdateExtentKeyAfterMigration
close:#22076233
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
7af36c991a fix(meta): if the storageClass of inode is the same as requested storageClass then return err.
close:#22067659
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
b34d8efcdb fix(meta): hybrid cloud function TxCreateInode should reply the storageClass of the inode.
close:#22060598

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
bb6e16be21 fix(lcnode): hybrid cloud NewEbsClient when ebsAddr is not nil (#22049286)
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
3a4a9f4be9 fix(sdk): hybrid cloud one streamer has multi server maybe leadto bad file descriptor.#21989411
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
5c911b1cc0 fix(meta): hybrid cloud to correctly determine whether the inode should be deleted when unlink
close:#22037078
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d7730f56ae fix(meta): hybrid cloud in function MarshalInodeValue, write length 0 to buff if migrate sortedEks is nil
close:#22031037
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d823d1f616 fix(meta): hybrid cloud set migrate storageClass in function fsmInternalDeleteMigrationExtentKey
close:#22029476
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
440058e0e5 fix(client): hybrid cloud assign open flags when opening file
close:#21969712

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
80ca15784b fix(client): hybrid cloud fix migrate check condition
close:#21969712

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
cf4dadf5bd fix(client): hybrid cloud create ebs reader or writer when storage class is changed
close:#21969712

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
3b5ab67dba feat(client): hybrid cloud if storage class has been changed, do not raise err when reading file
close:#21969712

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
a010a7b39d feat(fsck): hybrid cloud support scanning migrate-extent garbage
Signed-off-by: true1064 <true1063@163.com>
2024-12-26 09:24:22 +08:00
chihe
c642f0a29d fix(client): hybrid cloud if file is stored in ebs, do not fetch extentkey list from metanode in lookup operation
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
b6443f3b2b fix(clientmetanode): hybrid cloud remove duplicated logs for deleteMarkedInodes
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
9e688d76ae fix(metanodeclient): hybrid cloud if encountering storage class mismatch error, do not retry
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
f97367ad20 refactor(metanode): hybrid cloud remove unnecessary code
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
c296833d8e fix(metanode): hybrid cloud Save list element.prev pointer when the element is removed
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
318aca2758 fix(lcnode): hybrid cloud multipart migration to blobstore
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
7c185c7cf5 fix(client): hybrid cloud update file node cache if storage class had been changed
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
334200af1c feat(metanode): hybrid cloud inode marshall support empty file
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
52f2317304 fix(metanode): support empty file migration
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
08665970fd fix(lcnode): multipart migration to blobstore
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
baijiaruo
582b6f19aa fix(data): properly set the param isBackupWrite when invoking ExtentStore.Write()
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
ddfceda455 fix(metanode): hybrid cloud modify the logic of checking deferred deletion of migration extent key
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
cf5db8b6b6 fix(lcnode): hybrid cloud set delayDelMinute after migration
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
de7d0693b5 fix(metanode): hybrid cloud notify follower to delete migration ek if update migration ek failed
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
75658db207 fix(metanode): hybrid cloud Correct the type conversion error for logCurrentExtentKeys function
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
5b867906d2 fix(lcnode): hybrid cloud DeleteMigrationExtentKey before migration
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
698311248a fix(master): hybrid cloud set ebsblockSize when add blobStore to volume's allowedStorageClass
Signed-off-by: true1064 <true1063@163.com>
2024-12-26 09:24:22 +08:00
true1064
ec1975db4c fix(master): while creating a volume, if blobStore is in req.allowedStorageClass
but req.ebsBlockSize is not assigned, set it to default value.

Signed-off-by: true1064 <true1063@163.com>
2024-12-26 09:24:22 +08:00
chihe
13de007c2e feat(metanode): optimize extentkey logging logic of fsmUpdateExtentKeyAfterMigration function
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d3f1d3d734 feat(master): hybrid cloud Support querying the inode count and used size of volumes and metapartitions by storage class.
Signed-off-by: true1064 <true1063@163.com>
2024-12-26 09:24:22 +08:00
chihe
21d4c73847 feat(metanode): hybrid cloud Support for deleting discard migration data
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
e9f6dca415 feat(metanode): hybrid cloud Delaying deletion of data before migration
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
044a94d26a feat(metanode): hybrid cloud The deletion of inode support hybridcloud
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
4173cc9f4d fix(master): hybrid cloud When updating a volume, ebsBlockSize can be modified if allowedStorageClass contains blobstore.
Signed-off-by: true1064 <true1063@163.com>
2024-12-26 09:24:22 +08:00
chihe
0bf7b9b83e fix(client): hybrid cloud update openforwrite for reused streamer
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
ae018c58cd refactor(lcnode): hybrid cloud add start time in heartbeat
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
576d4ce771 refactor(clientmetanode): hybrid cloud add debug log to check opMetaExtentsList value
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
7a0f5d43bd fix(metanode): hybrid cloud copy storage class from HybridCouldExtentsMigration of inode when executing migration
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
30b8a98bbf fix(metanode): hybrid cloud Copy WriteGeneration and ForbiddenMigration when getting inode from btree
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
5f5fd78af9 fix(metanode): hybrid cloud fix writeGen rollback to 0
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
d207dcc6fe refactor(lcnode): hybrid cloud fix lcnode log
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
94dcb991db feat(metanode): hybrid cloud add audit log for migration
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d9c01f0af5 fix(client): hybrid cloud Fix some places where the original condition
should be changed to "vol storageClass is blobstore".
	Adds field volStorageClass to ExtentClient for this purpose.
	Remove field volumeType from ExtentClient by the way.

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
5baafaef59 feat(meta): hybrid cloud provide an API to modify inode's ctime, for debug/test purpose.
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
75925990f1 refactor(lcnode): hybrid cloud lifecycle transition
1. add debug service

Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
a62522f2f5 feat(meta): handle compatibility when old client send create request without field StorageClass
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
3de7e847a9 feat(master): handle compatibility of master when older version upgrade to hybrid cloud:
(1) auto set mediaType of datanode, zone, datapartiton by config legacy "legacyDataMediaType" and persist;
	(2) auto set storageClass of volume by config legacy "legacyDataMediaType" and persist;
	(3) if need to rollback master to older version, need to do nothing, just replace to old master and restart. because hybrid cloud master only add new fields to meta by not changed old fields.

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
88567fbf65 fix(master): hybrid cloud if vol.volStorageClass is blobStore, add allowedStorageClass is forbidden.
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
6f6ea34f2a fix(master): hybrid cloud amend the way judging if the volume has snapshot version, in update allowedStorageClass procedure.
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
a2c2d4a704 fix(metanode): hybrid cloud assign migration hdd ek in UpdateExtentKeyAfterMigration
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
4c73097a3d refactor(lcnode): hybrid cloud lifecycle transition
1. close extent client
2. use StorageClass_Replica_HDD and StorageClass_BlobStore
3. scanner init AllowedStorageClass
4. enhance lifecycle parameter check
5. add extent client for write

Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
eb2d65002b refactor(metanode): hybrid cloud 1.Simplify the logic of updating extent key after migration
2. reset inode reserved when excute marshall operation
	3. initial ebs client in mp
	4. remove cold vol or hot vol check in client and objectnode

Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
5f4ee4eacb fix(metanode): hybrid cloud fix bug when update extent key after migration
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
505015cd17 refactor(metanode): hybrid cloud add api for get full inode infomation include eks
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
f637d0cc19 fix(metanode): hybrid cloud check sortedEks is nil when excute fsmAppendExtentsWithCheck
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
0bc93129de refactor(client): hybrid cloud only file opened with write request needs to forbidden migration
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
zhaochenyang
d89812aaf0 feat(lcnode): hybrid cloud lifecycle transition
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
284ca0d211 feat(metanodeclient): hybrid cloud support hybridcloud data migration
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
35ed550795 feat(master): hybrid cloud forbidden AdminCreateVersion API because hybrid cloud not support snapshot version yet
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
8a5bc8583a feat(master):make the snapshot version and multiple storageClass mutually exclusive in a volume.
Because now multiple allowedStorageClass can not support snapshot version.

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
9d2bf3b483 feat(mastercli): add API to add storageClass to volume's allowedStorageClass list
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
5bcc78bb43 fix(master): in create vol procedure, update datapartition view cache right after the creation of datapartitions
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
5936cdfe8d fix(master): amend some logs
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
443199e0b0 fix(client): hybrid cloud only clear dp when volume storage class is blobstore
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
1f227e722c fix(master): in create volume, sort allowedStorageClass after check if append volStorageClass info
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
10685ceba0 fix(master): when updateVol, check that req.VolStorageClass should be in vol.allowedStorageClass
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
d250c3041a fix(master): check if the cluster has resource to support req.VolStorageClass when create vol
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
f04993070b fix(master): some fix about datapartition creation
(1) while creating dp in vol creation, check dp count by mediaType to judge if success.
	(2) when background periodical check if need to create dp, skip volumes whose createTime is too recently, to avoid background create dp while volume is creating.
	(3) display mediaType of dp in cfs-cli cmd "volume info -d"

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
9d0d2c9fef feat(master): hybrid cloud sort AllowedStorageClass[] while creating volume
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
1cdf8fcd39 fix(metanode): hybrid cloud fix log panic in function of deleteMarkedEBSInodes
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
51554785e3 fix(master): hybrid cloud not set zoneName as default value if not assigned in the create vol request.
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
4815a61444 fix(client): hybrid cloud fix bug about checking media type of dp
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
3373c73b4f fix(master): ybrid cloud not use var pointer dataNode if not got it from cluster, to avoid panic
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
7a7b663b6c feat(mastercli): hybrid cloud vol.volStorageClass can be changed by "cfs-cli volume update"
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
347208f189 refactor(clientmetanode): hybrid cloud check inode/vol storage class when checking vol type
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
1f9dab0eda feat(masterclientpreload): add property CacheDpStorageClass to volume.
CacheDpStorageClass is used to inform SDK which storageClass to use when access cache dp.

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
92d1d54832 feat(master): volume supports multi mediaType based on the refactored codes from v3.4.0
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
14d7e0e19c feat(masterclientcli): hybrid cloud add property mediaType to datapartition
(1)master: when creating vol, master creates dps of each mediaType according to vol.allowedStorageClass
	(2)client: when select dp to do append write, choose dp with spcific mediaType according to inode's storageClass

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
6cafecdb7d feat(masterclientcli): add property volStorageClass and allowedStorageClass to volume
now volType is not uesed while creating volume, but is maintained for compability

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
3081a30168 feat(master): hybrid cloud add mediaType property to zone
(1) zone mediaType is set as the first add-in datanode's mediaType
	(2) once zone mediaType is set, all datanodes in the zone must be the same mediaType.
	(3) the cmd 'cfs-cli zone info' shows zone mediaType.

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
029d1b359e feat(clientmetanode): hybrid cloud support change inode storageclass when updating ek
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
7a915e87e0 feat(client): hybrid cloud supports the option to choose SSD or HDD data partition
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
e1442f7de1 feat(clientmetanode): hybrid cloud support renewal inode forbidden migration
Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
7211b09cd6 feat(meta): hybrid cloud inode supprot hybrid-clound
2.client read/write support hybrid-clound

Signed-off-by: chihe <chi.he@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
f70b3cfe38 feat(masterdatacli): hybrid cloud add datanode's mediaType
for module master and datanode; the cmd 'cfs-cli datanode info' can show datanode's mediaType

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
fd428b4706 refactor(master): fix confilcts when pick 3.4.0. #22906448
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
dee812aded fix(master): canAllocDp compatible with 3.4.0 before
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
bff1bbca48 fix(metanode): inodeOnce marshall compatible with meta 3.3.2
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
1d196732dc fix(client): enableBcache is invalid even if it was specified.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
9c6438e631 feat(metanode): optimize quota infomation storage to reduce usage of memory
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
65cb8077e4 feat(metanode): optimize memory usage of metanode for multi snapshit
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
68a27c700d fix(client): goroutine for trash to build parent dir would not quit
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
1e8ffbeb73 refactor(client): if subdir is empty from cfg file, use cfg from option.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
b57d898709 fix(doc): fix path for cfs-arch-ec.png
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
60dbc1ac30 feat(docs): update Governance related documentation
1. Clarify the responsibilities of the TSC, maintainers, and committers.
	2. Fix the issue in security reporting as incorrect email address for reporting vulnerabilities.
	3. Clarify the governace of SIGs
	4. Add a link to the governance section in README.md for emphasis.

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
cf07bf261d fix(master): check quotaManager for vol when executing ListQuota
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
e4ebd42ae0 fix(metanode): delete extent_del file when reach end of the file.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
1113795e49 fix(meta): reset reserved flag when marshal inode.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
8faf83077f fix(meta): consider snapshot ver when unmarshal extents
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
8f9035c3a1 fix(meta): inode unmarshal logic is compatible with subsequent versions.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
bae8527daa fix(meta): check error when unmarshal inode value.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
d858cc505b fix(metanode): do not update Accesstime when excuting getInodeTopLayer
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
c43dd5eda2 fix(metanod): if clusterEnableSnapshot is not enbale, do not apply VersionOp
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
d3912d2042 fix(datanode): check initPartitionSize when calculating progress
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
46930ab462 refactor(raft): use decimal format to print number in raft log.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
1d79c40a29 refactor(raft): use decimal format to print number in raft log.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
cuishuang
a9c6e74bbf fix(util): fix slice init length
Signed-off-by: cuishuang <imcusg@gmail.com>
2024-12-26 09:24:22 +08:00
leonrayang
7558f203ec feat(metanode): enable metanode with version 3.4.0 compatible with master 3.3.2
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
fc71116a51 fix(client): enable Datanode with version 3.3.2 compatible with client 3.4.0
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
0647717f79 fix(client): enable Client with version 3.4.0 compatible with 3.3.2
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
5dbd5ba05e fix(master): compatible with 3.3.2 metanode(used for memory)
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
26a1a160b4 fix(master): only check offline with old version datanode
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
852dafafd2 fix(datanode): if dpBackupTimeout is not set, then do not delete back up directories.
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
111f9e9903 feat(dataemeta): cluster switch on snapshot take effect on module handle protocal process
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
d4d64fb931 feat(metanode): enable rollback from 3.4.0 to 3.3.2
1) Add protocal opFSMSentToChanWithVer, enable compatible during update version because []proto.ExtentKey has no version info
	2) Update inode marshal and unmarshal process, do not persist version 3 flag if not eable snapshot

Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
baihailong
003aa07305 fix(client): failure to mount other directories when the mount point is abnormal.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
a3a05ee4bd fix(client): alarm the mount point has been mounted incorrectly.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
f761097bde fix(master): set the cluster's stop channel to nil upon receiving the signal to prevent it from running again
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
cd73e762e4 fix(datanode): iterating through the cache of dps and disks when stopping space manager
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
0be1a11ad7 fix(master): some goroutines are stateless and do not require waiting for their transfer to a stopped state
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
fc5ac71931 fix(master): enable master exit process more ellgantly
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
6f3872f6db fix(client): when creating extent failed for disk full, remove dp from selector
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
cd5376cc20 fix(datanode): launch sechedule for raft log before staring raft when loading dp
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
1442c33a29 fix(master): if the replica being decommissioned is the one intended for decommissioning, no error is reported.
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
1888c9b8a8 fix(raft): if the previous member change did not return, reject the submission of the next member change
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
443b18aa28 fix(master): delete decommission disk from rocksdb when datanode is decommissioned
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
448ab8e54f test(data): add testcase for datanode op log when disk is full.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
b1cadb29d1 fix(client): client's extents cache should not be forcefully updated that may ignore the ek on flight in some scenarios
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
baihailong
845f106a8a fix(sdk): client update extents from meta and drop extents in cache leadto ek conflict.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
2ea78a48f1 fix(datanode): if reading applyid fails when loading dp, then delete from disk cache
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
ab6d34d481 fix(datanode): use lock for getPartitionsAPI
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
c52f8b35eb fix(master): release token before resetting decommission dst
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
a3fb3d301b fix(master): if the decommission fails and requires retry, set the status to 'mark' only at the end of the decommission function
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
ac54435341 feat(datanode): increasing retry interval when DataNode connects to Master during startup.
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
3dfdcf354e feat(master): improve the exit process in multiple goroutines to ensure proper resource cleanup and graceful shutdown.
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
a831f1e5a7 fix(mater): delete decommission disk record form rocksdb
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
65ce9f8b7c fix(master): deadlock for datanode and nodeset
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
8a76004126 fix(master): exiting the decommmission goroutine when leader is changed
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
1a003718ee fix(client): check whether the mountpoint has been mounted when mounting.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
36076b8cd8 fix(master): fix deadlock for deleteMissingDp
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
2645319183 fix(data): donot persist applyId by raftForce
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
96dd26f01a fix(master): the dp's zone selection logic supports decommission operations.
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
716044fd94 fix(master): when setting a RestoreReplica operation to fail
check if another replica is currently undergoing the offline process.

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
b8742d469a fix(master): use lock to set dp markDecommission
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
78bbb209f2 feat(datanode): enhance the preformace of the stat for disk opertion
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
W9068822
6e51516a8c feat(stat): datanode disk and dp operation log
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
82666bb21a feat(clientmaster): enable clients to report their version and flow information to the master
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
eb5787a7b3 fix(master): traverse all nodesets to check if dp is decommissioning
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
64afe661cb fix(master): do not check size of datanode when retrying to decommission special replica
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
ef8183b648 fix(cli): remove unnecessary commands for cli
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
f0e631799e fix(sdk): client update extents from meta and drop extents in cache leadto ek conflict.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
c3131b01f9 fix(datanode): use dp leader real size as to be repaired size.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
323133a9f9 fix(datanode): return error if receive OpDeleteDataPartition when disks are not loaded
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
39c07de007 fix(sdk): return err if getting extents failed in function ExtentClient
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
4428c3b64c feat(master): enhance the effectiveness of log output
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
043b559ba4 fix(master): use the largest volume ID in load vols process
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
53107ee952 fix(datanode): modifying the regular expression for backup directory:
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
61e0ab3aa6 fix(master): fix deadlock for getDataPartitionsView
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
da33bc2068 feat(cli): support raftForce for datanode decommission by cfs-cli
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
46157d2c06 refactor(all): resolve conflict when pick commit from 3.3.2 to 3.4.0.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
79579bacd2 fix(data): check response reqId to avoid data painc.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
493795f8db fix(master): reset bad dp report info after dp recover.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
27c66007c5 refactor(master): report datanode count which can alloc dp.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
a792521c86 refactor(master): add replica num label when report dp no leader metrics.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
2ba73be6be feat(master): add vol total count metric info.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
7b979b17e6 fix(data): fix delete gc data failed bug.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
d3fa6c9244 fix(metanode): fix tx bug in concurrent use case.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
79ce6ff6cf refactor(master): reduce dp&mp detail report info
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
5ef3f6c59b refactor(master): reduce prometheus metrics count for master.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
69ca9cd0f4 fix(metanode): only sync at among replicas when inode is not nil
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
3a4a54f3bc fix(cli): use macro value instead of hard code
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
f5484d9d98 fix(master): fix the bug that reset transaction info when update vol info.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
b1b5d5bd2b fix(meta): fix panic bug when delete empty dentry info.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
b5252646d0 refactor(cli): refactor cli hint message when update transaction info.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
716e489036 fix(master): return no leader for request before master change leader success.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
c869155d09 fix(master): fix http pool test case fail bug.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
a305b32b9c feat(master): cli support setting for persistting accessTime
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
136ee9704e fix(master): persist accesstimeInterval and EnablePersistAccessTime
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
6970b4570d feat(master): support set trashInterval with cli
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
be565f6609 refactor(server): refactor http connect pool when comminute with master.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
f721730cfb feat(client): reduce the massive getVol request from Quota routine
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
a487a828b4 feat(master): api for enable/disbale persist for accesstime
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
0f64f5010e feat(master): api for setting accesstime vaild interval by vol
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
58194e8f36 feat(metanode): add sdk for querying accesstime of inode
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
e92c00b752 feat(metanode): persist accesstime by raft
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
93c516105f fix(master): simplify the process of followe read jugement and resolve issues
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
Victor1319
88e0dc05dd fix(master): fix some potential deadlock issues.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
a2bc46218b fix(meta): fix delete dentry conflict with tx bug.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
80d6990c09 fix(datanode): check if host[0] exist when creating repair task
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
52c74006fe fix(datanode): stop raft if replica is deleted when StartRaftAfterRepair is finished
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
89af159e54 fix(master): remove replica on decommission dst by force when rolling back
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
68d6b4d09d fix(master): get disk path for replica when getting info for datanode
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
45686739d8 fix(datanode): use localServerAddr instead of replica[0]
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
808b47bddb fix(master): reset ignoreDecommissionDps when marking disk decommission
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
shuqiang-zheng
aefb1b2bd9 refactor(cli): update instructions for freezing clusters
@formatter:off
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
2313a509a7 fix(raft): set no leader for the application layer when raft stopped by panic.
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
c9b97d24a2 fix(master): reset RestoreReplica when resetting decommission status
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
f70f1ee08c fix(master): fix dead lock by getting copy of dp map
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
51240b319e fix(master): donot reset decommission status for datanode
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
efcc3ae581 feat(master): add a new schedule task for checking meta for replica meta
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
3ca9065975 fix(master): remove redundate replica from partition.replicas on master
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
2fb56e7282 feat(master): auto delete backup directories
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
tangdeyi
7ae6457821 fix(objectnode): separate read and write buffers
with

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
54e2526793 fix(datanode): delete backup directories by async
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
fa25b696ee fix(master): do not persist disk status when querying progress
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
1f16566a92 fix(data): correctly determine the extent type in function handleBatchMarkDeletePacket
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
d6e066f899 fix(util): improve the code style according to warnings from code check 2024-12-26 09:24:22 +08:00
chihe
78c6f40829 fix(master): return timeout error for setting restore replica status
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
a348b6acb3 feat(master): api for removing backup directories on disk
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
8d68de0acc fix(datanode): reduce the locking time when building heart beat
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
a2da2149c3 fix(master): only show running and failed decommisison disk when executing queryAllDecommissionDisk
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
65acca7fdd fix(datanode): write process skip check between offset and dataSize while do repair
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
ed7fc8d2af feat(master): add the switch for function of volume snapshot management
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
leonrayang
6792a393df fix(master): simplify the process of FolloweRead jugement and resolve issues
Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
chihe
c3a2fb153c fix(datanode): to accelerate the traversal of dp by goroutines
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
51cce6dd7d feat(master): add disk info when executing queryDecommissionToken
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
3bd78424ba fix(master): special replica dp with raftForce hungs in checking status of new replica
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
eedea5771e fix(datanode): remove extent from extentInfoMap if extent is deleted
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
bf9fdff28d feat(master): save previous decommission error msg when decommissioning another replica
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
dd9b9be7f5 fix(datanode): remove dp 0 from disk error set when recovering disk err
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
a2724225ec fix(master): enable disk when excuting datnode cancel decommission
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
44f9fce264 fix(master): when rolling back special replica dp.
only need to delete decommission src if new replica is recovered

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
e07aeac619 fix(fuse): if vol name not match regexp when mount, return failed immediately.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
6cc809434a fix(master): initialize reportTime for datanode when leader changed
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
shuqiang-zheng
2a9d99bdf9 fix(datanode): remove the gc operation to reduce the time required to create a dp.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
eb1daccedc fix(master): show ignore decommission dp when displaying decommission progress for dataNode
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
a8d8c96072 fix(master): do not delete decommission disk from list when recover task is submitted
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
d479a79f73 fix(master): optimize the calculation of datanode decommission progress
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
0ffe25c31d fix(datanode): reload dp by parallelism during recovering bad disk
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
67f5db91ce fix(datanode): only print root path in log
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
7d05d431e6 fix(datanode): optimize the process of constructing heartbeat packets.
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
8ad898a1e4 fix(master): modify logic of updateDecommissionStatus for datanode
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
39d2baa37e feat(master): add requestID for sending admin task
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
69f6960be9 fix(metanode): fix the issue that can't clear data when delete inode.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
8f48f3ac85 fix(client): if vol not exists, mount return failed immediately.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
f02d60be3d fix(master): remove disk from decommission list if it is recoverd
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
bb0f337f9e fix(master): do not decommission disk with cancel status
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
7a29ac6ba1 fix(datanode): reset diskErrorCnt when recovering bad disk
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
21463372eb fix(client): when volume is deleted, cfs-client need to exit.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
bc2867049f fix(datanode): fix panic raised by function of ExistDir
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
3d2137e545 refactor(client): reduce buffer chan size to reduce memory when client idle.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
ac5cde2a05 fix(client): fix the issuse of continuous memory growth on client side.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
43d8903d10 fix(master): skip auto add replica when dp lost leader
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
292f2abd45 feat(master): add api for recovering bad disk
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
75f8f1e07a fix(sdk): access nil pointer leadto cfs-client exit.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
0e7ab29565 refactor(client): add config to control stream op max timeout.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
b0faae7248 refactor(client): amplify retry interval once overwrite failed to avoid disk io busy.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
c297ded67e fix(master): mark disk as disabled when decommissioning disk
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
857d71602a refactor(data): use tryRun to limit delete io.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
Victor1319
c11b55c18b refactor(client): refactor random write retry strategy.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
d9ee4e5130 feat(data): limit memory used
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
313c9b0448 fix(master): cluster info show readable time
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
leonrayang
1b9b48f846 refactor(master): refactor the code of vol struct and cluster struct
:

Signed-off-by: leonrayang <chl696@sina.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
c551e5dbc2 fix(data): return limited io if failed to delete batch extents
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
6aa160552c feat(master): persist datanode bad disk
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
f36c40c07f fix(master):if all replica is unvaliable, mark dp as failed
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
942adaed7d feat(datanode): add debug log for heartbeat
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
5365949f7c feat(master): support config decommission settings
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
NaturalSelect
8386685205 feat(master): parallelism check dp meta
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
8401562ef6 fix(master): only choose from the specific zone in function canWriteForNode
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
54402d030a fix(master): clean decommission list when leader change
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
442714ad20 fix(master): wait for setting RestoreReplica of dp during MarkDecommissionStatus
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
145e53d2f6 fix(datanode): rename root dir of dp to dir with backup prefix.
when execute decommisison with raftForce

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
04ac20e2cb fix(master): calculating the decommission progress of the disk includes ignoring dps.
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
a650776bbf fix(master): execute recoverReplicaMeta when replica is IOError
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
a98a67358d fix(libsdk): add IsDir and IsRegular for java.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-12-26 09:24:22 +08:00
baihailong
92edf40c3e fix(fuse): MountOption add parameter DisableMountSubtype 2024-12-26 09:24:22 +08:00
chihe
cab9ec44f3 fix(master): dp is decommissioned by raftForce, disk manager check recovery for new replica
close:#21938887

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
true1064
ff8b40abae refactor(masterclient): add new field in the client's response of retrieving the partition view
indicating whether the volume is read-only.
	close:#21938435
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
2832f093f9 fix(master): dp with sepcical replicum delete raft failed, don't reset decommission src
close:#22054632

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
23421c97e2 fix(master): put success or failed dp to decommission list when reloading meta adjust debug level
Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
W9068822
d99ef09572 fix(master): fix get DP compression data, update cached data when needsUpdate is true
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-12-26 09:24:22 +08:00
shuqiang-zheng
0ebf6ffc26 feat(reconstruct): gofmt by gofumpt.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-12-26 09:24:22 +08:00
chihe
8baaee5ad9 debug(master): add debug log
close:#21980258

Signed-off-by: chihe <chihe@oppo.com>
2024-12-26 09:24:22 +08:00
zhangjianwei
6c91bc491e fix(clustermgr): fix kvDBPath argument for blobstore-cli cm listAllDB
kvDBPath introduced in 4961b84378,
add list volumeUnits when listAllDB.

now command is:
blobstore-cli cm listAllDB <volumeDBPath> <normalDBPath> <kvDBPath>

Signed-off-by: zhangjianwei <jianwei1216@qq.com>
Signed-off-by: slasher <shenjie1@oppo.com>
2024-12-24 14:11:28 +08:00
tangdeyi
359e9184a6 fix(clustermgr): remove raft wal try flush
Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-12-23 16:41:59 +08:00
Haifeng Liu
34947b1d08
Update my email address 2024-12-22 18:59:15 +08:00
JasonHu520
501f5de86e feat(common): add DisableProposalForwarding config to raftserver
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-12-19 11:21:18 +08:00
Reliey
c67c9b1b3e docs(docs): Modify rpm package download domain name
Signed-off-by: Reliey <616318745@qq.com>
2024-12-05 14:58:42 +08:00
Reliey
0d08deb406 feat(docs): add fsck tool usage
Signed-off-by: Reliey <616318745@qq.com>
2024-12-05 14:58:42 +08:00
aaronwu2010
c492f6c445 docs(kernel): Add kernel client design document
Add kernel client design and usage document.

Signed-off-by: Wu Huocheng <wuhuocheng@oppo.com>
2024-12-03 09:27:26 +08:00
Kursat Aktas
1e6552cb23 Introducing CubeFS Guru on Gurubase.io
Signed-off-by: Kursat Aktas <kursat.ce@gmail.com>
2024-12-02 14:43:02 +08:00
Reliey
1374333970 docs(docs): Correct incorrect commands in quota and autofs
Signed-off-by: Reliey <616318745@qq.com>
2024-11-29 16:41:09 +08:00
mawei029
b98e825a67 docs(blobnode): update blobnode config docs
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-11-12 11:01:05 +08:00
slasher
6c0b9bc00b chore(common): add new context function of tracer
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2024-11-12 11:01:05 +08:00
mawei029
1f8eb1f584 fix(bssdk): fix background delete when context is canceled
. #22765250 of #22357724

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-11-12 11:01:05 +08:00
mawei029
4224c19de0 fix(blobnode): fix blobnode hot change background mbps limit, it should less normal mbps
. #22759812

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-11-12 11:01:05 +08:00
mawei029
7653daafee refactor(blobnode): qos limit read and write bandwidth, discard overload io
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-11-12 11:01:05 +08:00
mawei029
8b4fa82ae1 fix(blobnode): fix blobnode lost disk report ok, when it is already being repairing
@formatter:off

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-11-12 11:01:05 +08:00
JasonHu520
2d90e0f96e perf(scheduler): update volume cache failed error replace with error code
@formatter:off

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-11-12 11:01:05 +08:00
mawei029
d3575df4d4 refactor(blobnode): put/get shard eio return error code 613
. #22358264 of #22357713

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-11-12 11:01:05 +08:00
mawei029
05155c157d refactor(blobnode): add log for register node, fix return error when boot disk
. #22358264 of #22357713

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-11-12 11:01:05 +08:00
mawei029
c7ece9f76f refactor(blobnode): when a faulty EIO disk occurs, disk read and write requests are disabled
. #22358325 of #22357713

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-11-12 11:01:05 +08:00
slasher
3d33e4f992 fix(access): force to send message to proxy and client cleans up
. #22411498

Signed-off-by: slasher <shenjie1@oppo.com>
2024-11-12 11:01:05 +08:00
chihe
6d8981bf9c feat(doc): add version 3.4.0 for doc
Signed-off-by: chihe <chihe@oppo.com>
(cherry picked from commit 10e31d808de3eb00195bfeffa2393b23b499667a)
2024-10-30 18:51:07 +08:00
chihe
189c7dd946 feat(doc): update doc for v3.4.0
Signed-off-by: chihe <chihe@oppo.com>
2024-10-30 17:36:30 +08:00
leonrayang
206d5ddadf feat(doc): Add rule for Peripheral Projects and describe the rule of joining and achriving
Signed-off-by: leonrayang <chl696@sina.com>
2024-10-29 17:23:35 +08:00
slasher
d18001a133 docs(access): fix limit of access upload and download
Signed-off-by: slasher <shenjie1@oppo.com>
2024-10-23 14:18:16 +08:00
Reliey
a28ac40474 docs(docs): Modify the details of the documentation in the dev-guide section
Signed-off-by: Reliey <616318745@qq.com>
2024-09-27 12:39:30 +08:00
Reliey
db8c58074a docs(docs): Modify the layout and text description of security_practice.md
Signed-off-by: Reliey <616318745@qq.com>
2024-09-27 09:28:46 +08:00
Reliey
64e7afaba2 docs(docs): Modifie the log.md and config.md in the ops chapter to be easier to understand
Signed-off-by: Reliey <616318745@qq.com>
2024-09-26 15:17:39 +08:00
Reliey
09806ae0b2 docs(docs): Revise capacity.md and zone.md to be easier to understand
Signed-off-by: Reliey <616318745@qq.com>
2024-09-26 11:30:03 +08:00
mingwei
cdbbfa5656 docs(ops): add auto-ops docs
Signed-off-by: mingwei <gongmingwei@oppo.com>
2024-09-25 19:19:38 +08:00
Reliey
13b92e50d7 docs(docs): Add some details and problem solutions to cluster-deploy documentation
Add some details to cluster-deploy.md

Signed-off-by: Reliey <616318745@qq.com>
2024-09-25 10:32:34 +08:00
Reliey
b8815f9423 docs(docs): Modify the description of the trash document to be more accurate and add some details
Signed-off-by: Reliey <616318745@qq.com>
2024-09-24 14:10:43 +08:00
Reliey
3923fbe5f5 docs(docs): Correct inaccuracies and typos in feature-cache documentation
commit message

Signed-off-by: Reliey <616318745@qq.com>
2024-09-20 09:21:08 +08:00
leonrayang
6e8066dcd5 feat(doc): Update the information of the maintainer members
Signed-off-by: leonrayang <chl696@sina.com>
2024-09-18 22:33:49 +08:00
Reliey
208451d4c6 docs(docs): correct the inaccuracies and typos in the module design section
commit message

signed-off-by: Reliey <616318745@qq.com>
2024-09-18 20:25:26 +08:00
leonrayang
4dde46d30b feat(doc): Update governance documentation to improve the accuracy of vendor-neutrality
Signed-off-by: leonrayang <chl696@sina.com>
2024-09-13 15:40:27 +08:00
Reliey
0b83e56790 feat(doc): Add more details on the single deployment for better governance
commit message

signed-off-by: Reliey <616318745@qq.com>
2024-09-13 10:18:49 +08:00
Reliey
65bd5eb51f feat(doc): Add instructions for yum deployment under arm architecture
commit message

Signed-off-by: Reliey <616318745@qq.com>
2024-09-11 15:45:38 +08:00
leonrayang
dbeab8ddbb feat(doc): Update OpenSSF Best Practices to silver badge
Signed-off-by: leonrayang <chl696@sina.com>
2024-09-10 09:57:08 +08:00
xiejian
19f6ea3ca7 fix(clustermgr): fix cm AllocChunks failure causes concurrency issues
with #22565373

Signed-off-by: xiejian <xiejian3@oppo.com>
2024-09-03 09:53:23 +08:00
leonrayang
e053fa3f07 feat(doc): Add CODEOWNERS to improve control over code merge approval priorities
Signed-off-by: leonrayang <chl696@sina.com>
2024-09-02 15:58:41 +08:00
leonrayang
959b61e3f4 enhance(doc): Organize documents of ecology
Signed-off-by: leonrayang <chl696@sina.com>
2024-09-02 11:30:23 +08:00
leonrayang
6617aa1eb7 feat(doc): Update OWNERS.md
Signed-off-by: leonrayang <chl696@sina.com>
2024-08-28 18:34:56 +08:00
leonrayang
2a041e7765 feat(docs): Update Governance related documentation
1. Clarify the responsibilities of the TSC, maintainers, and committers.
2. Fix the issue in security reporting as incorrect email address for reporting vulnerabilities.
3. Clarify the governace of SIGs
4. Add a link to the governance section in README.md for emphasis.

Signed-off-by: leonrayang <chl696@sina.com>
2024-08-28 17:14:02 +08:00
Huweicai
5ebd3e7e19 feat(build): check interface exist before using
Signed-off-by: Huweicai <i@huweicai.com>
2024-08-23 13:51:58 +08:00
shuqiang-zheng
3f1e45a22a fix(security): slice memory allocation with excessive size value.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-08-12 14:03:06 +08:00
baihailong
4a87988bf7 fix(sdk): fix Uncontrolled data used in network request
Signed-off-by: baihailong <baihailong@oppo.com>
2024-08-12 11:30:10 +08:00
shuqiang-zheng
dd741df686 fix(security): slice memory allocation with excessive size value.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-08-12 09:56:14 +08:00
shuqiang-zheng
f8c677a041 fix(security): slice memory allocation with excessive size value.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-08-09 19:04:31 +08:00
baihailong
6174cfb9bd fix(util): incorrect conversion between integer types
close:  #259

Signed-off-by: baihailong <baihailong@oppo.com>
2024-08-09 17:14:32 +08:00
slasher
68e970cbbd fix(util): incorrect conversion between integer types
fixup code scanning: see https://github.com/cubefs/cubefs/security/code-scanning

Signed-off-by: slasher <shenjie1@oppo.com>
2024-08-09 14:06:07 +08:00
leonrayang
b658d0db49 feat(doc): Add TestCase Guidelines for contributors
Signed-off-by: leonrayang <chl696@sina.com>
2024-08-09 10:59:09 +08:00
slasher
45a486ec22 chore(ci): add codeql of golang
Signed-off-by: slasher <shenjie1@oppo.com>
2024-08-08 17:42:50 +08:00
leonrayang
83d122e6dc feat(doc): Add CubeFS-self-assessment.md
Signed-off-by: leonrayang <chl696@sina.com>
2024-08-08 17:22:46 +08:00
JasonHu520
f6fd42f1b2 fix(scheduler): reclaim from clustermgr with source vuid
with: #22472242

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-08-07 10:27:22 +08:00
leonrayang
3576d88889 feat(doc): Add more rules on the sub project for better governance
Signed-off-by: leonrayang <chl696@sina.com>
2024-08-06 18:55:25 +08:00
leonrayang
a474dfbe26 feat(doc): Update some maintainer's Affiliation information
Signed-off-by: leonrayang <chl696@sina.com>
2024-08-06 18:55:25 +08:00
leonrayang
cde492bba6 fix(docker): Update docker-compose to docker compose to adapt to github unbuntu env change
Signed-off-by: leonrayang <chl696@sina.com>
2024-08-06 15:21:40 +08:00
leonrayang
1536a544f2 feat(doc): Update the governance documentation
1.Clearify the promotion and exit rules for committers.
2.Add the Expectations for maintainer and committers
3.Clearify the core maintainers

Signed-off-by: leonrayang <chl696@sina.com>
2024-07-31 14:20:53 +08:00
slasher
b34dfb8de0 chore(util): add default of switch, update err judgment
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-07-29 15:13:21 +08:00
slasher
753475c481 fix(access): return not exist volume in access cached
. #22420678

Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-29 15:13:21 +08:00
slasher
4aca6e2127 fix(rpc): return 598 http status code if fail to decode from response
. #22420678

Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-29 15:13:21 +08:00
tangdeyi
9d392be776 fix(clustermgr): fix pendingkey memory release when add disk to dropped node
with #22402652

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-29 15:13:21 +08:00
JasonHu520
9622635308 fix(scheduler): update volume unit failed, first get latest volume info to comfirm whether updated
. #22366648

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-07-29 15:13:21 +08:00
xiejian
5e5351780b fix(clustermgr): AllocVolumeUnit return error when inconsistent request vuid and cm vuid
. #22366648

Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-29 15:13:21 +08:00
leonrayang
88f826557b feat(doc): Update the release documentation and add docker image info
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-29 10:16:08 +08:00
chihe
2911125677 fix(datanode): check disk path for replica with master when executing attachPartition
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
9dd4c9cf1b fix(master): decommission concel ignore decommission running
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
6b82499eb7 feat(meta): async inode del file recycle
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
807581fe83 feat(meta): adjust delete INODE_DEL file water mark
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
33d820c27f fix(meta): fix INODE_DEL recycle
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
c2e20b6e2e fix(meta): limit the count of metanode inode audit log
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-22 17:10:59 +08:00
true1064
035fafbf52 fix(data): When loading the disk, strengthen the checking before removing the duplicated data partition directories.
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-07-22 17:10:59 +08:00
leonrayang
981b298ca3 refactor(master): refactor the code of zone moudule
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-22 17:10:59 +08:00
chihe
47a7a6dfa4 feat(master):recover replica deleted by raftForce
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
e9f4b5ab7e fix(master): remove the status of DecommissionNeedManualFix
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
3325185e75 fix(master): fix deadlock for progress of WarnMissingDp
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
e9804d0043 feature(datanode): do not remove root dir for dp deleted by raftForce with auto decommmission mode
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
Victor1319
601c736226 refactor(master): add log when over datanode dp cnt limit.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-22 17:10:59 +08:00
Victor1319
2c16aa9c47 fix(meta): add gen log when append extent key.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-22 17:10:59 +08:00
shuqiang-zheng
fb82f1bb4a feat(client): cleaning up the log that may be printed to standard output during write process.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-22 17:10:59 +08:00
Victor1319
3bc66f6c7d fix(data): fix reload datapartition error.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
e858b4d740 fix(meta): fix INODE_DEL recycle
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
shuqiang-zheng
28d1561188 fix(master): Fix the problem of loading volDelayDeleteTimeHour from rocksdb without determining whether the value is greater than 0 or not.
@formatter:off

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-22 17:10:59 +08:00
Victor1319
5d7464f05f refactor(master): reload data from rocksdb once leader changed.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
f9e319ff4f fix(master): avoid warningMetrics deadlock
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
leonrayang
5c82a084f1 fix(datanode): The contents on which the CRC check depends are inconsistent with each other
Update the crc check output from error to warn, the inconsistent may be false report and require
more output and make a jugement.

The applyId and crc cann't be atomic under the architecture and are not necessary for performance.

Signed-off-by: leonrayang <chl696@sina.com>
2024-07-22 17:10:59 +08:00
leonrayang
c9611557a2 fix(datanode):Refactor the paramter of storage write at datanode
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-22 17:10:59 +08:00
baihailong
39dc1dfaa8 fix(sdk): add gosdk.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
85445548b2 fix(data): avoid flush extent when it is not dirty
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
3a8a2633be fix(datanode): donot raise panic when ApplyMemberChange trigger disk error
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
c641056a38 fix(master): reset decommission type when dp decommission fail
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
0c89a008cf fix(master): remove excessive peer during checkReplicaMeta
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
7176a68346 fix(datanode): remove expired peers with expired nodeID
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
7b9efc560f fix(datanode): remove expired root of dp during loading dp
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
55f8ce3b67 fix(master):if dp has emtpy replicas when execute decommission,return error
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
83b51e236c fix(master): if raft is already started when repair for dp is finished, return error directly
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
01e1ed9c3b fix(master): add lock for accessing missingMpAddrSet
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
9f81498736 fix(master): change error msg for multiple replica are executing decommissioning
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
605371c336 fix(util): refactor audit log remove
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
bc5dd77fbd feat(master): support set dp heartbeat timeout
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
shuqiang-zheng
bf2753766e feat(log): Add support for standard output in the log module.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-22 17:10:59 +08:00
baihailong
f08ff32bff fix(sdk): add cfs_IsDir,cfs_IsRegular for libsdk.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
6aca325797 feat(master): feat support vol level dp meta repair
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
41d2a78dd7 fix(data): ensure that truncate index is less than applied index
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
414229e0b5 fix(master): update dp cache after create vol
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
f88206c3a2 fix(data): adjust extent flush period to 5min
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
baihailong
51b093afac fix(sdk): add statistical metrics for libsdk.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
9767a884b4 fix(meta): avoid leak EXTENT_DEL fd
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
baihailong
89d1a533f6 fix(client): remove the wrong code in function write.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-22 17:10:59 +08:00
baihailong
e80bdd732f fix(fuse): print goroutine info when cfs-client exiting normally.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-22 17:10:59 +08:00
baihailong
c4f9b9395e fix(sdk): add debug log for remove dp and select dp.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
e287f3a9ce fix(master): redundant replica not participate when decommissioning mutiple replicas of dp
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
48506bbd18 fix(data): avaliable space calculate consider decommissioned disks
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
W9068822
d25840b71f feat(metrics): report version of client, metanode, datanode, authnode, lcnode, objectnode
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-22 17:10:59 +08:00
baihailong
8459b9372b fix(fuse): report error when read size not expected.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-22 17:10:59 +08:00
Victor1319
0527b01ce9 refactor(data): remove autoComputeCrc func from snapshot process.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
7a1c60eeea feat(master): support enable or disable auto dp meta repair
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
f65dbefd4e feat(meta): batch delete extents in delete extent channel
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
W9068822
eef2eb1faf fix(dp): sendErrReply @formatter:off
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
a64437610e fix(master): modify condition for raftForce when executing checkReplicaMeta
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
2e0b1796fd fix(master): add log to debug add disabled disk failed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
b10c9a9ab0 fix(master): do not change error msg for decommission failed dp when master reboot
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
f70d464aad fix(master): the DecommissionNeedManualFix status should be included in the statistics for dataNode
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
9f875df15e fix(master): delete new replica when performing rollback in AutoAddReplica mode
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
d68b68a2a2 fix(master): support config dp repiar timeout
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
38b37bc52e fix(master): carry weight node selector ignore mp limit
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
cf772279a7 feat(master): nodeset info return can alloc metanode/datanode cnt
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
f665fbbfab fix(client): avoid remove dp concurrent
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
47d20e4b7e chore(master): fix ci test
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
Victor1319
77fdb47ea0 refactor(data): datanode only process random write op before node start.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
7df2c4f46b chore(master): fix ci tests
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
04d809365b fix(master): load decommission disk limit when load cluster
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
374018d88d fix(client): fix appendExtentKey extent conflict
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
Victor1319
b3f82108f3 fix(sdk): revert code to fix eh flush failed error.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
8b01841eb1 fix(master): only set RestoreReplica to RestoreReplicaMetaStop when removed from decommission list
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
b4b732d913 fix(master): use raft force to delete redundant peers when 1-replica rollback failed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
chihe
2d4c3db90e feat(client): update pom.xml for maven
Signed-off-by: chihe <chihe@oppo.com>
2024-07-22 17:10:59 +08:00
NaturalSelect
09c77b87b0 fix(master): when stop master wait 10 sec for background tasks to exit
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-22 17:10:59 +08:00
slasher
8ed2139413 chore(blobstore): format code with new gofumt
Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-19 09:42:11 +08:00
NaturalSelect
6b53973075 fix(master): assess replica[0] need dp lock
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
wangxiaodong1
ac3a91e105 feat(master): add replicas laber for dp and mp noleader metrics
Signed-off-by: wangxiaodong1 <wangxiaodong1@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
2848a2c6db fix(cli): decommission disk for cli tool add migrationType param
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
44aa80e27e feat(master):report the list of dps hold token
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
W9068822
24618be53c fix(cli): fix DataNodeMigrate, @formatter:off
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-18 16:57:38 +08:00
W9068822
bf336dc34d feat(master): add getAllDataNodes and getAllMetaNodes apis
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
f70de7e82f fix(data): tiny extent snapshot off fix to 128M
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
W9068822
d8d82481af fix(dp): add dp count limitation
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
402da3957d chore(data): change get store used size log level
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
025d2ff89c fix(data): load extents consider snapshot
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
d0352cc55c fix(master): fix abortDecommissionDisk interface
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
c19b690d1d feat(master): support reset dp restore status
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
c008fefa97 feat(master): audit log for try decommission disk
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
fd504244b7 fix(master): if RestoreReplica is MetaRunning, reset it to MetaStop when master reboot or change leader.
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
4acdeca1fd feat(master): return can alloc partition when query node info
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
3316b7ccf4 fix(client): revert reports file's metadata and data inconsistencies.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
4b91bec9aa fix(data): remove rlock to avoid deadlock.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
6dbd7368a9 fix(master): avoid panic when master exit
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
368b30f715 feat(master): add audit log for decommission datapartition
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
88b0f20c91 feat(master): add audit log for decommission disk
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
cafd844e8a feat(master): excute checkReplicaMeta when mark dp decommission
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
b6ca473ac9 feature(master): mutual exclusion between the decommission progress and restoreReplicaMeta progress
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
0cf259b89f feat(master): auto add missing repplica
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
12abd5d817 fix(master): the DecommissionNeedManualFix status should be included in the progress statistics
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
81b5f56c3b fix(fuse): when client starting, reports last exit info.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
4df91ebc6e refactor(all): reslove merge conflicts between 3.3.x and 3.4.0.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
2e124833bb refactor(meta): skip discard dp when delete extent failed.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
4245f15add fix(meta): correct inode size calculate
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
14f86322d0 feat(data): rewrite space manager stop function
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
bc87fcbeb1 fix(data): avoid panic during apply rand write after store close
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
326a91648b fix(client): avoid block flush when clean up stream.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
b7eeda10b4 refactor(data): revert data node dp delay load
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
978254d5a5 fix(data): avoid write extent after store closed
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
65878a4085 test(master): fix unit test
@formatter:off

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
b7b042feff fix(client): fix ek conflict error when invoke closeOpenHandler.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
fadcba2fce test(util): fix unit test
@formatter:off

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
93fedf5db5 fix(client): remove unused import
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
9aff977edb docs(docs): update rpm version from 3.3.0 to 3.3.2.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
0e1f9cf0aa docs(docs): add docs about v3.3.2.
1. update change log.
2. add doc for volume delay deletion.

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
c2e6e7aaab test(data): fix bad testcase for data, meta, master.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
27b8481bee test(data): fix bad testcase for data, meta, master.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
16bd33d9ec fix(client): if we meet limited io, recover directly
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
319e8eb4f5 fix(client): release all conns, if we meet an EOF
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
d9dff8981e fix(sdk): fix ek conflict caused by traverse.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
leonrayang
a9b3d54028 feat(master): Volume update enable crossZone
Signed-off-by: leonrayang <changliang@oppo.com>
2024-07-18 16:57:38 +08:00
leonrayang
68fea4c4fb fix(master): go routine for qos leak while raft change but forget close
Signed-off-by: leonrayang <changliang@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
6b63f25071 fix(pprof): Fix for pprof endpoint exposures.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
ec188331f0 feat(cli): support set trash interval
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
91c65e17ab feat(data): speed data node restart
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
1e9dec3c20 fix(data): Add to partitions map only after start raft success.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
45774a7aea feature(master): Compatible with old version trash
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
138ffa3004 fix(client): Don't remove non-empty directories when trash enable
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
89f370ea0e feat(data): Start the external service port first, then start Raft.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
53b269d7e5 fix(master): update decommission limit when load nodeset
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
4a61b225fb fix(meta): Print error log when remove raft member failed.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
a0fcae90e6 feat(data): flush extent cache in timer
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
f9006bb7f6 fix(data): Automatic cleanup of channels to avoid deadlock issues.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
96848ee256 fix(master): Support asynchronous deletion of volume persistent information to avoid occupation of locks.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
d95f005df9 fix(master): Avoid concurrent access exceptions when responding to HTTP requests with a map.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
0d255b3ee0 refactor(master): Optimize filecheck-related logs for easier issue troubleshooting.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
c7aba207cc refactor(cli): Optimize the print output results of fileInCore.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
b3f3278e5a feat(data): Support asynchronous deletion of expired partition lists.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
f7f012de3d feat(meta): audit log print millisecond
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
S9054862
297fd4627c feat(data): load extent info on demand
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
81ade8089a feat(meta): delete dentry support inode audit
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
0e47f7244d refactor(data): refactor print log whith req id when send or read follower failed.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
375c0efa5d feat(fsck): support unlock target dp.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
663f266210 fix(client): To prevent write and flush operations from timing out and failing to respond to interrupt.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
b0381b46c9 feat(fsck): support batch persistence of bad extents.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
8afb049908 fix(fsck): fix block bug when request same node. 2024-07-18 16:57:38 +08:00
Victor1319
a798901c6a feat(fsck): Limit the deletion of only 128 files at once.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
0d16adfbc7 feat(fsck): support gc extent mark and delete at the same time.
1. support mark gc extents and delete gc extents.
2. after delete gc extents success, rename extents to xx.succ.

Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
S9054862
e812d1c37a fix(data): speed up initBaseFileID
Signed-off-by: S9054862 <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
1df3baa7ea feat(datnode): support read enableExtentRepairReadLimit from conf and query dp holded read extent token
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
30ca51488b feat(datanode): Support the functionality of allowing only one extent data read at a time per disk
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
S9054862
00ecb62b94 feat(data): limit io current on a disk when load/stop dp
Signed-off-by: S9054862 <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
W9068822
0c6f5314da feat(master): compress client/partitions response data
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-18 16:57:38 +08:00
true1064
6f4b6fa498 enhance(master/cli): Reduce too much dp info printing about replica file count and size differ:
(1)master: not record replica file count and size differ if dp is in decommission
(2)cli: only print number of dp with replica file count and size differ in default; and add an argument to control whether print such dp info

Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-07-18 16:57:38 +08:00
true1064
a0554c572f fix(data): datapartition status should be readonly when disk status is read-only
Signed-off-by: tangjingyu <tangjingyu@oppo.com>
2024-07-18 16:57:38 +08:00
true1064
5285933e0a fix(master): correct the determination of DataNode writability
Signed-off-by: tangjingyu <tangjingyu@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
9720d3eb2e fix(data): rewrite disk selector
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
yhjiango
3797f6b0e8 fix(object): fix request parts check in complete multipart
Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
a54c02bda3 fix(master): Printing load metadata information to the output log.
close: #21966908

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
yhjiango
e487250c51 fix(object): adjust STS auth process
Signed-off-by: yhjiango <jiangyunhua@oppo.com>

(cherry picked from commit 1f23b3f620)
Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
45d644fdff fix(master): use DeleteRange to clear rocksdb
close: #3152

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
true1064
0cc6a3631d fix(data): when traversing the replicas slice, avoid panics caused by changes in the slice length
Signed-off-by: true1064 <true1063@163.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
4a43bbc799 fix(master): avoid cross device link when apply snapshot
close: #3145

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
true1064
4a285269a4 fix(metadata): Taking a local snapshot or applying raft snapshot in MP persist the UniqID field
when loading a local snapshot, if the UniqID is found to be 0, set it to a larger value.

Signed-off-by: true1064 <true1063@163.com>
2024-07-18 16:57:38 +08:00
Victor1319
45b6896c46 feat(data): when extent is mark delete, write op not failed.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
f6861102e0 feat(fsck): support print volume name after calc garbage extent.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
d09a8503dd feat(fsck): not fatal when get one dp info failed.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
8d68346c5c feat(fsck): support calcuate bad extent concurrently.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
true1064
2f0b2b1737 enhance(master): not calculate preload dp capacity every time in newSimpleView,to reduce CPU usage
Signed-off-by: true1064 <tangjingyu@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
66200ee8bb fix(fsck): return error when get connect failed.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
true1064
ffcf6b3483 fix(data): function startEvict() should not panic when failed to get volume info from master
Signed-off-by: true1064 <true1063@163.com>
2024-07-18 16:57:38 +08:00
baihailong
cd5ba1a177 fix(libsdk): rename file A to file B twice, file B not exist while open B
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
5f2a7da336 fix(libsdk): libsdk support cfs_link, cfs_symlink
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
152dca0fa2 feat(meta): Enhance the allocation and validation of txId to avoid potential duplicates.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
5076a34844 fix(data): cancel extent count limit when create extent.
Cancel the limit of "maxCount + 10" extents to avoid no available data partitions.

Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
b5b41237ad fix(master):Change the logic of checkReplicaNum in the update volume process.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
a18a3c1ba0 enhance(log):Modify the threshold for triggering log cleanup to logLeftSpaceLimitRatio of the total disk space.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
9ac7ca9128 enhance(cli):Modifying Volume Deletion Related Error Messages.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
3d7c51d170 fix(libsdk,meta): support dir lock
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
8ba6d7517d fix(master):Fixed the problem that volumes marked for deletion but still in the freeze period could not restore the dp and mp replicas after reboot and migration was not supported.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
c976358bbe refactor(cli): remove pasue flag in transaction flag hint.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
ee9aba1f3a fix(master&client&cli): Add a new variable EnableTransactionV1 to avoid compatibility issues
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
9a77a99cec fix(master): only new vol enable rename atomic operation default, and support close.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
baihailong
9f034bd556 fix(sdk): not check result of InodeGet_ll leadto panic in Truncate.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
83c839c6f8 feat(master): set rename atomic switch open default.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
leonrayang
926745dff4 fix(master):MaxDpCntLimit in load datanode and band with configure
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-18 16:57:38 +08:00
leonrayang
10e16e1593 enhance(client):tiny extent update 128KB to 1MB
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
0cada31f3d feat(master): update the volume freeze feature to make it unreadable when the volume is frozen.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
a812f33e7d fix(libsdk): fix bug, cfs_getattr return ENOENT after cfs_unlink, cfs_open,cfs_write.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
4a46d338b8 feat(master): Open the volume deletion interface to freeze the volume when performing a volume deletion and then wait 48 hours before deleting the volume.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
yhjiango
46246c4768 feat(objectnode): s3 sts and signature auth
1. sts federation token
2. signature auth code refactor

Signed-off-by: yhjiango <jiangyunhua@oppo.com>

(cherry picked from commit 4401624f96)
Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
7c08fedcd8 feat(master): add forbid vol feature
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
baihailong
274b5d8c0a feature(libsdk): cfs_rename support param overwritten
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
371a54e829 fix(libsdk): multi-thread call cfs_rename leadto same ino
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
9d82cd821e fix(libsdk): fix cfs_mkdirs bug when multi-thread call
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
cba84402b6 fix(libsdk): support cfs_truncate
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
55e4aaf5c1 🐞 fix(fsck): remove clean switch flag from fsck.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
941b71a2cf 🐞 fix(data): when read locked extent, only print error log not return error.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
chihe
c5771e50e6 feature(doc): update the content of doc to version 3.3.1
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
leonrayang
c29084e440 enhance(client): Log path check too strict to startup if have softlink in the path
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-18 16:57:38 +08:00
Victor1319
cb966c66c7 feat(data): refactor delete logic to check opcode first
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
c02a337d1c 🐞 fix(fsck): close clean switch before online.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
leonrayang
0a17538541 enhance(security document): Add note for user report private security issues with groups.io
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-18 16:57:38 +08:00
leonrayang
ed86a95ca2 fix(master):qos.Lock of assignClientsNewQos forget release and trigger deadlock
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-18 16:57:38 +08:00
slasher
fa71952e55 feat(build): build with goreleaser
Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
9e0a1d9484 refactor(util): remove lock from auditlog
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
625a7a3d62 feat(master): enable audit log by default
NOTE: Please be careful when cherry-picking this commit.

Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
zhaochenyang
b7cb75b8a0 feat(ci): add sast tools gosec and semgrep
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
68cf97ab68 fix(master):fix the problem of TestCreateColdVol
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
0d4b1254b5 🐞 fix(fsck): add lock to protect host map
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
0c62eecc3a 🐞 fix(data): not check before time when lock extent to avoid fail.
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
baihailong
f43822f661 fix(auditlog): fix multithread logAudit bug
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
9ede5a8cfe 🐞 fix(fsck&data): support repeat delete extent
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
7a45fc7ac2 🐞 fix(fsck): fix rename old dir bug
Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
Victor1319
2d79270c41 feat(fsck & data): refacotr gc logic
1. "getAllExtent?id=xx&beforeTime=xx" supports get extent GC flags.
2. When deleting extent, also check for GC flags. If there are no GC flags, return an error.
3. Optimize related log printing by outputting relationship information and execution time, reduce unnecessary logs, and improve performance.
4. Optimize the implementation of the "getExtents" list interface and the performance of batch locking interfaces. Read all the latest information of extents at once to avoid accessing the disk for each extent, reducing timeout calls.
5. Support outputting profiles for easy performance analysis.
6. "cleanBadExtents" and "rollbackBadExtents" support a "clean" parameter to control whether to perform data cleanup and overwrite.
7. Use a task pool to support multi-threaded concurrent tasks.
8. Limit the concurrent task number to 3 for each node.
9. Back up the execution result of the previous command each time it is executed for easy tracing.
10. Remove "from-dp" from "getMpExtents" and "getDpExtents" and directly support concurrent retrieval of full volume information.
11. When obtaining MP information, take the maximum value among the three nodes as the reference.
12. When persisting MP information, use a buffer to optimize performance and avoid reading and writing to disk each time.
13. Analyze performance bottlenecks and optimize the process of obtaining MP extents.
14. If there is an exception during the MP retrieval process, exit directly.

Signed-off-by: Victor1319 <834863182@qq.com>
2024-07-18 16:57:38 +08:00
chihe
70d7986e34 enhance(client): ignore exist error when creating parent dir in transaction mode
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
huyao2
60070d5696 feat(fsck): Optimize fsck gc features, including:
1. The before of getDpextent must be at least 3 hours smaller than the current time.
2. The use of locks in the lock extent is changed from mutual exclusion locks to read-write locks.
3. Add a time judgment when locking extent. If the time is greater than before time, it means it has been changed and it will fail.
4. Support concurrency when cleaning bad extent
5. Add verification of master and volume names

Signed-off-by: huyao2 <huyao2@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
00fdbe3dbc fix(util): fix audit log bug, not handle shiftFiles() returned error 2024-07-18 16:57:38 +08:00
NaturalSelect
3b2a91bdf6 fix(cli): fix ui error occured by cherry-pick
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
bcd5ff6740 fix(util): avoid lock in audit log
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
556a452ebf fix(util): audit log performance
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
fa23e44ad8 feat(metanode): merge GetDataPartitionsView RPCs and GetVolumeSimpleInfo RPCs in a volume into one RPC
close: #1908

Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
daeb0e1d72 feat(metanode): audit log support master control
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
chihe
cef4705ac2 feature(client): trash supports random interval to prevent a large number of concurrent deletions
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
77771938f7 bugfix(ci): fix some test case error
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
baijiaruo
d1e852f290 enhance(cli): Optimize get mp extent. If an mp exception is encountered, the request fails.
Signed-off-by: baijiaruo <baijiaruo@126.com>
2024-07-18 16:57:38 +08:00
chihe
4fd208f7f2 bugfix(client): trash will ignore nil inodeInfo when remove expired dir
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
baijiaruo
58fec1f635 fix(datanode): Fix the problem of extent lock error when the extent is copied in the scene
Signed-off-by: baijiaruo <baijiaruo@126.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
b66928aa08 feat(object): support full path audit log
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
177055f4e0 feat(meta): support back-end audit log
close: #2625

Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-07-18 16:57:38 +08:00
chihe
6af0545e28 enchance(client): modify ParentDirPrefix
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
84223360b4 fix(client): trash support back-end audit 2024-07-18 16:57:38 +08:00
chihe
80c6e6417f enhance(client): ingnore exist error when rebuild parent dir
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
80bdde78e0 bugfix(client): if file is not find in Current when setXattr, then try find it in expired dirs
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
43f112c65b fix(client): 1.Launch new deleteWorker when deleteInterval is changed
2.Change the  setxattr  operation to synchronous.

Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
baijiaruo
5b6723ab0f enhance(cli): add fsck gc tool
Signed-off-by: baijiaruo <baijiaruo@126.com>
2024-07-18 16:57:38 +08:00
chihe
a6b774a2e8 fix(client): 1. use ReadDir_ll when remove expired data 2.long name add uuid subfix
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
5f1503d70b enhance(client): trash read current directory in segments
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
Victor1319
dbb6970bdd fix(master): tmp code
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
7af24470b2 fix(client): 1.fix inode leak for trash 2. save long file name in xattr
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
832e745599 fix(client): add dir cache when delete expired trash dir
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
2356570e01 feature(client): support trash
Signed-off-by: chihe <chi.he@oppo.com>
2024-07-18 16:57:38 +08:00
slasher
847bdb062a chore(ci): run ci when merging to release
Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
e3d08a2504 fix(master): avoid metrics panic
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
d201f99c04 feat(master): support set decommission disk limit
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
3b287ce496 fix(master): initial WarnMetrics before schedual tasks for master
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
d3203d21f8 fix(master): when marking dp to start decommission, no need to concerned about the rollback times
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
e32bdb511e fix(master): delete decommission dst from hosts of master by force if rollback failed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
ceed02819a fix(master): do not set new replica status if new replica is not found
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
af7ae48674 feat(master): enhace audit log for master
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
025ded08fb fix(log): Fix problems that may be caused by concurrent flushing of logs.
@formatter:off

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
shuqiang-zheng
eed62c913f enhance(log): Modify the threshold triggering log to logLeftSpaceLimitRatio of the total disk space
@formatter:off

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-07-18 16:57:38 +08:00
leonrayang
76121f501d enhance(metanode): Reduce log output and memory cost
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-18 16:57:38 +08:00
chihe
c34141c911 fix(datanode): remove root dir for disk error dp not loaded
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
f516e148f5 fix(master): retry auto disk decommission when bad replica is removed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
de3a41a473 fix(datanode): remove peers from the monitor for raft after raftFsm is stopped
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
d012d0bf1a fix(client): release all conns, if we meet an EOF
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
c37c3ead4d fix(client): client reports file's metadata and data inconsistencies.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
c869d9366e fix(raft): check raft wal when rebuild log index
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
NaturalSelect
e58b1b005e refactor(master): change audit log format
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-18 16:57:38 +08:00
chihe
db4ce8dcb0 fix(datanode): add debug log for reading extent repair packet
Signed-off-by: chihe <chihe@oppo.com>
2024-07-18 16:57:38 +08:00
baihailong
1e975f2116 fix(sdk): fix streamer's multi server problem.
Signed-off-by: baihailong <baihailong@oppo.com>
2024-07-18 16:57:38 +08:00
slasher
f97f692c27 chore(ci): replace blobstore checking with main format
Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-16 11:39:45 +08:00
Zhenzhen-Li-0618
02ad20af7d fix(metanode): remove item may changed clone btree
Signed-off-by: Zhenzhen-Li-0618 <lizhenzhen0618@126.com>
2024-07-16 11:23:03 +08:00
Yu-Ang Cao
ae9ab070b9 enhance(sdk): NewMetaWrapper initializes the epoch with a random number.
close: #3416

Signed-off-by: Yu-Ang Cao <cyadxx@mail.ustc.edu.cn>
2024-07-16 10:50:18 +08:00
xiaojunxiang
68901bc30b fix(doc): Correct datanode.json in cluster-deploy.md
Signed-off-by: xiaojunxiang <xiaojunxiang@kingsoft.com>
2024-07-16 10:30:54 +08:00
slasher
b8211ebe58 refactor(access): change access request limited to 4xx
. #22358245

Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-15 16:38:24 +08:00
leonrayang
ef19fda5e7 feat(doc): Update the governace.md, add roadmap and sigs governace
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-15 15:20:12 +08:00
leonrayang
6a0ae6e1bf feat(doc): Add the document of governance in Chinese
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-15 15:20:12 +08:00
leonrayang
c4431deb41 feat(doc): Update the doc of CONTRIBUTING.md and add guide for contributors
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-15 15:20:12 +08:00
leonrayang
81d73dfcb0 feat(doc): Clarify the duty of maintainers and committers
Signed-off-by: leonrayang <chl696@sina.com>
2024-07-15 15:20:12 +08:00
xiejian
3226795533 fix(clustermgr): fix the issue of inconsistent vuid when AllocChunks is retried
with: ##22356967
Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
xiejian
954ca1dd48 fix(clustermgr): fix diskmgr refresh process of repeated counting of nodes
with: #22350063
Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
06a0eefab8 fix(clustermgr): add node without diskType
with #22347840

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
7e8583f42b fix(clustermgr): stabilize setID allocation result
with #22338769

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
dfc8a327e6 fix(clustermgr): nodeSetIdcCap conf init
with #22335363

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
a5be58eaf3 fix(clustermgr): reserve nodeset/diskset when all nodes/disks are not in use
with #22331837

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
mawei029
c96e97f097 fix(tools): blobnode check dropped disk, fix disks count beyound 10, with marker and count
Signed-off-by: mawei029 <mawei2@oppo.com>

with: #22328399 of #22196596
2024-07-15 11:03:57 +08:00
xiejian
fad52a9b44 fix(clustermgr): fix diskmgr refresh panic when spaceStatInfo is not initialized in compatibility mode
with: #22330124
Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
1406c74d41 fix(clustermgr): remove nodeSetIdcCap config
with #22328795

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
ad4e1a2fcb fix(clustermgr): diskSet capacity limit
with #22327756

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
Cloudstriff
2cdd890664 fix(clustermgr): fix ec volume with different disk type chunk problem
with #22325238

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2024-07-15 11:03:57 +08:00
mawei029
659930fa44 feat(tools): check chunk clean of dropped disk, blobnode cli tools
with: #22282964 of #22160501

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
1e6c86cc5c fix(clustermgr): copyset config default value
with #22313190 #22315591

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
Cloudstriff
546dc881b9 feat(blobnode): fix repair shard timeout return 500 code problem
with #22315849

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2024-07-15 11:03:57 +08:00
Cloudstriff
f8d40dd199 fix(clustermgr): fix unlock volume force while volume is unlocking
with #22304241

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2024-07-15 11:03:57 +08:00
slasher
bcc476d639 chore(common): codemode tactic valid with replicated
@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
dc9b760635 fix(clustermgr): ec volume unit alloc
with #22303365

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
cd0234a101 fix(clustermgr): add existed disk return created status
with #22295049

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
f57777b915 fix(clustermgr): ban add node without changing host and add disk to dropped node
with #22289797 #22290300

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
xiejian
0de0a8d38e fix(clustermgr): check task codemode by mode tactic
with: #22201875
Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
JasonHu520
793a8080ea fix(scheduler): fix statics of scheduler incorrect
with: #22283199 of #22283174

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-07-15 11:03:57 +08:00
slasher
4fd4e71198 fix(access): new back ground context for flush volume in proxy
. #22285709

Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
4b9bf234e6 fix(clustermgr): validate role when add node
with #22283384

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
mawei029
21ca13f370 fix(bssdk): add limit name rps
with: #22256852 of #22160501

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
dc91b64e02 fix(clustermgr): add error msg
with #22283083

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
xiejian
266f000adc fix(clustermgr): complete the error code message
with: #22204241 #22201875
Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
xiejian
eb5b423fed fix(clustermgr): compatible with old version blobnode alloc chunks retry
with #22282411

Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
mawei029
399613b0f9 refact(blobnode): we need re-add all disk, when first add node
Signed-off-by: mawei029 <mawei2@oppo.com>

with: #22265425 of #22160501
2024-07-15 11:03:57 +08:00
tangdeyi
4c8f8892be feat(clustermgr): clustermgr support copyset
1.allow disk register again to diskSet
2.remove allocNodeID and add getTopoInfo

with #22271762 #22271777 #22271792

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
xiejian
4d1601ee7a feat(clustermgr): support create replica volume
with #22040215

Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
tangdeyi
c1c66d0111 feat(clustermgr): clustermgr support copyset
1. add nodeAdd and nodeDrop api
2. add topoMgr struct
3. do refactor for copy set change

with #22171901 #22040204

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
JasonHu520
63e940b9e6 refactor(consul): consul client support acl token
with: #22274526 of #22040204

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-07-15 11:03:57 +08:00
mawei029
3acf81f151 refactor(blobnode): report network flow metric with io type
with: #22236519 of #22160501
with: #22237444 of #22160501

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-07-15 11:03:57 +08:00
Cloudstriff
f7f3d119b1 build(blobstore): replace target path of blobstore go build with current dir
with #22109605

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2024-07-15 11:03:57 +08:00
mawei029
653dcacd76 feat(blobnode): register node and disk to cm, support copy set
with: #22196753 of #22160501

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-07-15 11:03:57 +08:00
xiejian
84567b8d67 feat(blobnode): put shard time out return error code 675
with: #22201875 of #22040231
Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
xiejian
690c26fe43 feat(clustermgr): cm background worker return unsupported replica mode error
with: #22201875 of #22040231
Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
JasonHu520
2f688bbe94 refactor(common): auto set the default value of task switch key to cm
with: #22213629 of #22040231

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-07-15 11:03:57 +08:00
Cloudstriff
1102e822f0 fix(clustermgr): applying dropping disk progress add disk status filter
applying dropping disk progress add disk status filter, avoid add
dropping disk repeatedly after disk dropped concurrently
with #22212160

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2024-07-15 11:03:57 +08:00
tangdeyi
648e5cb9f3 feat(clustermgr): node/disk struct and node api
with #22209997

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-07-15 11:03:57 +08:00
xiejian
fc422bfe56 feat(clustermgr): support force unlock volume
with: #22173138
Signed-off-by: xiejian <xiejian3@oppo.com>
2024-07-15 11:03:57 +08:00
slasher
a0efbcb5be feat(rpc): disable unique host on the same host if failed
. #22182990 of #22109605

Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-15 11:03:57 +08:00
slasher
a792e031ff feat(access): reset clustermgr client if hosts changed
. #22182997 of #22109605

Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-15 11:03:57 +08:00
mawei029
1d19da99db refactor(blobnode): disk mount check during blobnode process startup
with: #22181981 of #22160501

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-07-15 11:03:57 +08:00
linfangrong
2648d5ba06 fix(metanode): metaPartition Reset, release memory when deletePartition
Signed-off-by: linfangrong <linfangrong.liuxin@qq.com>
2024-07-12 16:35:53 +08:00
NaturalSelect
488ff7434f test(master): fix unit tests
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
e887af06c2 fix(master): if special dp is decommissioned, disk manager check recovery progress for new replica
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
e39425fe83 feat(master): enhance for replica mata
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
7a6febec4b feat(cli): add decommissioned disks info for datanode node info display
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
d303bc8d3b fix(master): validate the existence of the disk and node when performing disk decommission
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
fadbdb3ebd feat(master): do not check decommission condition when raftForce is setted
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
65ee50a40a fix(cli): cli can display dps encountering IO errors during loading
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
d0ec3febe2 feat(master): exclude decommission src when acquiring token
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
352662ad60 fix(datanode): raise disk error when dp persist applied id
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
f3f98060ec feat(master): decommission all dp from disk if threshold for bad dp on disk is not set
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
c3c35e40f3 fix(datanode): replica for dp can only be updated by raft member change
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
Victor1319
523a04de95 fix(data): persist dp meta only when create dp to avoid reset apply id 0.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
fdec047ee4 feat(master): support abort disk decommission
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
0a158c3e96 feat(master): support query decommission failed disks
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
a1d27d729e feat(data): limit rw dp decrease count at once
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
3b03341425 feat(master): support max mp cnt limit
@formatter:off

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
14ce5dc2cd test(master): fix unit tests
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
shuqiang-zheng
3726ccf80d feature(master): If the dpCount is less than 10 when creating a volume, change it to 10.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>

@formatter:off
2024-07-05 17:05:43 +08:00
W9068822
470967aae4 feat(ci): fix format failed.
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
3f529a7b78 feat(master): if all disks decommissioned, not allow to alloc dp on datanode
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
d5851c01a4 feat(master): if special replica dp has reduant replica when marking decommission, return failed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
25098c069f feat(meta): batch delete extents in delete extent channel
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
292943e3f8 fix(datanode): enhance for raft panic
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
f3e17deaad fix(data): refactor snapshot extent deletion
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
81f99aab29 feat(master): support master decomm audit log
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
a59916a028 fix(datanode): when adding raft member,return failed if nodeID is different from meta replica
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
9a6ae28c4b feat(master): delete dp from badparitionIds when exceeding maximum rollback attempts.
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
905cef0868 fix(datanode): if raft trigger disk io when persisting wal logs, do not raise data server panic
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
NaturalSelect
495b8e4d77 fix(data): batch delete normal extent not punch del, if disable snap
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-05 17:05:43 +08:00
Victor1319
5f72c26013 fix(data): When a disk operation error occurs, only stop the current raft.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
ba31ce154c feat(master): support query for auto decommission progress
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
3ecdbe0af0 feat(master): enhance for auto decommission
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
f704f3fdac feat(cli): add report for disk error dp replica for cli
Signed-off-by: chihe <chihe@oppo.com>
2024-07-05 17:05:43 +08:00
chihe
3455d2965b feat(master,datanode): support recover meta for data replica
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
74d9bc806a fix(master): check peers length and content for replica
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
e2433de194 fix(master): don't set new created replica status to unavailable for specail dp
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
1172101007 fix(datnode): validata pair.Size in FormatSize
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
34dce27cc4 feat(master): add api for checking meta for dp replica with meta for dp keeped in master
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
65d3ce1410 fix(datanode): only remove redundant raft memeber when single replicum dp is noleader
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
569023a181 fix(master): when special replicum dp retry decommission, do not check recover flag
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
755a827cdb fix(datanode): when datanode remove raft memeber, use local nodeID
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
96ed7fd818 fix(master): persist decommission error message
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
d0fd485af7 fix(master): don't delete excess replica for the dp excuting decommission operation
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
Victor1319
e169e23dc6 fix(data): Use usedCap as totalCap when usedCap bigger than totalCap.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
3ab2260b3a fix(master): A leaderless single replica can self-recover into a state with a leader
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
78b692b207 fix(master): remove replica by force when reaching max rollback retry
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
dcf3215333 fix(master): when reaching retry max, don't reset decommission dst
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
389875a4c1 fix(master): data race may happens when background goroutine update decommission status
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
f0f94e77c4 fix(master): set dp as rollback failed when the maximum of token retrieval failures is reached
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
W9068822
f8db5d104b enchance(master): limit parameter count to 10 each time MP is created
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
25fd340c39 fix(data): avoid panic when remove dp
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
7167c72b59 feature(master): QueryDataNodeDecoProgress supports error message
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
f9fb1e6fa9 fix(master): release token before reset deocmmission dst
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
a250c250c3 refactor(master): check dp when sync update
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
7329d1f1e8 feat(master): check datapartition status when set dp discard
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
9ca77ba7aa feat(master): if dp is discard, decommission will success directly
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
1d0afe8602 fix(client): close tmpConn correctly
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
19fe22876a fix(client): use tmp conn to avoid reorder packet
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
S9054862
d6532c1794 fix(client): treat try again error as a special error
Signed-off-by: S9054862 <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
true1064
1462bbe944 refactor(master): add a new field indicating whether the volume is readonly
Signed-off-by: tangjingyu <tangjingyu@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
a82fbc56e6 fix(master): dp with sepcical replicum delete decommission src raft failed, not reset src
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
9d2ddde089 fix(datanode): single dp use delete new raft member with raftForce when rolling back
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
7fa9beba0e fix(master): restore the decommission progress of dp with special replica number when master restart
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
18e83cd45d fix(cli): foramt decommission dp info
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
610e6bd457 feat(master): support auto decommission disk and config
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
chihe
08f46f88e8 fix(master): display progress when decommission failed datanode restart
Signed-off-by: chihe <chihe@oppo.com>
2024-07-02 16:35:56 +08:00
NaturalSelect
38bd1924e0 fix(cli): datapartition query-progress
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-07-02 16:35:56 +08:00
true1064
0dbc434c36 fix(meta): To correctly determine whether the inode should be deleted when unlink
Signed-off-by: tangjingyu <tangjingyu@oppo.com>
2024-07-02 16:35:56 +08:00
true1064
356e2406d7 fix(meta): check if inode exists in function ExtentsList
Signed-off-by: tangjingyu <tangjingyu@oppo.com>
2024-07-02 16:35:56 +08:00
slasher
4bfad9399b chore(doc): improving the developer process
Signed-off-by: slasher <shenjie1@oppo.com>
2024-07-01 18:37:25 +08:00
S9054862
8ad316ecfc feat(data): repair block size support master config
Signed-off-by: S9054862 <huangzhibin1@oppo.com>
2024-07-01 15:09:55 +08:00
leonrayang
4ee2208263 feat(master): Optimize logic of uid calculate for better performance
1.use channel to instead of lock and isolate with main heartbeat routine
2.calculate in an aysnchoronus way periodically instead of real time
3.move heartbeat outside the goroutine, the startup of goroutine may delay the response time

Signed-off-by: leonrayang <changliang@oppo.com>
2024-07-01 15:09:55 +08:00
chihe
2b26a1fbcb enhance(master): if host 0 is down for 10 minutes during repairing, mark dp decomission failed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-01 15:09:55 +08:00
chihe
1330695c0f fix(datnode): get copy of dp replica when excuting updateMaxMinAppliedID
Signed-off-by: chihe <chihe@oppo.com>
2024-07-01 15:09:55 +08:00
chihe
a52614d955 fix(master): put success or failed dp to decommission list when reloading meta adjust debug level
Signed-off-by: chihe <chihe@oppo.com>
2024-07-01 15:09:55 +08:00
W9068822
63f1cbd41b fix(master): fix get DP compression data, update cached data when needsUpdate is true
Signed-off-by: W9068822 <v-lijianrong1@oppo.com>
2024-07-01 15:09:55 +08:00
chihe
199353bcae debug(master): add debug log
Signed-off-by: chihe <chihe@oppo.com>
2024-07-01 15:09:55 +08:00
chihe
b4ab10a1aa fix(master): reset decommissoin dst if decommissioning dp failed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-01 15:09:55 +08:00
chihe
ee7ece407c enhance(datanode): add log for extent repair speed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-01 15:09:55 +08:00
chihe
db6f8ab0ec fix(datanode): packerror if get extent token failed
Signed-off-by: chihe <chihe@oppo.com>
2024-07-01 15:09:55 +08:00
Victor1319
6d53e5667e fix(data): fix nil poniter bug when invoke partition api for repair replica.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-01 15:09:55 +08:00
Victor1319
119755987a feat(master): Optimizing Volume Deletion Performance and Speed.
Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-07-01 15:09:55 +08:00
leonrayang
cef58ab3db feat(doc): Correct minor issues and clarify certain decision-making processes
In particular, improve the necessary requirements and decision-making process
for becoming a committer or maintainer.

Signed-off-by: leonrayang <chl696@sina.com>
2024-06-07 19:38:33 +08:00
leonrayang
b87f2387eb feat(doc): Update the documentation for Release.md
update the documentation for Release.md as its filename's capitalization
does not match other .md files,and add more detailed information.

Signed-off-by: leonrayang <chl696@sina.com>
2024-05-31 11:49:24 +08:00
leonrayang
03c6917cea feat(doc): Update the document of the roadmap as the branch name has been changed
Make slight adjustments to the test name

Signed-off-by: leonrayang <chl696@sina.com>
2024-05-31 11:49:24 +08:00
slasher
49180bf576 fix(access): init upload token once
. #22237333 of #22237300

Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-29 19:34:47 +08:00
leonrayang
f0947021c9 feat(doc): Update the Governance Document
Signed-off-by: leonrayang <chl696@sina.com>
2024-05-27 15:54:29 +08:00
slasher
59538d3a98 feat(common): apply http argument parser in nodes
. #22032841 of #22032813

Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-24 10:43:02 +08:00
slasher
e0961daeb1 feat(common): add http argument parser
. #22032837 of #22032813

Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-24 10:43:02 +08:00
leonrayang
333c267ff5 feat(doc): Add the documentation of dependency details according to go.mod
and indicate CNCF projects

Signed-off-by: leonrayang <chl696@sina.com>
2024-05-24 10:27:02 +08:00
leonrayang
5688cb9df7 feat(doc): Update the document of Versioning support by CubeFS
Signed-off-by: leonrayang <chl696@sina.com>
2024-05-24 10:27:02 +08:00
leonrayang
0d8d15f017 feat(doc): Add documentation on the rules for branches, releases, and versions.
Signed-off-by: leonrayang <chl696@sina.com>
2024-05-23 10:47:09 +08:00
mingwei
fb0fb8861f fix(doc): fix readme pic's url and some name
Signed-off-by: mingwei <gongmingwei@oppo.com>
2024-05-23 10:23:08 +08:00
zhangchuanqing1
dacb598dc4 feat(doc): Add Chuanqing Zhang to be a committer.
Signed-off-by: zhangchuanqing1 <zhangchuanqing1@jd.com>
2024-05-22 16:19:54 +08:00
Huweicai
5d8120d7c2 refactor(master): remove redundant logging Sprintf
Signed-off-by: Huweicai <i@huweicai.com>
2024-05-21 11:22:15 +08:00
mingwei
f20edb00cf docs(all): update docs architecture
update the chinese and english docs architecture

Signed-off-by: mingwei <gongmingwei@oppo.com>
2024-05-21 10:42:30 +08:00
mawei029
b216b19a99 refactor(access): optimized read process and retry put
with: #22187720 of #22040152

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-05-21 10:17:28 +08:00
slasher
437c4f2126 feat(bssdk): blobstore sdk logger defined with interface
. #22181060

Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-21 10:17:28 +08:00
JasonHu520
f07065701f fix(scheduler): solve dead lock problem for drop manager
with: #22173113 of #22172987
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-05-21 10:17:28 +08:00
slasher
5daaa9e19a chore(access): change access config default values
1. MaxHostRetry = 0, means to retry all hosts.
2. FailRetryIntervalS = 300, means setting host to fail queue 5 minutes.
3. ServiceIntervalS = 300, means discovering service per 5 minutes.

with #22166504 of #22166054

Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-21 10:17:28 +08:00
slasher
64cbc677a1 chore(access): add retry get body function in put args
with #22167497 of #22166054

Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-21 10:17:28 +08:00
Cloudstriff
1895af4822 feat(taskpool): add task pool running API support
with #22040110

Signed-off-by: Cloudstriff <chenjiongwendao@qq.com>
2024-05-21 10:17:28 +08:00
mawei029
944aceba8d fix(blobnode): releaseEpochChunk the release chunk file is not thorough
with: #22164756 of #22134387

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-05-21 10:17:28 +08:00
tangdeyi
24387698c1 fix(clustermgr): fix used space when disk readonly
with #22159693 #22202452

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-05-21 10:17:28 +08:00
tangdeyi
0b3afe0869 perf(clustermgr): remove shard volume balance
with #22058112

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-05-21 10:17:28 +08:00
mawei029
a7af9fadc6 refactor(access): support alloc+putat part process
with: #22131293 of #22040152
with: #22125770 of #22040152

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-05-21 10:17:28 +08:00
mawei029
f52ea9ffc4 refactor(access): move stream files to stream directory
with: #22125787 of #22040152

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-05-21 10:17:28 +08:00
mawei029
33384a343a refactor(access): support putat and alloc
with: #22125770 of #22040152

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-05-21 10:17:28 +08:00
mawei029
01cdb54b3c feat(access): support sdk, merge blobstore access into cubefs sdk
with: #22095487 of #22040152

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-05-21 10:17:28 +08:00
xiejian
fcd5023bde test(blobstore): remove inconsistent results in different environments
with #22119364

Signed-off-by: xiejian <xiejian3@oppo.com>
2024-05-21 10:17:28 +08:00
slasher
589b10460a feat(common): start profile http before main server been loaded
. #22119364 of #22040110

Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-21 10:17:28 +08:00
tangdeyi
de81e3d98b perf(clustermgr): volume allocation optimization
. #22058112

Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-05-21 10:17:28 +08:00
shuqiang-zheng
9abd9ab35d feat(doc): Add Shuqiang Zheng to be a committer.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-05-20 17:34:22 +08:00
leonrayang
299ddcc6bc feat(doc): Update the document of adopters
Signed-off-by: leonrayang <chl696@sina.com>
2024-05-15 16:41:04 +08:00
BillXiang
25074c5d0c fix(metanode): return OpNotExistErr when inode does not exist in CheckQuota to not retry
Signed-off-by: BillXiang <xiangwencheng@gmail.com>
2024-05-14 16:43:08 +08:00
slasher
5c7898354f style(all): format all codes with golangci tools
closes #3371

@formatter:off

Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-14 09:54:13 +08:00
leonrayang
c2ea1de3d4 feat(doc): Update the document of adopters
Signed-off-by: leonrayang <chl696@sina.com>
2024-05-09 20:07:30 +08:00
leonrayang
82c1b64aaa feat(doc): Update the document of versioning support by CubeFS
Signed-off-by: leonrayang <chl696@sina.com>
2024-05-09 11:07:27 +08:00
slasher
9e0161a843 fix(blobstore): fix metric to microsecond of response duration
Signed-off-by: slasher <shenjie1@oppo.com>
2024-05-07 15:25:13 +08:00
leonrayang
89ffec03f0 feat(doc): Update the document of the roadmap
Signed-off-by: leonrayang <changliang@oppo.com>
2024-05-06 10:40:03 +08:00
leonrayang
63abbb9e57 feat(doc): "Update the document of the roadmap to improve readability
include features that are in preparation but not yet scheduled.

Signed-off-by: leonrayang <changliang@oppo.com>
2024-04-30 15:01:32 +08:00
leonrayang
0a6a5724c9 feat(doc): Update the document of contributing
Signed-off-by: leonrayang <changliang@oppo.com>
2024-04-30 14:50:13 +08:00
leonrayang
a4248db8ae feat(doc): Update the Governance Document
Signed-off-by: leonrayang <changliang@oppo.com>
2024-04-29 15:51:02 +08:00
slasher
d4fabb57f2 docs(template): change tips of pull request template as comment
Signed-off-by: slasher <shenjie1@oppo.com>
2024-04-25 14:34:33 +08:00
mawei029
851afbb5ff refactor(blobnode): wait all chunk file is remove, and then close disk handler
with: #22095475 of #22019399

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-04-25 10:27:27 +08:00
mawei029
6a95856248 fix(blobnode): initialize the config of chunk clean interval sec
with: #22095475 of #22019399

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-04-25 10:27:27 +08:00
mawei029
304b0e5a2d fix(blobnode): wait all physics chunk file is remove, and then close disk handler
with: #22095475 of #22019399

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-04-25 10:27:27 +08:00
slasher
9c9cbad5e4 chore(util): rename deprecated ioutil
with #21965980

Signed-off-by: slasher <mcq.sejust@gmail.com>
2024-04-25 10:27:27 +08:00
slasher
a8a4717f19 docs(action): update scorecard analysis action yaml
Signed-off-by: slasher <shenjie1@oppo.com>
2024-04-24 15:57:38 +08:00
Victor1319
28313b46f6 docs(docs): add docs about v3.3.2.
1. update change log.
2. add doc for volume delay deletion.

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-04-23 19:05:24 +08:00
morphes1995
b8c26ba20f feat(cli): cfs-cli add functionality to show disk info
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-04-19 14:06:35 +08:00
JasonHu520
38d6d23249 fix(scheduler): solve load panic issue while count junk task wrote by timeout task kv operation
with: #22023547 of #22019399
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-04-17 16:29:24 +08:00
JasonHu520
5e1d7bf6db fix(scheduler): fix generate duplicated task for chunk
with: #22023547 of #22019399
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-04-17 16:29:24 +08:00
mawei029
e587396b56 fix(scheduler): fix statistics of disk drop
with: #22023563 of #22019399

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-04-17 16:29:24 +08:00
mawei029
f0d3d52eef fix(scheduler): fix cannot delete bid, warning must mark delete
with: #22023547 of #22019399

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-04-17 16:29:24 +08:00
JasonHu520
854d6503d6 fix(scheduler): fix load disk drop task panic problem
with: #22023547 of #22019399
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-04-17 16:29:24 +08:00
JasonHu520
1bb497b83c feat(limit): add acquire with context function for blocking limit
1. this provides context arg to control the time of waiting limit

with: #22023547 of #22019399
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-04-17 16:29:24 +08:00
mawei029
ffea75f9a6 refactor(scheduler): update process of drop disk for scheduler
with: #22023547 of #22019399

Signed-off-by: mawei029 <mawei2@oppo.com>
Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-04-17 16:29:24 +08:00
mawei029
16963e947a test(scheduler): add ut for improving disk drop concurrency performance
with: #22023563 of #22019399

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
Signed-off-by: mawei029 <mawei2@oppo.com>
2024-04-17 16:29:24 +08:00
mawei029
fada020c27 perf(scheduler): disk drop concurrency, release limit on finish, task limit when load
with: #22023563 of #22019399

Signed-off-by: mawei029 <mawei2@oppo.com>
2024-04-17 16:29:24 +08:00
JasonHu520
a486320433 perf(scheduler): improve disk drop concurrency performance
with:  #22023547 of #22019399

Signed-off-by: JasonHu520 <huzongchao@oppo.com>
2024-04-17 16:29:24 +08:00
morphes1995
f0d42ff42f fix(datanode): fix some typo error
Signed-off-by: morphes1995 <morphes1995@gmail.com>
2024-04-15 11:10:56 +08:00
leonrayang
6f723d725b feat(doc): Update maintainer list according to activity and add steering commitee member
Signed-off-by: leonrayang <changliang@oppo.com>
2024-04-12 11:31:24 +08:00
slasher
d6577c7faa chore(doc): improve pull request template content
closes #3305

Signed-off-by: slasher <shenjie1@oppo.com>
2024-04-07 20:31:09 +08:00
slasher
bdffd66650 feat(cli): auto format struct and table
with #21965811

Signed-off-by: slasher <shenjie1@oppo.com>
2024-03-29 14:22:29 +08:00
shuqiang-zheng
e59f07a084 feat(reconstruct): gofmt by gofumpt.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
cffcc4bbfd fix(master): Modify the execution order of deletion after freezing.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
af739c6a3f fix(master): Fix the problem of updating a cold volume when cachecap and replicaNum is all 0.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
42fa6628f4 enhance(cli): Modifying Volume Deletion Related Error Messages.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
6d0de0df25 fix(master): Fixed the problem that delayed deleted volumes do not support migration.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
452d2a3239 enhance(cli): Dynamically configure volDeletionDelayTime through the interface.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
325694a4f7 enhance(cli): Add query interface to show the current delayed deletion time of the volume.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
7be84be6fa fix(master): Fix the bug that when the configured delayDeletionTime is changed.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
dea6c736c5 feat(master): Add a configuration item to determine if freezing before volume deletion.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
ae3b170fe6 feat(master): Make a volume unreadable when it freezes..
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
shuqiang-zheng
9c5185e9be feat(master): Freeze the volume when performing volume deletion.
Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-28 11:43:55 +08:00
BillXiang
e11d3cd638 fix(client): write qos of hot volume
Signed-off-by: BillXiang <xiangwencheng@gmail.com>
2024-03-27 15:14:45 +08:00
leonrayang
d740ec0654 feat(reconstruct): gofmt by gofumpt
Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
f117df54cf fix(code merge): Raft Partition mock be missed before
Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
NaturalSelect
3fefda48fe test(master): fix decommission unit test
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
92b2dcaff8 feature(master):support reset decommission dp status for datanode with no dp left
close#21938887
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
566401114b fix(master): restore dp host if adding replica failed
close:#22010510

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
shuqiang-zheng
8b7924818f debug(master): Print task-specific information about master's processing of dataNode heartbeat responses.
close: #22000400

Signed-off-by: shuqiang-zheng <zhengshuqiang@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
da7dbeec15 fix(master): fix complie error for last commit
close:#21938898
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
e9386a85f9 enhance(master): decommission failed dp without reaching rollback retry maximun can be put into decommission list
close:#21938898

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
78d380a60a enhance(datanode): remove mutex for extent repair read
close:#21999366

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
be9c0c9896 fix(datanode): if get extent repair read token for disk failed, release read token for datanoe
close:#21999366,#21999177,#21999095

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
Victor1319
9d3073f869 feat(data): Optimizing Network Connections for datanode. #21971464
1. fix dirty net connection problem.
2. not user connection pool when enableSumxPool

Signed-off-by: Victor1319 <zengxuewei@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
597ee1ac10 fix(master): a rollback is still required, even if the rollback conditions have not been triggered, when reached retry max
close:#21938898

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
f3c0006e1d fix(datanode):Don't delete datapartition when removing raft member
close:#21952262

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
NaturalSelect
df58ccb9b4 feat(master): show error message when decommission dp fails
close: #21952214

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
a3ce619a78 feat(master): retry decommission for failed dp first
close:##21952214

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
7c1382d762 feat(reconstruct): reconstruct code
Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
04fe04ede7 reconstruct(metanode): reconstruct dir snapshot deletion subprocess
Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
8e0f73b9c3 fix(datanode): Don't use zero for indicating completion in the load partition and Raft status
avoid conflicts with the initial value

close:#21991650

Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
7b93604b34 fix(datanode): dp may on decommision while doing auto compute crc, so change it to warn
close:#21979158

Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
1de4e44d55 feat(master): auto reduce redundant replica if rolling back
close:#21993948

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
729ac67268 feature(master): Decommission datapartition operation for cli tool is supported
close:#21975923

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
S9054862
21f13601a5 fix(master): avoid to pull old vol view from other followers
close: #21970720
Signed-off-by: S9054862 <huangzhibin1@oppo.com>
2024-03-27 14:24:50 +08:00
S9054862
97c3b94af9 fix(data): avoid panic when normal extent hole repair read
close: #21995943
Signed-off-by: S9054862 <huangzhibin1@oppo.com>
2024-03-27 14:24:50 +08:00
baihailong
f26dcfb48b fix(libsdk): cfs_close dir print error "stream is not opened yet".
Signed-off-by: baihailong <baihailong@oppo.com>
2024-03-27 14:24:50 +08:00
baihailong
4779613567 fix(sdk): when the stream's residual server coroutine exits, others stream maybe deleted
Signed-off-by: baihailong <baihailong@oppo.com>
2024-03-27 14:24:50 +08:00
baihailong
0073bdac33 fix(sdk): when the stream's residual server coroutine exits, others stream maybe deleted.#2827
Signed-off-by: baihailong <baihailong@oppo.com>
2024-03-27 14:24:50 +08:00
baihailong
6a5d6525a5 fix(sdk): flush operation appeared bad file descriptor
Signed-off-by: baihailong <baihailong@oppo.com>
2024-03-27 14:24:50 +08:00
baihailong
4c2ee76e74 fix(sdk): GetStreamer drop request in channel leadto deadlock
Signed-off-by: baihailong <baihailong@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
8d48ae1b44 fix(datanode): snapshot mod append should not allocate extent id in follower
close:#21938895

Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
c867f09bd7 feat(datanode): add testcase for repair routine
close:#21938895

Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
76675d4a61 feat(mock): Move raft mock to uitl for all module usage
close:#21938895

Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
leonrayang
b5895c07b1 fix(datanode): normal extent repair need punch hole in senario of snapshot
close:#21938895

Signed-off-by: leonrayang <changliang@oppo.com>
2024-03-27 14:24:50 +08:00
S9054862
54fad0d873 fix(util): disable gohook by default
close: #21985685

Signed-off-by: S9054862 <huangzhibin1@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
ba7a02d8be feat(master): some enhanced functionalities for checking datanode decommission status
close:#21975944

Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
e2c5fa0cda feat(master): If the service on the node where the new replica is created stops,attempt other nodes
close:#21967801
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
3202efb924 bugfix(datanode): remove logic of fetching replica from master after adding raft member
Signed-off-by: chihe <chi.he@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
901fb4be3b bugfix(datanode): Apply will be initialized when new datapartition is created
Signed-off-by: chihe <chi.he@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
ef7adaaed4 bugfix(master): 1.datanode with no disk reset to initial 2. restore dp replica if rollback failed
Signed-off-by: chihe <chi.he@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
b518b4c53a feat(datnode): 1.support read enableExtentRepairReadLimit from conf 2.query dp holded token
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
f66c732104 feat(datanode): Support the functionality of allowing only one extent data read at a time per disk
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
74dcb76aef feat(datanode): support api handler for reloading data partition
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
1042fa9857 feat(datanode): add log for extent repair speed
Signed-off-by: chihe <chi.he@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
a89ab7f919 enhance(datanode): add debug log for datanode repair
Signed-off-by: chihe <chi.he@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
dc3eca6638 fix(master): if vol for cache dp is deleted, mark dp decommission status as success directly
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
a6c1636381 fix(master): start to check decommission datanode or disk when meta data is ready
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
3766292316 feature(master): support specify count for datanode decomission
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
chihe
56a1caa057 debug(master): to debug length of dp.Replicas equals to 0
Signed-off-by: chihe <chihe@oppo.com>
2024-03-27 14:24:50 +08:00
tangdeyi
6ad04f6365 fix(object): listobjectv2 IsTruncated required
Signed-off-by: tangdeyi <tangdeyi@oppo.com>
2024-03-22 11:02:51 +08:00
slasher
724f850d4a style(util): change log level with name
Signed-off-by: slasher <mcq.sejust@gmail.com>
2024-03-14 17:27:55 +08:00
yhjiango
f7e7235694 fix(object): fix request parts check in complete multipart
Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2024-03-13 15:54:54 +08:00
yhjiango
611ef3263e fix(object): fix tagging valid verification
Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2024-03-13 15:54:54 +08:00
lily-lee
b3bc9eeeee refactor(docs): refactor evaluation env,add CPU,memory and disk information
Signed-off-by: lily-lee <lilylee88756@gmail.com>
2024-03-13 15:35:36 +08:00
slasher
100122c0ca perf(common): trace prefer to format track log
close #3224

Signed-off-by: slasher <mcq.sejust@gmail.com>
2024-03-11 18:48:30 +08:00
slasher
ebdc9f2763 perf(common): limit internal track log of trace span
close #3223

Signed-off-by: slasher <mcq.sejust@gmail.com>
2024-03-11 18:48:30 +08:00
NaturalSelect
491c1cbbd7 fix(meta): limit the count of metanode inode audit log
close: #3194
Signed-off-by: NaturalSelect <2145973003@qq.com>
2024-03-11 16:00:27 +08:00
NaturalSelect
9203f558bd test(util): fix routinepool test
close: #3211

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-03-08 17:38:43 +08:00
nasuiyile
714536eaf2 fix(meta): Protect MetaPartition UpdateXAttr interface
Signed-off-by: nasuiyile <3290213518@qq.com>
2024-03-08 12:32:11 +08:00
zhaochenyang
72d9291453 fix(lcnode): fix lcnode panic and reduce task allocation time
Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
2024-03-07 17:21:21 +08:00
baihailong
60e0650735 fix(fuse): MountOption add parameter DisableMountSubtype
Signed-off-by: baihailong <baihailong@oppo.com>
2024-03-07 10:29:50 +08:00
NaturalSelect
ebb1d14942 fix(util): recycle audit logs when rolling
close: #3178
Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-03-06 17:21:28 +08:00
yhjiango
234d30ec11 fix(object): partNumber must not be greater than 10000
Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2024-03-06 15:42:27 +08:00
yhjiango
1f23b3f620 fix(object): adjust STS auth process
Signed-off-by: yhjiango <jiangyunhua@oppo.com>
2024-03-06 15:42:27 +08:00
NaturalSelect
3a0e306ed3 feat(meta): batch delete extents when truncate file
close: #3169

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
2024-03-06 14:25:17 +08:00
2783 changed files with 298474 additions and 57546 deletions

3
.gitattributes vendored
View File

@ -2,3 +2,6 @@
* text=auto eol=lf
# Do not modify line endings for binary files
*.png binary
*.pdf binary
*.tar.gz binary
*.jpg binary

View File

@ -1,17 +1,110 @@
<!-- Thanks for sending a pull request! -->
<!-- Thanks for sending the pull request! -->
**What this PR does / why we need it**:
<!--
### Contribution Checklist
**Which issue this PR fixes**:
<!-- *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: -->
fixes #
- PR title format should be *type(scope): subject*. For details, see *[Pull Request Title](https://github.com/cubefs/cubefs/blob/master/.github/workflows/check_pull_request.yml)*.
**Special notes for your reviewer**:
- Each pull request should address only one issue, not mix up code from multiple issues.
**Release note**:
<!-- Steps to write your release note:
1. Use the release-note-* labels to set the release note state (if you have access)
2. Enter your extended release note in the below block; leaving it blank means using the PR title as the release note. If no release note is required, just write `NONE`.
- Each commit in the pull request has a meaningful commit message. For details, see *[Commit Message](https://github.com/cubefs/cubefs/blob/master/.github/workflows/check_pull_request.yml)*.
- Fill out the template below to describe the changes contributed by the pull request. That will give reviewers the context they need to do the review.
- Once all items of the checklist are addressed, remove the above text and this checklist, leaving only the filled out template below.
-->
```release-note
<!-- Either this PR fixes an issue, -->
Fixes: #xyz
<!-- or this PR is one task of an issue. -->
Main Issue: #xyz
### Motivation
<!-- Explain here the context, and why you're making that change. What is the problem you're trying to solve. -->
blaaaaa
### Modifications
<!-- Describe the modifications you've done. -->
``` text
blaaaaa
```
### Types of changes
<!-- Show in a checkbox-style, the expected types of changes your project is supposed to have: -->
<!-- _Put an `x` in the boxes that apply_ -->
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] Documentation Update (if none of the other choices apply)
- [ ] So on...
### Verifying this change
<!-- Please pick either of the following options. -->
- [ ] Make sure that the change passes the testing checks.
This change is a trivial rework / code cleanup without any test coverage.
*(or)*
This change is already covered by existing tests, such as *(please describe tests)*.
*(or)*
This change added tests and can be verified as follows:
*(example:)*
- *This can be verified in development debugging*
- *This can be realized in a mocked environment, like a test cluster consisting in docker*
*(or)*
This change `MUST` reappear in online clusters, or occur in that specific scenarios.
### Does this pull request potentially affect one of the following parts:
<!-- Which of the following parts are affected by this change? -->
- [ ] Master
- [ ] MetaNode
- [ ] DataNode
- [ ] ObjectNode
- [ ] AuthNode
- [ ] LcNode
- [ ] Blobstore
- [ ] Client
- [ ] Cli
- [ ] SDK
- [ ] Other Tools
- [ ] Common Packages
- [ ] Dependencies
- [ ] Anything that affects deployment
### Documentation
<!-- Is there a chinese and english document modification? -->
- [ ] `doc` <!-- Your PR contains doc changes. -->
- [ ] `doc-required` <!-- Your PR changes impact docs and you will update later -->
- [ ] `doc-not-needed` <!-- Your PR changes do not impact docs -->
- [ ] `doc-complete` <!-- Docs have been already added -->
### Review Expection
<!-- How long would you like the team to be completed in your contributing? -->
- [ ] `in-two-days`
- [ ] `weekly`
- [ ] `free-time`
- [ ] `whenever`
### Matching PR in forked repository
<!-- enter the url if has PR in forked repository. -->
PR in forked repository: <!-- ENTER URL HERE -->
<!-- Thanks for contributing, best days! -->

View File

@ -1,23 +0,0 @@
version: 1
env:
- CGO_ENABLED=0
flags:
- -trimpath
goos: linux
goarch: amd64
# (Optional) Entrypoint to compile.
main: ./preload/preload.go
binary: cfs-preload-{{ .Os }}-{{ .Arch }}
ldflags:
- "-X github.com/cubefs/cubefs/proto.Version={{ .Env.VERSION }}"
- "-X github.com/cubefs/cubefs/proto.CommitID={{ .Env.COMMIT_ID }}"
- "-X github.com/cubefs/cubefs/proto.BranchName={{ .Env.BRANCH_NAME }}"
- "-X github.com/cubefs/cubefs/proto.BuildTime={{ .Env.BUILD_TIME }}"
- "-X github.com/cubefs/cubefs/blobstore/util/version.version={{ .Env.BRANCH_NAME }}/{{ .Env.COMMIT_ID }}"
- "-w -s"

View File

@ -1,36 +0,0 @@
name: BlobStore-Checks
on:
push:
paths:
- 'blobstore/**.go'
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'blobstore/**'
permissions:
contents: read
jobs:
GolangFormat:
name: format
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Go code format with gofumpt
run: |
docker/run_docker.sh --bsgofumpt
GolangCI-Lint:
name: lint
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: run golangci-lint
run: |
docker/run_docker.sh --bsgolint

View File

@ -8,6 +8,9 @@ on:
- reopened
- synchronize
permissions:
contents: read
jobs:
check-pr-title:
name: Check Pull Request Title
@ -45,31 +48,41 @@ jobs:
check-commit-message:
name: Check Commit Message
runs-on: ubuntu-latest
env:
JOB_COMMIT_FILE: '/tmp/commits.json'
steps:
- name: Get PR Commits
id: 'get-pr-commits'
uses: tim-actions/get-pr-commits@3efc1387ead42029a0d488ab98f24b7452dc3cde # v1.3.0
uses: sejust/get-pr-commits@21ca1696fc716fa9423291cddc3d7a82668cfbc2 # v1.3.2
with:
token: ${{ secrets.GITHUB_TOKEN }}
output-file: ${{ env.JOB_COMMIT_FILE }}
- name: Check Title
uses: tim-actions/commit-message-checker-with-regex@094fc16ff83d04e2ec73edb5eaf6aa267db33791 # v0.3.2
uses: sejust/commit-message-checker-with-regex@5bedef5c21ee29bb438572bdb715ad65159264f8 # v0.3.3
with:
commits: ${{ steps.get-pr-commits.outputs.commits }}
pattern: '^[a-z]+\([a-z]+\): .+\n(\n.*)*$'
commits: ${{ env.JOB_COMMIT_FILE }}
pattern: '^[a-z]+\([a-z0-9_\-\.]+\): .+\n(\n.*)*$'
error: 'Title likes `<type>(<scope>): <subject>`'
- name: Check Subject Line Length
uses: tim-actions/commit-message-checker-with-regex@094fc16ff83d04e2ec73edb5eaf6aa267db33791 # v0.3.2
- name: Check Title Space
uses: sejust/commit-message-checker-with-regex@5bedef5c21ee29bb438572bdb715ad65159264f8 # v0.3.3
with:
commits: ${{ steps.get-pr-commits.outputs.commits }}
commits: ${{ env.JOB_COMMIT_FILE }}
pattern: '^[^ ]+(?: [^ ]+)*\n(\n.*)*$'
error: 'Title has consecutive spaces'
- name: Check Subject Line Length
uses: sejust/commit-message-checker-with-regex@5bedef5c21ee29bb438572bdb715ad65159264f8 # v0.3.3
with:
commits: ${{ env.JOB_COMMIT_FILE }}
pattern: '^.{0,100}\n(\n.*)*$'
error: 'Subject too long (max 100)'
- name: Check Body Line Length
uses: tim-actions/commit-message-checker-with-regex@094fc16ff83d04e2ec73edb5eaf6aa267db33791 # v0.3.2
uses: sejust/commit-message-checker-with-regex@5bedef5c21ee29bb438572bdb715ad65159264f8 # v0.3.3
with:
commits: ${{ steps.get-pr-commits.outputs.commits }}
commits: ${{ env.JOB_COMMIT_FILE }}
pattern: '^.+\n(\n.{0,100})*$'
error: 'Body line too long (max 100)'

View File

@ -16,12 +16,8 @@ on:
- release-*
- develop-*
- blobstore-*
paths-ignore:
# paths-ignore:
# - 'blobstore/**'
# - '.github/**'
# - 'docs/**'
# - 'docs-zh/**'
# - '**.md'
permissions:
contents: read
@ -33,7 +29,7 @@ jobs:
- name: Checkout repo
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
- name: Find changed files
- name: Find changed files of document
id: changed-files
uses: tj-actions/changed-files@87697c0dca7dd44e37a2b79a79489332556ff1f3 # v37.6.0
with:
@ -43,13 +39,42 @@ jobs:
docs-zh/**
**.md
- name: Find changed files of blobstore
id: changed-blobs
uses: tj-actions/changed-files@87697c0dca7dd44e37a2b79a79489332556ff1f3 # v37.6.0
with:
files: |
blobstore/**
- name: All changed documents
if: steps.changed-files.outputs.only_changed == 'true'
env:
CI_ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
run: |
for file in ${CI_ALL_CHANGED_FILES}; do
echo "<$file> was changed"
done
- name: Check gofmt
if: steps.changed-files.outputs.only_changed != 'true'
run: |
docker/run_docker.sh --format
- name: Unit tests
if: steps.changed-files.outputs.only_changed != 'true'
- name: Unit test for blobstore
if: steps.changed-blobs.outputs.only_changed == 'true'
run: |
docker/run_docker.sh --testblobstore
- name: Unit test for cubefs
if: ${{ (steps.changed-files.outputs.only_changed != 'true') &&
(steps.changed-blobs.outputs.any_changed != 'true') }}
run: |
docker/run_docker.sh --testcubefs
- name: Unit test for all
if: ${{ (steps.changed-files.outputs.only_changed != 'true') &&
(steps.changed-blobs.outputs.only_changed != 'true') &&
(steps.changed-blobs.outputs.any_changed == 'true') }}
run: |
docker/run_docker.sh --test

View File

@ -41,11 +41,21 @@ jobs:
strategy:
fail-fast: false
matrix:
language: [ 'java', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
include:
- language: go
build-mode: autobuild
- language: java-kotlin
build-mode: none # This mode only analyzes Java. Set this to 'autobuild' or 'manual' to analyze Kotlin too.
- language: python
build-mode: none
# CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
@ -53,9 +63,10 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4
uses: github/codeql-action/init@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
@ -63,12 +74,6 @@ jobs:
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@ -80,6 +85,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4
uses: github/codeql-action/analyze@9e8d0789d4a0fa9ceb6b1738f7e269594bdd67f0 # v3.28.9
with:
category: "/language:${{matrix.language}}"

View File

@ -14,7 +14,7 @@ jobs:
- name: analysis
uses: actions-cool/issues-similarity-analysis@8f46978e3e8b79d736997a225c95d27d9029f294 # v1.3.1
with:
filter-threshold: 0.6
filter-threshold: 0.8
comment-title: '### See'
comment-body: '${index}. ${similarity} #${number}'
show-footer: false

View File

@ -32,12 +32,12 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
with:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with:
results_file: results.sarif
results_format: sarif
@ -67,6 +67,6 @@ jobs:
# Upload the results to GitHub's code scanning dashboard.
- name: "Upload to code-scanning"
uses: github/codeql-action/upload-sarif@0ba4244466797eb048eb91a6cd43d5c03ca8bd05 # v2.21.2
uses: github/codeql-action/upload-sarif@4355270be187e1b672a7a1c7c7bae5afdc1ab94a # v3.24.10
with:
sarif_file: results.sarif

5
.gitignore vendored
View File

@ -20,3 +20,8 @@ java/src/main/resources/*.so
/cover.output
/cubefs_unittest.output
.version
.cache
.clangd
blobstore/cpp/build
blobstore/cpp/**/*.pb.cc
blobstore/cpp/**/*.pb.h

View File

@ -110,24 +110,6 @@ builds:
- -X {{.Env.PROTO}}.BuildTime={{.Date}}
- -X {{.Env.VV}}={{.Branch}}/{{.Date}}
- -w -s
- id: "preload"
main: ./preload
binary: cfs-preload
env:
- CGO_ENABLED=0
goos:
- linux
goarch:
- amd64
flags:
- -trimpath
ldflags:
- -X {{.Env.PROTO}}.Version={{.Version}}
- -X {{.Env.PROTO}}.CommitID={{.FullCommit}}
- -X {{.Env.PROTO}}.BranchName={{.Branch}}
- -X {{.Env.PROTO}}.BuildTime={{.Date}}
- -X {{.Env.VV}}={{.Branch}}/{{.Date}}
- -w -s
- id: "server"
main: ./cmd

View File

@ -8,11 +8,14 @@ rules:
- '*.go'
patterns:
- pattern-regex: '(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
- pattern-not-regex: '127\.0\.0\.\d+'
- pattern-not-regex: '10\.\d+\.\d+.\d+'
- pattern-not-regex: '192\.168\.\d+.\d+'
- pattern-not-regex: '192\.0\.2\.\d+' # 192.0.2.0/24 (TEST-NET-1, rfc5737)
- pattern-not-regex: '198\.51\.100\.\d+' # 198.51.100.0/24 (TEST-NET-2, rfc5737)
- pattern-not-regex: '203\.0\.113\.\d+' # 203.0.113.0/24 (TEST-NET-3, rfc5737)
- pattern-not-regex: '172\.16\.\d+\.\d+' # 172.16.0.0/12
- pattern-not-regex: '169\.254\.\d+\.\d+'# 169.254.0.0/16
severity: WARNING
- id: rfc-3849-ip-address
languages:
@ -22,5 +25,5 @@ rules:
include:
- '*.go'
patterns:
- pattern-regex: '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))'
severity: WARNING
- pattern-regex: '(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7})|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))'
severity: WARNING

2
.semgrepignore Normal file
View File

@ -0,0 +1,2 @@
depends/
vendor/

View File

@ -14,6 +14,7 @@ This page contains a list of organizations who are using CubeFS in production or
- **[LinkSure Network](https://cn.wifi.com)**: LinkSure uses CubeFS to store application logs running inside container environments as well as nginx logs. Also, they use CubeFS as the backend storage for Elasticsearch.
- **[Reconova](http://www.reconova.com):** Reconova uses CubeFS to store massive small files in the production environment. It currently uses one CubeFS volume to store more than 80 million small files and each file around 40 kilobytes in size.
- **[BIGO](https://www.bigo.sg/):** BIGO uses CubeFS to store logs for AI platform applications that running in the container environment, because CubeFS have excellent concurrent processing capability.
- **[Vipshop](https://www.vip.com/):** Cubefs is used in the offline hybrid deployment scenario of YARN on Kubernetes.After some adjustments, it has become quite stable.
## Adopters
@ -29,11 +30,19 @@ This page contains a list of organizations who are using CubeFS in production or
| [LinkSure Network](https://cn.wifi.com) | ![production](https://img.shields.io/badge/-production-blue?style=flat) |
| [BIGO LIVE](https://www.bigo.tv/cn/) | ![production](https://img.shields.io/badge/-production-blue?style=flat) |
| [Xiaomi](https://www.mi.com/global/) | ![production](https://img.shields.io/badge/-production-blue?style=flat) |
| [shengwang.cn](https://www.shengwang.cn/) | ![production](https://img.shields.io/badge/-production-blue?style=flat) |
| [Vipshop](https://www.vip.com/) | ![production](https://img.shields.io/badge/-production-blue?style=flat) |
| [CreditEase](https://www.creditease.com/) | ![production](https://img.shields.io/badge/-production-blue?style=flat) |
| [TD Tech](https://www.td-tech.com/) | ![production](https://img.shields.io/badge/-production-blue?style=flat) |
| [Digtal guangdong](https://www.digitalgd.com.cn/) | ![production](https://img.shields.io/badge/-production-blue?style=flat) |
| [PITS Global Data Recovery Services](https://www.pitsdatarecovery.net/) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [Da-Jiang Innovations](https://www.dji.com/cn) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [Yanhuang Data](https://yanhuangdata.com/) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [Sinosoft](http://www.sinosoft.com.cn) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [DADA](https://about.imdada.cn) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [Club Factory](https://www.wholeeprime.com/) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [Nanjing University](https://www.nju.edu.cn/en/) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [PSBC](https://www.psbc.com/) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [DeepMirror](https://deepmirror.vercel.app/) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [shoppe](https://shopee.com/) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [houdutech](https://www.houdutech.cn) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |
| [cecloud](https://www.cecloud.com/) | ![testing](https://img.shields.io/badge/-testing-green?style=flat) |

View File

@ -1,3 +1,159 @@
## Release v3.5.3 - 2025/12/31
### **UPGRAGDE NOTICE**
If you are using a CubeFS version earlier than v3.5.0, please refer to the UPGRADE NOTICE in version v3.5.0 for detailed upgrade steps and upgrade to v3.5.0 first.
Upgrade nodes in this order: flshnode → master → datanode → metanode → objectnode → lcnode → cli → client.
Upgrade lcnode and flashnode when needed.
Deploy flashgroupmanager when needed
Clients should use versions later than 3.2.0. Older versions need to be upgraded promptly; otherwise, there will be a risk of compromising stability.
### **Main Feature**
#### High-throughput LLM/MLLM training with 8ms+ computestorage latency tolerance
+ `client`: Support asynchronous flush for extent handler to improve write performance. Write speed exceeds 1.2 GB/s; on a high-spec H20 training node, a single client can achieve 10+ GB/s aggregate throughput with 10 concurrent large-file writes.(#3973,@bboyCH4)
+ `client`: Optimize the client read-ahead mechanism and memory footprint; single-file read speeds exceed 2 GB/s. (#3982,@bboyCH4)
+ `client`: Metadata cache acceleration for small-file prewarm (#3995,@Victor1319)
Note: Refer to the latest community documentation for enabling and tuning.
#### Distributed cache can run as an independent service
+ `flashgroupmanager`: Introduce flashgroupmanager node and topology to support flashnode cluster management. (@bboyCH4)
+ `flashnode`: Support block-level data read and write operations. (#3977, @clinx)
+ `tools`: Add `rctest` (benchmark) and `rcconfig` (config) tools for remote cache system. (#3981,@bboyCH4,@clinx)
+ `client`: Provide SDK for FlashNode object storage data block upload/download service #3985,@bboyCH4,@clinx
+ `client`: Implement NearRead strategy to prioritize reading from the nearest replica to reduce latency. (#3976,@zhumingze1108)
### **Enhance**
+ `client`: Fuse library supports parallel processing of FUSE requests to improve concurrency. (#3974,@Victor1319)
+ `client`: Optimize metadata cache performance. (#3974,@Victor1319)
+ `client`: Add `tcpAliveTime` parameter for better TCP connection management. (#3974,@Victor1319)
+ `master`: Support DP decommission status evolution history query. (#3987,@shuqiang-zheng)
+ `master`: Add `TryDecommissionRunningDiskIgnoreDps` to support differentiated strategies for disk decommission based on different reasons. (#3975,@shuqiang-zheng)
+ `master`: Add audit logs for `migrateMetaPartition` and record reasons for DP migration/rollback. (#3975,@shuqiang-zheng)
+ `datanode`: Support reason passthrough for DP migration. (#3975,@shuqiang-zheng)
+ `flashnode`: Optimize cache operation opcodes and processing logic. (#3988,@clinx,@bboyCH4)
### **Bugfix**
* `master`: Decommission token consumed twice on restart during two-replica DP decommissioning(#3978,@shuqiang-zheng)
* `client`: Fix `ltp iogen01` test failure when pre-reading (ahead read) is enabled. (#3980,@clinx)
* `client`: Offset calculation error during client readahead with partial hits(#3979,@bboyCH4)
* `master`: Some DPs remain in decommission queue when disk offline marking fails, affecting subsequent decommissions (#3983,@shuqiang-zheng)
* `master`: Incorrect disk/node decommission progress display for 2-replica DPs due to leader change(#3984,@Victor1319)
## Release v3.5.2 - 2025/07/31
### **UPGRAGDE NOTICE**
If you are using a CubeFS version earlier than v3.5.0, please refer to the UPGRADE NOTICE in version v3.5.0 for detailed upgrade steps and upgrade to v3.5.0 first.
Upgrade nodes in this order: master → metanode → datanode → objectnode → cli → client.
Upgrade lcnode and deploy flashnode when needed.
Clients should use versions later than 3.2.0. Older versions need to be upgraded promptly; otherwise, there will be a risk of compromising stability.
### **Main Feature**
#### For large language models (LLMs) and multimodal LLM (MLLM) training, delivers high throughput (LLM checkpoints) and tolerates high-latency computestorage separation (8 ms+), achieving training durations comparable to public cloud deployments in the same region
+ `master/lcnode`: Lifecycle adds filtering rule based on file size. (#3893, @Victor1319)
+ `master`: dp decommission support priority&concurrency control. (#3891, @shuqiang-zheng)
+ `master`: Add master replica abnormality alarm. (#3882, @zhumingze1108)
+ `master`: Add disk decommission success alarm. (#3886, @zhumingze1108)
+ `meta`: Support mp reload capability. (#3894, @leonrayang)
+ `meta`: Volume file size distribution statistics. (#3884, @M1eyu2018, @zhumingze1108)
+ `client`: Implement client pre-reading function. (#3889, @yanbin027, @Victor1319)
+ `client`: Client delay monitoring statistics. (#3885, @M1eyu2018, @aaronwu2010)
+ `data`: Bad disk detection and lost disk discovery. (#3878, @zhumingze1108)
+ `data`: Support asynchronous limitio restrictions. (#3881, @zhumingze1108)
+ `master/data/meta/cli`: dp and mp read-only reasons display. (#3880, @zhumingze1108)
### **Enhance**
+ `all`: Remove the part of the code that uses datanode as cache. (#3888, @Victor1319)
+ `master`: DataNode&Disk&dp Decommission logic optimization. (#3891, @shuqiang-zheng, @zhumingze1108)
+ `meta`: Optimize metanode memory usage. (#3892, @Victor1319)
+ `data`: Optimize datanode memory usage. (#3887, @aaronwu2010)
+ `data`: Optimize and repair the process of tinyDeleteRecord synchronization logic. (#3890, @Victor1319)
+ `cli`: cli datapartition check display optimization. (#3879, @zhumingze1108)
### **Bugfix**
* `master/data`: Repair process blocked by host0 replica. (@shuqiang-zheng)
* `master/raft`: Fixed the issue of dp no leader caused by failure to add raft members during decommission process. (@shuqiang-zheng)
## Release v3.5.1 - 2025/05/28
### **UPGRAGDE NOTICE**
If you are using a CubeFS version earlier than v3.5.0, please refer to the UPGRADE NOTICE in version v3.5.0 for detailed upgrade steps and upgrade to v3.5.0 first.
### **Main Feature**
+ `all`: flash cache in cluster. #2943 @bboyCH4, @longerfly, @slasher, @shuqiang-zheng, @clinx
+ `flash`: scale out the cache layer by adding more cache nodes to handle increased read traffic.
+ `master`: save the FlashNode topology state and push FlashNode topology data to the client.
+ `client`: data reads are routed to the appropriate cache node based on consistent hashing.
+ `cli`: use CLI commands to query the current cache status and control its behavior.
### **Enhance**
+ `data/meta`: support for dynamic adjustment of gogc. (#3816, @shuqiang-zheng)
+ `client`: actively release part of the client's memory to reduce memory footprint. (@bboyCH4)
+ `client`: support reading data with quorum consistency. (@zhumingze1108)
### **Bugfix**
* `meta`: tune the retry mechanism for failed volume creation to minimize the impact on volume deletion performance. (@bboyCH4)
* `data`: no longer allow single replica dp raftForce deletion. (@zhumingze1108)
* `data`: add CRC check for extent ID allocation. (@leonrayang)
* `client`: monitor already contains grouping label commit. (@zhumingze1108)
* `client`: failure to update the local extent cache generation resulted in an LTP failure.(@bboyCH4)
* `flash`: Removing an fn immediately after a single 200ms timeout on origin fetch is too sensitive. A better approach would be to remove it only after multiple consecutive timeouts. (@longerfly)
* `object`: copy data between different buckets. (@clinx)
## Release v3.5.0 - 2025/03/13
### **UPGRAGDE NOTICE**
If you are using a CubeFS version earlier than v3.4.0, please refer to the UPGRADE NOTICE in version v3.4.0 for detailed upgrade steps and upgrade to v3.4.0 first.
### **Attention:**
If you deployed the cluster based on an older version, please refer to the documentation [upgrade 3.5.0](https://github.com/cubefs/cubefs/wiki/CubeFS-v3.5.0-upgrade-manual) for upgrade steps to version 3.5.+
### **Main Feature**
+ `all`: Supports the capability to manage different storage media. #3603@bboyCH4, @true1064, @Victor1319
+ `master/lcnode`: Supports automatic migration of cold data via lifecycle management . (#3604 @bboyCH4, @honeyvinnie, @Victor1319)
+ `master/client`: Support querying all client versions and IP information. (#3606 , @Victor1319)
+ `datanode`: Support for direct I/O read operations with volume. (#3630, @Victor1319)
### **Enhance**
+ `bcache`: bcache supports configuration switches that work for non-SSD types. (#3607, @longerfly)
+ `sdk`: Support the ability of the tool to count the size of the directory by access time. (#3608, @longerfly)
+ `sdk`: Use distributed locks to prevent concurrent deletions from multiple clients in the recycle bin. (#3610, @Victor1319)
+ `sdk/datanode`: Optimize data read path performance for storage and compute separation scenarios. (#3631, @Victor1319)
+ `sdk/metanode`: Support metadata reads in a leaderless environment using quorum mode and meta follower mode. (#3632, @Victor1319)
### **Bugfix**
+ `raft`: Conflicts between Raft metadata and WAL logs (#3605, @Victor1319
+ `sdk`: Deleting files can cause client panic when the recycle bin is enabled (#3609, @bboyCH4)
+ `all`: Fix bugs related to historical version faults and anomalies. ( @Victor1319
## Release v3.4.0 - 2024/10/28
### **UPGRAGDE NOTICE**
@ -187,7 +343,7 @@ If your Blobstore version is v1.1.0 or before which built with cubefs-blobstore
### **Bugfix**
* `master`: master snapshot recover not reset local rocksdb info (#1522, @wuchunhuan )
* `master`:Memory cost too fast during restart in case of data partitions count is magnity (#1774 , @leonrayang)
* `master`:Memory cost too fast during restart in case of data partition's count is magnity (#1774 , @leonrayang)
* `client`: Readonly dp can still accept write request from client (#1779, @bboyCH4)
* `metanode`: Metanode should not establish connection to blobstore for cold volume (#1781, @bboyCH4)
* `client`: blockcache service may be oom when the client caches many large files concurrently (#1783, @zhangtianjiong)
@ -472,7 +628,7 @@ https://zhuanlan.zhihu.com/p/28417779
faultDomainGrpBatchCntdefault count:3can also set 2 or 1
If zone is unavaliable caused by network partition interruptioncreate nodeset group according to usable zone
Set “faultDomainBuildAsPossible” true, default is false
Set "faultDomainBuildAsPossible" true, default is false
The distribution of nodesets under the number of different faultDomainGrpBatchCnt
3 zone1 nodeset per zone
@ -509,7 +665,7 @@ Set “faultDomainBuildAsPossible” true, default is false
**3. Note**
**1) After the fault domain is enabled, all devices in the new zone will join the fault domain**
**2) The created volume will preferentially select the resources of the original zone**
**3) Need add configuration items to use domain resources when creating a new volume according to the table below. By default, the original zone resources are used first if its avaliable**
**3) Need add configuration items to use domain resources when creating a new volume according to the table below. By default, the original zone resources are used first if it's avaliable**
| Cluster:faultDomain | Vol:crossZone | Vol:defaultPriority | Rules for volume to use domain |
h| ------ | ------ | ------ |------ |
@ -525,16 +681,14 @@ example :` curl "http://10.177.200.119:17010/admin/createVol?name=vol_cross5&cap
### **Content Summary**
**1. Purpose**
In order to query the content summary information of a directory efficiently, e.g. total file size, total files and total directories, v2.5 stores such information as the parent directorys xattr.
In order to query the content summary information of a directory efficiently, e.g. total file size, total files and total directories, v2.5 stores such information as the parent directory's xattr.
The parent directory stores the files, directories and total file size of the current directory. Then only need to make recursive of the sub directories, and accumulate the information stored by the directories to query the content summary information of a directory.
**2. Configuration**
Client config file: fuse.json
**1) Enable XAttr**
”enableXattr”:”true”
**2) Enable Summary**
”enableSummary”:”true”
"enableXattr":"true"
Both of xattr and summay have to be set if you want to mount a volume to the local disk.
Set summary is enough if you want to access the volume via libsdk.so.
@ -547,7 +701,7 @@ The parent directory stores the files, directories and total file size of the cu
cfs_getsummary (libsdk/libsdk.go)
**4. Note**
1)The incremental files summary information will be held by their parent directories. But the old files will not. Use cfs_refreshsummary
1)The incremental files' summary information will be held by their parent directories. But the old files will not. Use cfs_refreshsummary
(libsdk/libsdk.go) interface to rebuild the content summary information.
2)The files, directories and total file size are updated asynchronously in the background. Users are not aware of these operations, but it does
increase the requests to meta servers (usually doubled). You are recommended to evaluate the impact to your cluster before using this
@ -791,7 +945,7 @@ Release2.1.0 did a lot of work to optimize memory usage.
* `object`: Change from hard link to soft link in **CopyObject** action. [#563](https://github.com/cubefs/cubefs/pull/563)
* `object`: Solved **parallel-safety** issue; Clean up useless data on failure in **upload** part. [#553](https://github.com/cubefs/cubefs/pull/553)
* `object`: Fixed a problem in listing multipart uploads. [#595](https://github.com/cubefs/cubefs/pull/595)
* `object`: Solve the problem that back-end report “NotExistErr” error when uploading files with the same key in parallel. [#685](https://github.com/cubefs/cubefs/pull/685)
* `object`: Solve the problem that back-end report "NotExistErr" error when uploading files with the same key in parallel. [#685](https://github.com/cubefs/cubefs/pull/685)
* `fuse`: Evict inode cache when dealing with forget. [#523](https://github.com/cubefs/cubefs/pull/523)
### Document

0
GOVERNANCE_CN.md Executable file → Normal file
View File

View File

@ -1,63 +1,63 @@
# Technical Steering Committee(TSC)
| Name | Email | Organization |
|------------------------------------------------------------------------|-----------------------------------------------------------------|--------------|
| Haifeng Liu ([@bladehliu](https://github.com/bladehliu)) | [bladehliu@qq.com](mailto:bladehliu@qq.com) | [Individual] |
| Weilong Guo ([@awzhgw](https://github.com/awzhgw)) | [guowl18702995996@gmail.com](mailto:guowl18702995996@gmail.com) | [JD.com] |
| Xiaochun He ([@xiaochunhe](https://github.com/xiaochunhe)) | [626148589@qq.com](mailto:626148589@qq.com) | [OPPO] |
| Mofei Zhang ([@mervinkid](https://github.com/mervinkid)) | [mofei2816@gmail.com](mailto:mofei2816@gmail.com) | [JD.com] |
| Liang Chang ([@leonrayang](https://github.com/leonrayang)) | [chl696@sina.com](mailto:chl696@sina.com) | [OPPO] |
| Name | Email | Organization |
| ---------------------------------------------------------- | --------------------------------------------------------------- | ------------ |
| Haifeng Liu ([@bladehliu](https://github.com/bladehliu)) | [bladehliu@gmail.com](mailto:bladehliu@gmail.com) | [Individual] |
| Weilong Guo ([@awzhgw](https://github.com/awzhgw)) | [guowl18702995996@gmail.com](mailto:guowl18702995996@gmail.com) | [JD.com] |
| Xiaochun He ([@xiaochunhe](https://github.com/xiaochunhe)) | [626148589@qq.com](mailto:626148589@qq.com) | [OPPO] |
| Mofei Zhang ([@mervinkid](https://github.com/mervinkid)) | [mofei2816@gmail.com](mailto:mofei2816@gmail.com) | [JD.com] |
| Liang Chang ([@leonrayang](https://github.com/leonrayang)) | [chl696@sina.com](mailto:chl696@sina.com) | [OPPO] |
# Maintainers
| Name | Email | Organization |
|------------------------------------------------------------------------|-----------------------------------------------------------------|--------------|
| Haifeng Liu ([@bladehliu](https://github.com/bladehliu)) | [bladehliu@qq.com](mailto:bladehliu@qq.com) | - |
| Weilong Guo ([@awzhgw](https://github.com/awzhgw)) | [guowl18702995996@gmail.com](mailto:guowl18702995996@gmail.com) | [JD.com] |
| Shuoran Liu ([@shuoranliu](https://github.com/shuoranliu)) | [shuoranliu@gmail.com](mailto:shuoranliu@gmail.com) | [BEIKE] |
| Xiaochun He ([@xiaochunhe](https://github.com/xiaochunhe)) | [626148589@qq.com](mailto:626148589@qq.com) | [OPPO] |
| Mofei Zhang ([@mervinkid](https://github.com/mervinkid)) | [mofei2816@gmail.com](mailto:mofei2816@gmail.com) | [JD.com] |
| Liang Chang ([@leonrayang](https://github.com/leonrayang)) | [chl696@sina.com](mailto:chl696@sina.com) | [OPPO] |
| Xuewei Zeng ([@Victor1319](https://github.com/Victor1319)) | [834863182@qq.com](mailto:834863182@qq.com) | [OPPO] |
| Dr. Wei Ding ([@wding109](https://github.com/wding109)) | [wding109@gmail.com](mailto:wding109@gmail.com) | [ByteDance] |
| Dr. Junyuan Zeng ([@jzeng4](https://github.com/jzeng4)) | [jzeng04@gmail.com](mailto:jzeng04@gmail.com) | [LinkedIn] |
| hooklee2000 ([@hooklee2000](https://github.com/hooklee2000)) | [hooklee2000@gmail.com](mailto:hooklee2000@gmail.com) | [XFusion] |
| Zhendong Li ([@lizhendong666](https://github.com/lizhendong666)) | [lizhendong666@gmail.com](mailto:lizhendong666@gmail.com) | [JD.com] |
| Xiaobo Yu ([@cessory](https://github.com/cessory)) | [yxbstorm@gmail.com](mailto:yxbstorm@gmail.com) | [OPPO] |
| Cloudstriff ([@Cloudstriff](https://github.com/Cloudstriff)) | [chenjiongwendao@qq.com](mailto:chenjiongwendao@qq.com) | [OPPO] |
| slasher ([@sejust](https://github.com/sejust)) | [mcq.sejust@gmail.com](mailto:mcq.sejust@gmail.com) | [OPPO] |
| Name | Email | Organization |
| ---------------------------------------------------------------- | --------------------------------------------------------------- | ------------ |
| Haifeng Liu ([@bladehliu](https://github.com/bladehliu)) | [bladehliu@gmail.com](mailto:bladehliu@gmail.com) | [Individual] |
| Weilong Guo ([@awzhgw](https://github.com/awzhgw)) | [guowl18702995996@gmail.com](mailto:guowl18702995996@gmail.com) | [JD.com] |
| Shuoran Liu ([@shuoranliu](https://github.com/shuoranliu)) | [shuoranliu@gmail.com](mailto:shuoranliu@gmail.com) | [BEIKE] |
| Xiaochun He ([@xiaochunhe](https://github.com/xiaochunhe)) | [626148589@qq.com](mailto:626148589@qq.com) | [OPPO] |
| Mofei Zhang ([@mervinkid](https://github.com/mervinkid)) | [mofei2816@gmail.com](mailto:mofei2816@gmail.com) | [JD.com] |
| Liang Chang ([@leonrayang](https://github.com/leonrayang)) | [chl696@sina.com](mailto:chl696@sina.com) | [OPPO] |
| Xuewei Zeng ([@Victor1319](https://github.com/Victor1319)) | [834863182@qq.com](mailto:834863182@qq.com) | [OPPO] |
| Dr. Wei Ding ([@wding109](https://github.com/wding109)) | [wding109@gmail.com](mailto:wding109@gmail.com) | [ByteDance] |
| Dr. Junyuan Zeng ([@jzeng4](https://github.com/jzeng4)) | [jzeng04@gmail.com](mailto:jzeng04@gmail.com) | [LinkedIn] |
| hooklee2000 ([@hooklee2000](https://github.com/hooklee2000)) | [hooklee2000@gmail.com](mailto:hooklee2000@gmail.com) | [XFusion] |
| Zhendong Li ([@lizhendong666](https://github.com/lizhendong666)) | [lizhendong666@gmail.com](mailto:lizhendong666@gmail.com) | [JD.com] |
| Xiaobo Yu ([@cessory](https://github.com/cessory)) | [yxbstorm@gmail.com](mailto:yxbstorm@gmail.com) | [OPPO] |
| Cloudstriff ([@Cloudstriff](https://github.com/Cloudstriff)) | [chenjiongwendao@qq.com](mailto:chenjiongwendao@qq.com) | [OPPO] |
| slasher ([@sejust](https://github.com/sejust)) | [mcq.sejust@gmail.com](mailto:mcq.sejust@gmail.com) | [OPPO] |
# Committers
| Name | Email | Organization |
|---------------------------------------------------------------------------------|------------------------------------------------------------------|--------------|
| Hongyan Wang ([@jadewang198510](https://github.com/jadewang198510)) | [741773046@qq.com](mailto:741773046@qq.com) | [OPPO] |
| Chi He ([bboyCH4](https://github.com/bboyCH4)) | [hechi1014@126.com](mailto:hechi1014@126.com) | [OPPO] |
| Jianxing Zhao ([@znlstar](https://github.com/znlstar)) | [znlstar@163.com](mailto:znlstar@163.com) | [JD.com] |
| Yong Sheng ([@shyodx](https://github.com/shyodx)) | [shengyong2021@gmail.com](mailto:shengyong2021@gmail.com) | [BEIKE] |
| Zhengyi Zhu ([@zhuzhengyi](https://github.com/wding109)) | [zhengyi.zhu.hust@gmail.com](mailto:zhengyi.zhu.hust@gmail.com) | [BEIKE] |
| Lei Yin ([@yinlei-jinan](https://github.com/yinlei-jinan)) | [297155992@qq.com](mailto:297155992@qq.com) | [JD.com] |
| Liying Zhang ([@Vivian7755](https://github.com/Vivian7755)) | [zly7755@163.com](mailto:zly7755@163.com) | [JD.com] |
| Xihao Xu ([@xxscott](https://github.com/xxscott)) | [xxscott@163.com](mailto:xxscott@163.com) | [JD.com] |
| Wenjia Wu ([@wenjia322](https://github.com/wenjia322)) | [buaa1214wwj@126.com](mailto:buaa1214wwj@126.com) | [JD.com] |
| pengtianyue ([@pengtianyue025](https://github.com/pengtianyue025)) | [pengtianyue025@gmail.com](mailto:pengtianyue025@gmail.com) | [ByteDance] |
| baijiaruo ([@baijiaruo](https://github.com/baijiaruo)) | [505892459@qq.com](mailto:505892459@qq.com) | [China United Telecommunications Co] |
| Tianjiong Zhang ([@tianjiongzhang](https://github.com/tianjiongzhang)) | [236556116@qq.com](mailto:236556116@qq.com) | [Sangfor] |
| Zongchao Hu ([@JasonHu520](https://github.com/JasonHu520)) | [hastyjason500@gmail.com](mailto:hastyjason500@gmail.com) | [OPPO] |
| Tianpeng Li ([@Skypigltp](https://github.com/skypigltp)) | [skypigltp@gmail.com](mailto:skypigltp@gmail.com) | [VIVO] |
| Hongyin Zhu ([@zhuhyc](https://github.com/zhuhyc)) | [zzhniy.163.niy@163.com](mailto:zzhniy.163.niy@163.com) | [JD.com] |
| Zhixiang Tang ([@xiangcai1215](https://github.com/xiangcai1215)) | [505892459@qq.com](mailto:505892459@qq.com) | [Xiaohongshu]|
| Yubo Li ([@yuboLee](https://github.com/yuboLee)) | [pangbolee@gmail.com](mailto:pangbolee@gmail.com) | [JD.com] |
| Tao Li ([@tomscut](https://github.com/tomscut)) | [tomleescut@gmail.com](mailto:tomleescut@gmail.com) | [BIGO] |
| Junhao Guo ([@M1eyu2018](https://github.com/M1eyu2018)) | [857037797@qq.com](mailto:857037797@qq.com) | [BIGO] |
| Bingxing Liu ([@liubingxing](https://github.com/liubingxing)) | [liubbingxing@gmail.com](mailto:liubbingxing@gmail.com) | [BIGO] |
| Xiang Li ([@lixiang](https://github.com/lixiang)) | [960754123@qq.com](mailto:960754123@qq.com) | [Sangfor] |
| Qing Li ([@qingli](https://github.com/liqingqiya)) | [liqing.qiya@gmail.com](mailto:liqing.qiya@gmail.com) | [ByteDance] |
| Zhihao Wang ([@Cresc](https://github.com/zhihao-wang)) | [wzh07@hotmail.com](mailto:liqing.qiya@gmail.com) | [ByteDance] |
| NaturalSelect ([@NaturalSelect](https://github.com/NaturalSelect)) | [2145973003@qq.com](mailto:2145973003@qq.com) | [Chengdu University of Information Technology] |
| setcy ([@setcy](https://github.com/setcy)) | [asetcy@gmail.com](mailto:asetcy@gmail.com) | [Hangzhou Dianzi University] |
| Shuqiang Zheng ([@shuqiang-zheng](https://github.com/shuqiang-zheng)) | [782879301@qq.com](mailto:782879301@qq.com) | [OPPO] |
| Chuanqing Zhang ([@zhangchuanqing5658](https://github.com/zhangchuanqing5658)) | [zhang691753540@gmail.com](mailto:zhang691753540@gmail.com) | [JD.com] |
| Name | Email | Organization |
| ------------------------------------------------------------------------------ | --------------------------------------------------------------- | ---------------------------------------------- |
| Hongyan Wang ([@jadewang198510](https://github.com/jadewang198510)) | [741773046@qq.com](mailto:741773046@qq.com) | [OPPO] |
| Chi He ([bboyCH4](https://github.com/bboyCH4)) | [hechi1014@126.com](mailto:hechi1014@126.com) | [OPPO] |
| Jianxing Zhao ([@znlstar](https://github.com/znlstar)) | [znlstar@163.com](mailto:znlstar@163.com) | [JD.com] |
| Yong Sheng ([@shyodx](https://github.com/shyodx)) | [shengyong2021@gmail.com](mailto:shengyong2021@gmail.com) | [BEIKE] |
| Zhengyi Zhu ([@zhuzhengyi](https://github.com/wding109)) | [zhengyi.zhu.hust@gmail.com](mailto:zhengyi.zhu.hust@gmail.com) | [BEIKE] |
| Lei Yin ([@yinlei-jinan](https://github.com/yinlei-jinan)) | [297155992@qq.com](mailto:297155992@qq.com) | [JD.com] |
| Liying Zhang ([@Vivian7755](https://github.com/Vivian7755)) | [zly7755@163.com](mailto:zly7755@163.com) | [JD.com] |
| Xihao Xu ([@xxscott](https://github.com/xxscott)) | [xxscott@163.com](mailto:xxscott@163.com) | [JD.com] |
| Wenjia Wu ([@wenjia322](https://github.com/wenjia322)) | [buaa1214wwj@126.com](mailto:buaa1214wwj@126.com) | [JD.com] |
| pengtianyue ([@pengtianyue025](https://github.com/pengtianyue025)) | [pengtianyue025@gmail.com](mailto:pengtianyue025@gmail.com) | [ByteDance] |
| baijiaruo ([@baijiaruo](https://github.com/baijiaruo)) | [505892459@qq.com](mailto:505892459@qq.com) | [China United Telecommunications Co] |
| Tianjiong Zhang ([@tianjiongzhang](https://github.com/tianjiongzhang)) | [236556116@qq.com](mailto:236556116@qq.com) | [Sangfor] |
| Zongchao Hu ([@JasonHu520](https://github.com/JasonHu520)) | [hastyjason500@gmail.com](mailto:hastyjason500@gmail.com) | [OPPO] |
| Tianpeng Li ([@Skypigltp](https://github.com/skypigltp)) | [skypigltp@gmail.com](mailto:skypigltp@gmail.com) | [VIVO] |
| Hongyin Zhu ([@zhuhyc](https://github.com/zhuhyc)) | [zzhniy.163.niy@163.com](mailto:zzhniy.163.niy@163.com) | [JD.com] |
| Zhixiang Tang ([@xiangcai1215](https://github.com/xiangcai1215)) | [505892459@qq.com](mailto:505892459@qq.com) | [Xiaohongshu] |
| Yubo Li ([@yuboLee](https://github.com/yuboLee)) | [pangbolee@gmail.com](mailto:pangbolee@gmail.com) | [JD.com] |
| Tao Li ([@tomscut](https://github.com/tomscut)) | [tomleescut@gmail.com](mailto:tomleescut@gmail.com) | [BIGO] |
| Junhao Guo ([@M1eyu2018](https://github.com/M1eyu2018)) | [857037797@qq.com](mailto:857037797@qq.com) | [BIGO] |
| Bingxing Liu ([@liubingxing](https://github.com/liubingxing)) | [liubbingxing@gmail.com](mailto:liubbingxing@gmail.com) | [BIGO] |
| Xiang Li ([@lixiang](https://github.com/lixiang)) | [960754123@qq.com](mailto:960754123@qq.com) | [Sangfor] |
| Qing Li ([@qingli](https://github.com/liqingqiya)) | [liqing.qiya@gmail.com](mailto:liqing.qiya@gmail.com) | [ByteDance] |
| Zhihao Wang ([@Cresc](https://github.com/zhihao-wang)) | [wzh07@hotmail.com](mailto:liqing.qiya@gmail.com) | [ByteDance] |
| NaturalSelect ([@NaturalSelect](https://github.com/NaturalSelect)) | [2145973003@qq.com](mailto:2145973003@qq.com) | [Chengdu University of Information Technology] |
| setcy ([@setcy](https://github.com/setcy)) | [asetcy@gmail.com](mailto:asetcy@gmail.com) | [Hangzhou Dianzi University] |
| Shuqiang Zheng ([@shuqiang-zheng](https://github.com/shuqiang-zheng)) | [782879301@qq.com](mailto:782879301@qq.com) | [OPPO] |
| Chuanqing Zhang ([@zhangchuanqing5658](https://github.com/zhangchuanqing5658)) | [zhang691753540@gmail.com](mailto:zhang691753540@gmail.com) | [JD.com] |
[OPPO]: https://www.oppo.com/en/

View File

@ -8,8 +8,8 @@ default: all
phony := all
all: build
phony += build server authtool client cli libsdkpre libsdk fsck fdstore preload bcache blobstore deploy
build: server authtool client cli libsdk fsck fdstore preload bcache blobstore deploy
phony += build server authtool client cli libsdkpre libsdk fsck fdstore bcache blobstore deploy
build: server authtool client cli libsdk fsck fdstore bcache blobstore deploy
server:
@build/build.sh server $(GOMOD) --threads=$(threads)
@ -22,6 +22,9 @@ deploy:
blobstore:
@build/build.sh blobstore $(GOMOD) --threads=$(threads)
blobstoredialtest:
@build/build.sh blobstoredialtest $(GOMOD) --threads=$(threads)
client:
@build/build.sh client $(GOMOD) --threads=$(threads)
@ -43,12 +46,15 @@ libsdk:
fdstore:
@build/build.sh fdstore $(GOMOD) --threads=$(threads)
preload:
@build/build.sh preload $(GOMOD) --threads=$(threads)
bcache:
@build/build.sh bcache $(GOMOD) --threads=$(threads)
rctest:
@build/build.sh rctest $(GOMOD) --threads=$(threads)
rcconfig:
@build/build.sh rcconfig $(GOMOD) --threads=$(threads)
phony += clean
clean:
@$(RM) -rf build/bin
@ -61,9 +67,13 @@ phony += test
test:
@build/build.sh test $(GOMOD) --threads=$(threads)
phony += testcover
phony += testcover testcovercubefs testcoverblobstore
testcover:
@build/build.sh testcover $(GOMOD) --threads=$(threads)
testcovercubefs:
@build/build.sh testcovercubefs $(GOMOD) --threads=$(threads)
testcoverblobstore:
@build/build.sh testcoverblobstore $(GOMOD) --threads=$(threads)
phony += mock
mock:

6
OWNERS.md Normal file
View File

@ -0,0 +1,6 @@
code approvers:
- maintainers
code reviewers:
- contributors && maintainers
docs:
- sig-docs

View File

@ -1,6 +1,6 @@
# CubeFS
[![CNCF Status](https://img.shields.io/badge/cncf%20status-incubating-blue.svg)](https://www.cncf.io/projects)
[![CNCF Status](https://img.shields.io/badge/cncf%20status-graduated-blue.svg)](https://www.cncf.io/projects)
[![Build Status](https://github.com/cubefs/cubefs/actions/workflows/ci.yml/badge.svg)](https://github.com/cubefs/cubefs/actions/workflows/ci.yml)
[![LICENSE](https://img.shields.io/github/license/cubefs/cubefs.svg)](https://github.com/cubefs/cubefs/blob/master/LICENSE)
[![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/)
@ -14,6 +14,7 @@
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fcubefs%2Fcubefs.svg?type=shield&issueType=security)](https://app.fossa.com/projects/git%2Bgithub.com%2Fcubefs%2Fcubefs?ref=badge_shield)
[![Release](https://img.shields.io/github/v/release/cubefs/cubefs.svg?color=161823&style=flat-square&logo=smartthings)](https://github.com/cubefs/cubefs/releases)
[![Tag](https://img.shields.io/github/v/tag/cubefs/cubefs.svg?color=ee8936&logo=fitbit&style=flat-square)](https://github.com/cubefs/cubefs/tags)
[![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20CubeFS%20Guru-006BFF)](https://gurubase.io/g/cubefs)
|<img src="https://user-images.githubusercontent.com/5708406/91202310-31eaab80-e734-11ea-84fc-c1b1882ae71c.png" height="24"/>&nbsp;Community Meeting|
|------------------|
@ -25,13 +26,14 @@
## Overview
CubeFS ("储宝" in Chinese) is an open-source cloud-native file storage system, hosted by the [Cloud Native Computing Foundation](https://cncf.io) (CNCF) as an [incubating](https://www.cncf.io/projects/) project.
CubeFS ("储宝" in Chinese) is an open-source cloud-native distributed file & object storage system, hosted by the [Cloud Native Computing Foundation](https://cncf.io) (CNCF) as a [graduated](https://www.cncf.io/projects/) project.
## What can you build with CubeFS
As an open-source distributed storage, CubeFS can serve as your datacenter filesystem, data lake storage infra, and private or hybrid cloud storage.
In particular, CubeFS enables the separation of storage/compute architecture for databases and AI/ML applications.
* As an open-source distributed storage, CubeFS can serve as your datacenter filesystem, data lake storage infra, and private or hybrid cloud storage.
* Moreover, it can be run in public cloud services, providing cache acceleration and file system semantics on top of public cloud storage such as S3.
* In particular, CubeFS enables the separation of storage/compute architecture for databases, search systems, and AI/ML applications.
Some key features of CubeFS include:
@ -43,7 +45,7 @@ Some key features of CubeFS include:
- Flexible storage policies, high-performance replication or low-cost erasure coding
<div width="100%" style="text-align:center;"><img alt="CubeFS Architecture" src="https://raw.githubusercontent.com/cubefs/cubefs/master/docs/source/pic/cfs-arch-ec.png"/></div>
<div width="100%" style="text-align:center;"><img alt="CubeFS Architecture" src="https://raw.githubusercontent.com/cubefs/cubefs/master/docs/source/overview/pic/cfs-arch-ec.png"/></div>
## Documents

0
RELEASE.md Executable file → Normal file
View File

View File

@ -1,4 +1,12 @@
# Roadmap of 2024
# Roadmap of 2026
https://github.com/cubefs/cubefs/issues/3064
### Release Scheduled
| Feature | Type | Version | Status | Development Branch | Scheduled Release Date | Details |
|:--|:--|:--|:--|:--|:--|:--|
| Hybrid Cloud Support & Metadata Cost Reduction | Feature | Release-3.6.0 | System Testing | develop-v3.6.0 | July | 1) Public Cloud Data Writeback<br>2) RocksDB metadata supports RocksDB persistence (Learner priority)<br>3) Learner capability: Raft group supports Learner capability<br>4) MP&&DP multi-region distribution and directed automatic migration |
| System Operations Automation and Stability Enhancement | Feature | Release-3.6.1 | In Development | develop-v3.6.1 | November | 1) DP supports capacity and quantity balancing<br>2) Master & Datanode IO tiered flow control + adaptive load<br>3) Rack balancing, NodeSet balancing<br>4) Cache node massive small files support and performance optimization<br>5) Cache prefetch optimization |
CubeFS will prioritize performance and feature requirements for AI and similar scenarios, and may adjust release content accordingly.

View File

@ -29,10 +29,6 @@ import (
"github.com/cubefs/cubefs/util/log"
)
const (
nodeType = "auth"
)
func (m *Server) getTicket(w http.ResponseWriter, r *http.Request) {
var (
plaintext []byte
@ -43,7 +39,7 @@ func (m *Server) getTicket(w http.ResponseWriter, r *http.Request) {
message string
)
if m.metaReady == false {
if !m.metaReady {
log.LogWarnf("action[handlerWithInterceptor] leader meta has not ready")
http.Error(w, m.leaderInfo.addr, http.StatusBadRequest)
}
@ -79,7 +75,6 @@ func (m *Server) getTicket(w http.ResponseWriter, r *http.Request) {
}
sendOkReply(w, r, newSuccessHTTPAuthReply(message))
return
}
func (m *Server) raftNodeOp(w http.ResponseWriter, r *http.Request) {
@ -145,21 +140,14 @@ func (m *Server) raftNodeOp(w http.ResponseWriter, r *http.Request) {
}
sendOkReply(w, r, newSuccessHTTPAuthReply(message))
return
}
func (m *Server) handleAddRaftNode(raftNodeInfo *proto.AuthRaftNodeInfo) (err error) {
if err = m.cluster.addRaftNode(raftNodeInfo.ID, raftNodeInfo.Addr); err != nil {
return
}
return
return m.cluster.addRaftNode(raftNodeInfo.ID, raftNodeInfo.Addr)
}
func (m *Server) handleRemoveRaftNode(raftNodeInfo *proto.AuthRaftNodeInfo) (err error) {
if err = m.cluster.removeRaftNode(raftNodeInfo.ID, raftNodeInfo.Addr); err != nil {
return
}
return
return m.cluster.removeRaftNode(raftNodeInfo.ID, raftNodeInfo.Addr)
}
func genAuthRaftNodeOpResp(req *proto.APIAccessReq, ts int64, key []byte, msg string) (message string, err error) {
@ -289,28 +277,18 @@ func (m *Server) apiAccessEntry(w http.ResponseWriter, r *http.Request) {
}
sendOkReply(w, r, newSuccessHTTPAuthReply(message))
return
}
func (m *Server) handleCreateKey(keyInfo *keystore.KeyInfo) (res *keystore.KeyInfo, err error) {
if res, err = m.cluster.CreateNewKey(keyInfo.ID, keyInfo); err != nil {
return
}
return
return m.cluster.CreateNewKey(keyInfo.ID, keyInfo)
}
func (m *Server) handleDeleteKey(keyInfo *keystore.KeyInfo) (res *keystore.KeyInfo, err error) {
if res, err = m.cluster.DeleteKey(keyInfo.ID); err != nil {
return
}
return
return m.cluster.DeleteKey(keyInfo.ID)
}
func (m *Server) handleGetKey(keyInfo *keystore.KeyInfo) (res *keystore.KeyInfo, err error) {
if res, err = m.getSecretKeyInfo(keyInfo.ID); err != nil {
return
}
return
return m.getSecretKeyInfo(keyInfo.ID)
}
func (m *Server) handleAddCaps(keyInfo *keystore.KeyInfo) (res *keystore.KeyInfo, err error) {
@ -437,7 +415,6 @@ func (m *Server) osCapsOp(w http.ResponseWriter, r *http.Request) {
}
sendOkReply(w, r, newSuccessHTTPAuthReply(message))
return
}
func (m *Server) genTicket(key []byte, serviceID string, IP string, caps []byte) (ticket cryptoutil.Ticket) {
@ -680,7 +657,6 @@ func send(w http.ResponseWriter, r *http.Request, reply []byte) {
return
}
log.LogInfof("URL[%v],remoteAddr[%v],response ok", r.URL, r.RemoteAddr)
return
}
func keyNotFound(name string) (err error) {
@ -700,5 +676,4 @@ func sendErrReply(w http.ResponseWriter, r *http.Request, HTTPAuthReply *proto.H
if _, err = w.Write(reply); err != nil {
log.LogErrorf("fail to write http reply[%s] len[%d].URL[%v],remoteAddr[%v] err:[%v]", string(reply), len(reply), r.URL, r.RemoteAddr, err)
}
return
}

View File

@ -36,7 +36,7 @@ func (m *Server) handleLeaderChange(leader uint64) {
log.LogWarnf("action[handleLeaderChange] change leader to [%v] ", m.leaderInfo.addr)
m.authProxy = m.newAuthProxy() // TODO no lock?
if m.metaReady == false {
if !m.metaReady {
if err := m.cluster.loadKeystore(); err != nil {
panic(err)
}
@ -57,7 +57,7 @@ func (m *Server) handlePeerChange(confChange *proto.ConfChange) (err error) {
msg = fmt.Sprintf("action[handlePeerChange] clusterID[%v] nodeAddr[%v] is invalid", m.clusterName, addr)
break
}
m.raftStore.AddNodeWithPort(confChange.Peer.ID, arr[0], int(m.config.heartbeatPort), int(m.config.replicaPort))
m.raftStore.AddNodeWithPort(confChange.Peer.ID, arr[0], m.config.heartbeatPort, m.config.replicaPort)
AddrDatabase[confChange.Peer.ID] = string(confChange.Context)
msg = fmt.Sprintf("clusterID[%v] peerID:%v,nodeAddr[%v] has been add", m.clusterName, confChange.Peer.ID, addr)
case proto.ConfRemoveNode:
@ -73,5 +73,4 @@ func (m *Server) handlePeerChange(confChange *proto.ConfChange) (err error) {
func (m *Server) handleApplySnapshot() {
log.LogInfof("clusterID[%v] peerID:%v action[handleApplySnapshot]", m.clusterName, m.id)
m.fsm.restore()
return
}

View File

@ -57,10 +57,7 @@ var action2PathMap = map[string]string{
OSGetCaps: proto.OSGetCaps,
}
var (
cflag string
flaginfo flagInfo
)
var flaginfo flagInfo
type ticketFlag struct {
key string
@ -364,7 +361,7 @@ func accessAuthServer() {
panic(err)
}
} else {
if res, err = resp.KeyInfo.DumpJSONStr(resp.AuthIDKey); err != nil {
if _, err = resp.KeyInfo.DumpJSONStr(resp.AuthIDKey); err != nil {
panic(err)
}
}

View File

@ -57,8 +57,8 @@ func newCluster(name string, leaderInfo *LeaderInfo, fsm *KeystoreFsm, partition
c.cfg = cfg
c.fsm = fsm
c.partition = partition
c.fsm.keystore = make(map[string]*keystore.KeyInfo, 0)
c.fsm.accessKeystore = make(map[string]*keystore.AccessKeyInfo, 0)
c.fsm.keystore = make(map[string]*keystore.KeyInfo)
c.fsm.accessKeystore = make(map[string]*keystore.AccessKeyInfo)
return
}
@ -66,10 +66,6 @@ func (c *Cluster) scheduleTask() {
c.scheduleToCheckHeartbeat()
}
func (c *Cluster) authAddr() (addr string) {
return c.leaderInfo.addr
}
func (c *Cluster) scheduleToCheckHeartbeat() {
go func() {
for {

View File

@ -42,8 +42,8 @@ const (
type clusterConfig struct {
peers []raftstore.PeerAddress
peerAddrs []string
heartbeatPort int64
replicaPort int64
heartbeatPort int
replicaPort int
}
// AddrDatabase is a map that stores the address of a given host (e.g., the leader)
@ -76,7 +76,7 @@ func (cfg *clusterConfig) parsePeers(peerStr string) error {
if err != nil {
return err
}
cfg.peers = append(cfg.peers, raftstore.PeerAddress{Peer: proto.Peer{ID: id}, Address: ip, HeartbeatPort: int(cfg.heartbeatPort), ReplicaPort: int(cfg.replicaPort)})
cfg.peers = append(cfg.peers, raftstore.PeerAddress{Peer: proto.Peer{ID: id}, Address: ip, HeartbeatPort: cfg.heartbeatPort, ReplicaPort: cfg.replicaPort})
address := fmt.Sprintf("%v:%v", ip, port)
syslog.Println(address)
AddrDatabase[id] = address

View File

@ -37,3 +37,9 @@ const (
akAcronym = "ak"
akPrefix = keySeparator + akAcronym + keySeparator
)
// TODO: unused
var (
_ = opSyncGetKey
_ = opSyncGetCaps
)

View File

@ -54,7 +54,6 @@ func (m *Server) startHTTPService() {
}
}
}()
return
}
func (m *Server) newAuthProxy() *AuthProxy {
@ -122,7 +121,6 @@ func (m *Server) handleFunctions() {
http.Handle(proto.OSAddCaps, m.handlerWithInterceptor())
http.Handle(proto.OSDeleteCaps, m.handlerWithInterceptor())
http.Handle(proto.OSGetCaps, m.handlerWithInterceptor())
return
}
func (m *Server) handlerWithInterceptor() http.Handler {

View File

@ -30,7 +30,6 @@ func (mf *KeystoreFsm) DeleteKey(id string) {
mf.ksMutex.Lock()
defer mf.ksMutex.Unlock()
delete(mf.keystore, id)
return
}
func (mf *KeystoreFsm) PutAKInfo(akInfo *keystore.AccessKeyInfo) {
@ -55,5 +54,4 @@ func (mf *KeystoreFsm) DeleteAKInfo(accessKey string) {
mf.aksMutex.Lock()
defer mf.aksMutex.Unlock()
delete(mf.accessKeystore, accessKey)
return
}

View File

@ -37,8 +37,6 @@ type raftLeaderChangeHandler func(leader uint64)
type raftPeerChangeHandler func(confChange *proto.ConfChange) (err error)
type raftCmdApplyHandler func(cmd *RaftCmd) (err error)
type raftApplySnapshotHandler func()
// KeystoreFsm represents the finite state machine of a keystore

View File

@ -118,7 +118,7 @@ func (c *Cluster) syncPutAccessKeyInfo(opType uint32, accessKeyInfo *keystore.Ac
}
func (c *Cluster) loadKeystore() (err error) {
ks := make(map[string]*keystore.KeyInfo, 0)
ks := make(map[string]*keystore.KeyInfo)
log.LogInfof("action[loadKeystore]")
result, err := c.fsm.store.SeekForPrefix([]byte(ksPrefix))
if err != nil {
@ -143,14 +143,8 @@ func (c *Cluster) loadKeystore() (err error) {
return
}
func (c *Cluster) clearKeystore() {
c.fsm.ksMutex.Lock()
defer c.fsm.ksMutex.Unlock()
c.fsm.keystore = nil
}
func (c *Cluster) loadAKstore() (err error) {
aks := make(map[string]*keystore.AccessKeyInfo, 0)
aks := make(map[string]*keystore.AccessKeyInfo)
log.LogInfof("action[loadAccessKeystore]")
result, err := c.fsm.store.SeekForPrefix([]byte(akPrefix))
if err != nil {
@ -175,12 +169,6 @@ func (c *Cluster) loadAKstore() (err error) {
return
}
func (c *Cluster) clearAKstore() {
c.fsm.aksMutex.Lock()
defer c.fsm.aksMutex.Unlock()
c.fsm.accessKeystore = nil
}
func (c *Cluster) addRaftNode(nodeID uint64, addr string) (err error) {
peer := proto.Peer{ID: nodeID}
_, err = c.partition.ChangeMember(proto.ConfAddNode, peer, []byte(addr))

View File

@ -109,8 +109,8 @@ func (m *Server) checkConfig(cfg *config.Config) (err error) {
if m.id, err = strconv.ParseUint(cfg.GetString(ID), 10, 64); err != nil {
return fmt.Errorf("%v,err:%v", proto.ErrInvalidCfg, err.Error())
}
m.config.heartbeatPort = cfg.GetInt64(heartbeatPortKey)
m.config.replicaPort = cfg.GetInt64(replicaPortKey)
m.config.heartbeatPort = cfg.GetInt(heartbeatPortKey)
m.config.replicaPort = cfg.GetInt(replicaPortKey)
if m.config.heartbeatPort <= 1024 {
m.config.heartbeatPort = raftstore.DefaultHeartbeatPort
}
@ -162,8 +162,8 @@ func (m *Server) createRaftServer(cfg *config.Config) (err error) {
NodeID: m.id,
RaftPath: m.walDir,
NumOfLogsToRetain: m.retainLogs,
HeartbeatPort: int(m.config.heartbeatPort),
ReplicaPort: int(m.config.replicaPort),
HeartbeatPort: m.config.heartbeatPort,
ReplicaPort: m.config.replicaPort,
TickInterval: m.tickInterval,
ElectionTick: m.electionTick,
}
@ -213,7 +213,7 @@ func (m *Server) Start(cfg *config.Config) (err error) {
return fmt.Errorf("action[Start] failed %v,err: auth root Key invalid=%s", proto.ErrInvalidCfg, AuthRootKey)
}
if cfg.GetBool(EnableHTTPS) == true {
if cfg.GetBool(EnableHTTPS) {
m.cluster.PKIKey.EnableHTTPS = true
if m.cluster.PKIKey.AuthRootPublicKey, err = os.ReadFile("/app/server.crt"); err != nil {
return fmt.Errorf("action[Start] failed,err[%v]", err)

4
blobstore/Dockerfile Executable file → Normal file
View File

@ -1,5 +1,7 @@
FROM golang:1.17.13@sha256:87262e4a4c7db56158a80a18fefdc4fee5accc41b59cde821e691d05541bbb18
FROM golang:1.18.10@sha256:50c889275d26f816b5314fc99f55425fa76b18fcaf16af255f5d57f09e1f48da
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list && \
sed -i 's/security.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list
ENV JAVA_HOME=bin/jdk1.8.0_321
ENV CLASSPATH=$CLASSPATH:$JAVA_HOME/lib

View File

@ -34,7 +34,7 @@ INSTALL=CGO_ENABLED=0 $(BUILD)
CGOINSTALL=CGO_ENABLED=1 $(BUILD)
PROJECTMOD=github.com/cubefs/cubefs/blobstore
CMDDIR=$(PROJECTMOD)/cmd
TARGETS=clustermgr blobnode access scheduler proxy cli
TARGETS=clustermgr blobnode access scheduler proxy cli shardnode
.PHONY: clean all $(TARGETS)
all:$(TARGETS)
@ -63,6 +63,10 @@ cli:
@echo "building blobstore-cli"
@$(CGOINSTALL) -o $(BINDIR)/blobstore-cli $(PROJECTMOD)/cli/cli
shardnode:
@echo "building shardnode"
@$(CGOINSTALL) $(CMDDIR)/shardnode
clean:
@go clean -i ./...
@rm -f $(BINDIR)/*

View File

@ -38,6 +38,9 @@ import (
"github.com/cubefs/cubefs/blobstore/util/log"
)
// just for cli write to readonly initialised cluster.
var ForceWriteReadonlyCluster = false
// AlgChoose algorithm of choose cluster
type AlgChoose uint32
@ -52,14 +55,17 @@ const (
maxAlg
)
var cachedClient = struct {
mu sync.Mutex
cache map[string]*cmapi.Client
}{
cache: make(map[string]*cmapi.Client),
type keyClient struct {
key string
cli *cmapi.Client
}
func getClusterClient(conf cmapi.Config) *cmapi.Client {
var cachedClient = struct {
mu sync.Mutex
cache map[proto.ClusterID]*keyClient
}{cache: make(map[proto.ClusterID]*keyClient)}
func getClusterClient(ctx context.Context, clusterID proto.ClusterID, conf cmapi.Config) *cmapi.Client {
hosts := make([]string, len(conf.Hosts))
copy(hosts, conf.Hosts[:])
sort.Strings(hosts)
@ -67,13 +73,20 @@ func getClusterClient(conf cmapi.Config) *cmapi.Client {
cachedClient.mu.Lock()
defer cachedClient.mu.Unlock()
cli, ok := cachedClient.cache[key]
if ok {
keyCli, ok := cachedClient.cache[clusterID]
if !ok {
cli := cmapi.New(&conf)
cachedClient.cache[clusterID] = &keyClient{key: key, cli: cli}
return cli
}
cli = cmapi.New(&conf)
cachedClient.cache[key] = cli
return cli
if keyCli.key != key {
span := trace.SpanFromContextSafe(ctx)
span.Warnf("change cluster(%d) clustermgr hosts %s -> %s", clusterID, keyCli.key, key)
cli := cmapi.New(&conf)
keyCli.key = key
*keyCli.cli = *cli
}
return keyCli.cli
}
// IsValid returns valid algorithm or not.
@ -115,6 +128,8 @@ type ClusterController interface {
GetConfig(ctx context.Context, key string) (string, error)
// ChangeChooseAlg change alloc algorithm
ChangeChooseAlg(alg AlgChoose) error
// GetShardController return IShardController in specified cluster
GetShardController(clusterID proto.ClusterID) (IShardController, error)
}
// ClusterConfig cluster config
@ -126,13 +141,15 @@ type ClusterConfig struct {
Region string `json:"region"`
RegionMagic string `json:"region_magic"`
ClusterReloadSecs int `json:"cluster_reload_secs"`
ServiceReloadSecs int `json:"service_reload_secs"`
ShardReloadSecs int `json:"shard_reload_secs"`
CMClientConfig cmapi.Config `json:"clustermgr_client_config"`
ServicePunishThreshold uint32 `json:"service_punish_threshold"`
ServicePunishValidIntervalS int `json:"service_punish_valid_interval_s"`
ServiceConfig
VolumeConfig
ConsulAgentAddr string `json:"consul_agent_addr"`
ConsulToken string `json:"consul_token"`
ConsulTokenFile string `json:"consul_token_file"`
Clusters []Cluster `json:"clusters"`
}
@ -140,6 +157,7 @@ type ClusterConfig struct {
type Cluster struct {
ClusterID proto.ClusterID `json:"cluster_id"`
Hosts []string `json:"hosts"`
Space SpaceConf `json:"space"` // one space - one cluster
}
type cluster struct {
@ -160,7 +178,8 @@ type clusterControllerImpl struct {
available atomic.Value // available clusters
serviceMgrs sync.Map
volumeGetters sync.Map
roundRobinCount uint64 // a count for round robin
shardMgrs sync.Map // cid -> shardController
roundRobinCount uint64 // a count for round robin
proxy proxy.Cacher
stopCh <-chan struct{}
@ -173,9 +192,15 @@ func NewClusterController(cfg *ClusterConfig, proxy proxy.Cacher, stopCh <-chan
consulConf := api.DefaultConfig()
consulConf.Address = cfg.ConsulAgentAddr
if cfg.ConsulTokenFile != "" {
consulConf.TokenFile = cfg.ConsulTokenFile
}
if cfg.ConsulToken != "" {
consulConf.Token = cfg.ConsulToken
}
var client *api.Client
var err error
if consulConf.Address != "" {
if cfg.ConsulAgentAddr != "" {
client, err = api.NewClient(consulConf)
if err != nil {
return nil, fmt.Errorf("new consul client failed, err: %v", err)
@ -230,7 +255,7 @@ func (c *clusterControllerImpl) loadWithConfig() error {
for _, cs := range c.config.Clusters {
conf := c.config.CMClientConfig
conf.Hosts = cs.Hosts
cmCli := getClusterClient(conf)
cmCli := getClusterClient(ctx, cs.ClusterID, conf)
stat, err := cmCli.Stat(ctx)
if err != nil {
@ -239,10 +264,13 @@ func (c *clusterControllerImpl) loadWithConfig() error {
}
clusterInfo := &cmapi.ClusterInfo{}
clusterInfo.ClusterID = cs.ClusterID
clusterInfo.Capacity = stat.SpaceStat.TotalSpace
clusterInfo.Available = stat.SpaceStat.WritableSpace
clusterInfo.Capacity = stat.BlobNodeSpaceStat.TotalSpace
clusterInfo.Available = stat.BlobNodeSpaceStat.WritableSpace
clusterInfo.Nodes = cs.Hosts
clusterInfo.Readonly = stat.ReadOnly
if clusterInfo.Readonly && ForceWriteReadonlyCluster {
clusterInfo.Readonly = false
}
allClusters[cs.ClusterID] = &cluster{client: cmCli, clusterInfo: clusterInfo}
@ -254,7 +282,6 @@ func (c *clusterControllerImpl) loadWithConfig() error {
span.Debug("readonly or no available cluster", clusterInfo.ClusterID)
}
}
return c.deal(ctx, available, allClusters, totalAvailable)
}
@ -305,7 +332,12 @@ func (c *clusterControllerImpl) loadWithConsul() error {
return c.deal(ctx, available, allClusters, totalAvailable)
}
func (c *clusterControllerImpl) deal(ctx context.Context, available []*cmapi.ClusterInfo, allClusters clusterMap, totalAvailable int64) error {
func (c *clusterControllerImpl) deal(ctx context.Context,
available []*cmapi.ClusterInfo, allClusters clusterMap, totalAvailable int64,
) error {
if len(allClusters) == 0 {
return nil
}
span := trace.SpanFromContextSafe(ctx)
sort.Slice(available, func(i, j int) bool {
@ -313,9 +345,14 @@ func (c *clusterControllerImpl) deal(ctx context.Context, available []*cmapi.Clu
})
newClusters := make([]*cmapi.ClusterInfo, 0, len(allClusters))
for clusterID := range allClusters {
for clusterID, cluster := range allClusters {
if _, ok := c.serviceMgrs.Load(clusterID); !ok {
newClusters = append(newClusters, allClusters[clusterID].clusterInfo)
newClusters = append(newClusters, cluster.clusterInfo)
} else {
// update cluster client if hosts changed
conf := c.config.CMClientConfig
conf.Hosts = cluster.clusterInfo.Nodes[:]
getClusterClient(ctx, clusterID, conf)
}
}
@ -325,7 +362,7 @@ func (c *clusterControllerImpl) deal(ctx context.Context, available []*cmapi.Clu
if allClusters[clusterID].client == nil {
conf := c.config.CMClientConfig
conf.Hosts = newCluster.Nodes
allClusters[clusterID].client = getClusterClient(conf)
allClusters[clusterID].client = getClusterClient(ctx, clusterID, conf)
}
cmCli := allClusters[clusterID].client
@ -343,26 +380,39 @@ func (c *clusterControllerImpl) deal(ctx context.Context, available []*cmapi.Clu
}
}
serviceController, err := NewServiceController(ServiceConfig{
ClusterID: clusterID,
IDC: c.config.IDC,
ReloadSec: c.config.ServiceReloadSecs,
ServicePunishThreshold: c.config.ServicePunishThreshold,
ServicePunishValidIntervalS: c.config.ServicePunishValidIntervalS,
}, cmCli, c.proxy, c.stopCh)
serviceConfig := c.config.ServiceConfig
serviceConfig.ClusterID = clusterID
serviceConfig.IDC = c.config.IDC
serviceController, err := NewServiceController(serviceConfig, cmCli, c.proxy, c.stopCh)
if err != nil {
removeThisCluster()
span.Warn("new service manager failed", clusterID, err)
continue
}
volumeGetter, err := NewVolumeGetter(clusterID, serviceController, c.proxy, -1)
volumeConfig := c.config.VolumeConfig
volumeConfig.ClusterID = clusterID
volumeGetter, err := NewVolumeGetter(volumeConfig, serviceController, c.proxy, c.stopCh)
if err != nil {
removeThisCluster()
span.Warn("new volume getter failed", clusterID, err)
continue
}
space := c.getSpaceConf(clusterID)
span.Debugf("get space config valid:%t, cluster:%d", space.IsValid(), clusterID)
if space.IsValid() { // need shard node, meta system
shardMgr, err := NewShardController(shardCtrlConf{
clusterID: clusterID,
reloadSecs: c.config.ShardReloadSecs,
space: space,
}, cmCli, serviceController, c.stopCh)
if err != nil {
span.Fatalf("new shard controller failed, clusterID=%d, err=%+v", clusterID, err)
}
c.shardMgrs.Store(clusterID, shardMgr)
}
c.serviceMgrs.Store(clusterID, serviceController)
c.volumeGetters.Store(clusterID, volumeGetter)
span.Debug("loaded new cluster", clusterID)
@ -475,3 +525,22 @@ func (c *clusterControllerImpl) GetConfig(ctx context.Context, key string) (ret
}
return
}
func (c *clusterControllerImpl) GetShardController(clusterID proto.ClusterID) (IShardController, error) {
if shardMgr, exist := c.shardMgrs.Load(clusterID); exist {
if controller, ok := shardMgr.(IShardController); ok {
return controller, nil
}
return nil, fmt.Errorf("not shard controller for %d", clusterID)
}
return nil, fmt.Errorf("no shard controller of %d", clusterID)
}
func (c *clusterControllerImpl) getSpaceConf(clusterID proto.ClusterID) SpaceConf {
for _, cs := range c.config.Clusters {
if clusterID == cs.ClusterID {
return cs.Space
}
}
return SpaceConf{}
}

View File

@ -146,7 +146,7 @@ func stat(w http.ResponseWriter, req *http.Request) {
info := &clustermgr.StatInfo{
LeaderHost: hostAddr,
ReadOnly: false,
SpaceStat: clustermgr.SpaceStatInfo{
BlobNodeSpaceStat: clustermgr.SpaceStatInfo{
TotalSpace: 1 << 40,
WritableSpace: 1 << 20,
},

View File

@ -17,12 +17,12 @@ package controller_test
import (
"context"
"math/rand"
"sync"
"testing"
"time"
"github.com/golang/mock/gomock"
bnapi "github.com/cubefs/cubefs/blobstore/api/blobnode"
cmapi "github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/api/proxy"
"github.com/cubefs/cubefs/blobstore/common/codemode"
@ -48,10 +48,11 @@ var (
cmcli cmapi.APIAccess
proxycli proxy.Cacher
dataMu sync.Mutex
dataCalled map[proto.Vid]int
dataNodes map[string]cmapi.ServiceInfo
dataVolumes map[proto.Vid]cmapi.VolumeInfo
dataDisks map[proto.DiskID]bnapi.DiskInfo
dataDisks map[proto.DiskID]cmapi.BlobNodeDiskInfo
)
func init() {
@ -63,15 +64,15 @@ func init() {
dataVolumes[1] = cmapi.VolumeInfo{
VolumeInfoBase: cmapi.VolumeInfoBase{Vid: 1, CodeMode: codemode.EC6P10L2},
Units: []cmapi.Unit{
{Vuid: 1011, DiskID: 1021, Host: "1031"},
{Vuid: 1012, DiskID: 1022, Host: "1032"},
{Vuid: 1011, DiskID: 1021},
{Vuid: 1012, DiskID: 1022},
},
}
dataVolumes[9] = cmapi.VolumeInfo{
VolumeInfoBase: cmapi.VolumeInfoBase{Vid: 9, CodeMode: codemode.EC16P20L2},
Units: []cmapi.Unit{
{Vuid: 9011, DiskID: 9021, Host: "9031"},
{Vuid: 9012, DiskID: 9022, Host: "9032"},
{Vuid: 9011, DiskID: 9021},
{Vuid: 9012, DiskID: 9022},
},
}
dataVolumes[vid404] = cmapi.VolumeInfo{VolumeInfoBase: cmapi.VolumeInfoBase{Vid: vid404}}
@ -84,20 +85,24 @@ func init() {
},
}
dataDisks = make(map[proto.DiskID]bnapi.DiskInfo)
dataDisks[10001] = bnapi.DiskInfo{
ClusterID: 1,
Idc: idc,
Host: "blobnode-1",
DiskHeartBeatInfo: bnapi.DiskHeartBeatInfo{
dataDisks = make(map[proto.DiskID]cmapi.BlobNodeDiskInfo)
dataDisks[10001] = cmapi.BlobNodeDiskInfo{
DiskInfo: cmapi.DiskInfo{
ClusterID: 1,
Idc: idc,
Host: "blobnode-1",
},
DiskHeartBeatInfo: cmapi.DiskHeartBeatInfo{
DiskID: 10001,
},
}
dataDisks[10002] = bnapi.DiskInfo{
ClusterID: 1,
Idc: idc,
Host: "blobnode-2",
DiskHeartBeatInfo: bnapi.DiskHeartBeatInfo{
dataDisks[10002] = cmapi.BlobNodeDiskInfo{
DiskInfo: cmapi.DiskInfo{
ClusterID: 1,
Idc: idc,
Host: "blobnode-2",
},
DiskHeartBeatInfo: cmapi.DiskHeartBeatInfo{
DiskID: 10002,
},
}
@ -112,26 +117,31 @@ func init() {
return cmapi.ServiceInfo{}, errNotFound
})
cli.EXPECT().ListDisk(A, A).AnyTimes().Return(cmapi.ListDiskRet{}, nil)
cli.EXPECT().ListShardNodeDisk(A, A).AnyTimes().Return(cmapi.ListShardNodeDiskRet{}, nil)
cmcli = cli
pcli := mocks.NewMockProxyClient(C(&testing.T{}))
pcli.EXPECT().GetCacheVolume(A, A, A).AnyTimes().DoAndReturn(
func(_ context.Context, _ string, args *proxy.CacheVolumeArgs) (*proxy.VersionVolume, error) {
volume := new(proxy.VersionVolume)
func(ctx context.Context, _ string, args *proxy.CacheVolumeArgs) (*cmapi.VolumeInfo, error) {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
vid := args.Vid
dataMu.Lock()
dataCalled[vid]++
dataMu.Unlock()
if val, ok := dataVolumes[vid]; ok {
if vid == vid404 {
return nil, errcode.ErrVolumeNotExist
}
volume.VolumeInfo = val
volume.Version = volume.GetVersion()
return volume, nil
return &val, nil
}
return nil, errNotFound
})
pcli.EXPECT().GetCacheDisk(A, A, A).AnyTimes().DoAndReturn(
func(_ context.Context, _ string, args *proxy.CacheDiskArgs) (*bnapi.DiskInfo, error) {
func(_ context.Context, _ string, args *proxy.CacheDiskArgs) (*cmapi.BlobNodeDiskInfo, error) {
if val, ok := dataDisks[args.DiskID]; ok {
return &val, nil
}

View File

@ -24,7 +24,6 @@ import (
"golang.org/x/sync/singleflight"
"github.com/cubefs/cubefs/blobstore/api/blobnode"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/api/proxy"
"github.com/cubefs/cubefs/blobstore/common/proto"
@ -35,12 +34,8 @@ import (
)
const (
_diskHostServicePrefix = "diskhost"
// default service punish check valid interval
defaultServicePinishValidIntervalS int = 30
// default service punish check threshold
defaultServicePinishThreshold uint32 = 3
_primaryDisk = "_disk_"
_primaryShardnodeDisk = "_sddisk_"
)
// HostIDC item of host with idc
@ -68,6 +63,15 @@ type ServiceController interface {
// PunishDiskWithThreshold will punish a disk host for
// an punishTimeSec interval if disk host failed times satisfied with threshold
PunishDiskWithThreshold(ctx context.Context, diskID proto.DiskID, punishTimeSec int)
// GetShardnodeHost return shardnode host
GetShardnodeHost(ctx context.Context, diskID proto.DiskID) (hostIDC *HostIDC, err error)
// PunishShardnode will punish a shardnode disk host for an punishTimeSec interval
PunishShardnode(ctx context.Context, diskID proto.DiskID, punishTimeSec int)
// PunishShardnodeDiskWithThreshold will punish a disk host for
// an punishTimeSec interval if disk host failed times satisfied with threshold
PunishShardnodeDiskWithThreshold(ctx context.Context, diskID proto.DiskID, punishTimeSec int)
// IsPunishShardnode return shardnode disk is punish
IsPunishShardnode(diskID proto.DiskID) bool
}
type (
@ -86,6 +90,8 @@ type hostItem struct {
lastModifyTime int64
// failedTimes record the service host failed times during some interval
failedTimes uint32
createAt time.Time
}
func (h *hostItem) isPunish() bool {
@ -94,19 +100,24 @@ func (h *hostItem) isPunish() bool {
// ServiceConfig service config
type ServiceConfig struct {
ClusterID proto.ClusterID
IDC string
ReloadSec int
LoadDiskInterval int
ServicePunishThreshold uint32
ServicePunishValidIntervalS int
ClusterID proto.ClusterID `json:"-"`
IDC string `json:"-"`
ServiceReloadSecs int `json:"service_reload_secs"`
LoadDiskIntervalS int `json:"load_disk_interval_s"`
DiskPunishThreshold uint32 `json:"disk_punish_threshold"`
DiskPunishValidIntervalS int `json:"disk_punish_valid_interval_s"`
DiskMemoryExpirationS int `json:"disk_memory_expiration_s"` // <= 0 means no expiration
ServicePunishThreshold uint32 `json:"service_punish_threshold"`
ServicePunishValidIntervalS int `json:"service_punish_valid_interval_s"`
}
type serviceControllerImpl struct {
// allServices hold all disk/service host map, use for quickly find out
allServices sync.Map
serviceHosts serviceMap
brokenDisks sync.Map
allServices sync.Map
serviceHosts serviceMap
brokenDisks sync.Map
sdBrokenDisks sync.Map // shard node broken disks
group singleflight.Group
serviceLocks map[string]*sync.RWMutex
@ -117,12 +128,15 @@ type serviceControllerImpl struct {
}
// NewServiceController returns a service controller
func NewServiceController(cfg ServiceConfig, cmCli clustermgr.APIAccess, proxy proxy.Cacher,
stopCh <-chan struct{}) (ServiceController, error) {
defaulter.Equal(&cfg.ServicePunishThreshold, defaultServicePinishThreshold)
defaulter.LessOrEqual(&cfg.ServicePunishValidIntervalS, defaultServicePinishValidIntervalS)
defaulter.LessOrEqual(&cfg.LoadDiskInterval, int(300))
defaulter.LessOrEqual(&cfg.ReloadSec, int(10))
func NewServiceController(cfg ServiceConfig,
cmCli clustermgr.APIAccess, proxy proxy.Cacher, stopCh <-chan struct{},
) (ServiceController, error) {
defaulter.IntegerLessOrEqual(&cfg.ServiceReloadSecs, 10)
defaulter.IntegerLessOrEqual(&cfg.LoadDiskIntervalS, 300)
defaulter.IntegerEqual(&cfg.DiskPunishThreshold, 3)
defaulter.IntegerLessOrEqual(&cfg.DiskPunishValidIntervalS, 30)
defaulter.IntegerEqual(&cfg.ServicePunishThreshold, 3)
defaulter.IntegerLessOrEqual(&cfg.ServicePunishValidIntervalS, 30)
controller := &serviceControllerImpl{
serviceHosts: serviceMap{
@ -145,7 +159,7 @@ func NewServiceController(cfg ServiceConfig, cmCli clustermgr.APIAccess, proxy p
return controller, nil
}
go func() {
tick := time.NewTicker(time.Duration(cfg.ReloadSec) * time.Second)
tick := time.NewTicker(time.Duration(cfg.ServiceReloadSecs) * time.Second)
defer tick.Stop()
for {
select {
@ -159,13 +173,12 @@ func NewServiceController(cfg ServiceConfig, cmCli clustermgr.APIAccess, proxy p
}
}()
go func() {
controller.loadBrokenDisks()
tick := time.NewTicker(time.Duration(cfg.LoadDiskInterval) * time.Second)
tick := time.NewTicker(time.Duration(cfg.LoadDiskIntervalS) * time.Second)
defer tick.Stop()
for {
controller.loadBrokenDisks()
select {
case <-tick.C:
controller.loadBrokenDisks()
case <-stopCh:
return
}
@ -196,7 +209,7 @@ func (s *serviceControllerImpl) load(cid proto.ClusterID, idc string) error {
}
if len(hostItems) > 0 {
for _, item := range hostItems {
s.allServices.Store(serviceName+item.host, item)
s.allServices.Store(s.getServiceKey(serviceName, item.host), item)
span.Debugf("store node %+v", item)
}
s.serviceHosts[serviceName].Store(hostItems)
@ -205,29 +218,65 @@ func (s *serviceControllerImpl) load(cid proto.ClusterID, idc string) error {
}
func (s *serviceControllerImpl) loadBrokenDisks() {
span, ctx := trace.StartSpanFromContext(context.Background(), "access_cluster_load_disks")
_, ctx := trace.StartSpanFromContext(context.Background(), "access_cluster_load_disks")
fnBlobnode := func(ctx context.Context, args *clustermgr.ListOptionArgs, diskMap map[proto.DiskID]struct{}) error {
list, err := s.cmClient.ListDisk(ctx, args)
if err != nil {
return err
}
for _, disk := range list.Disks {
diskMap[disk.DiskID] = struct{}{}
}
args.Marker = list.Marker
return nil
}
fnShardnode := func(ctx context.Context, args *clustermgr.ListOptionArgs, diskMap map[proto.DiskID]struct{}) error {
list, err := s.cmClient.ListShardNodeDisk(ctx, args)
if err != nil {
return err
}
for _, disk := range list.Disks {
diskMap[disk.DiskID] = struct{}{}
}
args.Marker = list.Marker
return nil
}
s.processBrokenDisks(ctx, fnBlobnode, &s.brokenDisks)
s.processBrokenDisks(ctx, fnShardnode, &s.sdBrokenDisks)
}
func (s *serviceControllerImpl) processBrokenDisks(
ctx context.Context,
fn func(context.Context, *clustermgr.ListOptionArgs, map[proto.DiskID]struct{}) error,
disks *sync.Map,
) {
span := trace.SpanFromContextSafe(ctx)
brokenDiskIDs := make(map[proto.DiskID]struct{})
for _, st := range []proto.DiskStatus{proto.DiskStatusBroken, proto.DiskStatusRepairing} {
for _, st := range []proto.DiskStatus{proto.DiskStatusBroken} {
span.Debugf("to load disks of cluster %d %s", s.config.ClusterID, st.String())
args := &clustermgr.ListOptionArgs{Status: st, Marker: 1, Count: 1 << 10}
for args.Marker > proto.InvalidDiskID {
list, err := s.cmClient.ListDisk(ctx, args)
args := &clustermgr.ListOptionArgs{Status: st, Count: 1 << 10}
for {
err := fn(ctx, args, brokenDiskIDs)
if err != nil {
span.Errorf("load disks of cluster %d %s", s.config.ClusterID, err.Error())
span.Errorf("load disks of cluster %d, err:%+v", s.config.ClusterID, err)
return
}
for _, disk := range list.Disks {
brokenDiskIDs[disk.DiskID] = struct{}{}
if args.Marker <= proto.InvalidDiskID {
break
}
args.Marker = list.Marker
}
}
// clean cached disks, ignore cases when concurrency getting disk.
s.brokenDisks.Range(func(key, value interface{}) bool {
s.brokenDisks.Delete(key)
disks.Range(func(key, value any) bool {
disks.Delete(key)
return true
})
if len(brokenDiskIDs) == 0 {
@ -235,7 +284,7 @@ func (s *serviceControllerImpl) loadBrokenDisks() {
}
span.Warnf("load disks of cluster %d broken %v", s.config.ClusterID, brokenDiskIDs)
for diskID := range brokenDiskIDs {
s.brokenDisks.Store(diskID, struct{}{})
disks.Store(diskID, struct{}{})
}
}
@ -330,16 +379,19 @@ func (s *serviceControllerImpl) GetDiskHost(ctx context.Context, diskID proto.Di
_, broken := s.brokenDisks.Load(diskID)
v, ok := s.allServices.Load(_diskHostServicePrefix + (diskID.ToString()))
v, ok := s.allServices.Load(s.getServiceKey(_primaryDisk, diskID))
if ok {
item := v.(*hostItem)
return &HostIDC{
Host: item.host,
IDC: item.idc,
Punished: broken || item.isPunish(),
}, nil
expiration := time.Second * time.Duration(s.config.DiskMemoryExpirationS)
if expiration <= 0 || time.Since(item.createAt) < expiration {
return &HostIDC{
Host: item.host,
IDC: item.idc,
Punished: broken || item.isPunish(),
}, nil
}
}
ret, err, _ := s.group.Do("get-diskinfo-"+diskID.ToString(), func() (interface{}, error) {
ret, err, _ := s.group.Do("get-diskinfo-"+diskID.ToString(), func() (any, error) {
hosts, err := s.GetServiceHosts(ctx, proto.ServiceNameProxy)
if err != nil {
return nil, err
@ -358,10 +410,48 @@ func (s *serviceControllerImpl) GetDiskHost(ctx context.Context, diskID proto.Di
span.Error("can't get disk host from proxy", err)
return nil, errors.Base(err, "get disk info", diskID)
}
diskInfo := ret.(*blobnode.DiskInfo)
diskInfo := ret.(*clustermgr.BlobNodeDiskInfo)
item := &hostItem{host: diskInfo.Host, idc: diskInfo.Idc, createAt: time.Now()}
s.allServices.Store(s.getServiceKey(_primaryDisk, diskInfo.DiskID), item)
return &HostIDC{
Host: item.host,
IDC: item.idc,
Punished: broken || item.isPunish(),
}, nil
}
func (s *serviceControllerImpl) GetShardnodeHost(ctx context.Context, diskID proto.DiskID) (hostIDC *HostIDC, err error) {
span := trace.SpanFromContextSafe(ctx)
_, broken := s.sdBrokenDisks.Load(diskID)
v, ok := s.allServices.Load(s.getServiceKey(_primaryShardnodeDisk, diskID))
if ok {
item := v.(*hostItem)
return &HostIDC{
Host: item.host,
IDC: item.idc,
Punished: broken || item.isPunish(),
}, nil
}
ret, err, _ := s.group.Do("get-shardnode-diskinfo-"+diskID.ToString(), func() (any, error) {
// todo: support proxy get disk host, next version
info, err := s.cmClient.ShardNodeDiskInfo(ctx, diskID)
if err != nil {
return nil, err
}
return info, nil
})
if err != nil {
span.Error("can't get shardnode disk host from cm", err)
return nil, errors.Base(err, "get shardnode disk info", diskID)
}
diskInfo := ret.(*clustermgr.ShardNodeDiskInfo)
item := &hostItem{host: diskInfo.Host, idc: diskInfo.Idc}
s.allServices.Store(_diskHostServicePrefix+(diskInfo.DiskID.ToString()), item)
s.allServices.Store(s.getServiceKey(_primaryShardnodeDisk, diskInfo.DiskID), item)
return &HostIDC{
Host: item.host,
IDC: item.idc,
@ -371,9 +461,9 @@ func (s *serviceControllerImpl) GetDiskHost(ctx context.Context, diskID proto.Di
// PunishService will punish an service host for an punishTimeSec interval
func (s *serviceControllerImpl) PunishService(ctx context.Context, service, host string, punishTimeSec int) {
v, ok := s.allServices.Load(service + host)
v, ok := s.allServices.Load(s.getServiceKey(service, host))
if !ok {
panic(fmt.Sprintf("can't find host in all services map, %s-%s", service, host))
panic(fmt.Sprintf("can't find host in all services map, %s", s.getServiceKey(service, host)))
}
item := v.(*hostItem)
@ -383,28 +473,63 @@ func (s *serviceControllerImpl) PunishService(ctx context.Context, service, host
// PunishDisk will punish a disk host for an punishTimeSec interval
func (s *serviceControllerImpl) PunishDisk(ctx context.Context, diskID proto.DiskID, punishTimeSec int) {
s.PunishService(ctx, _diskHostServicePrefix, diskID.ToString(), punishTimeSec)
s.PunishService(ctx, _primaryDisk, diskID.ToString(), punishTimeSec)
}
// PunishShardnode will punish a shardnode disk host for an punishTimeSec interval
func (s *serviceControllerImpl) PunishShardnode(ctx context.Context, diskID proto.DiskID, punishTimeSec int) {
s.PunishService(ctx, _primaryShardnodeDisk, diskID.ToString(), punishTimeSec)
}
// PunishShardnodeDiskWithThreshold will punish a disk host for
// an punishTimeSec interval if disk host failed times satisfied with threshold
func (s *serviceControllerImpl) PunishShardnodeDiskWithThreshold(ctx context.Context, diskID proto.DiskID, punishTimeSec int) {
s.punishWith(ctx, _primaryShardnodeDisk, diskID.ToString(), punishTimeSec,
s.config.DiskPunishThreshold, s.config.DiskPunishValidIntervalS)
}
func (s *serviceControllerImpl) IsPunishShardnode(diskID proto.DiskID) bool {
return s.isPunishService(_primaryShardnodeDisk, diskID.ToString())
}
func (s *serviceControllerImpl) isPunishService(primary, secondary string) bool {
v, ok := s.allServices.Load(s.getServiceKey(primary, secondary))
if !ok {
panic(fmt.Sprintf("can't find host in all services map, %s", s.getServiceKey(primary, secondary)))
}
item := v.(*hostItem)
return item.isPunish()
}
// PunishDiskWithThreshold will punish a disk host for
// an punishTimeSec interval if disk host failed times satisfied with threshold
func (s *serviceControllerImpl) PunishDiskWithThreshold(ctx context.Context, diskID proto.DiskID, punishTimeSec int) {
s.PunishServiceWithThreshold(ctx, _diskHostServicePrefix, diskID.ToString(), punishTimeSec)
s.punishWith(ctx, _primaryDisk, diskID.ToString(), punishTimeSec,
s.config.DiskPunishThreshold, s.config.DiskPunishValidIntervalS)
}
// PunishServiceWithThreshold will punish an service host for
// an punishTimeSec interval if service failed times satisfied with threshold
func (s *serviceControllerImpl) PunishServiceWithThreshold(ctx context.Context, service, host string, punishTimeSec int) {
v, ok := s.allServices.Load(service + host)
s.punishWith(ctx, service, host, punishTimeSec, s.config.ServicePunishThreshold, s.config.ServicePunishValidIntervalS)
}
func (s *serviceControllerImpl) punishWith(ctx context.Context,
primary, secondary string, punishTimeSec int,
threshold uint32, interval int,
) {
serviceKey := s.getServiceKey(primary, secondary)
v, ok := s.allServices.Load(serviceKey)
if !ok {
panic(fmt.Sprintf("can't can host in all services map, %s-%s", service, host))
panic(fmt.Sprintf("can't load host in all services map, %s", serviceKey))
}
item := v.(*hostItem)
new := atomic.AddUint32(&item.failedTimes, 1)
// failedTimes larger than threshold, then check the lastModifyTime
if new >= s.config.ServicePunishThreshold {
if time.Since(time.Unix(atomic.LoadInt64(&item.lastModifyTime), 0)) < time.Duration(s.config.ServicePunishValidIntervalS)*time.Second {
s.PunishService(ctx, service, host, punishTimeSec)
if new >= threshold {
if time.Since(time.Unix(atomic.LoadInt64(&item.lastModifyTime), 0)) < time.Duration(interval)*time.Second {
s.PunishService(ctx, primary, secondary, punishTimeSec)
return
}
atomic.AddUint32(&item.failedTimes, -(new - 1))
@ -415,3 +540,7 @@ func (s *serviceControllerImpl) PunishServiceWithThreshold(ctx context.Context,
func (s *serviceControllerImpl) getServiceLock(name string) *sync.RWMutex {
return s.serviceLocks[name]
}
func (s *serviceControllerImpl) getServiceKey(primary string, secondary any) string {
return fmt.Sprintf("%s/%v", primary, secondary)
}

View File

@ -23,7 +23,6 @@ import (
"github.com/stretchr/testify/require"
"github.com/cubefs/cubefs/blobstore/access/controller"
bnapi "github.com/cubefs/cubefs/blobstore/api/blobnode"
cmapi "github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/api/proxy"
"github.com/cubefs/cubefs/blobstore/common/proto"
@ -57,7 +56,7 @@ func TestAccessServiceNew(t *testing.T) {
}
{
sc, err := controller.NewServiceController(
controller.ServiceConfig{IDC: idc + "x", ReloadSec: 1}, cmcli, proxycli, nil)
controller.ServiceConfig{IDC: idc + "x", ServiceReloadSecs: 1}, cmcli, proxycli, nil)
require.NoError(t, err)
_, err = sc.GetServiceHost(serviceCtx, serviceName)
@ -67,7 +66,7 @@ func TestAccessServiceNew(t *testing.T) {
func TestAccessServiceGetServiceHost(t *testing.T) {
sc, err := controller.NewServiceController(
controller.ServiceConfig{IDC: idc, ReloadSec: 1}, cmcli, proxycli, nil)
controller.ServiceConfig{IDC: idc, ServiceReloadSecs: 1}, cmcli, proxycli, nil)
require.NoError(t, err)
keys := make(hostSet)
@ -87,7 +86,7 @@ func TestAccessServicePunishService(t *testing.T) {
stop := closer.New()
defer stop.Close()
sc, err := controller.NewServiceController(
controller.ServiceConfig{IDC: idc, ReloadSec: 1}, cmcli, proxycli, stop.Done())
controller.ServiceConfig{IDC: idc, ServiceReloadSecs: 1}, cmcli, proxycli, stop.Done())
require.NoError(t, err)
{
@ -138,7 +137,7 @@ func TestAccessServicePunishServiceWithThreshold(t *testing.T) {
sc, err := controller.NewServiceController(
controller.ServiceConfig{
IDC: idc,
ReloadSec: 1,
ServiceReloadSecs: 1,
ServicePunishThreshold: threshold,
ServicePunishValidIntervalS: 2,
}, cmcli, proxycli, stop.Done())
@ -190,7 +189,7 @@ func TestAccessServicePunishServiceWithThreshold(t *testing.T) {
func TestAccessServiceGetDiskHost(t *testing.T) {
sc, err := controller.NewServiceController(
controller.ServiceConfig{IDC: idc, ReloadSec: 1}, cmcli, proxycli, nil)
controller.ServiceConfig{IDC: idc, ServiceReloadSecs: 1}, cmcli, proxycli, nil)
require.NoError(t, err)
{
@ -204,11 +203,24 @@ func TestAccessServiceGetDiskHost(t *testing.T) {
}
}
func TestAccessServiceGetDiskHostExpired(t *testing.T) {
sc, err := controller.NewServiceController(
controller.ServiceConfig{IDC: idc, ServiceReloadSecs: 1, DiskMemoryExpirationS: 1}, cmcli, proxycli, nil)
require.NoError(t, err)
host, err := sc.GetDiskHost(serviceCtx, proto.DiskID(10001))
require.NoError(t, err)
require.True(t, host.Host == "blobnode-1")
time.Sleep(time.Second)
_, err = sc.GetDiskHost(serviceCtx, proto.DiskID(10001))
require.NoError(t, err)
}
func TestAccessServiceGetBrokenDiskHost(t *testing.T) {
brokenRet := cmapi.ListDiskRet{}
brokenRet.Disks = make([]*bnapi.DiskInfo, 2)
brokenRet.Disks[0] = &bnapi.DiskInfo{}
brokenRet.Disks[1] = &bnapi.DiskInfo{}
brokenRet.Disks = make([]*cmapi.BlobNodeDiskInfo, 2)
brokenRet.Disks[0] = &cmapi.BlobNodeDiskInfo{}
brokenRet.Disks[1] = &cmapi.BlobNodeDiskInfo{}
cli := mocks.NewMockClientAPI(C(t))
cli.EXPECT().GetService(A, A).Times(5).DoAndReturn(
@ -218,11 +230,12 @@ func TestAccessServiceGetBrokenDiskHost(t *testing.T) {
}
return cmapi.ServiceInfo{}, errNotFound
})
cli.EXPECT().ListDisk(A, A).Times(6).Return(brokenRet, nil)
cli.EXPECT().ListDisk(A, A).Times(3).Return(brokenRet, nil)
cli.EXPECT().ListShardNodeDisk(A, A).Times(3).Return(cmapi.ListShardNodeDiskRet{}, nil)
pcli := mocks.NewMockProxyClient(C(t))
pcli.EXPECT().GetCacheDisk(A, A, A).AnyTimes().DoAndReturn(
func(_ context.Context, _ string, args *proxy.CacheDiskArgs) (*bnapi.DiskInfo, error) {
func(_ context.Context, _ string, args *proxy.CacheDiskArgs) (*cmapi.BlobNodeDiskInfo, error) {
if val, ok := dataDisks[args.DiskID]; ok {
return &val, nil
}
@ -232,7 +245,7 @@ func TestAccessServiceGetBrokenDiskHost(t *testing.T) {
stop := closer.New()
defer stop.Close()
sc, err := controller.NewServiceController(
controller.ServiceConfig{IDC: idc, ReloadSec: 1, LoadDiskInterval: 1}, cli, pcli, stop.Done())
controller.ServiceConfig{IDC: idc, ServiceReloadSecs: 1, LoadDiskIntervalS: 1}, cli, pcli, stop.Done())
require.NoError(t, err)
{
@ -270,6 +283,7 @@ func TestAccessServiceGetBrokenDiskHost(t *testing.T) {
brokenRet.Disks[0].DiskID = 10000
brokenRet.Disks[1].DiskID = 10000
cli.EXPECT().ListDisk(A, A).Times(1).Return(brokenRet, errors.New("list error"))
cli.EXPECT().ListShardNodeDisk(A, A).Times(1).Return(cmapi.ListShardNodeDiskRet{}, errors.New("list error"))
time.Sleep(time.Second)
{
host, err := sc.GetDiskHost(serviceCtx, 10001)
@ -281,7 +295,8 @@ func TestAccessServiceGetBrokenDiskHost(t *testing.T) {
}
brokenRet.Disks = brokenRet.Disks[:0]
cli.EXPECT().ListDisk(A, A).Times(2).Return(brokenRet, nil)
cli.EXPECT().ListDisk(A, A).Times(1).Return(brokenRet, nil)
cli.EXPECT().ListShardNodeDisk(A, A).Times(1).Return(cmapi.ListShardNodeDiskRet{}, nil)
time.Sleep(time.Second)
{
host, err := sc.GetDiskHost(serviceCtx, 10001)
@ -297,7 +312,7 @@ func TestAccessServicePunishDisk(t *testing.T) {
stop := closer.New()
defer stop.Close()
sc, err := controller.NewServiceController(
controller.ServiceConfig{IDC: idc, ReloadSec: 1}, cmcli, proxycli, stop.Done())
controller.ServiceConfig{IDC: idc, ServiceReloadSecs: 1}, cmcli, proxycli, stop.Done())
require.NoError(t, err)
{

View File

@ -0,0 +1,728 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package controller
import (
"context"
"fmt"
"math/rand"
"sync"
"time"
"github.com/google/btree"
"golang.org/x/sync/singleflight"
acapi "github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/api/shardnode"
"github.com/cubefs/cubefs/blobstore/cli/common"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/sharding"
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/util/defaulter"
"github.com/cubefs/cubefs/blobstore/util/errors"
)
const (
defaultBTreeDegree = 16
defaultShardReloadSecs = 120
)
var (
errCatalogInvalid = errors.New("invalid catalog")
errCatalogNoLeader = errors.New("catalog item no leader")
errShardInvalid = errors.New("invalid shard info")
)
type IShardController interface {
GetShard(ctx context.Context, shardKeys []string) (Shard, error)
GetShardByID(ctx context.Context, shardID proto.ShardID) (Shard, error)
GetShardByRange(ctx context.Context, shardRange sharding.Range) (Shard, error)
GetFisrtShard(ctx context.Context) (Shard, error)
GetNextShard(ctx context.Context, shardRange sharding.Range) (Shard, error)
GetSpaceID() proto.SpaceID
UpdateRoute(ctx context.Context) error
UpdateShard(ctx context.Context, ss shardnode.ShardStats) error
GetShardSubRangeCount(ctx context.Context) int
}
type shardCtrlConf struct {
clusterID proto.ClusterID
reloadSecs int
space SpaceConf
}
type SpaceConf struct {
Name string `json:"name"`
AK string `json:"ak"`
SK string `json:"sk"`
}
func (c *SpaceConf) IsValid() bool {
return c.Name != "" && c.AK != "" && c.SK != ""
}
func NewShardController(conf shardCtrlConf, cmCli clustermgr.ClientAPI, punishCtrl ServiceController, stopCh <-chan struct{}) (IShardController, error) {
defaulter.Equal(&conf.reloadSecs, defaultShardReloadSecs)
s := &shardControllerImpl{
shards: make(map[proto.ShardID]*shard),
ranges: btree.New(defaultBTreeDegree),
conf: conf,
cmCli: cmCli,
stopCh: stopCh,
punishCtrl: punishCtrl,
}
span, ctx := trace.StartSpanFromContext(context.Background(), "")
span.Debugf("start new shard controller, conf:%+v", conf)
err := s.initSpace(ctx)
if err != nil {
return nil, err
}
err = s.initRoute(ctx)
// if err is nil, errCatalogNoLeader: OK. we can get leader from sn when write leader node ; else : FATAL
if err != nil && !errors.Is(err, errCatalogNoLeader) {
return nil, err
}
sd, err := s.GetFisrtShard(ctx)
if err != nil {
return nil, err
}
s.subRangeCnt = len(sd.(*shard).rangeExt.Subs)
go s.incrementalRoute()
span.Debugf("success to new shard controller, clusterID:%d, space:%s", conf.clusterID, conf.space.Name)
return s, nil
}
type shardControllerImpl struct {
shards map[proto.ShardID]*shard
ranges *btree.BTree
version proto.RouteVersion
spaceID proto.SpaceID
groupRun singleflight.Group
subRangeCnt int
sync.RWMutex // todo: I will optimize locker in the next version
conf shardCtrlConf
cmCli clustermgr.ClientAPI
punishCtrl ServiceController
stopCh <-chan struct{}
}
func (s *shardControllerImpl) GetShard(ctx context.Context, shardKeys []string) (Shard, error) {
// shard_1 ranges [1, 100) , shard 2: [100, 200), shard 3: [200, 300) ...
// if compare shard keys=20, it belong to shard 1 ; if keys=100, it belong to shard 2 ; keys=220, belong to shard 3
// if keys=120, will walk [shard 2, shard end]
s.RLock()
defer s.RUnlock()
span := trace.SpanFromContextSafe(ctx)
ci := sharding.NewCompareItem(sharding.RangeType_RangeTypeHash, shardKeys)
var si *shard
pivot := &compareItem{ci: *ci}
s.ranges.AscendGreaterOrEqual(pivot, func(i btree.Item) bool {
si = i.(*shard)
// span.Debugf("shardID=%d, max boundary=%d, compare=%d, shard=%+v", si.shardID, si.rangeExt.MaxBoundary(), ci.GetBoundary(), *si)
if si.belong(ci) {
return false
}
si = nil
return true
})
if si == nil { // not found expect shard
span.Errorf("not find shard. name:%s, shard len:%d, key boundary:%s", shardKeys, s.ranges.Len(), ci.GetBoundary())
return nil, errcode.ErrAccessNotFoundShard
}
return si, nil
}
func (s *shardControllerImpl) GetShardByID(ctx context.Context, shardID proto.ShardID) (Shard, error) {
sd, ok := s.getShardByID(shardID)
if ok {
return sd, nil
}
// not found expect shard
return nil, errcode.ErrAccessNotFoundShard
}
func (s *shardControllerImpl) GetFisrtShard(ctx context.Context) (Shard, error) {
s.RLock()
defer s.RUnlock()
span := trace.SpanFromContextSafe(ctx)
min := s.ranges.Min()
if min == nil { // not found expect shard
span.Errorf("not find shard. name:%s, shard len:%d", s.ranges.Len())
return nil, errcode.ErrAccessNotFoundShard
}
return min.(*shard), nil
}
func (s *shardControllerImpl) GetShardByRange(ctx context.Context, shardRange sharding.Range) (Shard, error) {
s.RLock()
defer s.RUnlock()
span := trace.SpanFromContextSafe(ctx)
var si *shard
pivot := &shard{rangeExt: shardRange}
// todo: shard ranges split, old shard range cant find
s.ranges.DescendLessOrEqual(pivot, func(i btree.Item) bool {
si = i.(*shard)
if si.contain(&shardRange) {
return false
}
si = nil
return true
})
if si == nil { // not found expect shard
span.Errorf("not find shard. range:%s, shard len:%d", common.RawString(shardRange), s.ranges.Len())
return nil, errcode.ErrAccessNotFoundShard
}
return si, nil
}
func (s *shardControllerImpl) GetNextShard(ctx context.Context, shardRange sharding.Range) (Shard, error) {
s.RLock()
defer s.RUnlock()
span := trace.SpanFromContextSafe(ctx)
// range is the end, the last one
if s.ranges.Max().(*shard).contain(&shardRange) {
return nil, nil
}
var si *shard
pivot := &shard{rangeExt: shardRange}
// todo: If two shard merge, it is possible that the shard queried contains the shard range
s.ranges.AscendGreaterOrEqual(pivot, func(i btree.Item) bool {
si = i.(*shard)
if !si.contain(&shardRange) {
return false
}
si = nil
return true
})
if si == nil { // not found expect shard
span.Errorf("not find shard. range:%s, shard len:%d", common.RawString(shardRange), s.ranges.Len())
return nil, errcode.ErrAccessNotFoundShard
}
return si, nil
}
func (s *shardControllerImpl) GetSpaceID() proto.SpaceID {
return s.spaceID
}
func (s *shardControllerImpl) UpdateRoute(ctx context.Context) error {
// Aggregation blob operations which comes from upper-layer
_, err, _ := s.groupRun.Do("updateRoute", func() (interface{}, error) {
// there is only one updateRoute, the same time. no concurrence
err1 := s.updateRoute(ctx)
return nil, err1
})
return err
}
// UpdateShard update leader disk id and units info
func (s *shardControllerImpl) UpdateShard(ctx context.Context, sd shardnode.ShardStats) error {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("will update shard, leaderDiskID=%d, LeaderSuid=%d, version=%d, suid=%d", sd.LeaderDiskID, sd.LeaderSuid, sd.RouteVersion, sd.Suid)
_, err, _ := s.groupRun.Do("shardID-"+sd.Suid.ShardID().ToString(), func() (interface{}, error) {
if isInvalidShardStat(sd) {
span.Errorf("invalid shard get from shard node. shard info:%+v", sd)
return nil, errShardInvalid
}
// todo: optimize lock at next version; will split smaller Lock or do a copy update
s.Lock()
defer s.Unlock()
// shard exist
oldShard, exist := s.getShardNoLock(sd.Suid.ShardID())
if !exist {
span.Warnf("dont need update shard, exist:%t, current shard:%+v, replace shard:%+v", exist, oldShard, sd)
return nil, errcode.ErrAccessNotFoundShard
}
// only update leader diskID/suid ; sd.LeaderDiskID must is in units
// don't need to judge or change RouteVersion, when switch the primary shardNode. only update version in cm GetCatalogChanges
if sd.LeaderSuid.Epoch() >= oldShard.units[sd.LeaderSuid.Index()].Suid.Epoch() {
oldShard.leaderDiskID = sd.LeaderDiskID
oldShard.leaderSuid = sd.LeaderSuid
return nil, nil
} else {
span.Warnf("skip update shard, leader suid epoch is less than old. old:%d, new:%d", oldShard.leaderSuid.Epoch(), sd.LeaderSuid.Epoch())
return nil, errCatalogNoLeader
}
})
return err
}
func (s *shardControllerImpl) GetShardSubRangeCount(ctx context.Context) int {
return s.subRangeCnt
}
func (s *shardControllerImpl) initSpace(ctx context.Context) error {
token, err := clustermgr.EncodeAuthInfo(&clustermgr.AuthInfo{
AccessKey: s.conf.space.AK,
SecretKey: s.conf.space.SK,
})
if err != nil {
return err
}
err = s.cmCli.AuthSpace(ctx, &clustermgr.AuthSpaceArgs{
Name: s.conf.space.Name,
Token: token,
})
if err != nil {
return err
}
ret, err := s.cmCli.GetSpaceByName(ctx, &clustermgr.GetSpaceByNameArgs{
Name: s.conf.space.Name,
})
if err != nil {
return err
}
s.spaceID = ret.SpaceID
return nil
}
func (s *shardControllerImpl) initRoute(ctx context.Context) error {
return s.updateRoute(ctx)
}
func (s *shardControllerImpl) incrementalRoute() {
tk := time.NewTicker(time.Second * time.Duration(s.conf.reloadSecs))
defer tk.Stop()
for {
span, ctx := trace.StartSpanFromContext(context.Background(), "")
select {
case <-tk.C:
// there is only one updateRoute, the same time. no concurrence
err := s.UpdateRoute(ctx)
span.Debugf("loop update catalog route, err:%+v", err)
case <-s.stopCh:
span.Info("exit shard controller")
return
}
}
}
// called by period task, or read/write fail, init route
// if err is nil, errCatalogNoLeader: OK. we can get leader from sn when write leader node ; else : FATAL
func (s *shardControllerImpl) updateRoute(ctx context.Context) error {
span := trace.SpanFromContextSafe(ctx)
s.RLock()
version := s.version
s.RUnlock()
// $RouteVersion is 0: means full catalog route ; RouteVersion is greater than 0: means fetch incremental route
// full catalog route: all type is CatalogChangeItemAddShard (may contain init item and modify update item)
// incremental route: all type is ItemUpdateShard at 1.5.0 branch; If splitting features are supported, there may be multiple types
// todo: shard ranges split, incremental route will handles the add and update types
ret, err := s.cmCli.GetCatalogChanges(ctx, &clustermgr.GetCatalogChangesArgs{
RouteVersion: version,
})
if err != nil {
span.Errorf("fail to get catalog from clusterMgr. err:%+v", err)
return err
}
// skip
if version >= ret.RouteVersion || len(ret.Items) == 0 {
span.Debugf("skip get catalog changes, version=%d, items=%+v", version, *ret)
return nil
}
// todo: optimize lock at next version; will split smaller Lock or do a copy update
s.Lock()
defer s.Unlock()
// Try to process the correct item in this batch, skip error item and wait for the next fetch catalog, or fetch from sn
// 1. catalog normal: leader disk is not zero, and it is in units
// 2. leader disk is 0: in the election: shardNode is restart, or leader disk is broken re_election
// 3. leader disk not zero, and not in units
succ, wrong, itemErr := 0, 0, error(nil)
for _, item := range ret.Items {
switch item.Type {
case proto.CatalogChangeItemAddShard:
itemErr = s.handleShardAdd(ctx, item)
case proto.CatalogChangeItemUpdateShard:
itemErr = s.handleShardUpdate(ctx, item)
default:
itemErr = fmt.Errorf("not expected catalog")
}
// Skip the item that failed. and then fetch from sn, or wait for the next cm catalog
if errors.Is(itemErr, errCatalogNoLeader) {
wrong++
err = errCatalogNoLeader
continue
}
if itemErr != nil {
span.Errorf("update shard catalog error:%+v, item:%+v", err, item)
return itemErr
}
succ++
}
s.version = ret.RouteVersion
span.Debugf("success to update catalog, version from %d to %d, correct:%d, wrong:%d, local range min:%s, max:%s",
version, ret.RouteVersion, succ, wrong, s.ranges.Min().(*shard).String(), s.ranges.Max().(*shard).String())
return err
}
func (s *shardControllerImpl) handleShardAdd(ctx context.Context, item clustermgr.CatalogChangeItem) error {
span := trace.SpanFromContextSafe(ctx)
val := clustermgr.CatalogChangeShardAdd{}
err := val.Unmarshal(item.Item.Value)
if err != nil {
span.Warnf("catalog json unmarshal failed. type=%d, version=%d, err=%+v", item.Type, item.RouteVersion, err)
return err
}
// check invalid item
leaderIdx, err := findAndCheckCatalogShardAdd(val)
if err != nil && !errors.Is(err, errCatalogNoLeader) {
return err
}
sh := &shard{
shardID: val.ShardID,
version: val.RouteVersion,
leaderDiskID: val.Units[leaderIdx].DiskID,
leaderSuid: val.Units[leaderIdx].Suid,
rangeExt: val.Units[leaderIdx].Range,
units: convertShardUnitInfo(val.Units),
punishCtrl: s.punishCtrl,
}
s.addShardNoLock(sh)
span.Debugf("handle one catalog item add :%+v", val)
// insert a no leader item. because we need shardID. and will fetch correct item from sn
if errors.Is(err, errCatalogNoLeader) {
span.Warnf("catalog handle item add, no leader disk, item:%+v", val)
return errCatalogNoLeader
}
return nil
}
func (s *shardControllerImpl) handleShardUpdate(ctx context.Context, item clustermgr.CatalogChangeItem) error {
span := trace.SpanFromContextSafe(ctx)
val := clustermgr.CatalogChangeShardUpdate{}
if err := val.Unmarshal(item.Item.Value); err != nil {
span.Warnf("catalog json unmarshal failed. type=%d, version=%d, err=%+v", item.Type, item.RouteVersion, err)
return err
}
// shard id not exist
info, exist := s.shards[val.ShardID]
if !exist {
return errCatalogInvalid
}
// RouteVersion must be monotonically increasing. The version is too small, less than expected, should discard invalid item
// In general, cm make sure that the version is correct, and will not happen here
if val.RouteVersion < info.version {
span.Warnf("catalog skip invalid version item update, item:%+v", val)
return errCatalogInvalid
}
// skip invalid item
err := checkCatalogShardUpdate(val)
if errors.Is(err, errCatalogInvalid) {
span.Warnf("catalog skip invalid item update, item:%+v", val)
return errCatalogInvalid
}
if val.Unit.Suid.Epoch() <= info.units[val.Unit.Suid.Index()].Suid.Epoch() {
span.Warnf("catalog skip invalid item update, old:%+v, new:%+v", info.units[val.Unit.Suid.Index()], val)
return errCatalogInvalid
}
// fix leader disk is 0: use new disk unit as leaderDisk, and we will fetch the correct leader later from sn
if errors.Is(err, errCatalogNoLeader) {
span.Warnf("catalog handle item update, no leader disk, item:%+v", val)
val.Unit.LeaderDiskID = val.Unit.DiskID
}
// we will update shard, after fix catalog val
s.setShardByID(ctx, info, &val)
span.Debugf("handle one catalog item update:%+v, shard:%+v", val, *info)
return err
}
func (s *shardControllerImpl) delShardNoLock(si *shard) {
sd, ok := s.shards[si.shardID]
if ok {
s.ranges.Delete(sd)
delete(s.shards, si.shardID)
}
}
func (s *shardControllerImpl) addShardNoLock(si *shard) {
s.shards[si.shardID] = si
s.ranges.ReplaceOrInsert(si)
}
func (s *shardControllerImpl) getShardNoLock(id proto.ShardID) (*shard, bool) {
sd, ok := s.shards[id]
return sd, ok
}
func (s *shardControllerImpl) getShardByID(shardID proto.ShardID) (*shard, bool) {
s.RLock()
defer s.RUnlock()
info, ok := s.shards[shardID]
return info, ok
}
func (s *shardControllerImpl) setShardByID(ctx context.Context, info *shard, val *clustermgr.CatalogChangeShardUpdate) {
info.version = val.RouteVersion
// info.rangeExt = val.Unit.Range // todo: will update range next version
idx := val.Unit.Suid.Index()
info.units[idx] = clustermgr.ShardUnit{
Suid: val.Unit.Suid,
DiskID: val.Unit.DiskID,
Learner: val.Unit.Learner, // most time, $learner is false
}
// update leader disk id and suid ; leader disk may not in units ; leader disk may not val.disk
for _, unit := range info.units {
if unit.DiskID == val.Unit.LeaderDiskID {
info.leaderDiskID = unit.DiskID
info.leaderSuid = unit.Suid
return
}
}
// leader disk not in units, fix it
span := trace.SpanFromContextSafe(ctx)
span.Infof("leader disk not in units. old leader:(%d, %d), new leader:%d, units:%+v",
info.leaderDiskID, info.leaderSuid, val.Unit.LeaderDiskID, info.units)
info.leaderDiskID = info.units[0].DiskID
info.leaderSuid = info.units[0].Suid
}
// ShardOpInfo for upper level(stream) use, get ShardOpHeader information
type ShardOpInfo struct {
DiskID proto.DiskID
Suid proto.Suid
RouteVersion proto.RouteVersion
}
type Shard interface {
GetShardID() proto.ShardID
GetRange() sharding.Range
GetMember(context.Context, acapi.GetShardMode, map[proto.DiskID]struct{}) (ShardOpInfo, error)
}
// shard implement btree.Item interface, shard route information
type shard struct {
shardID proto.ShardID
leaderDiskID proto.DiskID
leaderSuid proto.Suid
version proto.RouteVersion
rangeExt sharding.Range
units []clustermgr.ShardUnit
punishCtrl ServiceController
}
func (i *shard) Less(item btree.Item) bool {
switch than := item.(type) {
case *shard:
return i.rangeExt.MaxBoundary().Less(than.rangeExt.MaxBoundary())
case *compareItem:
return i.rangeExt.MaxBoundary().Less(than.ci.GetBoundary())
default:
return false
}
}
func (i *shard) String() string {
return i.rangeExt.String()
}
func (i *shard) GetShardID() proto.ShardID {
return i.shardID
}
func (i *shard) GetRange() sharding.Range {
return i.rangeExt
}
func (i *shard) GetMember(ctx context.Context, mode acapi.GetShardMode, exclude map[proto.DiskID]struct{}) (ShardOpInfo, error) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("get shard member, mode:%d, exclude:%d, shard:%+v", mode, exclude, *i)
// 1. get member exclude disk id
if len(exclude) != 0 {
return i.getMemberExcluded(ctx, exclude)
}
// 2. get member by mode
if mode == acapi.GetShardModeLeader {
return i.getMemberLeader(ctx)
}
return i.getMemberRandom(ctx, nil)
}
func (i *shard) getMemberExcluded(ctx context.Context, exclude map[proto.DiskID]struct{}) (ShardOpInfo, error) {
return i.getMemberRandom(ctx, exclude)
}
func (i *shard) getMemberLeader(ctx context.Context) (ShardOpInfo, error) {
return ShardOpInfo{
DiskID: i.leaderDiskID,
Suid: i.leaderSuid,
RouteVersion: i.version,
}, nil
}
func (i *shard) getMemberRandom(ctx context.Context, exclude map[proto.DiskID]struct{}) (ShardOpInfo, error) {
span := trace.SpanFromContextSafe(ctx)
n := len(i.units)
initIdx := rand.Intn(n)
idx := initIdx
for {
disk, err := i.punishCtrl.GetShardnodeHost(ctx, i.units[idx].DiskID)
if err != nil {
return ShardOpInfo{}, err
}
if _, exist := exclude[i.units[idx].DiskID]; !exist && !disk.Punished && !i.units[idx].Learner {
return i.getShardOpInfo(idx), nil
}
span.Warnf("skip invalid unit, punished or exclude: %+v, diskID:%d, suid:%d, learner:%t", disk, i.units[idx].DiskID, i.units[idx].Suid, i.units[idx].Learner)
idx = (idx + 1) % n
if idx == initIdx {
break
}
}
span.Warnf("can not find expect disk, exclude disk=%d, shard:%+v", exclude, *i)
return ShardOpInfo{}, fmt.Errorf("can not find expect shardnode disk")
}
func (i *shard) getShardOpInfo(idx int) ShardOpInfo {
return ShardOpInfo{
DiskID: i.units[idx].DiskID,
Suid: i.units[idx].Suid,
RouteVersion: i.version,
}
}
func (i *shard) belong(ci *sharding.CompareItem) bool {
return i.rangeExt.Belong(ci)
}
func (i *shard) contain(rg *sharding.Range) bool {
return i.rangeExt.Contain(rg)
}
type compareItem struct {
ci sharding.CompareItem
}
func (i *compareItem) Less(item btree.Item) bool {
than := item.(*shard)
return i.ci.GetBoundary().Less(than.rangeExt.MaxBoundary())
}
func (i *compareItem) String() string {
return i.ci.String()
}
func convertShardUnitInfo(units []clustermgr.ShardUnitInfo) []clustermgr.ShardUnit {
ret := make([]clustermgr.ShardUnit, len(units))
for i, unit := range units {
ret[i] = clustermgr.ShardUnit{
Suid: unit.Suid,
DiskID: unit.DiskID,
Learner: unit.Learner, // most time, $learner is false
}
}
return ret
}
func isInvalidShardStat(sd shardnode.ShardStats) bool {
if sd.Suid == 0 || sd.RouteVersion == 0 || sd.LeaderDiskID == 0 || sd.LeaderSuid == 0 {
return true
}
return false
}
func checkCatalogShardUpdate(val clustermgr.CatalogChangeShardUpdate) error {
if val.RouteVersion == 0 || val.ShardID == 0 || val.Unit.Suid == 0 || val.Unit.DiskID == 0 {
return errCatalogInvalid
}
if val.Unit.LeaderDiskID == 0 {
return errCatalogNoLeader
}
return nil
}
func findAndCheckCatalogShardAdd(val clustermgr.CatalogChangeShardAdd) (int, error) {
leaderIdx := -1
if val.ShardID == 0 || val.RouteVersion == 0 {
return leaderIdx, errCatalogInvalid
}
for i, unit := range val.Units {
if unit.Suid == 0 || unit.DiskID == 0 {
return leaderIdx, errCatalogInvalid
}
// leader disk may be not in the units
if unit.LeaderDiskID == unit.DiskID {
leaderIdx = i
break
}
}
if leaderIdx == -1 {
return 0, errCatalogNoLeader
}
return leaderIdx, nil
}

View File

@ -0,0 +1,856 @@
package controller
import (
"context"
"errors"
"testing"
"time"
"github.com/gogo/protobuf/types"
"github.com/golang/mock/gomock"
"github.com/google/btree"
"github.com/stretchr/testify/require"
acapi "github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/api/shardnode"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/sharding"
"github.com/cubefs/cubefs/blobstore/testing/mocks"
)
var (
gAny = gomock.Any()
errMock = errors.New("fake error")
)
func TestShardController(t *testing.T) {
ctx := context.Background()
stopCh := make(chan struct{})
ctr := gomock.NewController(t)
cmCli := mocks.NewMockClientAPI(ctr)
cmCli.EXPECT().AuthSpace(gAny, gAny).Return(nil)
cmCli.EXPECT().GetSpaceByName(gAny, gAny).Return(&clustermgr.Space{
SpaceID: 1,
Name: "spaceTest",
}, nil)
retCatlog := &clustermgr.GetCatalogChangesRet{}
retCatlog.RouteVersion = 1
cmCli.EXPECT().GetCatalogChanges(gAny, gAny).Return(retCatlog, nil)
cmCli.EXPECT().GetService(gAny, gAny).Return(clustermgr.ServiceInfo{
Nodes: []clustermgr.ServiceNode{
{ClusterID: 1, Name: proto.ServiceNameProxy, Host: "proxy-1", Idc: "test-idc"},
{ClusterID: 1, Name: proto.ServiceNameProxy, Host: "proxy-2", Idc: "test-idc"},
},
}, nil)
svrCtrl, err := NewServiceController(ServiceConfig{IDC: "test-idc"}, cmCli, nil, nil)
require.NoError(t, err)
require.NoError(t, err)
s, err := NewShardController(shardCtrlConf{}, cmCli, svrCtrl, stopCh)
require.NotNil(t, err)
require.NotEqual(t, errMock, err)
require.ErrorIs(t, err, errcode.ErrAccessNotFoundShard)
require.Nil(t, s)
blobName := "blob1"
shardKeys := []string{blobName}
// empty tree
// _, err = s.GetShard(ctx, shardKeys)
// require.NotNil(t, err)
sh := &shard{
shardID: 1,
version: 1,
}
// rangePtr := sharding.New(sharding.RangeType_RangeTypeHash, 2) // keys len=1; subs len=2. will panic
rangePtr := sharding.New(sharding.RangeType_RangeTypeHash, 1)
for i := range rangePtr.Subs {
rangePtr.Subs[i].Min = uint64(i * 1)
rangePtr.Subs[i].Max = uint64(i+1) * 1
}
sh.rangeExt = *rangePtr
svr := &shardControllerImpl{
shards: make(map[proto.ShardID]*shard),
ranges: btree.New(defaultBTreeDegree),
subRangeCnt: 1,
}
// add one, not found blob
svr.addShardNoLock(sh)
require.Equal(t, 1, len(svr.shards))
_, err = svr.GetShard(ctx, shardKeys)
require.NotNil(t, err)
svr.delShardNoLock(sh)
require.Equal(t, 0, len(svr.shards))
svr.subRangeCnt = 2
ranges := sharding.InitShardingRange(sharding.RangeType_RangeTypeHash, 1, 8)
{
// add 8 shard
shards := make([]*shard, 8)
for i := 0; i < 8; i++ {
sd := &shard{
shardID: proto.ShardID(i + 1),
leaderDiskID: 1,
version: proto.RouteVersion(i + 1),
units: []clustermgr.ShardUnit{
{
Suid: proto.EncodeSuid(proto.ShardID(i+1), 0, 0),
DiskID: 1,
// Host: "testHost1",
},
{
Suid: proto.EncodeSuid(proto.ShardID(i+1), 1, 0),
DiskID: 2,
},
{
Suid: proto.EncodeSuid(proto.ShardID(i+1), 2, 0),
DiskID: 3,
},
},
punishCtrl: svrCtrl,
}
sd.rangeExt = *ranges[i]
shards[i] = sd
}
for i := 0; i < 8; i++ {
svr.addShardNoLock(shards[i])
}
require.Equal(t, 8, len(svr.shards))
svr.punishCtrl = svrCtrl
svr.version = 8
// ret, err := svr.GetShard(ctx, []byte("blob1__xxx")) // expect 2 keys
ret, err := svr.GetShard(ctx, []string{"blob1__xxx"}) // expect 2 keys
sk := []string{"blob1__xxx"}
bd := sharding.NewCompareItem(sharding.RangeType_RangeTypeHash, sk).GetBoundary()
t.Logf("shard key 1, key boundary=%d, shardBounary=%d, range=%s, treeLen=%d", bd, ret.(*shard).rangeExt.MaxBoundary(), ret.(*shard).String(), svr.ranges.Len())
// for i := range shards {
// sBd := shards[i].rangeExt.MaxBoundary()
// t.Logf("shard=%d, boundary=%d, isLess=%v", shards[i].shardID, sBd, bd.Less(sBd))
// }
require.Nil(t, err)
require.Equal(t, proto.ShardID(2), ret.(*shard).shardID)
// ret, err = svr.GetShard(ctx, []byte("{blob2__yy}{11}"))
ret, err = svr.GetShard(ctx, []string{"blob2__yy", "11"})
bd = sharding.NewCompareItem(sharding.RangeType_RangeTypeHash, []string{"blob2__yy", "11"}).GetBoundary()
t.Logf("shard key 2, get boundary=%d", bd)
require.Nil(t, err)
require.Equal(t, proto.ShardID(7), ret.(*shard).shardID)
}
{
// get
si, ok := svr.getShardByID(1)
require.True(t, ok)
require.Equal(t, proto.ShardID(1), si.shardID)
svr.spaceID = 1
spID := svr.GetSpaceID()
require.Equal(t, proto.SpaceID(1), spID)
// update shard, switch leader 3 -> 2 ; (1, 2 leader, 4)
newShard := *si
// newShard.version++ // shard node switch leader don't increment version
newShard.leaderDiskID = 2
newShard.units[2].Learner = true
newShard.units = append(newShard.units, clustermgr.ShardUnit{
Suid: proto.EncodeSuid(newShard.shardID, 2, 1),
DiskID: 4,
})
err = svr.UpdateShard(ctx, shardnode.ShardStats{
Suid: proto.EncodeSuid(newShard.shardID, 1, 1),
LeaderDiskID: newShard.leaderDiskID,
LeaderSuid: proto.EncodeSuid(newShard.shardID, 1, 1),
RouteVersion: newShard.version,
Range: newShard.rangeExt,
Units: newShard.units,
})
require.NoError(t, err)
require.Equal(t, newShard.leaderDiskID, si.leaderDiskID)
si, ok = svr.getShardByID(1)
require.True(t, ok)
require.Equal(t, clustermgr.ShardUnit{Suid: proto.EncodeSuid(1, 0, 0), DiskID: 1}, si.units[0])
require.Equal(t, clustermgr.ShardUnit{Suid: proto.EncodeSuid(1, 1, 0), DiskID: 2}, si.units[1])
// require.Equal(t, clustermgr.ShardUnit{Suid: proto.EncodeSuid(1, 2, 1), DiskID: 4}, si.units[2])
opInfo, err := si.GetMember(ctx, acapi.GetShardModeLeader, nil)
require.NoError(t, err)
require.Equal(t, ShardOpInfo{
DiskID: 2,
Suid: proto.EncodeSuid(1, 1, 1),
RouteVersion: 1,
}, opInfo)
// update route, disk:3 -> disk:4
si.units[2] = clustermgr.ShardUnit{Suid: proto.EncodeSuid(1, 2, 1), DiskID: 4}
// switch leader 2 -> 4; (1, 2, 4 leader)
newShard.units[2] = newShard.units[3]
newShard.units = newShard.units[:3]
newShard.leaderDiskID = 4
newShard.leaderSuid = proto.EncodeSuid(newShard.shardID, 2, 2)
newShard.version = si.version
err = svr.UpdateShard(ctx, shardnode.ShardStats{
Suid: newShard.units[2].Suid,
LeaderDiskID: newShard.leaderDiskID,
LeaderSuid: newShard.leaderSuid,
RouteVersion: newShard.version,
Range: newShard.rangeExt,
Units: newShard.units,
})
require.NoError(t, err)
require.Equal(t, newShard.leaderDiskID, si.leaderDiskID)
si, ok = svr.getShardByID(1)
require.True(t, ok)
require.Equal(t, newShard, *si)
}
{
// switch leader: oldLeader 4 -> leader 2, units[1,2,4]
si, ok := svr.getShardByID(1)
require.True(t, ok)
require.Equal(t, proto.ShardID(1), si.shardID)
newShard := *si
newShard.leaderDiskID = 2
newShard.leaderSuid = si.units[1].Suid // disk 2 old suid proto.EncodeSuid(newShard.shardID, 1, 0)
err = svr.UpdateShard(ctx, shardnode.ShardStats{
Suid: newShard.units[2].Suid,
LeaderDiskID: newShard.leaderDiskID,
LeaderSuid: newShard.leaderSuid,
RouteVersion: newShard.version,
})
require.NoError(t, err)
require.Equal(t, newShard.leaderDiskID, si.leaderDiskID)
require.Equal(t, newShard.leaderSuid, si.leaderSuid)
si, ok = svr.getShardByID(1)
require.True(t, ok)
require.Equal(t, newShard, *si)
}
{
err = svr.UpdateShard(ctx, shardnode.ShardStats{
Suid: 1,
LeaderDiskID: 2,
LeaderSuid: 0,
RouteVersion: 1,
})
require.ErrorIs(t, err, errShardInvalid)
}
}
func TestShardUpdate(t *testing.T) {
ctx := context.Background()
ctr := gomock.NewController(t)
cmCli := mocks.NewMockClientAPI(ctr)
svr := &shardControllerImpl{
shards: make(map[proto.ShardID]*shard),
ranges: btree.New(defaultBTreeDegree),
}
// concurrence
{
// update
cmCli.EXPECT().GetCatalogChanges(gAny, gAny).DoAndReturn(
func(ctx context.Context, args *clustermgr.GetCatalogChangesArgs) (ret *clustermgr.GetCatalogChangesRet, err error) {
time.Sleep(time.Millisecond * 10)
return &clustermgr.GetCatalogChangesRet{}, errMock
}).Times(1)
svr.cmCli = cmCli
resultCh := make(chan error, 3)
for i := 0; i < 3; i++ {
go func() {
err := svr.UpdateRoute(ctx)
resultCh <- err
}()
}
for i := 0; i < 3; i++ {
err := <-resultCh
require.ErrorIs(t, err, errMock)
}
}
ranges := sharding.InitShardingRange(sharding.RangeType_RangeTypeHash, 1, 10)
{
// error
val := clustermgr.CatalogChangeShardAdd{
ShardID: 0,
}
data, err := val.Marshal()
require.NoError(t, err)
retCatlog := &clustermgr.GetCatalogChangesRet{
RouteVersion: 1,
Items: []clustermgr.CatalogChangeItem{
{
Type: proto.CatalogChangeItemAddShard,
RouteVersion: 1,
Item: &types.Any{
TypeUrl: "",
Value: data,
},
},
},
}
cmCli.EXPECT().GetCatalogChanges(gAny, gAny).Return(retCatlog, nil)
err = svr.UpdateRoute(ctx)
require.ErrorIs(t, err, errCatalogInvalid)
}
{
// update, leader disk is 0, 2 success and 2 wrong
val := clustermgr.CatalogChangeShardAdd{
ShardID: 1,
RouteVersion: 1,
Units: []clustermgr.ShardUnitInfo{
{
Suid: proto.EncodeSuid(1, 0, 0),
DiskID: 1,
AppliedIndex: 0,
LeaderDiskID: 1,
Range: *ranges[0],
RouteVersion: 1,
Host: "testHost1",
Learner: false,
},
},
}
data1, err := val.Marshal()
require.NoError(t, err)
val = clustermgr.CatalogChangeShardAdd{
ShardID: 2,
RouteVersion: 2,
Units: []clustermgr.ShardUnitInfo{
{
Suid: proto.EncodeSuid(2, 0, 0),
DiskID: 2,
LeaderDiskID: 0, // wrong
Range: *ranges[1],
RouteVersion: 2,
},
},
}
data2, err := val.Marshal()
require.NoError(t, err)
val3 := clustermgr.CatalogChangeShardUpdate{
ShardID: 1,
RouteVersion: 3,
Unit: clustermgr.ShardUnitInfo{
Suid: proto.EncodeSuid(1, 0, 1),
DiskID: 3,
LeaderDiskID: 0, // wrong
RouteVersion: 3,
Range: *ranges[0],
},
}
data3, err := val3.Marshal()
require.NoError(t, err)
val4 := clustermgr.CatalogChangeShardUpdate{
ShardID: 1,
RouteVersion: 4,
Unit: clustermgr.ShardUnitInfo{
Suid: proto.EncodeSuid(1, 0, 2),
DiskID: 3,
LeaderDiskID: 3,
RouteVersion: 3,
Range: *ranges[0],
},
}
data4, err := val4.Marshal()
require.NoError(t, err)
retCatlog := &clustermgr.GetCatalogChangesRet{
RouteVersion: val4.RouteVersion,
Items: []clustermgr.CatalogChangeItem{
{
Type: proto.CatalogChangeItemAddShard,
RouteVersion: 1,
Item: &types.Any{TypeUrl: "", Value: data1}, // success
},
{
Type: proto.CatalogChangeItemAddShard,
RouteVersion: 2,
Item: &types.Any{Value: data2}, // wrong
},
{
Type: proto.CatalogChangeItemUpdateShard,
RouteVersion: 3,
Item: &types.Any{Value: data3}, // wrong
},
{
Type: proto.CatalogChangeItemUpdateShard,
RouteVersion: 4,
Item: &types.Any{Value: data4}, // success
},
},
}
cmCli.EXPECT().GetCatalogChanges(gAny, gAny).Return(retCatlog, nil)
err = svr.UpdateRoute(ctx)
require.Equal(t, errCatalogNoLeader, err)
require.Equal(t, proto.RouteVersion(4), svr.version)
require.Equal(t, 2, len(svr.shards))
}
{
// add shard id=9
const shardID = 9
const version = 5
val := clustermgr.CatalogChangeShardAdd{
ShardID: shardID,
RouteVersion: version,
Units: []clustermgr.ShardUnitInfo{
{
Suid: proto.EncodeSuid(shardID, 0, 0),
DiskID: 1,
AppliedIndex: 0,
LeaderDiskID: 2,
Range: *ranges[8],
RouteVersion: version,
Host: "testHost1",
Learner: false,
},
{
Suid: proto.EncodeSuid(shardID, 1, 0),
DiskID: 2,
AppliedIndex: 0,
LeaderDiskID: 2,
Range: *ranges[8],
RouteVersion: version,
Host: "testHost2",
Learner: false,
},
{
Suid: proto.EncodeSuid(shardID, 2, 0),
DiskID: 3,
AppliedIndex: 0,
LeaderDiskID: 2,
Range: *ranges[8],
RouteVersion: version,
Host: "testHost3",
Learner: false,
},
},
}
data, err := val.Marshal()
require.NoError(t, err)
retCatlog := &clustermgr.GetCatalogChangesRet{
RouteVersion: version,
Items: []clustermgr.CatalogChangeItem{
{
RouteVersion: version,
Type: proto.CatalogChangeItemAddShard,
Item: &types.Any{
TypeUrl: "",
Value: data,
},
},
},
}
cmCli.EXPECT().GetCatalogChanges(gAny, gAny).Return(retCatlog, nil)
svr.cmCli = cmCli
err = svr.UpdateRoute(ctx)
require.NoError(t, err)
require.Equal(t, proto.RouteVersion(version), svr.version)
si, ok := svr.getShardByID(shardID)
require.True(t, ok)
require.Equal(t, proto.ShardID(shardID), si.shardID)
require.Equal(t, 3, len(svr.shards))
expect := shard{
shardID: shardID,
leaderDiskID: val.Units[0].LeaderDiskID,
leaderSuid: val.Units[1].Suid,
version: version,
rangeExt: val.Units[1].Range,
units: convertShardUnitInfo(val.Units),
punishCtrl: svr.punishCtrl,
}
require.Equal(t, expect, *si)
}
{
// add shard id=10
const shardID = 10
const oldVersion = 4
const version = 5
sd := &shard{
shardID: proto.ShardID(shardID),
version: oldVersion,
units: make([]clustermgr.ShardUnit, 1),
}
sd.rangeExt = *ranges[9]
svr.addShardNoLock(sd)
require.Equal(t, 4, len(svr.shards))
val := clustermgr.CatalogChangeShardUpdate{
ShardID: shardID,
RouteVersion: version,
Unit: clustermgr.ShardUnitInfo{
Suid: proto.EncodeSuid(shardID, 0, 0),
DiskID: 2,
AppliedIndex: 0,
LeaderDiskID: 2,
Range: *ranges[9],
RouteVersion: version,
Host: "testHost2",
Learner: false,
},
}
data, err := val.Marshal()
require.NoError(t, err)
retCatlog := &clustermgr.GetCatalogChangesRet{
RouteVersion: version,
Items: []clustermgr.CatalogChangeItem{
{
Type: proto.CatalogChangeItemUpdateShard,
RouteVersion: version,
Item: &types.Any{
TypeUrl: "",
Value: data,
},
},
},
}
cmCli.EXPECT().GetCatalogChanges(gAny, gAny).Return(retCatlog, nil)
svr.cmCli = cmCli
err = svr.UpdateRoute(ctx)
require.NoError(t, err)
require.Equal(t, proto.RouteVersion(version), svr.version)
si, ok := svr.getShardByID(shardID)
require.True(t, ok)
require.Equal(t, proto.ShardID(shardID), si.shardID)
require.Equal(t, 4, len(svr.shards))
}
{
// update version, leader disk, suid
rv := svr.version + 1
shardID := proto.ShardID(9)
oldShard, exist := svr.getShardNoLock(shardID)
require.True(t, exist)
val := clustermgr.CatalogChangeShardUpdate{
ShardID: shardID,
RouteVersion: rv,
Unit: clustermgr.ShardUnitInfo{
Suid: proto.EncodeSuid(shardID, 2, 1),
DiskID: 3,
LeaderDiskID: 2,
Range: *ranges[8],
RouteVersion: rv,
Host: "testHost3",
Learner: false,
},
}
data, err := val.Marshal()
require.NoError(t, err)
item := clustermgr.CatalogChangeItem{
RouteVersion: svr.version + 1,
Type: proto.CatalogChangeItemUpdateShard,
Item: &types.Any{
TypeUrl: "",
Value: data,
},
}
err = svr.handleShardUpdate(ctx, item)
require.NoError(t, err)
sd, exist := svr.getShardNoLock(shardID)
require.True(t, exist)
expect := shard{
shardID: oldShard.shardID,
leaderDiskID: 2,
leaderSuid: proto.EncodeSuid(shardID, 1, 0),
version: rv,
rangeExt: oldShard.rangeExt,
units: oldShard.units,
punishCtrl: oldShard.punishCtrl,
}
idx := val.Unit.Suid.Index()
expect.units[idx] = clustermgr.ShardUnit{
Suid: val.Unit.Suid,
DiskID: val.Unit.DiskID,
Learner: val.Unit.Learner,
}
require.Equal(t, expect, *sd)
}
{
// update version, leader disk not in units(old leader)
rv := svr.version + 1
shardID := proto.ShardID(9)
oldShard, exist := svr.getShardNoLock(shardID)
require.True(t, exist)
val := clustermgr.CatalogChangeShardUpdate{
ShardID: shardID,
RouteVersion: rv,
Unit: clustermgr.ShardUnitInfo{
Suid: proto.EncodeSuid(shardID, 2, 2),
DiskID: 5,
LeaderDiskID: 3,
Range: *ranges[8],
RouteVersion: rv,
Host: "testHost3",
Learner: false,
},
}
data, err := val.Marshal()
require.NoError(t, err)
item := clustermgr.CatalogChangeItem{
RouteVersion: svr.version + 1,
Type: proto.CatalogChangeItemUpdateShard,
Item: &types.Any{
TypeUrl: "",
Value: data,
},
}
err = svr.handleShardUpdate(ctx, item)
require.NoError(t, err)
sd, exist := svr.getShardNoLock(shardID)
require.True(t, exist)
opHeader, err := sd.GetMember(ctx, acapi.GetShardModeLeader, nil)
require.NoError(t, err)
expect := ShardOpInfo{
DiskID: 1,
Suid: proto.EncodeSuid(shardID, 0, 0),
RouteVersion: rv,
}
require.Equal(t, expect, opHeader)
require.Equal(t, oldShard.leaderDiskID, expect.DiskID)
}
{
// leader disk is 0
rv := svr.version + 1
shardID := proto.ShardID(9)
oldShard, exist := svr.getShardNoLock(shardID)
require.True(t, exist)
val := clustermgr.CatalogChangeShardUpdate{
ShardID: shardID,
RouteVersion: rv,
Unit: clustermgr.ShardUnitInfo{
Suid: proto.EncodeSuid(shardID, 1, 1),
DiskID: 4,
LeaderDiskID: 0,
Range: *ranges[8],
RouteVersion: rv,
},
}
data, err := val.Marshal()
require.NoError(t, err)
item := clustermgr.CatalogChangeItem{
RouteVersion: rv,
Type: proto.CatalogChangeItemUpdateShard,
Item: &types.Any{
TypeUrl: "",
Value: data,
},
}
err = svr.handleShardUpdate(ctx, item)
require.ErrorIs(t, err, errCatalogNoLeader)
sd, exist := svr.getShardNoLock(shardID)
require.True(t, exist)
expect := shard{
shardID: oldShard.shardID,
leaderDiskID: 4,
leaderSuid: proto.EncodeSuid(shardID, 1, 1),
version: rv,
rangeExt: oldShard.rangeExt,
units: oldShard.units,
punishCtrl: oldShard.punishCtrl,
}
idx := val.Unit.Suid.Index()
expect.units[idx] = clustermgr.ShardUnit{
Suid: val.Unit.Suid,
DiskID: val.Unit.DiskID,
Learner: val.Unit.Learner,
}
require.Equal(t, expect, *sd)
// error
val.RouteVersion = 1
data, err = val.Marshal()
require.NoError(t, err)
item.RouteVersion = val.RouteVersion
item.Item.Value = data
err = svr.handleShardUpdate(ctx, item)
require.ErrorIs(t, err, errCatalogInvalid)
}
}
func TestShardGetShard(t *testing.T) {
ctx := context.Background()
svr := &shardControllerImpl{
shards: make(map[proto.ShardID]*shard),
ranges: btree.New(defaultBTreeDegree),
subRangeCnt: 2,
}
ctr := gomock.NewController(t)
cmCli := mocks.NewMockClientAPI(ctr)
cmCli.EXPECT().GetService(gAny, gAny).Return(clustermgr.ServiceInfo{
Nodes: []clustermgr.ServiceNode{
{ClusterID: 1, Name: proto.ServiceNameProxy, Host: "proxy-1", Idc: "test-idc"},
},
}, nil)
cmCli.EXPECT().ShardNodeDiskInfo(gAny, proto.DiskID(1)).Return(&clustermgr.ShardNodeDiskInfo{
DiskInfo: clustermgr.DiskInfo{Host: "testHost1", Idc: "test-idc"},
ShardNodeDiskHeartbeatInfo: clustermgr.ShardNodeDiskHeartbeatInfo{DiskID: 1},
}, nil)
cmCli.EXPECT().ShardNodeDiskInfo(gAny, proto.DiskID(2)).Return(&clustermgr.ShardNodeDiskInfo{
DiskInfo: clustermgr.DiskInfo{Host: "testHost2", Idc: "test-idc"},
ShardNodeDiskHeartbeatInfo: clustermgr.ShardNodeDiskHeartbeatInfo{DiskID: 2},
}, nil)
cmCli.EXPECT().ShardNodeDiskInfo(gAny, proto.DiskID(3)).Return(&clustermgr.ShardNodeDiskInfo{
DiskInfo: clustermgr.DiskInfo{Host: "testHost3", Idc: "test-idc"},
ShardNodeDiskHeartbeatInfo: clustermgr.ShardNodeDiskHeartbeatInfo{DiskID: 3},
}, nil)
svrCtrl, err := NewServiceController(ServiceConfig{IDC: "test-idc"}, cmCli, nil, nil)
require.NoError(t, err)
svrCtrl.GetShardnodeHost(ctx, 1)
svrCtrl.GetShardnodeHost(ctx, 2)
svrCtrl.GetShardnodeHost(ctx, 3)
// add 8 shard
shards := make([]*shard, 8)
ranges := sharding.InitShardingRange(sharding.RangeType_RangeTypeHash, 2, 8)
for i := 0; i < 8; i++ {
sd := &shard{
shardID: proto.ShardID(i + 1),
version: 1,
leaderDiskID: 1,
leaderSuid: proto.EncodeSuid(proto.ShardID(i+1), 0, 0),
units: []clustermgr.ShardUnit{
{
Suid: proto.EncodeSuid(proto.ShardID(i+1), 0, 0),
DiskID: 1,
Host: "testHost1",
},
{
Suid: proto.EncodeSuid(proto.ShardID(i+1), 1, 0),
DiskID: 2,
Host: "testHost2",
},
{
Suid: proto.EncodeSuid(proto.ShardID(i+1), 2, 0),
DiskID: 3,
Host: "testHost3",
},
},
punishCtrl: svrCtrl,
}
sd.rangeExt = *ranges[i]
shards[i] = sd
}
// shards[7].rangeExt.Subs[0].Max = math.MaxUint64
for i := 0; i < 8; i++ {
svr.addShardNoLock(shards[i])
}
require.Equal(t, 8, len(svr.shards))
{
// sd, err := svr.GetShard(ctx, []byte("{blob1}{1}"))
sd, err := svr.GetShard(ctx, []string{"blob1", "1"})
require.NoError(t, err)
require.Equal(t, proto.ShardID(2), sd.GetShardID())
// sd, err = svr.GetShard(ctx, []byte("{blob1}{}"))
sd, err = svr.GetShard(ctx, []string{"blob1", ""})
require.NoError(t, err)
require.Equal(t, proto.ShardID(2), sd.GetShardID())
// shard others
sd, err = svr.GetShardByID(ctx, proto.ShardID(1))
require.NoError(t, err)
shardInfo, err := sd.GetMember(ctx, acapi.GetShardModeLeader, nil)
require.NoError(t, err)
require.Equal(t, shards[0].shardID, shardInfo.Suid.ShardID())
shardInfo, err = sd.GetMember(ctx, acapi.GetShardModeRandom, nil)
require.NoError(t, err)
require.Equal(t, shards[0].shardID, shardInfo.Suid.ShardID())
shardID := sd.GetShardID()
require.Equal(t, shards[0].shardID, shardID)
}
// get first shard
{
sd, err := svr.GetFisrtShard(ctx)
require.NoError(t, err)
require.Equal(t, proto.ShardID(1), sd.GetShardID())
newDisk, err := sd.GetMember(ctx, acapi.GetShardModeRandom, map[proto.DiskID]struct{}{2: {}, 1: {}})
require.NoError(t, err)
require.NotEqual(t, proto.DiskID(2), newDisk.DiskID)
require.NotEqual(t, proto.DiskID(1), newDisk.DiskID)
require.Contains(t, []proto.DiskID{3}, newDisk.DiskID)
}
// get shard by range
{
sd, err := svr.GetShardByID(ctx, proto.ShardID(2))
require.NoError(t, err)
shardRange := sd.GetRange()
sd, err = svr.GetShardByRange(ctx, shardRange)
require.NoError(t, err)
require.Equal(t, proto.ShardID(2), sd.GetShardID())
require.Equal(t, shardRange, sd.GetRange())
sd, err = svr.GetShardByRange(ctx, shards[0].rangeExt)
require.NoError(t, err)
require.Equal(t, proto.ShardID(1), sd.GetShardID())
sd, err = svr.GetShardByRange(ctx, shards[7].rangeExt)
require.NoError(t, err)
require.Equal(t, proto.ShardID(8), sd.GetShardID())
sd, err = svr.GetNextShard(ctx, shardRange)
require.NoError(t, err)
require.Equal(t, proto.ShardID(3), sd.GetShardID())
require.NotEqual(t, shardRange, sd.GetRange())
// err == nil && shard == nil, means last shard, reach end
sd, err = svr.GetNextShard(ctx, shards[7].rangeExt)
require.NoError(t, err)
require.Nil(t, sd)
}
}

View File

@ -17,6 +17,7 @@ package controller
import (
"context"
"fmt"
"sync"
"time"
"golang.org/x/sync/singleflight"
@ -29,15 +30,11 @@ import (
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/util/defaulter"
"github.com/cubefs/cubefs/blobstore/util/errors"
"github.com/cubefs/cubefs/blobstore/util/retry"
)
const (
_defaultCacheSize = 1 << 20
_defaultCacheExpiration = int64(2 * time.Minute)
)
// Unit alias of clustermgr.Unit
type Unit = clustermgr.Unit
@ -51,23 +48,23 @@ type VolumePhy struct {
Vid proto.Vid
CodeMode codemode.CodeMode
IsPunish bool
Version uint32
Version uint64
Timestamp int64
Units []Unit
}
// VolumeGetter getter of volume physical location
//
// ctx: context with trace or something
//
// isCache: is false means reading from proxy cluster then updating memcache
//
// otherwise reading from memcache -> proxy -> cluster
// ctx: context with trace or something
// isCache: is false means reading from proxy cluster then updating memcache
// otherwise reading from memcache -> proxy -> cluster
type VolumeGetter interface {
// Get returns volume physical location of vid
Get(ctx context.Context, vid proto.Vid, isCache bool) *VolumePhy
// Punish punish vid with interval seconds
Punish(ctx context.Context, vid proto.Vid, punishIntervalS int)
// Update try to flush volume of proxy
Update(ctx context.Context, vid proto.Vid)
}
type cvid uint64
@ -106,9 +103,6 @@ func (vc *volumeMemCache) Set(key cvid, value *VolumePhy) {
}
type volumeGetterImpl struct {
ctx context.Context
cid proto.ClusterID
volumeMemCache volumePhyCacher
memExpiration int64
punishCache *memcache.MemCache
@ -116,40 +110,71 @@ type volumeGetterImpl struct {
service ServiceController
proxy proxy.Cacher
singleRun *singleflight.Group
unusualLock sync.Mutex
unusualVolume map[proto.Vid]int
config VolumeConfig
}
// VolumeConfig controller of volume's config
type VolumeConfig struct {
ClusterID proto.ClusterID `json:"-"`
VolumeMemcacheSize int `json:"volume_memcache_size"`
VolumeMemcachePunishSize int `json:"volume_memcache_punish_size"`
VolumeMemcacheExpirationMs int64 `json:"volume_memcache_expiration_ms"` // -1 means no expiration
VolumePunishThreshold int `json:"volume_punish_threshold"`
VolumePunishIntervalS int `json:"volume_punish_interval_s"`
}
// NewVolumeGetter new a volume getter
//
// memExpiration expiration of memcache, 0 means no expiration
func NewVolumeGetter(clusterID proto.ClusterID, service ServiceController,
proxy proxy.Cacher, memExpiration time.Duration) (VolumeGetter, error) {
_, ctx := trace.StartSpanFromContext(context.Background(), "")
func NewVolumeGetter(cfg VolumeConfig, service ServiceController,
proxy proxy.Cacher, stop <-chan struct{},
) (VolumeGetter, error) {
expiration := cfg.VolumeMemcacheExpirationMs * int64(time.Millisecond)
defaulter.IntegerEqual(&expiration, int64(2*time.Minute))
defaulter.IntegerLess(&expiration, 0)
expiration := int64(memExpiration)
if expiration < 0 {
expiration = _defaultCacheExpiration
}
defaulter.IntegerLessOrEqual(&cfg.VolumeMemcacheSize, 1<<20)
defaulter.IntegerLessOrEqual(&cfg.VolumeMemcachePunishSize, 1<<10)
defaulter.IntegerLessOrEqual(&cfg.VolumePunishThreshold, 10)
defaulter.IntegerLessOrEqual(&cfg.VolumePunishIntervalS, 600)
mc, err := memcache.NewMemCache(_defaultCacheSize)
mc, err := memcache.NewMemCache(cfg.VolumeMemcacheSize)
if err != nil {
return nil, err
}
punishCache, err := memcache.NewMemCache(1024)
punishCache, err := memcache.NewMemCache(cfg.VolumeMemcachePunishSize)
if err != nil {
return nil, err
}
getter := &volumeGetterImpl{
ctx: ctx,
cid: clusterID,
volumeMemCache: &volumeMemCache{cache: mc},
memExpiration: expiration,
punishCache: punishCache,
service: service,
proxy: proxy,
singleRun: new(singleflight.Group),
unusualVolume: make(map[proto.Vid]int),
config: cfg,
}
go func() {
ticker := time.NewTicker(time.Duration(cfg.VolumePunishIntervalS) * time.Second)
defer ticker.Stop()
for {
getter.tickerUpdate()
select {
case <-ticker.C:
case <-stop:
getter.tickerUpdate()
return
}
}
}()
return getter, nil
}
@ -159,8 +184,8 @@ func NewVolumeGetter(clusterID proto.ClusterID, service ServiceController,
// 2.second level cache from proxy cluster
func (v *volumeGetterImpl) Get(ctx context.Context, vid proto.Vid, isCache bool) (phy *VolumePhy) {
span := trace.SpanFromContextSafe(ctx)
cid := v.cid.ToString()
id := addCVid(v.cid, vid)
cid := v.config.ClusterID.ToString()
id := addCVid(v.config.ClusterID, vid)
// check if volume punish
defer func() {
@ -215,7 +240,7 @@ func (v *volumeGetterImpl) Get(ctx context.Context, vid proto.Vid, isCache bool)
}
singleID := fmt.Sprintf("get-volume-%d", id)
ver := uint32(0)
ver := uint64(0)
if phy != nil {
ver = phy.Version
}
@ -225,6 +250,7 @@ func (v *volumeGetterImpl) Get(ctx context.Context, vid proto.Vid, isCache bool)
if err != nil {
cacheMetric.WithLabelValues(cid, "proxy", "miss").Inc()
span.Error("get volume location from proxy failed", errors.Detail(err))
phy = nil
return
}
cacheMetric.WithLabelValues(cid, "proxy", "hit").Inc()
@ -238,34 +264,41 @@ func (v *volumeGetterImpl) Get(ctx context.Context, vid proto.Vid, isCache bool)
return
}
func (v *volumeGetterImpl) Punish(ctx context.Context, vid proto.Vid, punishIntervalS int) {
v.punishCache.Set(addCVid(v.cid, vid), time.Now().Add(time.Duration(punishIntervalS)*time.Second).Unix())
func (v *volumeGetterImpl) Punish(_ context.Context, vid proto.Vid, punishIntervalS int) {
v.punishCache.Set(addCVid(v.config.ClusterID, vid), time.Now().Add(time.Duration(punishIntervalS)*time.Second).Unix())
}
func (v *volumeGetterImpl) setToLocalCache(ctx context.Context, id cvid, phy *VolumePhy) {
func (v *volumeGetterImpl) Update(_ context.Context, vid proto.Vid) {
v.unusualLock.Lock()
v.unusualVolume[vid] += 1
v.unusualLock.Unlock()
}
func (v *volumeGetterImpl) setToLocalCache(_ context.Context, id cvid, phy *VolumePhy) {
v.volumeMemCache.Set(id, phy)
}
func (v *volumeGetterImpl) getFromLocalCache(ctx context.Context, id cvid) *VolumePhy {
func (v *volumeGetterImpl) getFromLocalCache(_ context.Context, id cvid) *VolumePhy {
return v.volumeMemCache.Get(id)
}
func (v *volumeGetterImpl) getFromProxy(ctx context.Context, vid proto.Vid, flush bool, ver uint32) (*VolumePhy, error) {
func (v *volumeGetterImpl) getFromProxy(ctx context.Context, vid proto.Vid, flush bool, ver uint64) (*VolumePhy, error) {
span := trace.SpanFromContextSafe(ctx)
hosts, err := v.service.GetServiceHosts(ctx, proto.ServiceNameProxy)
if err != nil {
return nil, err
}
var volume *proxy.VersionVolume
id := addCVid(v.cid, vid)
var volume *clustermgr.VolumeInfo
cid := v.config.ClusterID
id := addCVid(cid, vid)
triedHosts := make(map[string]struct{})
if err = retry.ExponentialBackoff(3, 30).RuptOn(func() (bool, error) {
for _, host := range hosts {
triedHosts[host] = struct{}{}
if volume, err = v.proxy.GetCacheVolume(ctx, host,
&proxy.CacheVolumeArgs{Vid: vid, Flush: flush, Version: ver}); err != nil {
if rpc.DetectStatusCode(err) == errcode.CodeVolumeNotExist {
if err == context.Canceled || rpc.DetectStatusCode(err) == errcode.CodeVolumeNotExist {
return true, err
}
span.Warnf("get from proxy(%s) volume(%d) error(%s)", host, vid, err.Error())
@ -281,22 +314,26 @@ func (v *volumeGetterImpl) getFromProxy(ctx context.Context, vid proto.Vid, flus
Vid: vid,
Timestamp: -time.Now().UnixNano(),
}
span.Infof("to update memcache on not exist volume(%d-%d) %+v", v.cid, vid, phy)
span.Infof("to update memcache on not exist volume(%d-%d) %+v", cid, vid, phy)
v.setToLocalCache(ctx, id, phy)
} else if flush {
span.Warnf("to flush force on all proxy of volume(%d-%d)", cid, vid)
v.setToLocalCache(ctx, id, nil)
v.flush(ctx, vid, 0, hosts, map[string]struct{}{})
}
return nil, errors.Base(err, "get volume from proxy", v.cid, vid)
return nil, errors.Base(err, "get volume from proxy", cid, vid)
}
phy := &VolumePhy{
Vid: volume.Vid,
CodeMode: volume.CodeMode,
Version: volume.Version,
Version: uint64(volume.RouteVersion),
Timestamp: time.Now().UnixNano(),
Units: make([]Unit, len(volume.Units)),
}
copy(phy.Units, volume.Units[:])
span.Debugf("to update memcache on volume(%d-%d) %+v", v.cid, vid, phy)
span.Debugf("to update memcache on volume(%d-%d) %+v", cid, vid, phy)
v.setToLocalCache(ctx, id, phy)
if flush {
@ -307,7 +344,7 @@ func (v *volumeGetterImpl) getFromProxy(ctx context.Context, vid proto.Vid, flus
}
// flush update all proxy cache of this idc
func (v *volumeGetterImpl) flush(ctx context.Context, vid proto.Vid, ver uint32, hosts []string, except map[string]struct{}) {
func (v *volumeGetterImpl) flush(ctx context.Context, vid proto.Vid, ver uint64, hosts []string, except map[string]struct{}) {
span := trace.SpanFromContextSafe(ctx)
span.Infof("to flush volume cache %d on proxy:%v version:%d except:%v", vid, hosts, ver, except)
@ -316,15 +353,16 @@ func (v *volumeGetterImpl) flush(ctx context.Context, vid proto.Vid, ver uint32,
continue
}
bgSpan, bgCtx := trace.StartSpanFromContextWithTraceID(context.Background(), "flush_proxy_volume", span.TraceID())
go func(host string) {
retry.ExponentialBackoff(2, 10).RuptOn(func() (bool, error) {
if _, err := v.proxy.GetCacheVolume(ctx, host,
if _, err := v.proxy.GetCacheVolume(bgCtx, host,
&proxy.CacheVolumeArgs{Vid: vid, Flush: true, Version: ver}); err != nil {
if rpc.DetectStatusCode(err) == errcode.CodeVolumeNotExist {
span.Info("not found volume", vid)
bgSpan.Info("not found volume", vid)
return true, err
}
span.Warnf("flush volume:%d error:%s", vid, err.Error())
bgSpan.Warnf("flush volume:%d error:%s", vid, err.Error())
return false, err
}
return true, nil
@ -332,3 +370,23 @@ func (v *volumeGetterImpl) flush(ctx context.Context, vid proto.Vid, ver uint32,
}(host)
}
}
func (v *volumeGetterImpl) tickerUpdate() {
var vids []proto.Vid
v.unusualLock.Lock()
for vid, n := range v.unusualVolume {
if n > v.config.VolumePunishThreshold {
vids = append(vids, vid)
if len(vids) >= 10 {
break
}
delete(v.unusualVolume, vid)
}
}
v.unusualLock.Unlock()
for _, vid := range vids {
_, ctx := trace.StartSpanFromContext(context.Background(), "update-unusual")
v.getFromProxy(ctx, vid, true, 0)
}
}

View File

@ -26,6 +26,12 @@ import (
"github.com/cubefs/cubefs/blobstore/common/trace"
)
func closedCh() <-chan struct{} {
c := make(chan struct{})
close(c)
return c
}
func proxyService() controller.ServiceController {
service, _ := controller.NewServiceController(controller.ServiceConfig{IDC: idc}, cmcli, proxycli, nil)
return service
@ -34,7 +40,8 @@ func proxyService() controller.ServiceController {
func TestAccessVolumeGetterNew(t *testing.T) {
_, ctx := trace.StartSpanFromContext(context.Background(), "TestAccessVolumeGetterNew")
getter, err := controller.NewVolumeGetter(1, proxyService(), proxycli, time.Millisecond*200)
cfg := controller.VolumeConfig{ClusterID: 1, VolumeMemcacheExpirationMs: 200}
getter, err := controller.NewVolumeGetter(cfg, proxyService(), proxycli, closedCh())
require.Nil(t, err)
require.Nil(t, getter.Get(ctx, proto.Vid(0), true))
@ -62,7 +69,8 @@ func TestAccessVolumeGetterNew(t *testing.T) {
func TestAccessVolumeGetterNotExistVolume(t *testing.T) {
_, ctx := trace.StartSpanFromContext(context.Background(), "TestAccessVolumeGetterNotExistVolume")
getter, err := controller.NewVolumeGetter(0xfe, proxyService(), proxycli, time.Millisecond*200)
cfg := controller.VolumeConfig{ClusterID: 0xfe, VolumeMemcacheExpirationMs: 200}
getter, err := controller.NewVolumeGetter(cfg, proxyService(), proxycli, closedCh())
require.NoError(t, err)
id := vid404
@ -78,7 +86,8 @@ func TestAccessVolumeGetterNotExistVolume(t *testing.T) {
getter.Get(ctx, id, true)
require.Equal(t, 2, dataCalled[id])
getter, err = controller.NewVolumeGetter(0xee, proxyService(), proxycli, 0)
cfg = controller.VolumeConfig{ClusterID: 0xee, VolumeMemcacheExpirationMs: -1}
getter, err = controller.NewVolumeGetter(cfg, proxyService(), proxycli, closedCh())
require.NoError(t, err)
id = vid404
dataCalled[id] = 0
@ -94,10 +103,34 @@ func TestAccessVolumeGetterNotExistVolume(t *testing.T) {
require.Equal(t, 6, dataCalled[id])
}
func TestAccessVolumeGetterNotExistFlush(t *testing.T) {
_, ctx := trace.StartSpanFromContext(context.Background(), "TestAccessVolumeGetterNotExistVolumeFlush")
cfg := controller.VolumeConfig{ClusterID: 0xfe, VolumeMemcacheExpirationMs: 200}
getter, err := controller.NewVolumeGetter(cfg, proxyService(), proxycli, closedCh())
require.NoError(t, err)
id := vid404
require.Nil(t, getter.Get(ctx, id, true))
for range [10]struct{}{} {
require.Nil(t, getter.Get(ctx, id, false))
}
time.Sleep(time.Millisecond * 210)
cfg = controller.VolumeConfig{ClusterID: 0xee, VolumeMemcacheExpirationMs: -1}
getter, err = controller.NewVolumeGetter(cfg, proxyService(), proxycli, closedCh())
require.NoError(t, err)
for range [10]struct{}{} {
require.Nil(t, getter.Get(ctx, id, false))
}
}
func TestAccessVolumeGetterExpiration(t *testing.T) {
_, ctx := trace.StartSpanFromContext(context.Background(), "TestAccessVolumeGetterExpiration")
getter, err := controller.NewVolumeGetter(1, proxyService(), proxycli, time.Millisecond*200)
cfg := controller.VolumeConfig{ClusterID: 1, VolumeMemcacheExpirationMs: 200}
getter, err := controller.NewVolumeGetter(cfg, proxyService(), proxycli, closedCh())
require.Nil(t, err)
id := proto.Vid(1)
@ -118,7 +151,8 @@ func TestAccessVolumeGetterExpiration(t *testing.T) {
func TestAccessVolumePunish(t *testing.T) {
_, ctx := trace.StartSpanFromContext(context.Background(), "TestAccessVolumePunish")
getter, err := controller.NewVolumeGetter(1, proxyService(), proxycli, 0)
cfg := controller.VolumeConfig{ClusterID: 1, VolumeMemcacheExpirationMs: -1}
getter, err := controller.NewVolumeGetter(cfg, proxyService(), proxycli, closedCh())
require.Nil(t, err)
require.Nil(t, getter.Get(ctx, proto.Vid(0), true))
@ -141,3 +175,50 @@ func TestAccessVolumePunish(t *testing.T) {
require.NotNil(t, info)
require.False(t, info.IsPunish)
}
func TestAccessVolumeUpdate(t *testing.T) {
_, ctx := trace.StartSpanFromContext(context.Background(), "TestAccessVolumeUpdate")
ch := make(chan struct{})
go func() {
time.Sleep(time.Second)
close(ch)
}()
cfg := controller.VolumeConfig{ClusterID: 1, VolumeMemcacheExpirationMs: -1}
getter, err := controller.NewVolumeGetter(cfg, proxyService(), proxycli, ch)
require.NoError(t, err)
getter.Update(ctx, 1)
for range [11]struct{}{} {
getter.Update(ctx, vid404)
}
for idx := range [11]struct{}{} {
for range [11]struct{}{} {
getter.Update(ctx, proto.Vid(idx+1))
}
}
getter.Update(ctx, 123)
getter.Update(ctx, 11)
<-ch
}
func TestAccessVolumeUpdateForce(t *testing.T) {
_, ctx := trace.StartSpanFromContext(context.Background(), "TestAccessVolumeUpdateForce")
ctxDone, cancel := context.WithCancel(ctx)
cancel()
ch := make(chan struct{})
go func() {
time.Sleep(time.Second)
close(ch)
}()
cfg := controller.VolumeConfig{ClusterID: 1, VolumeMemcacheExpirationMs: -1}
getter, err := controller.NewVolumeGetter(cfg, proxyService(), proxycli, ch)
require.NoError(t, err)
id := proto.Vid(1)
require.Nil(t, getter.Get(ctxDone, id, false))
require.NotNil(t, getter.Get(ctx, id, true))
<-ch
}

View File

@ -1,305 +0,0 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/cubefs/cubefs/blobstore/access/controller (interfaces: ClusterController,ServiceController,VolumeGetter)
// Package access is a generated GoMock package.
package access
import (
context "context"
reflect "reflect"
controller "github.com/cubefs/cubefs/blobstore/access/controller"
clustermgr "github.com/cubefs/cubefs/blobstore/api/clustermgr"
proto "github.com/cubefs/cubefs/blobstore/common/proto"
gomock "github.com/golang/mock/gomock"
)
// MockClusterController is a mock of ClusterController interface.
type MockClusterController struct {
ctrl *gomock.Controller
recorder *MockClusterControllerMockRecorder
}
// MockClusterControllerMockRecorder is the mock recorder for MockClusterController.
type MockClusterControllerMockRecorder struct {
mock *MockClusterController
}
// NewMockClusterController creates a new mock instance.
func NewMockClusterController(ctrl *gomock.Controller) *MockClusterController {
mock := &MockClusterController{ctrl: ctrl}
mock.recorder = &MockClusterControllerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockClusterController) EXPECT() *MockClusterControllerMockRecorder {
return m.recorder
}
// All mocks base method.
func (m *MockClusterController) All() []*clustermgr.ClusterInfo {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "All")
ret0, _ := ret[0].([]*clustermgr.ClusterInfo)
return ret0
}
// All indicates an expected call of All.
func (mr *MockClusterControllerMockRecorder) All() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockClusterController)(nil).All))
}
// ChangeChooseAlg mocks base method.
func (m *MockClusterController) ChangeChooseAlg(arg0 controller.AlgChoose) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChangeChooseAlg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// ChangeChooseAlg indicates an expected call of ChangeChooseAlg.
func (mr *MockClusterControllerMockRecorder) ChangeChooseAlg(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeChooseAlg", reflect.TypeOf((*MockClusterController)(nil).ChangeChooseAlg), arg0)
}
// ChooseOne mocks base method.
func (m *MockClusterController) ChooseOne() (*clustermgr.ClusterInfo, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChooseOne")
ret0, _ := ret[0].(*clustermgr.ClusterInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ChooseOne indicates an expected call of ChooseOne.
func (mr *MockClusterControllerMockRecorder) ChooseOne() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChooseOne", reflect.TypeOf((*MockClusterController)(nil).ChooseOne))
}
// GetConfig mocks base method.
func (m *MockClusterController) GetConfig(arg0 context.Context, arg1 string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetConfig", arg0, arg1)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetConfig indicates an expected call of GetConfig.
func (mr *MockClusterControllerMockRecorder) GetConfig(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfig", reflect.TypeOf((*MockClusterController)(nil).GetConfig), arg0, arg1)
}
// GetServiceController mocks base method.
func (m *MockClusterController) GetServiceController(arg0 proto.ClusterID) (controller.ServiceController, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetServiceController", arg0)
ret0, _ := ret[0].(controller.ServiceController)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetServiceController indicates an expected call of GetServiceController.
func (mr *MockClusterControllerMockRecorder) GetServiceController(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceController", reflect.TypeOf((*MockClusterController)(nil).GetServiceController), arg0)
}
// GetVolumeGetter mocks base method.
func (m *MockClusterController) GetVolumeGetter(arg0 proto.ClusterID) (controller.VolumeGetter, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetVolumeGetter", arg0)
ret0, _ := ret[0].(controller.VolumeGetter)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetVolumeGetter indicates an expected call of GetVolumeGetter.
func (mr *MockClusterControllerMockRecorder) GetVolumeGetter(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVolumeGetter", reflect.TypeOf((*MockClusterController)(nil).GetVolumeGetter), arg0)
}
// Region mocks base method.
func (m *MockClusterController) Region() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Region")
ret0, _ := ret[0].(string)
return ret0
}
// Region indicates an expected call of Region.
func (mr *MockClusterControllerMockRecorder) Region() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Region", reflect.TypeOf((*MockClusterController)(nil).Region))
}
// MockServiceController is a mock of ServiceController interface.
type MockServiceController struct {
ctrl *gomock.Controller
recorder *MockServiceControllerMockRecorder
}
// MockServiceControllerMockRecorder is the mock recorder for MockServiceController.
type MockServiceControllerMockRecorder struct {
mock *MockServiceController
}
// NewMockServiceController creates a new mock instance.
func NewMockServiceController(ctrl *gomock.Controller) *MockServiceController {
mock := &MockServiceController{ctrl: ctrl}
mock.recorder = &MockServiceControllerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockServiceController) EXPECT() *MockServiceControllerMockRecorder {
return m.recorder
}
// GetDiskHost mocks base method.
func (m *MockServiceController) GetDiskHost(arg0 context.Context, arg1 proto.DiskID) (*controller.HostIDC, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetDiskHost", arg0, arg1)
ret0, _ := ret[0].(*controller.HostIDC)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetDiskHost indicates an expected call of GetDiskHost.
func (mr *MockServiceControllerMockRecorder) GetDiskHost(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDiskHost", reflect.TypeOf((*MockServiceController)(nil).GetDiskHost), arg0, arg1)
}
// GetServiceHost mocks base method.
func (m *MockServiceController) GetServiceHost(arg0 context.Context, arg1 string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetServiceHost", arg0, arg1)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetServiceHost indicates an expected call of GetServiceHost.
func (mr *MockServiceControllerMockRecorder) GetServiceHost(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceHost", reflect.TypeOf((*MockServiceController)(nil).GetServiceHost), arg0, arg1)
}
// GetServiceHosts mocks base method.
func (m *MockServiceController) GetServiceHosts(arg0 context.Context, arg1 string) ([]string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetServiceHosts", arg0, arg1)
ret0, _ := ret[0].([]string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetServiceHosts indicates an expected call of GetServiceHosts.
func (mr *MockServiceControllerMockRecorder) GetServiceHosts(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceHosts", reflect.TypeOf((*MockServiceController)(nil).GetServiceHosts), arg0, arg1)
}
// PunishDisk mocks base method.
func (m *MockServiceController) PunishDisk(arg0 context.Context, arg1 proto.DiskID, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishDisk", arg0, arg1, arg2)
}
// PunishDisk indicates an expected call of PunishDisk.
func (mr *MockServiceControllerMockRecorder) PunishDisk(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishDisk", reflect.TypeOf((*MockServiceController)(nil).PunishDisk), arg0, arg1, arg2)
}
// PunishDiskWithThreshold mocks base method.
func (m *MockServiceController) PunishDiskWithThreshold(arg0 context.Context, arg1 proto.DiskID, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishDiskWithThreshold", arg0, arg1, arg2)
}
// PunishDiskWithThreshold indicates an expected call of PunishDiskWithThreshold.
func (mr *MockServiceControllerMockRecorder) PunishDiskWithThreshold(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishDiskWithThreshold", reflect.TypeOf((*MockServiceController)(nil).PunishDiskWithThreshold), arg0, arg1, arg2)
}
// PunishService mocks base method.
func (m *MockServiceController) PunishService(arg0 context.Context, arg1, arg2 string, arg3 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishService", arg0, arg1, arg2, arg3)
}
// PunishService indicates an expected call of PunishService.
func (mr *MockServiceControllerMockRecorder) PunishService(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishService", reflect.TypeOf((*MockServiceController)(nil).PunishService), arg0, arg1, arg2, arg3)
}
// PunishServiceWithThreshold mocks base method.
func (m *MockServiceController) PunishServiceWithThreshold(arg0 context.Context, arg1, arg2 string, arg3 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishServiceWithThreshold", arg0, arg1, arg2, arg3)
}
// PunishServiceWithThreshold indicates an expected call of PunishServiceWithThreshold.
func (mr *MockServiceControllerMockRecorder) PunishServiceWithThreshold(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishServiceWithThreshold", reflect.TypeOf((*MockServiceController)(nil).PunishServiceWithThreshold), arg0, arg1, arg2, arg3)
}
// MockVolumeGetter is a mock of VolumeGetter interface.
type MockVolumeGetter struct {
ctrl *gomock.Controller
recorder *MockVolumeGetterMockRecorder
}
// MockVolumeGetterMockRecorder is the mock recorder for MockVolumeGetter.
type MockVolumeGetterMockRecorder struct {
mock *MockVolumeGetter
}
// NewMockVolumeGetter creates a new mock instance.
func NewMockVolumeGetter(ctrl *gomock.Controller) *MockVolumeGetter {
mock := &MockVolumeGetter{ctrl: ctrl}
mock.recorder = &MockVolumeGetterMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockVolumeGetter) EXPECT() *MockVolumeGetterMockRecorder {
return m.recorder
}
// Get mocks base method.
func (m *MockVolumeGetter) Get(arg0 context.Context, arg1 proto.Vid, arg2 bool) *controller.VolumePhy {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", arg0, arg1, arg2)
ret0, _ := ret[0].(*controller.VolumePhy)
return ret0
}
// Get indicates an expected call of Get.
func (mr *MockVolumeGetterMockRecorder) Get(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockVolumeGetter)(nil).Get), arg0, arg1, arg2)
}
// Punish mocks base method.
func (m *MockVolumeGetter) Punish(arg0 context.Context, arg1 proto.Vid, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Punish", arg0, arg1, arg2)
}
// Punish indicates an expected call of Punish.
func (mr *MockVolumeGetterMockRecorder) Punish(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Punish", reflect.TypeOf((*MockVolumeGetter)(nil).Punish), arg0, arg1, arg2)
}

View File

@ -15,14 +15,13 @@
package access
import (
"crypto/sha1"
"fmt"
"net/http"
"strconv"
"sync"
"time"
"github.com/cubefs/cubefs/blobstore/access/controller"
"github.com/cubefs/cubefs/blobstore/access/stream"
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/cmd"
@ -32,8 +31,8 @@ import (
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/resourcepool"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/common/security"
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/common/uptoken"
"github.com/cubefs/cubefs/blobstore/util/closer"
"github.com/cubefs/cubefs/blobstore/util/errors"
"github.com/cubefs/cubefs/blobstore/util/log"
@ -48,46 +47,11 @@ const (
limitNameSign = "sign"
)
const (
_tokenExpiration = time.Hour * 12
)
var (
// tokenSecretKeys alloc token with the first secret key always,
// so that you can change the secret key.
//
// parse-1: insert a new key at the first index,
// parse-2: delete the old key at the last index after _tokenExpiration duration.
tokenSecretKeys = [...][20]byte{
{0x5f, 0x00, 0x88, 0x96, 0x00, 0xa1, 0xfe, 0x1b},
{0xff, 0x1f, 0x2f, 0x4f, 0x7f, 0xaf, 0xef, 0xff},
}
_initTokenSecret sync.Once
)
func initTokenSecret(b []byte) {
_initTokenSecret.Do(func() {
for idx := range tokenSecretKeys {
copy(tokenSecretKeys[idx][7:], b)
}
})
}
func initWithRegionMagic(regionMagic string) {
if regionMagic == "" {
log.Warn("no region magic setting, using default secret keys for checksum")
return
}
b := sha1.Sum([]byte(regionMagic))
initTokenSecret(b[:8])
initLocationSecret(b[:8])
}
type accessStatus struct {
Limit Status `json:"limit"`
Limit stream.Status `json:"limit"`
Pool resourcepool.Status `json:"pool"`
Config StreamConfig `json:"config"`
Config stream.StreamConfig `json:"config"`
Clusters []*clustermgr.ClusterInfo `json:"clusters"`
Services map[proto.ClusterID]map[string][]string `json:"services"`
}
@ -96,29 +60,34 @@ type accessStatus struct {
type Config struct {
cmd.Config
ServiceRegister consul.Config `json:"service_register"`
Stream StreamConfig `json:"stream"`
Limit LimitConfig `json:"limit"`
ServiceRegister consul.Config `json:"service_register"`
Stream stream.StreamConfig `json:"stream"`
Limit stream.LimitConfig `json:"limit"`
}
// Service rpc service
type Service struct {
config Config
streamHandler StreamHandler
limiter Limiter
streamHandler stream.StreamHandler
limiter stream.Limiter
closer closer.Closer
}
// New returns an access service
func New(cfg Config) *Service {
// add region magic checksum to the secret keys
initWithRegionMagic(cfg.Stream.ClusterConfig.RegionMagic)
security.InitWithRegionMagic(cfg.Stream.ClusterConfig.RegionMagic)
cl := closer.New()
h, err := stream.NewStreamHandler(&cfg.Stream, cl.Done())
if err != nil {
log.Fatalf("new stream handler failed, err: %+v", err)
}
return &Service{
config: cfg,
streamHandler: NewStreamHandler(&cfg.Stream, cl.Done()),
limiter: NewLimiter(cfg.Limit),
streamHandler: h,
limiter: stream.NewLimiter(cfg.Limit),
closer: cl,
}
}
@ -142,9 +111,9 @@ func (s *Service) RegisterService() {
// RegisterAdminHandler register admin handler to profile
func (s *Service) RegisterAdminHandler() {
profile.HandleFunc(http.MethodGet, "/access/status", func(c *rpc.Context) {
var admin *streamAdmin
var admin *stream.StreamAdmin
if sa := s.streamHandler.Admin(); sa != nil {
if ad, ok := sa.(*streamAdmin); ok {
if ad, ok := sa.(*stream.StreamAdmin); ok {
admin = ad
}
}
@ -158,13 +127,13 @@ func (s *Service) RegisterAdminHandler() {
status := new(accessStatus)
status.Limit = s.limiter.Status()
status.Pool = admin.memPool.Status()
status.Config = admin.config
status.Clusters = admin.controller.All()
status.Pool = admin.MemPool.Status()
status.Config = admin.Config
status.Clusters = admin.Controller.All()
status.Services = make(map[proto.ClusterID]map[string][]string, len(status.Clusters))
for _, cluster := range status.Clusters {
service, err := admin.controller.GetServiceController(cluster.ClusterID)
service, err := admin.Controller.GetServiceController(cluster.ClusterID)
if err != nil {
span.Warn(err.Error())
continue
@ -191,8 +160,8 @@ func (s *Service) RegisterAdminHandler() {
alg := controller.AlgChoose(algInt)
if sa := s.streamHandler.Admin(); sa != nil {
if admin, ok := sa.(*streamAdmin); ok {
if err := admin.controller.ChangeChooseAlg(alg); err != nil {
if admin, ok := sa.(*stream.StreamAdmin); ok {
if err := admin.Controller.ChangeChooseAlg(alg); err != nil {
c.RespondWith(http.StatusForbidden, "", []byte(err.Error()))
return
}
@ -265,7 +234,7 @@ func (s *Service) Put(c *rpc.Context) {
}
rc := s.limiter.Reader(ctx, c.Request.Body)
loc, err := s.streamHandler.Put(ctx, rc, args.Size, hasherMap)
loc, err := s.streamHandler.Put(ctx, rc, args.Size, hasherMap, args.AssignClusterID, args.CodeMode)
if err != nil {
span.Error("stream put failed", errors.Detail(err))
c.RespondError(httpError(err))
@ -277,7 +246,7 @@ func (s *Service) Put(c *rpc.Context) {
hashSumMap[alg] = hasher.Sum(nil)
}
if err := fillCrc(loc); err != nil {
if err := security.LocationCrcFill(loc); err != nil {
span.Error("stream put fill location crc", err)
c.RespondError(httpError(err))
return
@ -308,8 +277,8 @@ func (s *Service) PutAt(c *rpc.Context) {
}
valid := false
for _, secretKey := range tokenSecretKeys {
token := uptoken.DecodeToken(args.Token)
for _, secretKey := range security.TokenSecretKeys() {
token := security.DecodeToken(args.Token)
if token.IsValid(args.ClusterID, args.Vid, args.BlobID, uint32(args.Size), secretKey[:]) {
valid = true
break
@ -369,7 +338,7 @@ func (s *Service) Alloc(c *rpc.Context) {
return
}
if err := fillCrc(location); err != nil {
if err := security.LocationCrcFill(location); err != nil {
span.Error("stream alloc fill location crc", err)
c.RespondError(httpError(err))
return
@ -377,7 +346,7 @@ func (s *Service) Alloc(c *rpc.Context) {
resp := access.AllocResp{
Location: *location,
Tokens: genTokens(location),
Tokens: security.StreamGenTokens(location),
}
c.RespondJSON(resp)
span.Infof("done /alloc request resp:%+v", resp)
@ -395,7 +364,7 @@ func (s *Service) Get(c *rpc.Context) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("accept /get request args:%+v", args)
if !args.IsValid() || !verifyCrc(&args.Location) {
if !args.IsValid() || !security.LocationCrcVerify(&args.Location) {
c.RespondError(errcode.ErrIllegalArguments)
return
}
@ -411,9 +380,9 @@ func (s *Service) Get(c *rpc.Context) {
w.Header().Set(rpc.HeaderContentType, rpc.MIMEStream)
w.Header().Set(rpc.HeaderContentLength, strconv.FormatInt(int64(args.ReadSize), 10))
if args.ReadSize > 0 && args.ReadSize != args.Location.Size {
if args.ReadSize > 0 && args.ReadSize != args.Location.Size_ {
w.Header().Set(rpc.HeaderContentRange, fmt.Sprintf("bytes %d-%d/%d",
args.Offset, args.Offset+args.ReadSize-1, args.Location.Size))
args.Offset, args.Offset+args.ReadSize-1, args.Location.Size_))
c.RespondStatus(http.StatusPartialContent)
} else {
c.RespondStatus(http.StatusOK)
@ -424,7 +393,7 @@ func (s *Service) Get(c *rpc.Context) {
err = transfer()
if err != nil {
reportDownload(args.Location.ClusterID, "StatusOKError", "-")
stream.SteamReportDownload(args.Location.ClusterID, "StatusOKError", "-")
span.Error("stream get transfer failed", errors.Detail(err))
return
}
@ -471,19 +440,19 @@ func (s *Service) Delete(c *rpc.Context) {
clusterBlobsN := make(map[proto.ClusterID]int, 4)
for _, loc := range args.Locations {
if !verifyCrc(&loc) {
if !security.LocationCrcVerify(&loc) {
span.Infof("invalid crc %+v", loc)
err = errcode.ErrIllegalArguments
return
}
clusterBlobsN[loc.ClusterID] += len(loc.Blobs)
clusterBlobsN[loc.ClusterID] += len(loc.Slices)
}
if len(args.Locations) == 1 {
loc := args.Locations[0]
if err := s.streamHandler.Delete(ctx, &loc); err != nil {
span.Error("stream delete failed", errors.Detail(err))
resp.FailedLocations = []access.Location{loc}
resp.FailedLocations = []proto.Location{loc}
}
return
}
@ -495,12 +464,12 @@ func (s *Service) Delete(c *rpc.Context) {
// max delete locations is 1024, one location is max to 5G,
// merged message max size about 40MB.
merged := make(map[proto.ClusterID][]access.SliceInfo, len(clusterBlobsN))
merged := make(map[proto.ClusterID][]proto.Slice, len(clusterBlobsN))
for id, n := range clusterBlobsN {
merged[id] = make([]access.SliceInfo, 0, n)
merged[id] = make([]proto.Slice, 0, n)
}
for _, loc := range args.Locations {
merged[loc.ClusterID] = append(merged[loc.ClusterID], loc.Blobs...)
merged[loc.ClusterID] = append(merged[loc.ClusterID], loc.Slices...)
}
var wg sync.WaitGroup
@ -509,7 +478,7 @@ func (s *Service) Delete(c *rpc.Context) {
go func() {
for id := range failedCh {
if resp.FailedLocations == nil {
resp.FailedLocations = make([]access.Location, 0, len(args.Locations))
resp.FailedLocations = make([]proto.Location, 0, len(args.Locations))
}
for _, loc := range args.Locations {
if loc.ClusterID == id {
@ -523,10 +492,10 @@ func (s *Service) Delete(c *rpc.Context) {
wg.Add(len(merged))
for id := range merged {
go func(id proto.ClusterID) {
if err := s.streamHandler.Delete(ctx, &access.Location{
if err := s.streamHandler.Delete(ctx, &proto.Location{
ClusterID: id,
BlobSize: 1,
Blobs: merged[id],
SliceSize: 1,
Slices: merged[id],
}); err != nil {
span.Error("stream delete failed", id, errors.Detail(err))
failedCh <- id
@ -558,8 +527,8 @@ func (s *Service) DeleteBlob(c *rpc.Context) {
}
valid := false
for _, secretKey := range tokenSecretKeys {
token := uptoken.DecodeToken(args.Token)
for _, secretKey := range security.TokenSecretKeys() {
token := security.DecodeToken(args.Token)
if token.IsValid(args.ClusterID, args.Vid, args.BlobID, uint32(args.Size), secretKey[:]) {
valid = true
break
@ -571,13 +540,13 @@ func (s *Service) DeleteBlob(c *rpc.Context) {
return
}
if err := s.streamHandler.Delete(ctx, &access.Location{
if err := s.streamHandler.Delete(ctx, &proto.Location{
ClusterID: args.ClusterID,
BlobSize: 1,
Blobs: []access.SliceInfo{{
MinBid: args.BlobID,
Vid: args.Vid,
Count: 1,
SliceSize: 1,
Slices: []proto.Slice{{
MinSliceID: args.BlobID,
Vid: args.Vid,
Count: 1,
}},
}); err != nil {
span.Error("stream delete blob failed", errors.Detail(err))
@ -608,7 +577,7 @@ func (s *Service) Sign(c *rpc.Context) {
loc := args.Location
crcOld := loc.Crc
if err := signCrc(&loc, args.Locations); err != nil {
if err := security.LocationCrcSign(&loc, args.Locations); err != nil {
span.Error("stream sign failed", errors.Detail(err))
c.RespondError(errcode.ErrIllegalArguments)
return
@ -627,39 +596,3 @@ func httpError(err error) error {
}
return errcode.ErrUnexpected
}
// genTokens generate tokens
// 1. Returns 0 token if has no blobs.
// 2. Returns 1 token if file size less than blobsize.
// 3. Returns len(blobs) tokens if size divided by blobsize.
// 4. Otherwise returns len(blobs)+1 tokens, the last token
// will be used by the last blob, even if the last slice blobs' size
// less than blobsize.
// 5. Each segment blob has its specified token include the last blob.
func genTokens(location *access.Location) []string {
tokens := make([]string, 0, len(location.Blobs)+1)
hasMultiBlobs := location.Size >= uint64(location.BlobSize)
lastSize := uint32(location.Size % uint64(location.BlobSize))
for idx, blob := range location.Blobs {
// returns one token if size < blobsize
if hasMultiBlobs {
count := blob.Count
if idx == len(location.Blobs)-1 && lastSize > 0 {
count--
}
tokens = append(tokens, uptoken.EncodeToken(uptoken.NewUploadToken(location.ClusterID,
blob.Vid, blob.MinBid, count,
location.BlobSize, _tokenExpiration, tokenSecretKeys[0][:])))
}
// token of the last blob
if idx == len(location.Blobs)-1 && lastSize > 0 {
tokens = append(tokens, uptoken.EncodeToken(uptoken.NewUploadToken(location.ClusterID,
blob.Vid, blob.MinBid+proto.BlobID(blob.Count)-1, 1,
lastSize, _tokenExpiration, tokenSecretKeys[0][:])))
}
}
return tokens
}

View File

@ -1,127 +0,0 @@
// Copyright 2022 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
import (
"fmt"
"hash/crc32"
"sync"
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/util/bytespool"
)
const (
// DO NOT CHANGE IT.
_crcPoly = uint32(0x59c8943c)
)
var (
// DO NOT CHANGE IT.
_crcTable = crc32.MakeTable(_crcPoly)
_crcMagicKey = [20]byte{
0x52, 0xe, 0x53, 0x53, 0x81,
0x1f, 0x51, 0xb7, 0xa4, 0x72,
0x10, 0x33, 0x64, 0xa7, 0x3a,
0x10, 0x19, 0xbc, 0x60, 0x7,
}
_initLocationSecret sync.Once
)
func initLocationSecret(b []byte) {
_initLocationSecret.Do(func() {
copy(_crcMagicKey[7:], b)
})
}
func calcCrc(loc *access.Location) (uint32, error) {
crcWriter := crc32.New(_crcTable)
buf := bytespool.Alloc(1024)
defer bytespool.Free(buf)
n := loc.Encode2(buf)
if n < 4 {
return 0, fmt.Errorf("no enough bytes(%d) fill into buf", n)
}
if _, err := crcWriter.Write(_crcMagicKey[:]); err != nil {
return 0, fmt.Errorf("fill crc %s", err.Error())
}
if _, err := crcWriter.Write(buf[4:n]); err != nil {
return 0, fmt.Errorf("fill crc %s", err.Error())
}
return crcWriter.Sum32(), nil
}
func fillCrc(loc *access.Location) error {
crc, err := calcCrc(loc)
if err != nil {
return err
}
loc.Crc = crc
return nil
}
func verifyCrc(loc *access.Location) bool {
crc, err := calcCrc(loc)
if err != nil {
return false
}
return loc.Crc == crc
}
func signCrc(loc *access.Location, locs []access.Location) error {
first := locs[0]
bids := make(map[proto.BlobID]struct{}, 64)
if loc.ClusterID != first.ClusterID ||
loc.CodeMode != first.CodeMode ||
loc.BlobSize != first.BlobSize {
return fmt.Errorf("not equal in constant field")
}
for _, l := range locs {
if !verifyCrc(&l) {
return fmt.Errorf("not equal in crc %d", l.Crc)
}
// assert
if l.ClusterID != first.ClusterID ||
l.CodeMode != first.CodeMode ||
l.BlobSize != first.BlobSize {
return fmt.Errorf("not equal in constant field")
}
for _, blob := range l.Blobs {
for c := 0; c < int(blob.Count); c++ {
bids[blob.MinBid+proto.BlobID(c)] = struct{}{}
}
}
}
for _, blob := range loc.Blobs {
for c := 0; c < int(blob.Count); c++ {
bid := blob.MinBid + proto.BlobID(c)
if _, ok := bids[bid]; !ok {
return fmt.Errorf("not equal in blob_id(%d)", bid)
}
}
}
return fillCrc(loc)
}

View File

@ -30,26 +30,65 @@ import (
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"github.com/cubefs/cubefs/blobstore/access/stream"
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/common/codemode"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/common/uptoken"
"github.com/cubefs/cubefs/blobstore/common/security"
mocks "github.com/cubefs/cubefs/blobstore/testing/mocks"
_ "github.com/cubefs/cubefs/blobstore/testing/nolog"
)
var (
ctx = context.Background()
_blobSize uint32 = 1 << 20
location = &access.Location{
location = &proto.Location{
ClusterID: 1,
CodeMode: 1,
BlobSize: _blobSize,
CodeMode: codemode.EC15P12,
SliceSize: _blobSize,
Crc: 0,
Blobs: []access.SliceInfo{{
MinBid: 111,
Vid: 1111,
Count: 11,
Slices: []proto.Slice{{
MinSliceID: 111,
Vid: 1111,
Count: 11,
}},
}
locationForClusterID = &proto.Location{
ClusterID: 11,
CodeMode: codemode.EC3P3,
SliceSize: _blobSize,
Crc: 0,
Slices: []proto.Slice{{
MinSliceID: 111,
Vid: 1111,
Count: 1,
}},
}
locationForCodeMode = &proto.Location{
ClusterID: 22,
CodeMode: codemode.EC6P6,
SliceSize: _blobSize,
Crc: 0,
Slices: []proto.Slice{{
MinSliceID: 111,
Vid: 1111,
Count: 1,
}},
}
locationForClusterIDAndCodeMode = &proto.Location{
ClusterID: 99,
CodeMode: codemode.EC12P4,
SliceSize: _blobSize,
Crc: 0,
Slices: []proto.Slice{{
MinSliceID: 111,
Vid: 1111,
Count: 1,
}},
}
@ -66,54 +105,66 @@ func runMockService(s *Service) string {
func newService() *Service {
ctr := gomock.NewController(&testing.T{})
s := NewMockStreamHandler(ctr)
s := mocks.NewMockStreamHandler(ctr)
s.EXPECT().Alloc(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
func(ctx context.Context, size uint64, blobSize uint32,
assignClusterID proto.ClusterID, codeMode codemode.CodeMode) (*access.Location, error) {
assignClusterID proto.ClusterID, codeMode codemode.CodeMode,
) (*proto.Location, error) {
if size < 1024 {
return nil, errors.New("fake alloc location")
}
loc := location.Copy()
loc.Size = uint64(size)
fillCrc(&loc)
loc.Size_ = uint64(size)
security.LocationCrcFill(&loc)
return &loc, nil
})
s.EXPECT().PutAt(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(),
gomock.Any()).AnyTimes().DoAndReturn(
func(ctx context.Context, rc io.Reader,
clusterID proto.ClusterID, vid proto.Vid, bid proto.BlobID, size int64,
hasherMap access.HasherMap) error {
clusterID proto.ClusterID, vid proto.Vid, bid proto.BlobID, size int64, hasherMap access.HasherMap,
) error {
if size < 1024 {
return errcode.ErrAccessLimited
}
return nil
})
s.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
func(ctx context.Context, rc io.Reader, size int64, hasherMap access.HasherMap) (*access.Location, error) {
s.EXPECT().Put(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
func(ctx context.Context, rc io.Reader, size int64, hasherMap access.HasherMap,
assignClusterID proto.ClusterID, codeMode codemode.CodeMode,
) (*proto.Location, error) {
if size < 1024 {
return nil, errors.New("fake put nil body")
}
loc := location.Copy()
loc.Size = uint64(size)
fillCrc(&loc)
var loc proto.Location
if assignClusterID == 0 && codeMode == codemode.CodeModeNone {
loc = location.Copy()
} else if assignClusterID == 11 && codeMode == codemode.CodeModeNone {
loc = locationForClusterID.Copy()
} else if assignClusterID == 0 && codeMode == codemode.EC6P6 {
loc = locationForCodeMode.Copy()
} else if assignClusterID == 99 && codeMode == codemode.EC12P4 {
loc = locationForClusterIDAndCodeMode.Copy()
}
loc.Size_ = uint64(size)
security.LocationCrcFill(&loc)
return &loc, nil
})
s.EXPECT().Get(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
func(ctx context.Context, w io.Writer, location access.Location, readSize, offset uint64) (func() error, error) {
func(ctx context.Context, w io.Writer, location proto.Location, readSize, offset uint64) (func() error, error) {
if readSize < 1024 {
return nil, errors.New("fake get nil body")
}
return func() error { return nil }, nil
})
s.EXPECT().Delete(gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
func(ctx context.Context, location *access.Location) error {
func(ctx context.Context, location *proto.Location) error {
if location.ClusterID >= 10 {
return errors.New("fake delete error with cluster")
} else if location.ClusterID == 1 && location.Crc > 0 && location.Size < 1024 {
} else if location.ClusterID == 1 && location.Crc > 0 && location.Size_ < 1024 {
return errors.New("fake delete error")
}
return nil
@ -121,7 +172,7 @@ func newService() *Service {
return &Service{
streamHandler: s,
limiter: NewLimiter(LimitConfig{
limiter: stream.NewLimiter(stream.LimitConfig{
NameRps: map[string]int{
limitNameAlloc: 2,
},
@ -168,21 +219,21 @@ func TestAccessServiceAlloc(t *testing.T) {
resp := &access.AllocResp{}
err := cli.PostWith(ctx, url(), resp, args)
require.NoError(t, err)
require.Equal(t, uint64(1024), resp.Location.Size)
require.Equal(t, uint64(1024), resp.Location.Size_)
}
{
args.Size = uint64(_blobSize)
resp := &access.AllocResp{}
err := cli.PostWith(ctx, url(), resp, args)
require.NoError(t, err)
require.Equal(t, uint64(_blobSize), resp.Location.Size)
require.Equal(t, uint64(_blobSize), resp.Location.Size_)
}
{
args.Size = uint64(_blobSize) + 1
resp := &access.AllocResp{}
err := cli.PostWith(ctx, url(), resp, args)
require.NoError(t, err)
require.Equal(t, uint64(_blobSize)+1, resp.Location.Size)
require.Equal(t, uint64(_blobSize)+1, resp.Location.Size_)
}
}
@ -220,7 +271,7 @@ func TestAccessServicePutAt(t *testing.T) {
resp := &access.PutAtResp{}
req, _ := http.NewRequest(method, url(args.Size, "c1fdcecaacbfafd86f0b00"), bytes.NewReader(buf))
err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
assertErrorCode(t, 552, err)
assertErrorCode(t, errcode.CodeAccessLimited, err)
}
{
args.Size = 1024
@ -245,6 +296,21 @@ func TestAccessServicePut(t *testing.T) {
return fmt.Sprintf("%s/put?size=%d&hashes=%d", host, size, hashes)
}
urlForClusterID := func(size int64, hashes access.HashAlgorithm, assignClusterID proto.ClusterID) string {
return fmt.Sprintf("%s/put?size=%d&hashes=%d&assign_cluster_id=%d", host, size, hashes, assignClusterID)
}
urlForCodeMode := func(size int64, hashes access.HashAlgorithm, codeMode codemode.CodeMode) string {
return fmt.Sprintf("%s/put?size=%d&hashes=%d&code_mode=%d", host, size, hashes, codeMode)
}
urlForClusterIDAndCodeMode := func(size int64, hashes access.HashAlgorithm,
assignClusterID proto.ClusterID, codeMode codemode.CodeMode,
) string {
return fmt.Sprintf("%s/put?size=%d&hashes=%d&assign_cluster_id=%d&code_mode=%d",
host, size, hashes, assignClusterID, codeMode)
}
for _, method := range []string{http.MethodPut, http.MethodPost} {
args := access.PutArgs{
Size: 0,
@ -276,7 +342,38 @@ func TestAccessServicePut(t *testing.T) {
resp := &access.PutResp{}
err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
require.NoError(t, err)
require.Equal(t, uint64(1024), resp.Location.Size)
require.Equal(t, uint64(1024), resp.Location.Size_)
require.Equal(t, proto.ClusterID(1), resp.Location.ClusterID)
require.Equal(t, codemode.EC15P12, resp.Location.CodeMode)
}
{
args.Body = bytes.NewReader(make([]byte, 1024))
req, _ := http.NewRequest(method,
urlForClusterIDAndCodeMode(1024, args.Hashes, proto.ClusterID(99), codemode.EC12P4), args.Body)
resp := &access.PutResp{}
err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
require.NoError(t, err)
require.Equal(t, uint64(1024), resp.Location.Size_)
require.Equal(t, proto.ClusterID(99), resp.Location.ClusterID)
require.Equal(t, codemode.EC12P4, resp.Location.CodeMode)
}
{
args.Body = bytes.NewReader(make([]byte, 1024))
req, _ := http.NewRequest(method, urlForClusterID(1024, args.Hashes, proto.ClusterID(11)), args.Body)
resp := &access.PutResp{}
err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
require.NoError(t, err)
require.Equal(t, uint64(1024), resp.Location.Size_)
require.Equal(t, proto.ClusterID(11), resp.Location.ClusterID)
}
{
args.Body = bytes.NewReader(make([]byte, 1024))
req, _ := http.NewRequest(method, urlForCodeMode(1024, args.Hashes, codemode.EC6P6), args.Body)
resp := &access.PutResp{}
err := cli.DoWith(ctx, req, resp, rpc.WithCrcEncode())
require.NoError(t, err)
require.Equal(t, uint64(1024), resp.Location.Size_)
require.Equal(t, codemode.EC6P6, resp.Location.CodeMode)
}
}
}
@ -301,28 +398,28 @@ func TestAccessServiceGet(t *testing.T) {
require.Equal(t, 400, resp.StatusCode, resp.Status)
}
{
args.Location.Size = 1023
args.Location.Size_ = 1023
args.ReadSize = 1023
fillCrc(&args.Location)
security.LocationCrcFill(&args.Location)
resp, err := cli.Post(ctx, url(), args)
require.NoError(t, err)
resp.Body.Close()
require.Equal(t, 500, resp.StatusCode, resp.Status)
}
{
args.Location.Size = 1024
args.Location.Size_ = 1024
args.ReadSize = 1024
fillCrc(&args.Location)
security.LocationCrcFill(&args.Location)
resp, err := cli.Post(ctx, url(), args)
require.NoError(t, err)
resp.Body.Close()
require.Equal(t, 200, resp.StatusCode, resp.Status)
}
{
args.Location.Size = 10240
args.Location.Size_ = 10240
args.Offset = 1000
args.ReadSize = 1024
fillCrc(&args.Location)
security.LocationCrcFill(&args.Location)
resp, err := cli.Post(ctx, url(), args)
require.NoError(t, err)
resp.Body.Close()
@ -362,7 +459,7 @@ func TestAccessServiceDelete(t *testing.T) {
}
args := access.DeleteArgs{
Locations: []access.Location{location.Copy()},
Locations: []proto.Location{location.Copy()},
}
{
code, _, err := deleteRequest(access.DeleteArgs{})
@ -375,7 +472,7 @@ func TestAccessServiceDelete(t *testing.T) {
require.Equal(t, 400, code)
}
{
fillCrc(&args.Locations[0])
security.LocationCrcFill(&args.Locations[0])
code, resp, err := deleteRequest(args)
require.NoError(t, err)
require.Equal(t, 226, code)
@ -383,17 +480,17 @@ func TestAccessServiceDelete(t *testing.T) {
}
{
loc := &args.Locations[0]
loc.Size = 1024
fillCrc(loc)
loc.Size_ = 1024
security.LocationCrcFill(loc)
code, _, err := deleteRequest(args)
require.NoError(t, err)
require.Equal(t, 200, code)
}
{
loc := location.Copy()
loc.Size = 1024
fillCrc(&loc)
locs := make([]access.Location, access.MaxDeleteLocations)
loc.Size_ = 1024
security.LocationCrcFill(&loc)
locs := make([]proto.Location, access.MaxDeleteLocations)
for idx := range locs {
locs[idx] = loc
}
@ -404,9 +501,9 @@ func TestAccessServiceDelete(t *testing.T) {
}
{
loc := location.Copy()
loc.Size = 1024
fillCrc(&loc)
locs := make([]access.Location, access.MaxDeleteLocations+1)
loc.Size_ = 1024
security.LocationCrcFill(&loc)
locs := make([]proto.Location, access.MaxDeleteLocations+1)
for idx := range locs {
locs[idx] = loc
}
@ -416,22 +513,22 @@ func TestAccessServiceDelete(t *testing.T) {
}
{
loc := location.Copy()
loc.Size = 1024
loc.Size_ = 1024
loc.ClusterID = proto.ClusterID(11)
fillCrc(&loc)
code, resp, err := deleteRequest(access.DeleteArgs{Locations: []access.Location{loc}})
security.LocationCrcFill(&loc)
code, resp, err := deleteRequest(access.DeleteArgs{Locations: []proto.Location{loc}})
require.NoError(t, err)
require.Equal(t, 226, code)
require.Equal(t, 1, len(resp.FailedLocations))
require.Equal(t, proto.ClusterID(11), resp.FailedLocations[0].ClusterID)
}
{
locs := make([]access.Location, access.MaxDeleteLocations)
locs := make([]proto.Location, access.MaxDeleteLocations)
for idx := range locs {
loc := location.Copy()
loc.Size = 1024
loc.Size_ = 1024
loc.ClusterID = proto.ClusterID(idx % 11)
fillCrc(&loc)
security.LocationCrcFill(&loc)
locs[idx] = loc
}
code, resp, err := deleteRequest(access.DeleteArgs{Locations: locs})
@ -502,7 +599,7 @@ func TestAccessServiceSign(t *testing.T) {
return fmt.Sprintf("%s/sign", host)
}
args := access.SignArgs{
Locations: []access.Location{location.Copy()},
Locations: []proto.Location{location.Copy()},
Location: location.Copy(),
}
{
@ -516,7 +613,7 @@ func TestAccessServiceSign(t *testing.T) {
assertErrorCode(t, 400, err)
}
{
fillCrc(&args.Locations[0])
security.LocationCrcFill(&args.Locations[0])
resp := &access.SignResp{}
err := cli.PostWith(ctx, url(), resp, args)
require.NoError(t, err)
@ -530,153 +627,162 @@ func assertErrorCode(t *testing.T, code int, err error) {
}
func TestAccessServiceTokens(t *testing.T) {
skey := tokenSecretKeys[0][:]
checker := func(loc *access.Location, tokens []string) {
if loc.Size == 0 {
skey := security.TokenSecretKeys()[0][:]
checker := func(loc *proto.Location, tokens []string) {
if loc.Size_ == 0 {
require.Equal(t, 0, len(tokens))
return
}
hasMultiBlobs := loc.Size >= uint64(loc.BlobSize)
lastSize := uint32(loc.Size % uint64(loc.BlobSize))
hasMultiBlobs := loc.Size_ >= uint64(loc.SliceSize)
lastSize := uint32(loc.Size_ % uint64(loc.SliceSize))
if !hasMultiBlobs {
require.Equal(t, 1, len(tokens))
token := uptoken.DecodeToken(tokens[0])
blob := loc.Blobs[0]
for bid := blob.MinBid - 100; bid < blob.MinBid+100; bid++ {
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
token := security.DecodeToken(tokens[0])
blob := loc.Slices[0]
for bid := blob.MinSliceID - 100; bid < blob.MinSliceID+100; bid++ {
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.SliceSize, skey))
}
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, blob.MinBid, lastSize, skey))
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, blob.MinSliceID, lastSize, skey))
return
}
if lastSize == 0 {
require.Equal(t, len(loc.Blobs), len(tokens))
for idx, blob := range loc.Blobs {
token := uptoken.DecodeToken(tokens[idx])
require.Equal(t, len(loc.Slices), len(tokens))
for idx, blob := range loc.Slices {
token := security.DecodeToken(tokens[idx])
for ii := uint32(0); ii < 100; ii++ {
bid := blob.MinBid - proto.BlobID(ii) - 1
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
bid = blob.MinBid + proto.BlobID(blob.Count+ii)
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
bid := blob.MinSliceID - proto.BlobID(ii) - 1
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.SliceSize, skey))
bid = blob.MinSliceID + proto.BlobID(blob.Count+ii)
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.SliceSize, skey))
}
for ii := uint32(0); ii < blob.Count; ii++ {
bid := blob.MinBid + proto.BlobID(ii)
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
bid := blob.MinSliceID + proto.BlobID(ii)
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.SliceSize, skey))
}
}
return
}
require.Equal(t, len(loc.Blobs)+1, len(tokens))
for ii := 0; ii < len(loc.Blobs)-1; ii++ {
token := uptoken.DecodeToken(tokens[ii])
blob := loc.Blobs[ii]
if loc.Slices[len(loc.Slices)-1].Count == 1 {
require.Equal(t, len(loc.Slices), len(tokens))
idx := len(loc.Slices) - 1
blob := loc.Slices[idx]
token := security.DecodeToken(tokens[idx])
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, blob.MinSliceID, lastSize, skey))
return
}
require.Equal(t, len(loc.Slices)+1, len(tokens))
for ii := 0; ii < len(loc.Slices)-1; ii++ {
token := security.DecodeToken(tokens[ii])
blob := loc.Slices[ii]
for ii := uint32(0); ii < blob.Count; ii++ {
bid := blob.MinBid + proto.BlobID(ii)
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
bid := blob.MinSliceID + proto.BlobID(ii)
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.SliceSize, skey))
}
}
token := uptoken.DecodeToken(tokens[len(loc.Blobs)-1])
blob := loc.Blobs[len(loc.Blobs)-1]
token := security.DecodeToken(tokens[len(loc.Slices)-1])
blob := loc.Slices[len(loc.Slices)-1]
for ii := uint32(0); ii < 100; ii++ {
bid := blob.MinBid - proto.BlobID(ii) - 1
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
bid = blob.MinBid + proto.BlobID(blob.Count+ii) - 1
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
bid := blob.MinSliceID - proto.BlobID(ii) - 1
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.SliceSize, skey))
bid = blob.MinSliceID + proto.BlobID(blob.Count+ii) - 1
require.False(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.SliceSize, skey))
}
for ii := uint32(0); ii < blob.Count-1; ii++ {
bid := blob.MinBid + proto.BlobID(ii)
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.BlobSize, skey))
bid := blob.MinSliceID + proto.BlobID(ii)
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, bid, loc.SliceSize, skey))
}
token = uptoken.DecodeToken(tokens[len(loc.Blobs)])
lastbid := blob.MinBid + proto.BlobID(blob.Count) - 1
token = security.DecodeToken(tokens[len(loc.Slices)])
lastbid := blob.MinSliceID + proto.BlobID(blob.Count) - 1
require.True(t, token.IsValid(loc.ClusterID, blob.Vid, lastbid, lastSize, skey))
}
{
loc := &access.Location{
Size: 0,
BlobSize: 333,
Blobs: []access.SliceInfo{},
loc := &proto.Location{
Size_: 0,
SliceSize: 333,
Slices: []proto.Slice{},
}
checker(loc, genTokens(loc))
checker(loc, security.StreamGenTokens(loc))
}
{
loc := &access.Location{
Size: 1,
BlobSize: 1024,
Blobs: []access.SliceInfo{
{MinBid: 100, Vid: 1000, Count: 1},
loc := &proto.Location{
Size_: 1,
SliceSize: 1024,
Slices: []proto.Slice{
{MinSliceID: 100, Vid: 1000, Count: 1},
},
}
checker(loc, genTokens(loc))
checker(loc, security.StreamGenTokens(loc))
}
{
loc := &access.Location{
Size: 1024,
BlobSize: 1024,
Blobs: []access.SliceInfo{
{MinBid: 100, Vid: 1000, Count: 1},
loc := &proto.Location{
Size_: 1024,
SliceSize: 1024,
Slices: []proto.Slice{
{MinSliceID: 100, Vid: 1000, Count: 1},
},
}
checker(loc, genTokens(loc))
checker(loc, security.StreamGenTokens(loc))
}
{
loc := &access.Location{
Size: 1025,
BlobSize: 1024,
Blobs: []access.SliceInfo{
{MinBid: 100, Vid: 1000, Count: 2},
loc := &proto.Location{
Size_: 1025,
SliceSize: 1024,
Slices: []proto.Slice{
{MinSliceID: 100, Vid: 1000, Count: 2},
},
}
checker(loc, genTokens(loc))
checker(loc, security.StreamGenTokens(loc))
}
{
loc := &access.Location{
Size: 2048,
BlobSize: 1024,
Blobs: []access.SliceInfo{
{MinBid: 100, Vid: 1000, Count: 2},
loc := &proto.Location{
Size_: 2048,
SliceSize: 1024,
Slices: []proto.Slice{
{MinSliceID: 100, Vid: 1000, Count: 2},
},
}
checker(loc, genTokens(loc))
checker(loc, security.StreamGenTokens(loc))
}
{
loc := &access.Location{
Size: 10240,
BlobSize: 1024,
Blobs: []access.SliceInfo{
{MinBid: 100, Vid: 1000, Count: 4},
{MinBid: 200, Vid: 1000, Count: 6},
loc := &proto.Location{
Size_: 10240,
SliceSize: 1024,
Slices: []proto.Slice{
{MinSliceID: 100, Vid: 1000, Count: 4},
{MinSliceID: 200, Vid: 1000, Count: 6},
},
}
checker(loc, genTokens(loc))
checker(loc, security.StreamGenTokens(loc))
}
{
loc := &access.Location{
Size: 1025,
BlobSize: 1024,
Blobs: []access.SliceInfo{
{MinBid: 100, Vid: 1000, Count: 1},
{MinBid: 200, Vid: 1000, Count: 1},
loc := &proto.Location{
Size_: 1025,
SliceSize: 1024,
Slices: []proto.Slice{
{MinSliceID: 100, Vid: 1000, Count: 1},
{MinSliceID: 200, Vid: 1000, Count: 1},
},
}
checker(loc, genTokens(loc))
checker(loc, security.StreamGenTokens(loc))
}
{
loc := &access.Location{
Size: 10242,
BlobSize: 1024,
Blobs: []access.SliceInfo{
{MinBid: 100, Vid: 1000, Count: 5},
{MinBid: 200, Vid: 1000, Count: 6},
loc := &proto.Location{
Size_: 10242,
SliceSize: 1024,
Slices: []proto.Slice{
{MinSliceID: 100, Vid: 1000, Count: 5},
{MinSliceID: 200, Vid: 1000, Count: 6},
},
}
checker(loc, genTokens(loc))
checker(loc, security.StreamGenTokens(loc))
}
}
@ -698,7 +804,7 @@ func TestAccessServiceLimited(t *testing.T) {
if err != nil {
assertErrorCode(t, errcode.CodeAccessLimited, err)
} else {
require.Equal(t, uint64(1024), resp.Location.Size)
require.Equal(t, uint64(1024), resp.Location.Size_)
}
}()
}

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"fmt"
@ -43,3 +43,22 @@ func (c CodeModePairs) SelectCodeMode(size int64) codemode.CodeMode {
panic(fmt.Sprintf("no codemode policy to be selected by size %d, %+v", size, c))
}
// Verify select codemode
func (c CodeModePairs) VerifySelectCodeMode(selectCodeMode codemode.CodeMode) bool {
if !selectCodeMode.IsValid() {
return false
}
for codeMode, pair := range c {
policy := pair.Policy
if !policy.Enable {
continue
}
if selectCodeMode == codeMode {
return true
}
}
return false
}

View File

@ -12,20 +12,20 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access_test
package stream_test
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/cubefs/cubefs/blobstore/access"
"github.com/cubefs/cubefs/blobstore/access/stream"
"github.com/cubefs/cubefs/blobstore/common/codemode"
)
func TestAccessStreamCodeModePairs(t *testing.T) {
m := access.CodeModePairs{
codemode.EC6P6: access.CodeModePair{
m := stream.CodeModePairs{
codemode.EC6P6: stream.CodeModePair{
Policy: codemode.Policy{
ModeName: codemode.EC6P6.Name(),
MinSize: 1 << 10,
@ -34,7 +34,7 @@ func TestAccessStreamCodeModePairs(t *testing.T) {
},
Tactic: codemode.EC6P6.Tactic(),
},
codemode.EC6P10L2: access.CodeModePair{
codemode.EC6P10L2: stream.CodeModePair{
Policy: codemode.Policy{
ModeName: codemode.EC6P10L2.Name(),
MinSize: 1 << 30,

View File

@ -12,17 +12,19 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
const (
defaultMaxBlobSize uint32 = 1 << 22 // 4MB
defaultDiskPunishIntervalS int = 60
defaultServicePunishIntervalS int = 60
defaultAllocRetryTimes int = 3
defaultAllocRetryIntervalMS int = 100
defaultEncoderConcurrency int = 1000
defaultMinReadShardsX int = 1
defaultDiskPunishIntervalS int = 60
defaultServicePunishIntervalS int = 60
defaultAllocRetryTimes int = 3
defaultAllocRetryIntervalMS int = 100
defaultEncoderConcurrency int = 1000
defaultMinReadShardsX int = 1
defaultShardnodeRetryTimes int = 3
defaultShardnodeRetryIntervalMS int = 200
// client timeout ms
defaultTimeoutClusterMgr int64 = 1000 * 3

View File

@ -0,0 +1,608 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/cubefs/cubefs/blobstore/access/controller (interfaces: ClusterController,ServiceController,VolumeGetter,IShardController,Shard)
// Package stream is a generated GoMock package.
package stream
import (
context "context"
reflect "reflect"
controller "github.com/cubefs/cubefs/blobstore/access/controller"
access "github.com/cubefs/cubefs/blobstore/api/access"
clustermgr "github.com/cubefs/cubefs/blobstore/api/clustermgr"
shardnode "github.com/cubefs/cubefs/blobstore/api/shardnode"
proto "github.com/cubefs/cubefs/blobstore/common/proto"
sharding "github.com/cubefs/cubefs/blobstore/common/sharding"
gomock "github.com/golang/mock/gomock"
)
// MockClusterController is a mock of ClusterController interface.
type MockClusterController struct {
ctrl *gomock.Controller
recorder *MockClusterControllerMockRecorder
}
// MockClusterControllerMockRecorder is the mock recorder for MockClusterController.
type MockClusterControllerMockRecorder struct {
mock *MockClusterController
}
// NewMockClusterController creates a new mock instance.
func NewMockClusterController(ctrl *gomock.Controller) *MockClusterController {
mock := &MockClusterController{ctrl: ctrl}
mock.recorder = &MockClusterControllerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockClusterController) EXPECT() *MockClusterControllerMockRecorder {
return m.recorder
}
// All mocks base method.
func (m *MockClusterController) All() []*clustermgr.ClusterInfo {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "All")
ret0, _ := ret[0].([]*clustermgr.ClusterInfo)
return ret0
}
// All indicates an expected call of All.
func (mr *MockClusterControllerMockRecorder) All() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "All", reflect.TypeOf((*MockClusterController)(nil).All))
}
// ChangeChooseAlg mocks base method.
func (m *MockClusterController) ChangeChooseAlg(arg0 controller.AlgChoose) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChangeChooseAlg", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// ChangeChooseAlg indicates an expected call of ChangeChooseAlg.
func (mr *MockClusterControllerMockRecorder) ChangeChooseAlg(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChangeChooseAlg", reflect.TypeOf((*MockClusterController)(nil).ChangeChooseAlg), arg0)
}
// ChooseOne mocks base method.
func (m *MockClusterController) ChooseOne() (*clustermgr.ClusterInfo, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ChooseOne")
ret0, _ := ret[0].(*clustermgr.ClusterInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ChooseOne indicates an expected call of ChooseOne.
func (mr *MockClusterControllerMockRecorder) ChooseOne() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ChooseOne", reflect.TypeOf((*MockClusterController)(nil).ChooseOne))
}
// GetConfig mocks base method.
func (m *MockClusterController) GetConfig(arg0 context.Context, arg1 string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetConfig", arg0, arg1)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetConfig indicates an expected call of GetConfig.
func (mr *MockClusterControllerMockRecorder) GetConfig(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfig", reflect.TypeOf((*MockClusterController)(nil).GetConfig), arg0, arg1)
}
// GetServiceController mocks base method.
func (m *MockClusterController) GetServiceController(arg0 proto.ClusterID) (controller.ServiceController, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetServiceController", arg0)
ret0, _ := ret[0].(controller.ServiceController)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetServiceController indicates an expected call of GetServiceController.
func (mr *MockClusterControllerMockRecorder) GetServiceController(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceController", reflect.TypeOf((*MockClusterController)(nil).GetServiceController), arg0)
}
// GetShardController mocks base method.
func (m *MockClusterController) GetShardController(arg0 proto.ClusterID) (controller.IShardController, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetShardController", arg0)
ret0, _ := ret[0].(controller.IShardController)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetShardController indicates an expected call of GetShardController.
func (mr *MockClusterControllerMockRecorder) GetShardController(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShardController", reflect.TypeOf((*MockClusterController)(nil).GetShardController), arg0)
}
// GetVolumeGetter mocks base method.
func (m *MockClusterController) GetVolumeGetter(arg0 proto.ClusterID) (controller.VolumeGetter, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetVolumeGetter", arg0)
ret0, _ := ret[0].(controller.VolumeGetter)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetVolumeGetter indicates an expected call of GetVolumeGetter.
func (mr *MockClusterControllerMockRecorder) GetVolumeGetter(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVolumeGetter", reflect.TypeOf((*MockClusterController)(nil).GetVolumeGetter), arg0)
}
// Region mocks base method.
func (m *MockClusterController) Region() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Region")
ret0, _ := ret[0].(string)
return ret0
}
// Region indicates an expected call of Region.
func (mr *MockClusterControllerMockRecorder) Region() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Region", reflect.TypeOf((*MockClusterController)(nil).Region))
}
// MockServiceController is a mock of ServiceController interface.
type MockServiceController struct {
ctrl *gomock.Controller
recorder *MockServiceControllerMockRecorder
}
// MockServiceControllerMockRecorder is the mock recorder for MockServiceController.
type MockServiceControllerMockRecorder struct {
mock *MockServiceController
}
// NewMockServiceController creates a new mock instance.
func NewMockServiceController(ctrl *gomock.Controller) *MockServiceController {
mock := &MockServiceController{ctrl: ctrl}
mock.recorder = &MockServiceControllerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockServiceController) EXPECT() *MockServiceControllerMockRecorder {
return m.recorder
}
// GetDiskHost mocks base method.
func (m *MockServiceController) GetDiskHost(arg0 context.Context, arg1 proto.DiskID) (*controller.HostIDC, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetDiskHost", arg0, arg1)
ret0, _ := ret[0].(*controller.HostIDC)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetDiskHost indicates an expected call of GetDiskHost.
func (mr *MockServiceControllerMockRecorder) GetDiskHost(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDiskHost", reflect.TypeOf((*MockServiceController)(nil).GetDiskHost), arg0, arg1)
}
// GetServiceHost mocks base method.
func (m *MockServiceController) GetServiceHost(arg0 context.Context, arg1 string) (string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetServiceHost", arg0, arg1)
ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetServiceHost indicates an expected call of GetServiceHost.
func (mr *MockServiceControllerMockRecorder) GetServiceHost(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceHost", reflect.TypeOf((*MockServiceController)(nil).GetServiceHost), arg0, arg1)
}
// GetServiceHosts mocks base method.
func (m *MockServiceController) GetServiceHosts(arg0 context.Context, arg1 string) ([]string, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetServiceHosts", arg0, arg1)
ret0, _ := ret[0].([]string)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetServiceHosts indicates an expected call of GetServiceHosts.
func (mr *MockServiceControllerMockRecorder) GetServiceHosts(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceHosts", reflect.TypeOf((*MockServiceController)(nil).GetServiceHosts), arg0, arg1)
}
// GetShardnodeHost mocks base method.
func (m *MockServiceController) GetShardnodeHost(arg0 context.Context, arg1 proto.DiskID) (*controller.HostIDC, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetShardnodeHost", arg0, arg1)
ret0, _ := ret[0].(*controller.HostIDC)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetShardnodeHost indicates an expected call of GetShardnodeHost.
func (mr *MockServiceControllerMockRecorder) GetShardnodeHost(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShardnodeHost", reflect.TypeOf((*MockServiceController)(nil).GetShardnodeHost), arg0, arg1)
}
// IsPunishShardnode mocks base method.
func (m *MockServiceController) IsPunishShardnode(arg0 proto.DiskID) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "IsPunishShardnode", arg0)
ret0, _ := ret[0].(bool)
return ret0
}
// IsPunishShardnode indicates an expected call of IsPunishShardnode.
func (mr *MockServiceControllerMockRecorder) IsPunishShardnode(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsPunishShardnode", reflect.TypeOf((*MockServiceController)(nil).IsPunishShardnode), arg0)
}
// PunishDisk mocks base method.
func (m *MockServiceController) PunishDisk(arg0 context.Context, arg1 proto.DiskID, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishDisk", arg0, arg1, arg2)
}
// PunishDisk indicates an expected call of PunishDisk.
func (mr *MockServiceControllerMockRecorder) PunishDisk(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishDisk", reflect.TypeOf((*MockServiceController)(nil).PunishDisk), arg0, arg1, arg2)
}
// PunishDiskWithThreshold mocks base method.
func (m *MockServiceController) PunishDiskWithThreshold(arg0 context.Context, arg1 proto.DiskID, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishDiskWithThreshold", arg0, arg1, arg2)
}
// PunishDiskWithThreshold indicates an expected call of PunishDiskWithThreshold.
func (mr *MockServiceControllerMockRecorder) PunishDiskWithThreshold(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishDiskWithThreshold", reflect.TypeOf((*MockServiceController)(nil).PunishDiskWithThreshold), arg0, arg1, arg2)
}
// PunishService mocks base method.
func (m *MockServiceController) PunishService(arg0 context.Context, arg1, arg2 string, arg3 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishService", arg0, arg1, arg2, arg3)
}
// PunishService indicates an expected call of PunishService.
func (mr *MockServiceControllerMockRecorder) PunishService(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishService", reflect.TypeOf((*MockServiceController)(nil).PunishService), arg0, arg1, arg2, arg3)
}
// PunishServiceWithThreshold mocks base method.
func (m *MockServiceController) PunishServiceWithThreshold(arg0 context.Context, arg1, arg2 string, arg3 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishServiceWithThreshold", arg0, arg1, arg2, arg3)
}
// PunishServiceWithThreshold indicates an expected call of PunishServiceWithThreshold.
func (mr *MockServiceControllerMockRecorder) PunishServiceWithThreshold(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishServiceWithThreshold", reflect.TypeOf((*MockServiceController)(nil).PunishServiceWithThreshold), arg0, arg1, arg2, arg3)
}
// PunishShardnode mocks base method.
func (m *MockServiceController) PunishShardnode(arg0 context.Context, arg1 proto.DiskID, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishShardnode", arg0, arg1, arg2)
}
// PunishShardnode indicates an expected call of PunishShardnode.
func (mr *MockServiceControllerMockRecorder) PunishShardnode(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishShardnode", reflect.TypeOf((*MockServiceController)(nil).PunishShardnode), arg0, arg1, arg2)
}
// PunishShardnodeDiskWithThreshold mocks base method.
func (m *MockServiceController) PunishShardnodeDiskWithThreshold(arg0 context.Context, arg1 proto.DiskID, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "PunishShardnodeDiskWithThreshold", arg0, arg1, arg2)
}
// PunishShardnodeDiskWithThreshold indicates an expected call of PunishShardnodeDiskWithThreshold.
func (mr *MockServiceControllerMockRecorder) PunishShardnodeDiskWithThreshold(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PunishShardnodeDiskWithThreshold", reflect.TypeOf((*MockServiceController)(nil).PunishShardnodeDiskWithThreshold), arg0, arg1, arg2)
}
// MockVolumeGetter is a mock of VolumeGetter interface.
type MockVolumeGetter struct {
ctrl *gomock.Controller
recorder *MockVolumeGetterMockRecorder
}
// MockVolumeGetterMockRecorder is the mock recorder for MockVolumeGetter.
type MockVolumeGetterMockRecorder struct {
mock *MockVolumeGetter
}
// NewMockVolumeGetter creates a new mock instance.
func NewMockVolumeGetter(ctrl *gomock.Controller) *MockVolumeGetter {
mock := &MockVolumeGetter{ctrl: ctrl}
mock.recorder = &MockVolumeGetterMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockVolumeGetter) EXPECT() *MockVolumeGetterMockRecorder {
return m.recorder
}
// Get mocks base method.
func (m *MockVolumeGetter) Get(arg0 context.Context, arg1 proto.Vid, arg2 bool) *controller.VolumePhy {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", arg0, arg1, arg2)
ret0, _ := ret[0].(*controller.VolumePhy)
return ret0
}
// Get indicates an expected call of Get.
func (mr *MockVolumeGetterMockRecorder) Get(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockVolumeGetter)(nil).Get), arg0, arg1, arg2)
}
// Punish mocks base method.
func (m *MockVolumeGetter) Punish(arg0 context.Context, arg1 proto.Vid, arg2 int) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Punish", arg0, arg1, arg2)
}
// Punish indicates an expected call of Punish.
func (mr *MockVolumeGetterMockRecorder) Punish(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Punish", reflect.TypeOf((*MockVolumeGetter)(nil).Punish), arg0, arg1, arg2)
}
// Update mocks base method.
func (m *MockVolumeGetter) Update(arg0 context.Context, arg1 proto.Vid) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "Update", arg0, arg1)
}
// Update indicates an expected call of Update.
func (mr *MockVolumeGetterMockRecorder) Update(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockVolumeGetter)(nil).Update), arg0, arg1)
}
// MockShardController is a mock of IShardController interface.
type MockShardController struct {
ctrl *gomock.Controller
recorder *MockShardControllerMockRecorder
}
// MockShardControllerMockRecorder is the mock recorder for MockShardController.
type MockShardControllerMockRecorder struct {
mock *MockShardController
}
// NewMockShardController creates a new mock instance.
func NewMockShardController(ctrl *gomock.Controller) *MockShardController {
mock := &MockShardController{ctrl: ctrl}
mock.recorder = &MockShardControllerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockShardController) EXPECT() *MockShardControllerMockRecorder {
return m.recorder
}
// GetFisrtShard mocks base method.
func (m *MockShardController) GetFisrtShard(arg0 context.Context) (controller.Shard, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetFisrtShard", arg0)
ret0, _ := ret[0].(controller.Shard)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetFisrtShard indicates an expected call of GetFisrtShard.
func (mr *MockShardControllerMockRecorder) GetFisrtShard(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetFisrtShard", reflect.TypeOf((*MockShardController)(nil).GetFisrtShard), arg0)
}
// GetNextShard mocks base method.
func (m *MockShardController) GetNextShard(arg0 context.Context, arg1 sharding.Range) (controller.Shard, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetNextShard", arg0, arg1)
ret0, _ := ret[0].(controller.Shard)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetNextShard indicates an expected call of GetNextShard.
func (mr *MockShardControllerMockRecorder) GetNextShard(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNextShard", reflect.TypeOf((*MockShardController)(nil).GetNextShard), arg0, arg1)
}
// GetShard mocks base method.
func (m *MockShardController) GetShard(arg0 context.Context, arg1 []string) (controller.Shard, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetShard", arg0, arg1)
ret0, _ := ret[0].(controller.Shard)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetShard indicates an expected call of GetShard.
func (mr *MockShardControllerMockRecorder) GetShard(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShard", reflect.TypeOf((*MockShardController)(nil).GetShard), arg0, arg1)
}
// GetShardByID mocks base method.
func (m *MockShardController) GetShardByID(arg0 context.Context, arg1 proto.ShardID) (controller.Shard, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetShardByID", arg0, arg1)
ret0, _ := ret[0].(controller.Shard)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetShardByID indicates an expected call of GetShardByID.
func (mr *MockShardControllerMockRecorder) GetShardByID(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShardByID", reflect.TypeOf((*MockShardController)(nil).GetShardByID), arg0, arg1)
}
// GetShardByRange mocks base method.
func (m *MockShardController) GetShardByRange(arg0 context.Context, arg1 sharding.Range) (controller.Shard, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetShardByRange", arg0, arg1)
ret0, _ := ret[0].(controller.Shard)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetShardByRange indicates an expected call of GetShardByRange.
func (mr *MockShardControllerMockRecorder) GetShardByRange(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShardByRange", reflect.TypeOf((*MockShardController)(nil).GetShardByRange), arg0, arg1)
}
// GetShardSubRangeCount mocks base method.
func (m *MockShardController) GetShardSubRangeCount(arg0 context.Context) int {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetShardSubRangeCount", arg0)
ret0, _ := ret[0].(int)
return ret0
}
// GetShardSubRangeCount indicates an expected call of GetShardSubRangeCount.
func (mr *MockShardControllerMockRecorder) GetShardSubRangeCount(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShardSubRangeCount", reflect.TypeOf((*MockShardController)(nil).GetShardSubRangeCount), arg0)
}
// GetSpaceID mocks base method.
func (m *MockShardController) GetSpaceID() proto.SpaceID {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSpaceID")
ret0, _ := ret[0].(proto.SpaceID)
return ret0
}
// GetSpaceID indicates an expected call of GetSpaceID.
func (mr *MockShardControllerMockRecorder) GetSpaceID() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSpaceID", reflect.TypeOf((*MockShardController)(nil).GetSpaceID))
}
// UpdateRoute mocks base method.
func (m *MockShardController) UpdateRoute(arg0 context.Context) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateRoute", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// UpdateRoute indicates an expected call of UpdateRoute.
func (mr *MockShardControllerMockRecorder) UpdateRoute(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateRoute", reflect.TypeOf((*MockShardController)(nil).UpdateRoute), arg0)
}
// UpdateShard mocks base method.
func (m *MockShardController) UpdateShard(arg0 context.Context, arg1 shardnode.ShardStats) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UpdateShard", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// UpdateShard indicates an expected call of UpdateShard.
func (mr *MockShardControllerMockRecorder) UpdateShard(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateShard", reflect.TypeOf((*MockShardController)(nil).UpdateShard), arg0, arg1)
}
// MockShard is a mock of Shard interface.
type MockShard struct {
ctrl *gomock.Controller
recorder *MockShardMockRecorder
}
// MockShardMockRecorder is the mock recorder for MockShard.
type MockShardMockRecorder struct {
mock *MockShard
}
// NewMockShard creates a new mock instance.
func NewMockShard(ctrl *gomock.Controller) *MockShard {
mock := &MockShard{ctrl: ctrl}
mock.recorder = &MockShardMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockShard) EXPECT() *MockShardMockRecorder {
return m.recorder
}
// GetMember mocks base method.
func (m *MockShard) GetMember(arg0 context.Context, arg1 access.GetShardMode, arg2 map[proto.DiskID]struct{}) (controller.ShardOpInfo, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetMember", arg0, arg1, arg2)
ret0, _ := ret[0].(controller.ShardOpInfo)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetMember indicates an expected call of GetMember.
func (mr *MockShardMockRecorder) GetMember(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMember", reflect.TypeOf((*MockShard)(nil).GetMember), arg0, arg1, arg2)
}
// GetRange mocks base method.
func (m *MockShard) GetRange() sharding.Range {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetRange")
ret0, _ := ret[0].(sharding.Range)
return ret0
}
// GetRange indicates an expected call of GetRange.
func (mr *MockShardMockRecorder) GetRange() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRange", reflect.TypeOf((*MockShard)(nil).GetRange))
}
// GetShardID mocks base method.
func (m *MockShard) GetShardID() proto.ShardID {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetShardID")
ret0, _ := ret[0].(proto.ShardID)
return ret0
}
// GetShardID indicates an expected call of GetShardID.
func (mr *MockShardMockRecorder) GetShardID() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetShardID", reflect.TypeOf((*MockShard)(nil).GetShardID))
}

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"context"
@ -118,20 +118,20 @@ type Writer struct {
var _ io.Writer = &Writer{}
func (w *Writer) Write(p []byte) (n int, err error) {
n, err = w.underlying.Write(p)
now := time.Now()
reserve := w.rate.ReserveN(now, n)
reserve := w.rate.ReserveN(now, len(p))
// Wait if necessary
delay := reserve.DelayFrom(now)
if delay == 0 {
n, err = w.underlying.Write(p)
return
}
span := trace.SpanFromContextSafe(w.ctx)
if !reserve.OK() {
span.Warnf("writer exceeds limiter n:%d, burst:%d", n, w.rate.Burst())
span.Warnf("writer exceeds limiter n:%d, burst:%d", len(p), w.rate.Burst())
n, err = w.underlying.Write(p)
return
}
t := time.NewTimer(delay)
@ -143,6 +143,7 @@ func (w *Writer) Write(p []byte) (n int, err error) {
select {
case <-t.C:
// We can proceed.
n, err = w.underlying.Write(p)
return
case <-w.ctx.Done():
// Context was canceled before we could proceed. Cancel the

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"context"

View File

@ -12,12 +12,15 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"os"
"github.com/prometheus/client_golang/prometheus"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc/auditlog"
)
var unhealthMetric = prometheus.NewCounterVec(
@ -40,9 +43,27 @@ var downloadMetric = prometheus.NewCounterVec(
[]string{"cluster", "way", "reason"},
)
var readwriteMetric *prometheus.HistogramVec
var SteamReportDownload = reportDownload
func init() {
prometheus.MustRegister(unhealthMetric)
prometheus.MustRegister(downloadMetric)
hostname, _ := os.Hostname()
readwriteMetric = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: "blobstore",
Subsystem: "access",
Name: "read_write_duration_ms",
Help: "read write duration ms",
Buckets: auditlog.Buckets,
ConstLabels: map[string]string{"host": hostname},
},
[]string{"cluster", "idc", "api"},
)
prometheus.MustRegister(readwriteMetric)
}
func reportUnhealth(cid proto.ClusterID, action, module, host, reason string) {
@ -52,3 +73,8 @@ func reportUnhealth(cid proto.ClusterID, action, module, host, reason string) {
func reportDownload(cid proto.ClusterID, way, reason string) {
downloadMetric.WithLabelValues(cid.ToString(), way, reason).Inc()
}
// upload_read, upload_write, download_read, download_write
func reportReadwrite(cid, idc, api string, ms int64) {
readwriteMetric.WithLabelValues(cid, idc, api).Observe(float64(ms))
}

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"context"
@ -20,12 +20,17 @@ import (
"fmt"
"io"
"strings"
"sync/atomic"
"github.com/afex/hystrix-go/hystrix"
"golang.org/x/sync/singleflight"
"github.com/cubefs/cubefs/blobstore/access/controller"
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/blobnode"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/api/proxy"
"github.com/cubefs/cubefs/blobstore/api/shardnode"
"github.com/cubefs/cubefs/blobstore/common/codemode"
"github.com/cubefs/cubefs/blobstore/common/ec"
"github.com/cubefs/cubefs/blobstore/common/proto"
@ -33,7 +38,6 @@ import (
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/util/defaulter"
"github.com/cubefs/cubefs/blobstore/util/errors"
"github.com/cubefs/cubefs/blobstore/util/log"
"github.com/cubefs/cubefs/blobstore/util/retry"
)
@ -45,6 +49,7 @@ const (
rwCommand = "rw"
serviceProxy = proto.ServiceNameProxy
serviceShard = proto.ServiceNameShardNode
)
// StreamHandler stream http handler
@ -56,7 +61,7 @@ type StreamHandler interface {
// codeMode > 0, alloc in this codemode
// return: a location of file
Alloc(ctx context.Context, size uint64, blobSize uint32,
assignClusterID proto.ClusterID, codeMode codemode.CodeMode) (*access.Location, error)
assignClusterID proto.ClusterID, codeMode codemode.CodeMode) (*proto.Location, error)
// PutAt access interface /putat, put one blob
// required: rc file reader
@ -69,7 +74,9 @@ type StreamHandler interface {
// Put put one object
// required: size, file size
// optional: hasher map to calculate hash.Hash
Put(ctx context.Context, rc io.Reader, size int64, hasherMap access.HasherMap) (*access.Location, error)
// optional: code to specify codemode and not choose codemode by size
Put(ctx context.Context, rc io.Reader, size int64, hasherMap access.HasherMap,
assignClusterID proto.ClusterID, codeMode codemode.CodeMode) (*proto.Location, error)
// Get read file
// required: location, readSize
@ -93,19 +100,35 @@ type StreamHandler interface {
//...
//read-9 [d4 p5]
//failed
Get(ctx context.Context, w io.Writer, location access.Location, readSize, offset uint64) (func() error, error)
Get(ctx context.Context, w io.Writer, location proto.Location, readSize, offset uint64) (func() error, error)
// Delete delete all blobs in this location
Delete(ctx context.Context, location *access.Location) error
Delete(ctx context.Context, location *proto.Location) error
// Admin returns internal admin interface.
Admin() interface{}
Admin() any
// GetBlob returns location
GetBlob(ctx context.Context, args *access.GetBlobArgs) (*proto.Location, error)
// DeleteBlob returns error
DeleteBlob(ctx context.Context, args *access.DelBlobArgs) error
// SealBlob returns error
SealBlob(ctx context.Context, args *access.SealBlobArgs) error
// CreateBlob returns location
CreateBlob(ctx context.Context, args *access.CreateBlobArgs) (*proto.Location, error)
// ListBlob returns blobs
ListBlob(ctx context.Context, args *access.ListBlobArgs) (shardnode.ListBlobRet, error)
// AllocSlice returns alloc blob
AllocSlice(ctx context.Context, args *access.AllocSliceArgs) (shardnode.AllocSliceRet, error)
}
type streamAdmin struct {
config StreamConfig
memPool *resourcepool.MemPool
controller controller.ClusterController
type StreamAdmin struct {
Config StreamConfig
MemPool *resourcepool.MemPool
Controller controller.ClusterController
}
type ShardnodeConfig struct {
shardnode.Config
}
// StreamConfig access stream handler config
@ -113,25 +136,52 @@ type StreamConfig struct {
IDC string `json:"idc"`
MaxBlobSize uint32 `json:"max_blob_size"`
VolumePunishIntervalS int `json:"volume_punish_interval_s"`
DiskPunishIntervalS int `json:"disk_punish_interval_s"`
DiskTimeoutPunishIntervalS int `json:"disk_timeout_punish_interval_s"`
ServicePunishIntervalS int `json:"service_punish_interval_s"`
ServicePunishIntervalS int `json:"service_punish_interval_s"` // just service of proxy
ShardnodePunishIntervalS int `json:"shardnode_punish_interval_s"`
AllocRetryTimes int `json:"alloc_retry_times"`
AllocRetryIntervalMS int `json:"alloc_retry_interval_ms"`
EncoderEnableVerify bool `json:"encoder_enableverify"`
EncoderConcurrency int `json:"encoder_concurrency"`
MinReadShardsX int `json:"min_read_shards_x"`
ShardCrcDisabled bool `json:"shard_crc_disabled"`
ReadDataOnlyTimeoutMS int `json:"read_data_only_timeout_ms"`
ShardCrcWriteDisable bool `json:"shard_crc_write_disable"`
ShardCrcReadEnable bool `json:"shard_crc_read_enable"`
ShardnodeRetryTimes int `json:"shardnode_retry_times"`
ShardnodeRetryIntervalMS int `json:"shardnode_retry_interval_ms"`
LogSlowBaseTimeMS int `json:"log_slow_base_time_ms"`
LogSlowBaseSpeedKB int `json:"log_slow_base_speed_kb"`
LogSlowTimeFator float32 `json:"log_slow_time_fator"`
// DeleteIntoShardnodePercentage roundrobin percentage [1-100]
DeleteIntoShardnodePercentage int64 `json:"delete_into_shardnode_percentage"`
deleteRoundrobin int64 `json:"-"`
// RepairIntoShardnodePercentage roundrobin percentage [1-100]
RepairIntoShardnodePercentage int64 `json:"repair_into_shardnode_percentage"`
repairRoundrobin int64 `json:"-"`
MemPoolSizeClasses map[int]int `json:"mem_pool_size_classes"`
// CodeModesPutQuorums
// just for one AZ is down, cant write quorum in all AZs
CodeModesPutQuorums map[codemode.CodeMode]int `json:"code_mode_put_quorums"`
// CodeModesGetOrdered shards with volume unit order to
// reduce reedsolom's inverted matrix cache
//
// EC24P8 in 1AZ, C(32, 8) = 10518300 matrix
// Inverted matrix memory: (24 + 24*24 + 24*24*8) * 10518300 ~= 51 GB
CodeModesGetOrdered map[codemode.CodeMode]bool `json:"code_mode_get_ordered"`
// CodeModesGetIgnoreIDC no distance when getting cross idc
CodeModesGetIgnoreIDC map[codemode.CodeMode]bool `json:"code_mode_get_ignore_idc"`
ClusterConfig controller.ClusterConfig `json:"cluster_config"`
BlobnodeConfig blobnode.Config `json:"blobnode_config"`
ProxyConfig proxy.Config `json:"proxy_config"`
ClusterConfig controller.ClusterConfig `json:"cluster_config"`
BlobnodeConfig blobnode.Config `json:"blobnode_config"`
ProxyConfig proxy.Config `json:"proxy_config"`
ShardnodeConfig *ShardnodeConfig `json:"shardnode_config"`
// hystrix command config
AllocCommandConfig hystrix.CommandConfig `json:"alloc_command_config"`
@ -160,9 +210,11 @@ type Handler struct {
memPool *resourcepool.MemPool
encoder map[codemode.CodeMode]ec.Encoder
clusterController controller.ClusterController
groupRun singleflight.Group
blobnodeClient blobnode.StorageAPI
proxyClient proxy.Client
blobnodeClient blobnode.StorageAPI
proxyClient proxy.Client
shardnodeClient shardnode.AccessAPI
allCodeModes CodeModePairs
maxObjectSize int64
@ -173,12 +225,12 @@ type Handler struct {
StreamConfig
}
func confCheck(cfg *StreamConfig) {
func confCheck(cfg *StreamConfig) error {
if cfg.IDC == "" {
log.Fatal("idc config can not be null")
return errors.New("idc config can not be null")
}
if cfg.ClusterConfig.ConsulAgentAddr == "" && len(cfg.ClusterConfig.Clusters) == 0 {
log.Panic("consul or clusters can not all be empty")
return errors.New("consul or clusters can not all be empty")
}
cfg.ClusterConfig.IDC = cfg.IDC
@ -189,20 +241,37 @@ func confCheck(cfg *StreamConfig) {
for mode, quorum := range cfg.CodeModesPutQuorums {
tactic := mode.Tactic()
if quorum < tactic.N+tactic.L+1 || quorum > mode.GetShardNum() {
log.Fatalf("invalid put quorum(%d) in codemode(%d): %+v", quorum, mode, tactic)
return errors.Newf("invalid put quorum(%d) in codemode(%d): %+v", quorum, mode, tactic)
}
}
defaulter.Equal(&cfg.MaxBlobSize, defaultMaxBlobSize)
defaulter.IntegerLessOrEqual(&cfg.VolumePunishIntervalS, 60)
defaulter.LessOrEqual(&cfg.DiskPunishIntervalS, defaultDiskPunishIntervalS)
defaulter.LessOrEqual(&cfg.DiskTimeoutPunishIntervalS, defaultDiskPunishIntervalS/10)
defaulter.LessOrEqual(&cfg.ServicePunishIntervalS, defaultServicePunishIntervalS)
defaulter.IntegerLessOrEqual(&cfg.ShardnodePunishIntervalS, 60)
defaulter.LessOrEqual(&cfg.AllocRetryTimes, defaultAllocRetryTimes)
if cfg.AllocRetryIntervalMS <= 100 {
cfg.AllocRetryIntervalMS = defaultAllocRetryIntervalMS
defaulter.LessOrEqual(&cfg.AllocRetryIntervalMS, defaultAllocRetryIntervalMS)
defaulter.LessOrEqual(&cfg.ShardnodeRetryTimes, defaultShardnodeRetryTimes)
if cfg.ShardnodeRetryIntervalMS <= defaultShardnodeRetryIntervalMS {
cfg.ShardnodeRetryIntervalMS = defaultShardnodeRetryIntervalMS
}
defaulter.LessOrEqual(&cfg.EncoderConcurrency, defaultEncoderConcurrency)
defaulter.LessOrEqual(&cfg.MinReadShardsX, defaultMinReadShardsX)
defaulter.LessOrEqual(&cfg.ReadDataOnlyTimeoutMS, 3*1000)
defaulter.LessOrEqual(&cfg.LogSlowBaseTimeMS, 500)
defaulter.Equal(&cfg.LogSlowBaseSpeedKB, 1<<10)
defaulter.LessOrEqual(&cfg.LogSlowTimeFator, float32(2.0))
defaulter.IntegerLess(&cfg.DeleteIntoShardnodePercentage, 0)
if cfg.DeleteIntoShardnodePercentage > 100 {
cfg.DeleteIntoShardnodePercentage = 100
}
defaulter.IntegerLess(&cfg.RepairIntoShardnodePercentage, 0)
if cfg.RepairIntoShardnodePercentage > 100 {
cfg.RepairIntoShardnodePercentage = 100
}
defaulter.LessOrEqual(&cfg.ClusterConfig.CMClientConfig.Config.ClientTimeoutMs, defaultTimeoutClusterMgr)
defaulter.LessOrEqual(&cfg.BlobnodeConfig.ClientTimeoutMs, defaultTimeoutBlobnode)
@ -223,39 +292,60 @@ func confCheck(cfg *StreamConfig) {
defaulter.LessOrEqual(&hc.SleepWindow, defaultBlobnodeSleepWindow)
defaulter.LessOrEqual(&hc.ErrorPercentThreshold, defaultBlobnodeErrorPercentThreshold)
cfg.RWCommandConfig = hc
return nil
}
// NewStreamHandler returns a stream handler
func NewStreamHandler(cfg *StreamConfig, stopCh <-chan struct{}) StreamHandler {
confCheck(cfg)
func NewStreamHandler(cfg *StreamConfig, stopCh <-chan struct{}) (h StreamHandler, e error) {
if e = confCheck(cfg); e != nil {
return nil, e
}
proxyClient := proxy.New(&cfg.ProxyConfig)
clusterController, err := controller.NewClusterController(&cfg.ClusterConfig, proxyClient, stopCh)
if err != nil {
log.Fatalf("new cluster controller failed, err: %v", err)
e = errors.Newf("new cluster controller failed, err: %v", err)
return
}
handler := &Handler{
memPool: resourcepool.NewMemPool(cfg.MemPoolSizeClasses),
clusterController: clusterController,
blobnodeClient: blobnode.New(&cfg.BlobnodeConfig),
proxyClient: proxyClient,
blobnodeClient: blobnode.New(&cfg.BlobnodeConfig),
proxyClient: proxyClient,
shardnodeClient: shardnode.NewNonsupportShardnode(),
maxObjectSize: defaultMaxObjectSize,
StreamConfig: *cfg,
}
if cfg.ShardnodeConfig != nil { // enable shard node
// Do not use rpc retry, because the stream blob handles retries itself
defaulter.LessOrEqual(&cfg.ShardnodeConfig.Config.Retry, int(1))
handler.shardnodeClient = shardnode.New(cfg.ShardnodeConfig.Config)
} else { // disable write delete/repair msg to shardnode
handler.StreamConfig.DeleteIntoShardnodePercentage = 0
handler.StreamConfig.RepairIntoShardnodePercentage = 0
}
if err = clustermgr.LoadExtendCodemode(context.Background(), handler.clusterController); err != nil {
e = errors.Newf("load extend codemode failed, err: %+v", err)
return
}
rawCodeModePolicies, err := handler.clusterController.GetConfig(context.Background(), proto.CodeModeConfigKey)
if err != nil {
log.Fatal("get codemode policy from cluster manager failed, err: ", err)
e = errors.Newf("get codemode policy from cluster manager failed, err: %+v", err)
return
}
codeModePolicies := make([]codemode.Policy, 0)
err = json.Unmarshal([]byte(rawCodeModePolicies), &codeModePolicies)
if err != nil {
log.Fatal("json decode codemode policy failed, err: ", err)
e = errors.Newf("json decode codemode policy failed, err: %+v", err)
return
}
if len(codeModePolicies) <= 0 {
log.Fatal("invalid codemode policy raw: ", rawCodeModePolicies)
e = errors.Newf("invalid codemode policy raw: %s", rawCodeModePolicies)
return
}
allCodeModes := make(CodeModePairs)
@ -277,7 +367,8 @@ func NewStreamHandler(cfg *StreamConfig, stopCh <-chan struct{}) StreamHandler {
Concurrency: cfg.EncoderConcurrency,
})
if err != nil {
log.Fatalf("new encoder failed, err: %v", err)
e = errors.Newf("new encoder failed, err: %v", err)
return
}
encoders[codeMode] = encoder
}
@ -293,22 +384,29 @@ func NewStreamHandler(cfg *StreamConfig, stopCh <-chan struct{}) StreamHandler {
handler.discardVidChan = make(chan discardVid, 8)
handler.stopCh = stopCh
handler.loopDiscardVids()
return handler
return handler, nil
}
// Delete delete all blobs in this location
func (h *Handler) Delete(ctx context.Context, location *access.Location) error {
func (h *Handler) Delete(ctx context.Context, location *proto.Location) error {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("to delete %+v", location)
if h.DeleteIntoShardnodePercentage > 0 {
percentage := (atomic.AddInt64(&h.deleteRoundrobin, 1) % 100) + 1
if percentage <= h.DeleteIntoShardnodePercentage {
span.Debugf("to delete into shardnode %+v", location)
return h.clearGarbageIntoShardnode(ctx, location)
}
}
span.Debugf("to delete into proxy %+v", location)
return h.clearGarbage(ctx, location)
}
// Admin returns internal admin interface.
func (h *Handler) Admin() interface{} {
return &streamAdmin{
config: h.StreamConfig,
memPool: h.memPool,
controller: h.clusterController,
func (h *Handler) Admin() any {
return &StreamAdmin{
Config: h.StreamConfig,
MemPool: h.memPool,
Controller: h.clusterController,
}
}
@ -322,6 +420,15 @@ func (h *Handler) sendRepairMsg(ctx context.Context, blob blobIdent, badIdxes []
span := trace.SpanFromContextSafe(ctx)
span.Infof("to repair %s indexes(%+v)", blob.String(), badIdxes)
if h.RepairIntoShardnodePercentage > 0 {
percentage := (atomic.AddInt64(&h.repairRoundrobin, 1) % 100) + 1
if percentage <= h.RepairIntoShardnodePercentage {
span.Debugf("to repair into shardnode %s", blob.String())
h.sendRepairMsgIntoShardnode(ctx, blob, badIdxes)
return
}
}
clusterID := blob.cid
serviceController, err := h.clusterController.GetServiceController(clusterID)
if err != nil {
@ -338,24 +445,30 @@ func (h *Handler) sendRepairMsg(ctx context.Context, blob blobIdent, badIdxes []
Reason: "access-repair",
}
hosts, err := serviceController.GetServiceHosts(ctx, serviceProxy)
if err != nil {
span.Error(errors.Detail(err))
return
}
for len(hosts) < 3 {
hosts = append(hosts, hosts...)
}
if err := retry.Timed(3, 200).On(func() error {
host, err := serviceController.GetServiceHost(ctx, serviceProxy)
if err != nil {
span.Warn(err)
return err
}
host := hosts[0]
hosts = hosts[1:]
err = h.proxyClient.SendShardRepairMsg(ctx, host, repairArgs)
if err != nil {
if errorTimeout(err) || errorConnectionRefused(err) {
serviceController.PunishServiceWithThreshold(ctx, serviceProxy, host, h.ServicePunishIntervalS)
reportUnhealth(clusterID, "punish", serviceProxy, host, "failed")
} else {
reportUnhealth(clusterID, "repair.msg", serviceProxy, host, "failed")
}
span.Warnf("send to %s repair message(%+v) %s", host, repairArgs, err.Error())
reportUnhealth(clusterID, "punish", serviceProxy, host, "failed")
err = errors.Base(err, host)
}
return err
}); err != nil {
reportUnhealth(clusterID, "repair.msg", serviceProxy, "-", "failed")
span.Errorf("send repair message(%+v) failed %s", repairArgs, errors.Detail(err))
return
}
@ -363,7 +476,7 @@ func (h *Handler) sendRepairMsg(ctx context.Context, blob blobIdent, badIdxes []
span.Infof("send repair message(%+v)", repairArgs)
}
func (h *Handler) clearGarbage(ctx context.Context, location *access.Location) error {
func (h *Handler) clearGarbage(ctx context.Context, location *proto.Location) error {
span := trace.SpanFromContextSafe(ctx)
serviceController, err := h.clusterController.GetServiceController(location.ClusterID)
if err != nil {
@ -384,28 +497,34 @@ func (h *Handler) clearGarbage(ctx context.Context, location *access.Location) e
})
}
var logMsg interface{} = location
var logMsg any = location
if len(deleteArgs.Blobs) <= 20 {
logMsg = deleteArgs
}
hosts, err := serviceController.GetServiceHosts(ctx, serviceProxy)
if err != nil {
span.Error(err)
return err
}
for len(hosts) < 3 {
hosts = append(hosts, hosts...)
}
if err := retry.Timed(3, 200).On(func() error {
host, err := serviceController.GetServiceHost(ctx, serviceProxy)
if err != nil {
span.Warn(err)
return err
}
host := hosts[0]
hosts = hosts[1:]
err = h.proxyClient.SendDeleteMsg(ctx, host, deleteArgs)
if err != nil {
if errorTimeout(err) || errorConnectionRefused(err) {
serviceController.PunishServiceWithThreshold(ctx, serviceProxy, host, h.ServicePunishIntervalS)
reportUnhealth(location.ClusterID, "punish", serviceProxy, host, "failed")
} else {
reportUnhealth(location.ClusterID, "delete.msg", serviceProxy, host, "failed")
}
span.Warnf("send to %s delete message(%+v) %s", host, logMsg, err.Error())
reportUnhealth(location.ClusterID, "punish", serviceProxy, host, "failed")
err = errors.Base(err, host)
}
return err
}); err != nil {
reportUnhealth(location.ClusterID, "delete.msg", serviceProxy, "-", "failed")
span.Errorf("send delete message(%+v) failed %s", logMsg, errors.Detail(err))
return errors.Base(err, "send delete message:", logMsg)
}
@ -420,19 +539,25 @@ func (h *Handler) getVolume(ctx context.Context, clusterID proto.ClusterID, vid
if err != nil {
return nil, err
}
volume := volumeGetter.Get(ctx, vid, isCache)
if volume == nil {
return nil, errors.Newf("not found volume of (%d %d)", clusterID, vid)
}
return volume, nil
}
func (h *Handler) updateVolume(ctx context.Context, clusterID proto.ClusterID, vid proto.Vid) {
volumeGetter, err := h.clusterController.GetVolumeGetter(clusterID)
if err != nil {
return
}
volumeGetter.Update(ctx, vid)
}
func (h *Handler) punishVolume(ctx context.Context, clusterID proto.ClusterID, vid proto.Vid, host, reason string) {
reportUnhealth(clusterID, "punish", "volume", host, reason)
if volumeGetter, err := h.clusterController.GetVolumeGetter(clusterID); err == nil {
volumeGetter.Punish(ctx, vid, h.DiskPunishIntervalS)
volumeGetter.Punish(ctx, vid, h.VolumePunishIntervalS)
}
}
@ -450,16 +575,18 @@ func (h *Handler) punishDiskWith(ctx context.Context, clusterID proto.ClusterID,
}
}
// blobCount blobSize > 0 is certain
func blobCount(size uint64, blobSize uint32) uint64 {
return (size + uint64(blobSize) - 1) / uint64(blobSize)
func (h *Handler) punishShardnodeDisk(ctx context.Context, clusterID proto.ClusterID, diskID proto.DiskID, host, reason string) {
reportUnhealth(clusterID, "punish", "shardnode", host, reason)
if serviceController, err := h.clusterController.GetServiceController(clusterID); err == nil {
serviceController.PunishShardnode(ctx, diskID, h.ShardnodePunishIntervalS)
}
}
func minU64(a, b uint64) uint64 {
if a <= b {
return a
func (h *Handler) punishShardnodeDiskWith(ctx context.Context, clusterID proto.ClusterID, diskID proto.DiskID, host, reason string) {
reportUnhealth(clusterID, "punish", "shardnode", host, reason)
if serviceController, err := h.clusterController.GetServiceController(clusterID); err == nil {
serviceController.PunishShardnodeDiskWithThreshold(ctx, diskID, h.ShardnodePunishIntervalS)
}
return b
}
func errorTimeout(err error) bool {

View File

@ -12,19 +12,21 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"context"
"sync/atomic"
"github.com/afex/hystrix-go/hystrix"
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/proxy"
"github.com/cubefs/cubefs/blobstore/common/codemode"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/util"
"github.com/cubefs/cubefs/blobstore/util/errors"
"github.com/cubefs/cubefs/blobstore/util/retry"
)
@ -39,7 +41,8 @@ var errAllocatePunishedVolume = errors.New("allocate punished volume")
// codeMode > 0, alloc in this codemode
// return: a location of file
func (h *Handler) Alloc(ctx context.Context, size uint64, blobSize uint32,
assignClusterID proto.ClusterID, codeMode codemode.CodeMode) (*access.Location, error) {
assignClusterID proto.ClusterID, codeMode codemode.CodeMode,
) (*proto.Location, error) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("alloc request with size:%d blobsize:%d cluster:%d codemode:%d",
size, blobSize, assignClusterID, codeMode)
@ -54,7 +57,7 @@ func (h *Handler) Alloc(ctx context.Context, size uint64, blobSize uint32,
span.Debugf("fill blobsize:%d", blobSize)
}
if codeMode == 0 {
if codeMode == codemode.CodeModeNone {
codeMode = h.allCodeModes.SelectCodeMode(int64(size))
span.Debugf("select codemode:%d", codeMode)
}
@ -70,19 +73,20 @@ func (h *Handler) Alloc(ctx context.Context, size uint64, blobSize uint32,
}
span.Debugf("allocated from %d %+v", clusterID, blobs)
location := &access.Location{
location := &proto.Location{
ClusterID: clusterID,
CodeMode: codeMode,
Size: size,
BlobSize: blobSize,
Blobs: blobs,
Size_: size,
SliceSize: blobSize,
Slices: blobs,
}
span.Debugf("alloc ok %+v", location)
return location, nil
}
func (h *Handler) allocFromAllocatorWithHystrix(ctx context.Context, codeMode codemode.CodeMode, size uint64, blobSize uint32,
clusterID proto.ClusterID) (cid proto.ClusterID, bidRets []access.SliceInfo, err error) {
func (h *Handler) allocFromAllocatorWithHystrix(ctx context.Context,
codeMode codemode.CodeMode, size uint64, blobSize uint32, clusterID proto.ClusterID,
) (cid proto.ClusterID, bidRets []proto.Slice, err error) {
err = hystrix.Do(allocCommand, func() error {
cid, bidRets, err = h.allocFromAllocator(ctx, codeMode, size, blobSize, clusterID)
return err
@ -90,8 +94,9 @@ func (h *Handler) allocFromAllocatorWithHystrix(ctx context.Context, codeMode co
return
}
func (h *Handler) allocFromAllocator(ctx context.Context, codeMode codemode.CodeMode, size uint64, blobSize uint32,
clusterID proto.ClusterID) (proto.ClusterID, []access.SliceInfo, error) {
func (h *Handler) allocFromAllocator(ctx context.Context,
codeMode codemode.CodeMode, size uint64, blobSize uint32, clusterID proto.ClusterID,
) (proto.ClusterID, []proto.Slice, error) {
span := trace.SpanFromContextSafe(ctx)
if blobSize == 0 {
@ -108,32 +113,28 @@ func (h *Handler) allocFromAllocator(ctx context.Context, codeMode codemode.Code
args := proxy.AllocVolsArgs{
Fsize: size,
CodeMode: codeMode,
BidCount: blobCount(size, blobSize),
BidCount: util.AlignedBlocks(size, uint64(blobSize)),
}
serviceController, err := h.clusterController.GetServiceController(clusterID)
if err != nil {
span.Error(err)
return 0, nil, err
}
hosts, err := serviceController.GetServiceHosts(ctx, serviceProxy)
if err != nil {
span.Error(err)
return 0, nil, err
}
for len(hosts) < h.AllocRetryTimes {
hosts = append(hosts, hosts...)
}
var allocRets []proxy.AllocRet
var allocHost string
hostsSet := make(map[string]struct{}, 1)
if err := retry.ExponentialBackoff(h.AllocRetryTimes, uint32(h.AllocRetryIntervalMS)).On(func() error {
serviceController, err := h.clusterController.GetServiceController(clusterID)
if err != nil {
span.Warn(err)
return errors.Info(err, "get service controller", clusterID)
}
var host string
for range [10]struct{}{} {
host, err = serviceController.GetServiceHost(ctx, serviceProxy)
if err != nil {
span.Warn(err)
return errors.Info(err, "get proxy host", clusterID)
}
if _, ok := hostsSet[host]; ok {
continue
}
hostsSet[host] = struct{}{}
break
}
if err := retry.ExponentialBackoff(h.AllocRetryTimes, uint32(h.AllocRetryIntervalMS)).RuptOn(func() (bool, error) {
host := hosts[0]
hosts = hosts[1:]
allocHost = host
allocRets, err = h.proxyClient.VolumeAlloc(ctx, host, &args)
@ -144,7 +145,10 @@ func (h *Handler) allocFromAllocator(ctx context.Context, codeMode codemode.Code
serviceController.PunishServiceWithThreshold(ctx, serviceProxy, host, h.ServicePunishIntervalS)
}
span.Warn(host, err)
return errors.Base(err, "alloc from proxy", host)
if err == context.Canceled {
return true, err
}
return false, errors.Base(err, "alloc from proxy", host)
}
// filter punished volume in allocating progress
@ -152,18 +156,18 @@ func (h *Handler) allocFromAllocator(ctx context.Context, codeMode codemode.Code
vInfo, err := h.getVolume(ctx, clusterID, ret.Vid, true)
if err != nil {
span.Warn(err)
return err
return false, err
}
if vInfo.IsPunish {
// return err and retry allocate
err = errAllocatePunishedVolume
args.Excludes = append(args.Excludes, vInfo.Vid)
span.Warn("next retry exclude vid:", vInfo.Vid, err)
return err
return false, err
}
}
return nil
return true, nil
}); err != nil {
if err != errAllocatePunishedVolume {
reportUnhealth(clusterID, "allocate", "-", "-", "failed")
@ -178,20 +182,20 @@ func (h *Handler) allocFromAllocator(ctx context.Context, codeMode codemode.Code
setCacheVidHost(clusterID, ret.Vid, allocHost)
}
blobN := blobCount(size, blobSize)
blobs := make([]access.SliceInfo, 0, blobN)
blobN := util.AlignedBlocks(size, uint64(blobSize))
blobs := make([]proto.Slice, 0, blobN)
for _, bidRet := range allocRets {
if blobN <= 0 {
break
}
count := minU64(blobN, uint64(bidRet.BidEnd)-uint64(bidRet.BidStart)+1)
count := util.Min(blobN, uint64(bidRet.BidEnd)-uint64(bidRet.BidStart)+1)
blobN -= count
blobs = append(blobs, access.SliceInfo{
MinBid: bidRet.BidStart,
Vid: bidRet.Vid,
Count: uint32(count),
blobs = append(blobs, proto.Slice{
MinSliceID: bidRet.BidStart,
Vid: bidRet.Vid,
Count: uint32(count),
})
}
if blobN > 0 {

View File

@ -12,9 +12,10 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"context"
"testing"
"time"
@ -32,26 +33,26 @@ func TestAccessStreamAllocBase(t *testing.T) {
require.NoError(t, err)
require.Equal(t, clusterID, loc.ClusterID)
require.Equal(t, codemode.EC6P6, loc.CodeMode)
require.Equal(t, uint64(1<<30), loc.Size)
require.Equal(t, uint32(1<<22), loc.BlobSize)
require.Equal(t, 2, len(loc.Blobs))
require.Equal(t, uint32(1), loc.Blobs[0].Count)
require.Equal(t, uint32((1<<8)-1), loc.Blobs[1].Count)
require.Equal(t, uint64(1<<30), loc.Size_)
require.Equal(t, uint32(1<<22), loc.SliceSize)
require.Equal(t, 2, len(loc.Slices))
require.Equal(t, uint32(1), loc.Slices[0].Count)
require.Equal(t, uint32((1<<8)-1), loc.Slices[1].Count)
}
{
loc, err := streamer.Alloc(ctx(), (1<<30)+1, 0, 0, 0)
require.NoError(t, err)
require.Equal(t, 2, len(loc.Blobs))
require.Equal(t, uint32(1), loc.Blobs[0].Count)
require.Equal(t, uint32(1<<8), loc.Blobs[1].Count)
require.Equal(t, 2, len(loc.Slices))
require.Equal(t, uint32(1), loc.Slices[0].Count)
require.Equal(t, uint32(1<<8), loc.Slices[1].Count)
}
// 1M blobsize
{
loc, err := streamer.Alloc(ctx(), 1<<30, 1<<20, 0, 0)
require.NoError(t, err)
require.Equal(t, 2, len(loc.Blobs))
require.Equal(t, uint32(1), loc.Blobs[0].Count)
require.Equal(t, uint32((1<<10)-1), loc.Blobs[1].Count)
require.Equal(t, 2, len(loc.Slices))
require.Equal(t, uint32(1), loc.Slices[0].Count)
require.Equal(t, uint32((1<<10)-1), loc.Slices[1].Count)
}
// max size + 1
{
@ -68,3 +69,11 @@ func TestAccessStreamAllocBase(t *testing.T) {
require.Error(t, err)
}
}
func TestAccessStreamAllocCanceled(t *testing.T) {
ctxfunc := ctxWithName("TestAccessStreamAllocCanceled")
ctx, cancel := context.WithCancel(ctxfunc())
cancel()
_, err := streamer.Alloc(ctx, 1, 0, 0, 0)
require.ErrorIs(t, err, context.Canceled)
}

View File

@ -0,0 +1,784 @@
package stream
import (
"context"
"fmt"
"sync/atomic"
"time"
"github.com/cubefs/cubefs/blobstore/access/controller"
acapi "github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/shardnode"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/common/sharding"
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/util/errors"
"github.com/cubefs/cubefs/blobstore/util/retry"
)
func (h *Handler) GetBlob(ctx context.Context, args *acapi.GetBlobArgs) (*proto.Location, error) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("get blob args:%+v", *args)
var blob shardnode.GetBlobRet
rerr := retry.ExponentialBackoff(3, 200).RuptOn(func() (bool, error) {
header, err := h.getShardOpHeader(ctx, acapi.GetShardCommonArgs{
ClusterID: args.ClusterID,
BlobName: args.BlobName,
Mode: args.Mode,
})
if err != nil {
return true, err // not retry
}
host, err := h.getShardHost(ctx, args.ClusterID, header.DiskID)
if err != nil {
return true, err
}
blob, err = h.shardnodeClient.GetBlob(ctx, host, shardnode.GetBlobArgs{
Header: header,
Name: args.BlobName,
})
if err != nil {
return h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: header,
clusterID: args.ClusterID,
host: host,
mode: args.Mode,
err: err,
})
}
return true, nil
})
if rerr != nil {
span.Errorf("get blob failed, args:%+v, err:%+v", *args, rerr)
}
return &blob.Blob.Location, rerr
}
func (h *Handler) CreateBlob(ctx context.Context, args *acapi.CreateBlobArgs) (*proto.Location, error) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("create blob args:%+v", *args)
err := h.fixCreateBlobArgs(ctx, args)
if err != nil {
return nil, err
}
var blob shardnode.CreateBlobRet
rerr := retry.ExponentialBackoff(3, 200).RuptOn(func() (bool, error) {
header, err := h.getShardOpHeader(ctx, acapi.GetShardCommonArgs{
ClusterID: args.ClusterID,
BlobName: args.BlobName,
Mode: acapi.GetShardModeLeader,
})
if err != nil {
return true, err
}
host, err := h.getShardHost(ctx, args.ClusterID, header.DiskID)
if err != nil {
return true, err
}
blob, err = h.shardnodeClient.CreateBlob(ctx, host, shardnode.CreateBlobArgs{
Header: header,
Name: args.BlobName,
CodeMode: args.CodeMode,
Size_: args.Size,
SliceSize: args.SliceSize,
})
if err != nil {
return h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: header,
clusterID: args.ClusterID,
host: host,
mode: acapi.GetShardModeLeader,
err: err,
})
}
return true, nil
})
if rerr != nil {
span.Errorf("create blob failed, args:%+v, err:%+v", *args, rerr)
}
return &blob.Blob.Location, rerr
}
func (h *Handler) DeleteBlob(ctx context.Context, args *acapi.DelBlobArgs) error {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("delete blob args:%+v", *args)
rerr := retry.ExponentialBackoff(3, 200).RuptOn(func() (bool, error) {
header, err := h.getShardOpHeader(ctx, acapi.GetShardCommonArgs{
ClusterID: args.ClusterID,
BlobName: args.BlobName,
Mode: acapi.GetShardModeLeader,
})
if err != nil {
return true, err
}
host, err := h.getShardHost(ctx, args.ClusterID, header.DiskID)
if err != nil {
return true, err
}
if err = h.shardnodeClient.DeleteBlob(ctx, host, shardnode.DeleteBlobArgs{
Header: header,
Name: args.BlobName,
}); err != nil {
return h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: header,
clusterID: args.ClusterID,
host: host,
mode: acapi.GetShardModeLeader,
err: err,
})
}
return true, nil
})
if rerr != nil {
span.Errorf("delete blob failed, args:%+v, err:%+v", *args, rerr)
}
return rerr
}
func (h *Handler) SealBlob(ctx context.Context, args *acapi.SealBlobArgs) error {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("seal blob args:%+v", *args)
rerr := retry.ExponentialBackoff(3, 200).RuptOn(func() (bool, error) {
header, err := h.getShardOpHeader(ctx, acapi.GetShardCommonArgs{
ClusterID: args.ClusterID,
BlobName: args.BlobName,
Mode: acapi.GetShardModeLeader,
})
if err != nil {
return true, err
}
host, err := h.getShardHost(ctx, args.ClusterID, header.DiskID)
if err != nil {
return true, err
}
err = h.shardnodeClient.SealBlob(ctx, host, shardnode.SealBlobArgs{
Header: header,
Name: args.BlobName,
Size_: args.Size,
Slices: args.Slices,
})
if err != nil {
return h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: header,
clusterID: args.ClusterID,
host: host,
mode: acapi.GetShardModeLeader,
err: err,
})
}
return true, nil
})
if rerr != nil {
span.Errorf("seal blob failed, args:%+v, err:%+v", *args, rerr)
}
return rerr
}
func (h *Handler) ListBlob(ctx context.Context, args *acapi.ListBlobArgs) (ret shardnode.ListBlobRet, err error) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("list blob args:%+v", *args)
defer func() {
if err != nil {
span.Errorf("list blob failed, args:%+v, err:%+v", *args, err)
}
}()
if args.ShardID != 0 {
return h.listSpecificShard(ctx, args)
}
return h.listManyShards(ctx, args)
}
func (h *Handler) AllocSlice(ctx context.Context, args *acapi.AllocSliceArgs) (shardnode.AllocSliceRet, error) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("alloc blob args:%+v", *args)
var slices shardnode.AllocSliceRet
rerr := retry.ExponentialBackoff(3, 200).RuptOn(func() (bool, error) {
header, err := h.getShardOpHeader(ctx, acapi.GetShardCommonArgs{
ClusterID: args.ClusterID,
BlobName: args.BlobName,
Mode: acapi.GetShardModeLeader,
})
if err != nil {
return true, err
}
host, err := h.getShardHost(ctx, args.ClusterID, header.DiskID)
if err != nil {
return true, err
}
slices, err = h.shardnodeClient.AllocSlice(ctx, host, shardnode.AllocSliceArgs{
Header: header,
Name: args.BlobName,
CodeMode: args.CodeMode,
Size_: args.Size,
FailedSlice: args.FailSlice,
})
if err != nil {
return h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: header,
clusterID: args.ClusterID,
host: host,
mode: acapi.GetShardModeLeader,
err: err,
})
}
return true, nil
})
if rerr != nil {
span.Errorf("alloc slice failed, args:%+v, err:%+v", *args, rerr)
}
return slices, rerr
}
func (h *Handler) listSpecificShard(ctx context.Context, args *acapi.ListBlobArgs) (shardnode.ListBlobRet, error) {
span := trace.SpanFromContextSafe(ctx)
var ret shardnode.ListBlobRet
rerr := retry.ExponentialBackoff(3, 200).RuptOn(func() (bool, error) {
header, err := h.getOpHeaderByID(ctx, args.ClusterID, args.ShardID, args.Mode)
if err != nil {
return true, err
}
interrupt := false
ret, interrupt, err = h.listSingleShardEnough(ctx, args, header)
span.Debugf("list blob, shardID=%d, interrupt:%t, length:%d, err:%+v", args.ShardID, interrupt, len(ret.Blobs), err)
if err != nil {
return interrupt, err
}
return true, nil
})
return ret, rerr
}
func (h *Handler) listManyShards(ctx context.Context, args *acapi.ListBlobArgs) (shardnode.ListBlobRet, error) {
span := trace.SpanFromContextSafe(ctx)
shardMgr, err := h.clusterController.GetShardController(args.ClusterID)
if err != nil {
return shardnode.ListBlobRet{}, err
}
var (
shard controller.Shard
allBlob shardnode.ListBlobRet
)
if len(args.Marker) == 0 {
shard, err = shardMgr.GetFisrtShard(ctx)
if err != nil {
return shardnode.ListBlobRet{}, err
}
} else {
unionMarker := acapi.ListBlobEncodeMarker{}
if err = unionMarker.UnmarshalFromString(args.Marker); err != nil {
return shardnode.ListBlobRet{}, fmt.Errorf("fail to unmarshal marker, err: %+v", err)
}
allBlob.NextMarker = unionMarker.Marker
shard, err = shardMgr.GetShardByRange(ctx, unionMarker.Range)
if err != nil {
return shardnode.ListBlobRet{}, err
}
span.Debugf("list blob at multi shards, prefix=%s, range=%s, marker=%s", args.Prefix, unionMarker.Range.String(), unionMarker.Marker)
}
lastRange := shard.GetRange()
count := int64(args.Count)
for count > 0 {
var ret shardnode.ListBlobRet
interrupt := false
rerr := retry.ExponentialBackoff(3, 200).RuptOn(func() (bool, error) {
header, err := h.getOpHeaderByShard(ctx, shardMgr, shard, args.Mode)
if err != nil {
return interrupt, err
}
args.Marker = allBlob.NextMarker
args.Count = uint64(count)
ret, interrupt, err = h.listSingleShardEnough(ctx, args, header)
span.Debugf("list blob, shardID=%d, interrupt:%t, length:%d, err:%+v", args.ShardID, interrupt, len(ret.Blobs), err)
if err != nil {
return interrupt, err
}
return true, nil
})
if rerr != nil {
return shardnode.ListBlobRet{}, rerr
}
allBlob.Blobs = append(allBlob.Blobs, ret.Blobs...)
allBlob.NextMarker = ret.NextMarker
count -= int64(len(ret.Blobs))
if ret.NextMarker == "" {
shard, err = shardMgr.GetNextShard(ctx, lastRange)
if err != nil {
return shardnode.ListBlobRet{}, err
}
// err == nil && shard == nil, means last shard, reach end
if shard == nil {
lastRange = sharding.Range{}
break // reach end
}
lastRange = shard.GetRange()
}
}
// reach end, don't need marshal
if len(allBlob.NextMarker) == 0 && lastRange.Type == 0 {
return allBlob, nil
}
markers := acapi.ListBlobEncodeMarker{
Range: lastRange, // empty, means reach the end; else, means next expect shard
Marker: allBlob.NextMarker, // empty, means current shard list end; else, means expect begin blob name
}
unionMarker, err := markers.MarshalToString()
allBlob.NextMarker = unionMarker
return allBlob, err
}
func (h *Handler) listSingleShardEnough(ctx context.Context, args *acapi.ListBlobArgs, header shardnode.ShardOpHeader) (shardnode.ListBlobRet, bool, error) {
host, err := h.getShardHost(ctx, args.ClusterID, header.DiskID)
if err != nil {
return shardnode.ListBlobRet{}, true, err
}
ret, err := h.shardnodeClient.ListBlob(ctx, host, shardnode.ListBlobArgs{
Header: header,
Prefix: args.Prefix,
Marker: args.Marker,
Count: args.Count,
})
if err != nil {
interrupt, err1 := h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: header,
clusterID: args.ClusterID,
host: host,
mode: args.Mode,
err: err,
})
return shardnode.ListBlobRet{}, interrupt, err1
}
return ret, true, nil
}
func (h *Handler) getShardOpHeader(ctx context.Context, args acapi.GetShardCommonArgs) (shardnode.ShardOpHeader, error) {
shardMgr, err := h.clusterController.GetShardController(args.ClusterID)
if err != nil {
return shardnode.ShardOpHeader{}, err
}
shardKeys := shardnode.DecodeShardKeys(args.BlobName, shardMgr.GetShardSubRangeCount(ctx))
shard, err := shardMgr.GetShard(ctx, shardKeys)
if err != nil {
return shardnode.ShardOpHeader{}, err
}
oh, err := h.getOpHeaderByShard(ctx, shardMgr, shard, args.Mode)
return oh, err
}
func (h *Handler) getOpHeaderByID(ctx context.Context, clusterID proto.ClusterID, shardID proto.ShardID, mode acapi.GetShardMode) (shardnode.ShardOpHeader, error) {
shardMgr, err := h.clusterController.GetShardController(clusterID)
if err != nil {
return shardnode.ShardOpHeader{}, err
}
shard, err := shardMgr.GetShardByID(ctx, shardID)
if err != nil {
return shardnode.ShardOpHeader{}, err
}
return h.getOpHeaderByShard(ctx, shardMgr, shard, mode)
}
func (h *Handler) getOpHeaderByShard(ctx context.Context, shardMgr controller.IShardController, shard controller.Shard,
mode acapi.GetShardMode,
) (shardnode.ShardOpHeader, error) {
span := trace.SpanFromContextSafe(ctx)
spaceID := shardMgr.GetSpaceID()
info, err := shard.GetMember(ctx, mode, nil)
if err != nil {
return shardnode.ShardOpHeader{}, err
}
oh := shardnode.ShardOpHeader{
SpaceID: spaceID,
DiskID: info.DiskID,
Suid: info.Suid,
RouteVersion: info.RouteVersion,
}
span.Debugf("shard op header: %+v", oh)
return oh, nil
}
func (h *Handler) getShardHost(ctx context.Context, clusterID proto.ClusterID, diskID proto.DiskID) (string, error) {
span := trace.SpanFromContextSafe(ctx)
s, err := h.clusterController.GetServiceController(clusterID)
if err != nil {
return "", err
}
hostInfo, err := s.GetShardnodeHost(ctx, diskID)
if err != nil {
return "", err
}
span.Debugf("get shard host:%+v", *hostInfo)
return hostInfo.Host, nil
}
type punishArgs struct {
shardnode.ShardOpHeader
clusterID proto.ClusterID
host string
mode acapi.GetShardMode
exclude map[proto.DiskID]struct{}
err error
}
func (h *Handler) punishAndUpdate(ctx context.Context, args *punishArgs) (bool, error) {
span := trace.SpanFromContextSafe(ctx)
// This error is coming from the shardnode interface, and we want to make sure that the error can be parsed into an error code
code := rpc.DetectStatusCode(args.err)
// leader disk status: normal->EIO->broken->repairing->repaired. it greater than broken will mark punished
// if bad disk(punished), we select another disk as leader; old leader is not in disk units, after update route(replace suid index unit)
// and then call sn return NoLeader, and we fetch and update new leader shard
// 1. old leader: repaired(eio, or status >= broken), sn will remove disk and return DiskNotFound, update route
// 2. old leader: broken(eio, broken, repairing), sn return DiskBroken
// cm catalog units is always correct, but its leaderDiskID may be wrong
switch code {
case errcode.CodeDiskBroken: // read shard at bad disk, but shard/disk is reparing
// if follow node broken disk, it will not election, just try again, change other shard;
// if leader node broken disk, it cant get shard stats, wait new leader
h.punishShardnodeDisk(ctx, args.clusterID, args.DiskID, args.host, "Broken")
if args.mode == acapi.GetShardModeLeader {
err1 := h.updateLeaderFromNewHost(ctx, args)
if err1 != nil {
span.Warnf("fail to change other shard node, cluster:%d, err:%+v", args.clusterID, err1)
}
}
return false, args.err
// update route and punish
case errcode.CodeShardNodeDiskNotFound: // read shard at bad disk, but old broken disk is repaired, all shard repaired
h.punishShardnodeDisk(ctx, args.clusterID, args.DiskID, args.host, "NotFound")
if err1 := h.updateShardRoute(ctx, args.clusterID); err1 != nil {
span.Warnf("fail to update shard route, cluster:%d, err:%+v", args.clusterID, err1)
}
return false, args.err
// update route
case errcode.CodeShardDoesNotExist, // intermediate state disk, not a final state; shard is removed, disk is repairing/repaired ; suid not match disk id
errcode.CodeShardRouteVersionNeedUpdate: // header op version less than shardnode version
if err1 := h.updateShardRoute(ctx, args.clusterID); err1 != nil {
span.Warnf("fail to update shard route, cluster:%d, err:%+v", args.clusterID, err1)
}
return false, args.err
// select master
case errcode.CodeShardNodeNotLeader: // leader disk id error when create/delete/seal
if err1 := h.updateLeaderFromNewHost(ctx, args); err1 != nil {
span.Warnf("fail to update leader and shard info, cluster:%d, err:%+v", args.clusterID, err1)
}
return false, args.err
default:
}
// err:dial tcp 127.0.0.1:9100: connect: connection refused code:500
if errorConnectionRefused(args.err) {
span.Warnf("shardnode connection refused/timeout, args:%+v, err:%+v", *args, args.err)
h.groupRun.Do("shardnode-leader-"+args.DiskID.ToString(), func() (interface{}, error) {
// must wait have master leader, block wait
h.punishShardnodeDisk(ctx, args.clusterID, args.DiskID, args.host, "Refused")
err1 := h.updateLeaderFromNewHost(ctx, args)
if err1 != nil {
span.Warnf("fail to change other shard node, cluster:%d, err:%+v", args.clusterID, err1)
}
return nil, err1
})
return false, errcode.ErrConnectionRefused
}
if errorTimeout(args.err) {
h.punishShardnodeDiskWith(ctx, args.clusterID, args.DiskID, args.host, "Timeout")
return false, args.err
}
// eio or other error; if shardNode restarts quickly so wait for it to start, and try again
return false, args.err
}
func (h *Handler) updateShardRoute(ctx context.Context, clusterID proto.ClusterID) error {
shardMgr, err := h.clusterController.GetShardController(clusterID)
if err != nil {
return err
}
return shardMgr.UpdateRoute(ctx)
}
// updateLeaderFromCurrentHost from old current shard host/disk, get leader and update shard
func (h *Handler) updateLeaderFromCurrentHost(ctx context.Context, args *punishArgs) error {
shardMgr, err := h.clusterController.GetShardController(args.clusterID)
if err != nil {
return err
}
shardStat, err := h.getLeaderShardInfo(ctx, args.clusterID, args.host, args.DiskID, args.Suid, 0)
if err != nil {
return err
}
return shardMgr.UpdateShard(ctx, shardStat)
}
// updateLeaderFromNewHost from other shard host/disk, get leader and update shard
func (h *Handler) updateLeaderFromNewHost(ctx context.Context, args *punishArgs) error {
shardMgr, err := h.clusterController.GetShardController(args.clusterID)
if err != nil {
return err
}
shard, err := shardMgr.GetShardByID(ctx, args.Suid.ShardID())
if err != nil {
return err
}
if args.exclude == nil {
args.exclude = make(map[proto.DiskID]struct{})
args.exclude[args.DiskID] = struct{}{}
}
// we get new disk, exclude bad diskID
newDisk, err := shard.GetMember(ctx, acapi.GetShardModeRandom, args.exclude)
if err != nil {
return err
}
newHost, err := h.getShardHost(ctx, args.clusterID, newDisk.DiskID)
if err != nil {
return err
}
// span := trace.SpanFromContextSafe(ctx)
// span.Debugf("get newDisk:%+v, old host:%s, old disk:%d", newDisk, args.host, args.DiskID)
shardStat, err := h.getLeaderShardInfo(ctx, args.clusterID, newHost, newDisk.DiskID, newDisk.Suid, args.DiskID)
if err != nil {
args.exclude[newDisk.DiskID] = struct{}{}
return err
}
return shardMgr.UpdateShard(ctx, shardStat)
}
func (h *Handler) getLeaderShardInfo(ctx context.Context, clusterID proto.ClusterID, host string, diskID proto.DiskID, suid proto.Suid, badDisk proto.DiskID) (shardnode.ShardStats, error) {
span := trace.SpanFromContextSafe(ctx)
for i := 0; i < h.ShardnodeRetryTimes; i++ {
// 1. get leader info
leader, err := h.shardnodeClient.GetShardStats(ctx, host, shardnode.GetShardArgs{
DiskID: diskID,
Suid: suid,
})
if err != nil {
if code := rpc.DetectStatusCode(err); code == errcode.CodeShardNoLeader {
span.Warnf("shard node is in the election, host:%s, disk:%d, suid:%d, badDisk:%d", host, diskID, suid, badDisk)
time.Sleep(time.Millisecond * time.Duration(h.ShardnodeRetryIntervalMS))
continue
}
return shardnode.ShardStats{}, err
}
// skip bad host. LeaderDiskID is 0 means in the election. bad disk is last leader, not start election yet
if leader.LeaderDiskID == 0 || leader.LeaderDiskID == badDisk {
span.Warnf("shard node is in the election, host:%s, disk:%d, suid:%d, badDisk:%d", host, diskID, suid, badDisk)
time.Sleep(time.Millisecond * time.Duration(h.ShardnodeRetryIntervalMS))
continue
}
return leader, nil
}
return shardnode.ShardStats{}, errcode.ErrShardNoLeader
}
func (h *Handler) fixCreateBlobArgs(ctx context.Context, args *acapi.CreateBlobArgs) error {
span := trace.SpanFromContextSafe(ctx)
if int64(args.Size) > h.maxObjectSize {
span.Info("exceed max object size", h.maxObjectSize)
return errcode.ErrAccessExceedSize
}
if args.SliceSize == 0 {
args.SliceSize = atomic.LoadUint32(&h.MaxBlobSize)
span.Debugf("fill slice size:%d", args.SliceSize)
}
if args.CodeMode == 0 {
args.CodeMode = h.allCodeModes.SelectCodeMode(int64(args.Size))
span.Debugf("select codemode:%d", args.CodeMode)
}
if !args.CodeMode.IsValid() {
span.Infof("invalid codemode:%d", args.CodeMode)
return errcode.ErrIllegalArguments
}
if args.ClusterID == 0 {
cluster, err := h.clusterController.ChooseOne()
if err != nil {
return err
}
args.ClusterID = cluster.ClusterID
span.Debugf("choose cluster[%+v]", cluster)
}
return nil
}
func (h *Handler) getRepairMessageShardnode(ctx context.Context,
shardController controller.IShardController, clusterID proto.ClusterID, blob blobIdent, badIdxes []uint8,
) (args shardnode.RepairSliceArgs, host string, err error) {
args.Vid = blob.vid
args.Bid = blob.bid
args.Reason = "access-repair"
for _, idx := range badIdxes {
args.BadIdx = append(args.BadIdx, uint32(idx))
}
tagNum := shardController.GetShardSubRangeCount(ctx)
var shard controller.Shard
shard, err = shardController.GetShard(ctx, args.GetShardKeys(tagNum))
if err != nil {
return
}
args.Header, err = h.getOpHeaderByShard(ctx, shardController, shard, acapi.GetShardModeLeader)
if err != nil {
return
}
host, err = h.getShardHost(ctx, clusterID, args.Header.DiskID)
return
}
func (h *Handler) sendRepairMsgIntoShardnode(ctx context.Context, blob blobIdent, badIdxes []uint8) {
span := trace.SpanFromContextSafe(ctx)
clusterID := blob.cid
shardController, err := h.clusterController.GetShardController(clusterID)
if err != nil {
span.Error(errors.Detail(err))
return
}
if err := retry.Timed(3, 100).On(func() error {
args, host, err := h.getRepairMessageShardnode(ctx, shardController, clusterID, blob, badIdxes)
if err != nil {
reportUnhealth(clusterID, "repair.msg", serviceShard, "-", "failed")
span.Warn(err)
return err
}
if err = h.shardnodeClient.RepairSlice(ctx, host, args); err != nil {
span.Warnf("send to shardnode %s repair message(%+v) %s", host, args, err.Error())
reportUnhealth(clusterID, "repair.msg", serviceShard, host, "failed")
_, err = h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: args.Header,
clusterID: clusterID,
host: host,
mode: acapi.GetShardModeLeader,
err: err,
})
err = errors.Base(err, host)
}
return err
}); err != nil {
span.Errorf("send shardnode repair message(%+v) failed %s", blob, errors.Detail(err))
return
}
span.Infof("send shardnode repair message(%+v)", blob)
}
func (h *Handler) getDeleteMessageShardnode(ctx context.Context,
shardController controller.IShardController, clusterID proto.ClusterID, slice proto.Slice,
) (args shardnode.DeleteBlobRawArgs, host string, err error) {
args.Slice = slice
tagNum := shardController.GetShardSubRangeCount(ctx)
var shard controller.Shard
shard, err = shardController.GetShard(ctx, args.GetShardKeys(tagNum))
if err != nil {
return
}
args.Header, err = h.getOpHeaderByShard(ctx, shardController, shard, acapi.GetShardModeLeader)
if err != nil {
return
}
host, err = h.getShardHost(ctx, clusterID, args.Header.DiskID)
return
}
func (h *Handler) clearGarbageIntoShardnode(ctx context.Context, location *proto.Location) error {
span := trace.SpanFromContextSafe(ctx)
shardController, err := h.clusterController.GetShardController(location.ClusterID)
if err != nil {
span.Error(errors.Detail(err))
return errors.Base(err, "clear location:", *location)
}
clusterID := location.ClusterID
for _, slice := range location.Slices {
if err := retry.Timed(3, 100).On(func() error {
args, host, err := h.getDeleteMessageShardnode(ctx, shardController, clusterID, slice)
if err != nil {
reportUnhealth(clusterID, "delete.msg", serviceShard, "-", "failed")
span.Warn(err)
return err
}
if err = h.shardnodeClient.DeleteBlobRaw(ctx, host, args); err != nil {
span.Warnf("send to shardnode %s delete message(%+v) %s", host, slice, err.Error())
reportUnhealth(clusterID, "delete.msg", serviceShard, host, "failed")
_, err = h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: args.Header,
clusterID: clusterID,
host: host,
mode: acapi.GetShardModeLeader,
err: err,
})
err = errors.Base(err, host)
}
return err
}); err != nil {
span.Errorf("send shardnode delete message(%+v) failed %s", slice, errors.Detail(err))
return errors.Base(err, "send shardnode delete message:", slice)
}
}
span.Infof("send shardnode delete message(%+v)", location)
return nil
}

View File

@ -0,0 +1,568 @@
package stream
import (
"context"
"errors"
"io"
"math"
"strings"
"testing"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/require"
"github.com/cubefs/cubefs/blobstore/access/controller"
acapi "github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/api/shardnode"
"github.com/cubefs/cubefs/blobstore/common/codemode"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/sharding"
"github.com/cubefs/cubefs/blobstore/testing/mocks"
)
func newStreamHandlerSuccess(t *testing.T) *Handler {
ctr := gomock.NewController(t)
gAny := gomock.Any()
info := controller.ShardOpInfo{
DiskID: 101,
Suid: proto.EncodeSuid(1, 0, 1),
RouteVersion: 1,
}
shardInfo := NewMockShard(ctr)
shardInfo.EXPECT().GetMember(gAny, gAny, gAny).Return(info, nil).AnyTimes()
shardMgr := NewMockShardController(ctr)
shardMgr.EXPECT().GetShard(gAny, gAny).Return(shardInfo, nil).AnyTimes()
shardMgr.EXPECT().GetSpaceID().Return(proto.SpaceID(1)).AnyTimes()
shardMgr.EXPECT().UpdateRoute(gAny).Return(nil).AnyTimes()
shardMgr.EXPECT().GetShardSubRangeCount(gAny).Return(2).AnyTimes()
svrCtrl := NewMockServiceController(ctr)
svrCtrl.EXPECT().GetShardnodeHost(gAny, gAny).Return(&controller.HostIDC{Host: "host"}, nil).AnyTimes()
clu := NewMockClusterController(ctr)
clu.EXPECT().GetShardController(gAny).Return(shardMgr, nil).AnyTimes()
clu.EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).AnyTimes()
shardCli := mocks.NewMockShardnodeAccess(ctr)
proxyClient := mocks.NewMockProxyClient(ctr)
allCodeModes := CodeModePairs{
codemode.EC3P3: CodeModePair{
Policy: codemode.Policy{
ModeName: codemode.EC3P3.Name(),
MaxSize: math.MaxInt64,
Enable: true,
},
Tactic: codemode.EC3P3.Tactic(),
},
}
handler := &Handler{
clusterController: clu,
shardnodeClient: shardCli,
proxyClient: proxyClient,
maxObjectSize: 100,
allCodeModes: allCodeModes,
}
return handler
}
func TestStreamBlobGet(t *testing.T) {
ctx := context.Background()
ctr := gomock.NewController(t)
gAny := gomock.Any()
info := controller.ShardOpInfo{}
shardInfo := NewMockShard(ctr)
shardInfo.EXPECT().GetMember(gAny, gAny, gAny).Return(info, nil).Times(2)
shardMgr := NewMockShardController(ctr)
shardMgr.EXPECT().GetShard(gAny, gAny).Return(shardInfo, nil).Times(2)
shardMgr.EXPECT().GetSpaceID().Return(proto.SpaceID(1)).Times(2)
shardMgr.EXPECT().UpdateRoute(gAny).Return(nil)
shardMgr.EXPECT().GetShardSubRangeCount(gAny).Return(2).AnyTimes()
svrCtrl := NewMockServiceController(ctr)
svrCtrl.EXPECT().GetShardnodeHost(gAny, gAny).Return(&controller.HostIDC{Host: "host"}, nil).Times(2)
clu := NewMockClusterController(ctr)
clu.EXPECT().GetShardController(gAny).Return(shardMgr, nil).Times(3)
clu.EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).Times(2)
blobName := "blob1"
blob := &proto.Blob{
Name: blobName,
Location: proto.Location{
ClusterID: 1,
CodeMode: codemode.EC3P3,
Size_: 1,
SliceSize: 1,
Crc: 1,
Slices: nil,
},
}
ret := shardnode.GetBlobRet{
Blob: *blob,
}
shardCli := mocks.NewMockShardnodeAccess(ctr)
shardCli.EXPECT().GetBlob(gAny, gAny, gAny).Return(ret, errcode.ErrShardRouteVersionNeedUpdate)
shardCli.EXPECT().GetBlob(gAny, gAny, gAny).Return(ret, nil)
handler := &Handler{
clusterController: clu,
shardnodeClient: shardCli,
}
args := acapi.GetBlobArgs{
BlobName: string(blobName),
Mode: acapi.GetShardModeRandom,
}
loc, err := handler.GetBlob(ctx, &args)
require.NoError(t, err)
require.Equal(t, ret.Blob.Location, *loc)
}
func TestStreamBlobCreate(t *testing.T) {
ctx := context.Background()
gAny := gomock.Any()
h := newStreamHandlerSuccess(t)
args := acapi.CreateBlobArgs{
BlobName: ("blob-create"),
CodeMode: 0,
ClusterID: 0,
Size: 10,
SliceSize: 4,
}
ret := shardnode.CreateBlobRet{
Blob: proto.Blob{
Name: "blob-create",
Location: proto.Location{
ClusterID: 1,
CodeMode: codemode.EC3P3,
Size_: 10,
SliceSize: 4,
Crc: 1,
Slices: nil,
},
},
}
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().CreateBlob(gAny, gAny, gAny).Return(ret, errcode.ErrShardRouteVersionNeedUpdate)
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().CreateBlob(gAny, gAny, gAny).Return(ret, nil)
h.clusterController.(*MockClusterController).EXPECT().ChooseOne().Return(&clustermgr.ClusterInfo{
ClusterID: 1,
}, nil)
loc, err := h.CreateBlob(ctx, &args)
require.NoError(t, err)
require.Equal(t, ret.Blob.Location, *loc)
}
func TestStreamBlobDelete(t *testing.T) {
ctx := context.Background()
gAny := gomock.Any()
h := newStreamHandlerSuccess(t)
args := acapi.DelBlobArgs{ClusterID: 1, BlobName: "blob-del"}
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().DeleteBlob(gAny, gAny, gAny).Return(errcode.ErrShardRouteVersionNeedUpdate)
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().DeleteBlob(gAny, gAny, gAny).Return(nil)
require.NoError(t, h.DeleteBlob(ctx, &args))
}
func TestStreamBlobDeleteRaw(t *testing.T) {
ctx, gAny := context.Background(), gomock.Any()
h := newStreamHandlerSuccess(t)
h.StreamConfig.DeleteIntoShardnodePercentage = 100
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().DeleteBlobRaw(gAny, gAny, gAny).Return(errcode.ErrUnexpected).Times(3)
require.Error(t, h.Delete(ctx, &proto.Location{Slices: []proto.Slice{{}, {}}}))
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().DeleteBlobRaw(gAny, gAny, gAny).Return(nil).Times(2)
require.NoError(t, h.Delete(ctx, &proto.Location{Slices: []proto.Slice{{}, {}}}))
}
func TestStreamBlobSeal(t *testing.T) {
ctx := context.Background()
gAny := gomock.Any()
h := newStreamHandlerSuccess(t)
args := acapi.SealBlobArgs{
BlobName: ("blob-seal"),
ClusterID: 1,
Slices: make([]proto.Slice, 1),
}
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().SealBlob(gAny, gAny, gAny).Return(errcode.ErrShardRouteVersionNeedUpdate)
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().SealBlob(gAny, gAny, gAny).Return(nil)
err := h.SealBlob(ctx, &args)
require.NoError(t, err)
}
func TestStreamBlobList(t *testing.T) {
ctx := context.Background()
gAny := gomock.Any()
errMock := errors.New("fake error")
ctr := gomock.NewController(t)
info := controller.ShardOpInfo{
DiskID: 101,
Suid: proto.EncodeSuid(1, 0, 1),
RouteVersion: 1,
}
shardInfo := NewMockShard(ctr)
shardInfo.EXPECT().GetMember(gAny, gAny, gAny).Return(info, nil).Times(3)
shardMgr := NewMockShardController(ctr)
shardMgr.EXPECT().GetShardByID(gAny, gAny).Return(shardInfo, nil).Times(3)
shardMgr.EXPECT().GetSpaceID().Return(proto.SpaceID(1)).Times(3)
shardMgr.EXPECT().UpdateRoute(gAny).Return(nil).Times(3)
shardMgr.EXPECT().GetShardSubRangeCount(gAny).Return(2).AnyTimes()
svrCtrl := NewMockServiceController(ctr)
svrCtrl.EXPECT().GetShardnodeHost(gAny, gAny).Return(&controller.HostIDC{Host: "host"}, nil).Times(3)
clu := NewMockClusterController(ctr)
clu.EXPECT().GetShardController(gAny).Return(shardMgr, nil).Times(3 * 2)
clu.EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).Times(3)
h := &Handler{
clusterController: clu,
shardnodeClient: mocks.NewMockShardnodeAccess(ctr),
}
args := acapi.ListBlobArgs{
ClusterID: 1,
ShardID: 1,
Prefix: ("test-"),
Marker: ("test-blob-1"),
Count: 4,
}
// list one shard
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().ListBlob(gAny, gAny, gAny).Return(shardnode.ListBlobRet{}, errcode.ErrShardRouteVersionNeedUpdate).Times(3)
ret, err := h.ListBlob(ctx, &args)
require.NotNil(t, err)
require.ErrorIs(t, err, errcode.ErrShardRouteVersionNeedUpdate)
require.Equal(t, 0, len(ret.Blobs))
// list one shard, 3 blob
shardInfo.EXPECT().GetMember(gAny, gAny, gAny).Return(info, nil)
shardMgr.EXPECT().GetShardByID(gAny, gAny).Return(shardInfo, nil)
shardMgr.EXPECT().GetSpaceID().Return(proto.SpaceID(1))
svrCtrl.EXPECT().GetShardnodeHost(gAny, gAny).Return(&controller.HostIDC{Host: "host"}, nil)
clu.EXPECT().GetShardController(gAny).Return(shardMgr, nil)
clu.EXPECT().GetServiceController(gAny).Return(svrCtrl, nil)
listRet := shardnode.ListBlobRet{
Blobs: []proto.Blob{
{Name: "test-blob-1"},
{Name: "test-blob-2"},
{Name: "test-blob-3"},
},
NextMarker: "",
}
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().ListBlob(gAny, gAny, gAny).Return(listRet, nil)
ret, err = h.ListBlob(ctx, &args)
require.NoError(t, err)
require.Equal(t, "", ret.NextMarker) // require.Equal(t, []byte(nil), ret.NextMarker)
require.Equal(t, 3, len(ret.Blobs))
// list all
shards := make([]controller.Shard, 4)
ranges := sharding.InitShardingRange(sharding.RangeType_RangeTypeHash, 1, 3)
for i := range shards {
shards[i] = NewMockShard(ctr)
shards[i].(*MockShard).EXPECT().GetShardID().Return(proto.ShardID(i + 1)).AnyTimes()
shards[i].(*MockShard).EXPECT().GetRange().Return(*ranges[i]).AnyTimes()
shards[i].(*MockShard).EXPECT().GetMember(gAny, gAny, gAny).Return(info, nil).AnyTimes()
}
shardMgr.EXPECT().GetFisrtShard(gAny).Return(shards[0], nil).Times(1)
shardMgr.EXPECT().GetNextShard(gAny, gAny).Return(shards[1], nil)
shardMgr.EXPECT().GetNextShard(gAny, gAny).Return(shards[2], nil)
shardMgr.EXPECT().GetSpaceID().Return(proto.SpaceID(1)).Times(2)
svrCtrl.EXPECT().GetShardnodeHost(gAny, gAny).Return(&controller.HostIDC{Host: "host"}, nil).Times(2)
h.clusterController.(*MockClusterController).EXPECT().GetShardController(gAny).Return(shardMgr, nil).Times(1)
h.clusterController.(*MockClusterController).EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).Times(2)
listRet = shardnode.ListBlobRet{
Blobs: []proto.Blob{
{Name: "test-blob-1"},
{Name: "test-blob-2"},
},
NextMarker: "",
}
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().ListBlob(gAny, gAny, gAny).Return(listRet, nil).Times(2)
args.ShardID = 0
args.Marker = ""
args.Count = 4
ret, err = h.ListBlob(ctx, &args)
expectMarker := acapi.ListBlobEncodeMarker{
Range: *ranges[2],
Marker: "",
}
require.NoError(t, err)
require.Equal(t, 4, len(ret.Blobs))
actual := acapi.ListBlobEncodeMarker{}
err = actual.Unmarshal([]byte(ret.NextMarker))
require.NoError(t, err)
require.Equal(t, expectMarker, actual) // string(ret.NextMarker))
// list all, from next shard 3, list twice
args.ShardID = 0
args.Count = 4
args.Marker = ret.NextMarker
shardMgr.EXPECT().GetSpaceID().Return(proto.SpaceID(1)).Times(2)
shardMgr.EXPECT().GetShardByRange(gAny, expectMarker.Range).Return(shards[2], nil)
shardMgr.EXPECT().GetNextShard(gAny, gAny).Return(nil, errMock)
svrCtrl.EXPECT().GetShardnodeHost(gAny, gAny).Return(&controller.HostIDC{Host: "host"}, nil).Times(2)
h.clusterController.(*MockClusterController).EXPECT().GetShardController(gAny).Return(shardMgr, nil).Times(1)
h.clusterController.(*MockClusterController).EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).Times(2)
listRet.NextMarker = ret.NextMarker
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().ListBlob(gAny, gAny, gAny).Return(listRet, nil)
listRet.NextMarker = ""
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().ListBlob(gAny, gAny, gAny).Return(listRet, nil)
ret, err = h.ListBlob(ctx, &args)
require.NotNil(t, err)
require.ErrorIs(t, err, errMock)
require.Equal(t, 0, len(ret.Blobs))
// list all, access until last shard not enough count
lastEndMarker := acapi.ListBlobEncodeMarker{
Range: *ranges[2], // total count 4
Marker: args.Marker,
}
lastEnd, err := lastEndMarker.Marshal()
require.NoError(t, err)
args.ShardID = 0
args.Count = 100
args.Marker = string(lastEnd)
h.clusterController.(*MockClusterController).EXPECT().GetShardController(gAny).Return(shardMgr, nil)
shardMgr.EXPECT().GetShardByRange(gAny, lastEndMarker.Range).Return(shards[2], nil)
shardMgr.EXPECT().GetSpaceID().Return(proto.SpaceID(1)).Times(2)
shardMgr.EXPECT().GetNextShard(gAny, gAny).Return(shards[3], nil)
shardMgr.EXPECT().GetNextShard(gAny, gAny).Return(nil, nil)
svrCtrl.EXPECT().GetShardnodeHost(gAny, gAny).Return(&controller.HostIDC{Host: "host"}, nil).Times(2)
h.clusterController.(*MockClusterController).EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).Times(2)
listRet.NextMarker = ""
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().ListBlob(gAny, gAny, gAny).Return(listRet, nil).Times(2)
ret, err = h.ListBlob(ctx, &args)
require.NoError(t, err)
require.Equal(t, 4, len(ret.Blobs))
// endOneMarker := acapi.ListBlobEncodeMarker{
// Range: sharding.Range{}, // *ranges[3],
// Marker: args.Marker,
// }
// endOne, err := endOneMarker.Marshal()
// require.NoError(t, err)
require.Equal(t, "", ret.NextMarker) // require.Equal(t, []byte(nil), ret.NextMarker)
// list all, error marker
args = acapi.ListBlobArgs{
ClusterID: 1,
Mode: 1,
ShardID: 0,
Prefix: "", //[]byte("test-"),
Marker: ("abcd"),
Count: 100,
}
h.clusterController.(*MockClusterController).EXPECT().GetShardController(gAny).Return(shardMgr, nil)
ret, err = h.ListBlob(ctx, &args)
require.NotNil(t, err)
require.True(t, strings.Contains(err.Error(), "fail to unmarshal marker"))
}
func TestStreamBlobAlloc(t *testing.T) {
ctx := context.Background()
gAny := gomock.Any()
h := newStreamHandlerSuccess(t)
args := acapi.AllocSliceArgs{
BlobName: ("blob-seal"),
ClusterID: 1,
CodeMode: 1,
Size: 1,
FailSlice: proto.Slice{},
}
ret := shardnode.AllocSliceRet{
Slices: make([]proto.Slice, 1),
}
ret.Slices[0].Vid = 1
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().AllocSlice(gAny, gAny, gAny).Return(ret, errcode.ErrShardRouteVersionNeedUpdate)
h.shardnodeClient.(*mocks.MockShardnodeAccess).EXPECT().AllocSlice(gAny, gAny, gAny).Return(ret, nil)
loc, err := h.AllocSlice(ctx, &args)
require.NoError(t, err)
require.NotNil(t, loc)
require.Equal(t, 1, len(loc.Slices))
require.Equal(t, proto.Vid(1), loc.Slices[0].Vid)
}
func TestStreamBlobOther(t *testing.T) {
ctx := context.Background()
gAny := gomock.Any()
ctr := gomock.NewController(t)
svrCtrl := NewMockServiceController(ctr)
svrCtrl.EXPECT().PunishShardnode(gAny, gAny, gAny).Times(2)
shardMgr := NewMockShardController(ctr)
shardMgr.EXPECT().UpdateRoute(gAny).Return(nil).Times(2)
shardMgr.EXPECT().UpdateShard(gAny, gAny).Return(nil)
clu := NewMockClusterController(ctr)
clu.EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).Times(2)
clu.EXPECT().GetShardController(gAny).Return(shardMgr, nil).Times(3)
h := &Handler{
clusterController: clu,
}
interrupt, err1 := h.punishAndUpdate(ctx, &punishArgs{
err: errcode.ErrShardNodeDiskNotFound,
})
require.Equal(t, false, interrupt)
require.ErrorIs(t, err1, errcode.ErrShardNodeDiskNotFound)
interrupt, err1 = h.punishAndUpdate(ctx, &punishArgs{
err: errcode.ErrShardDoesNotExist,
})
require.Equal(t, false, interrupt)
require.ErrorIs(t, err1, errcode.ErrShardDoesNotExist)
interrupt, err1 = h.punishAndUpdate(ctx, &punishArgs{
err: io.EOF,
})
require.Equal(t, false, interrupt)
require.ErrorIs(t, err1, io.EOF)
// broken disk
interrupt, err1 = h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: shardnode.ShardOpHeader{},
clusterID: 0,
host: "",
err: errcode.ErrDiskBroken,
})
require.Equal(t, false, interrupt)
require.ErrorIs(t, err1, errcode.ErrDiskBroken)
shardnodeClient := mocks.NewMockShardnodeAccess(ctr)
shardnodeClient.EXPECT().GetShardStats(gAny, gAny, gAny).Return(shardnode.ShardStats{LeaderDiskID: 11}, nil).Times(1)
h.shardnodeClient = shardnodeClient
h.ShardnodeRetryTimes = defaultShardnodeRetryTimes
err1 = h.updateLeaderFromCurrentHost(ctx, &punishArgs{
err: errcode.ErrShardNodeNotLeader,
})
require.NoError(t, err1)
// wait connect refused
h.ShardnodeRetryTimes = defaultShardnodeRetryTimes
info := controller.ShardOpInfo{
DiskID: 101,
Suid: proto.EncodeSuid(1, 0, 1),
RouteVersion: 1,
}
clu.EXPECT().GetShardController(gAny).Return(shardMgr, nil)
clu.EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).Times(2)
shardInfo := NewMockShard(ctr)
shardInfo.EXPECT().GetMember(gAny, gAny, map[proto.DiskID]struct{}{1: {}}).Return(info, nil)
shardMgr.EXPECT().GetShardByID(gAny, gAny).Return(shardInfo, nil)
shardMgr.EXPECT().UpdateShard(gAny, gAny).Return(nil)
svrCtrl.EXPECT().GetShardnodeHost(gAny, proto.DiskID(101)).Return(&controller.HostIDC{Host: "host101"}, nil)
svrCtrl.EXPECT().PunishShardnode(gAny, gAny, gAny)
shardnodeClient.EXPECT().GetShardStats(gAny, gAny, gAny).Return(shardnode.ShardStats{LeaderDiskID: 1}, nil)
shardnodeClient.EXPECT().GetShardStats(gAny, "host101", shardnode.GetShardArgs{
DiskID: proto.DiskID(101),
Suid: info.Suid,
}).Return(shardnode.ShardStats{LeaderDiskID: 102}, nil)
interrupt, err1 = h.punishAndUpdate(ctx, &punishArgs{
ShardOpHeader: shardnode.ShardOpHeader{
DiskID: 1,
Suid: 2,
},
err: errors.New("dial tcp localhost:9100: connect: connection refused"),
})
require.Equal(t, false, interrupt)
// require.True(t, strings.Contains(err1.Error(), "connection refused"))
require.ErrorIs(t, err1, errcode.ErrConnectionRefused)
// interrupt, err1 = convertError(kvstore.ErrNotFound)
// require.Equal(t, true, interrupt)
// require.ErrorIs(t, err1, errcode.ErrCallShardNodeFail)
}
func TestStreamBlob_NotLeader_RetrySuccess(t *testing.T) {
ctx := context.Background()
ctr := gomock.NewController(t)
gAny := gomock.Any()
// old leader, Not Leader
oldInfo := controller.ShardOpInfo{
DiskID: 101,
Suid: proto.EncodeSuid(1, 0, 1),
RouteVersion: 1,
}
// new leader
newInfo := controller.ShardOpInfo{
DiskID: 102,
Suid: proto.EncodeSuid(1, 0, 2),
RouteVersion: 1,
}
// shard mock
shard := NewMockShard(ctr)
shard.EXPECT().GetMember(gAny, gAny, gAny).Return(oldInfo, nil).AnyTimes() // getShardOpHeader
shard.EXPECT().GetMember(gAny, acapi.GetShardModeRandom, map[proto.DiskID]struct{}{oldInfo.DiskID: {}}).Return(newInfo, nil).AnyTimes() // waitShardnodeNextLeader
shard.EXPECT().GetShardID().Return(proto.ShardID(1)).AnyTimes()
// shard controller mock
shardMgr := NewMockShardController(ctr)
shardMgr.EXPECT().GetShard(gAny, gAny).Return(shard, nil).AnyTimes()
shardMgr.EXPECT().GetShardByID(gAny, proto.ShardID(1)).Return(shard, nil).AnyTimes()
shardMgr.EXPECT().GetSpaceID().Return(proto.SpaceID(1)).AnyTimes()
shardMgr.EXPECT().UpdateRoute(gAny).Return(nil).AnyTimes()
shardMgr.EXPECT().GetShardSubRangeCount(gAny).Return(2).AnyTimes()
shardMgr.EXPECT().UpdateShard(gAny, gAny).Return(nil).Times(1) // waitShardnodeNextLeader finally
// service controller mock
svrCtrl := NewMockServiceController(ctr)
svrCtrl.EXPECT().GetShardnodeHost(gAny, proto.DiskID(oldInfo.DiskID)).Return(&controller.HostIDC{Host: "host-old"}, nil).AnyTimes()
svrCtrl.EXPECT().GetShardnodeHost(gAny, proto.DiskID(newInfo.DiskID)).Return(&controller.HostIDC{Host: "host-new"}, nil).AnyTimes()
// cluster controller mock
clu := NewMockClusterController(ctr)
clu.EXPECT().GetShardController(gAny).Return(shardMgr, nil).AnyTimes()
clu.EXPECT().GetServiceController(gAny).Return(svrCtrl, nil).AnyTimes()
// shardnode client mockfirst NotLeaderand then success
shardCli := mocks.NewMockShardnodeAccess(ctr)
shardCli.EXPECT().DeleteBlob(gAny, gAny, gAny).Return(errcode.ErrShardNodeNotLeader)
shardCli.EXPECT().GetShardStats(gAny, gAny, gAny).Return(shardnode.ShardStats{LeaderDiskID: newInfo.DiskID}, nil)
shardCli.EXPECT().DeleteBlob(gAny, gAny, gAny).Return(nil)
h := &Handler{
clusterController: clu,
shardnodeClient: shardCli,
}
h.ShardnodeRetryTimes = defaultShardnodeRetryTimes
args := acapi.DelBlobArgs{ClusterID: 1, BlobName: "blob-notleader"}
require.NoError(t, h.DeleteBlob(ctx, &args))
}

View File

@ -12,11 +12,12 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"context"
"fmt"
"hash/crc32"
"io"
"math/rand"
"sort"
@ -26,7 +27,6 @@ import (
"github.com/afex/hystrix-go/hystrix"
"github.com/cubefs/cubefs/blobstore/access/controller"
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/blobnode"
"github.com/cubefs/cubefs/blobstore/common/codemode"
"github.com/cubefs/cubefs/blobstore/common/ec"
@ -34,6 +34,7 @@ import (
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/util"
"github.com/cubefs/cubefs/blobstore/util/errors"
"github.com/cubefs/cubefs/blobstore/util/retry"
)
@ -66,6 +67,7 @@ type shardData struct {
index int
status bool
buffer []byte
time int
}
type sortedVuid struct {
@ -110,7 +112,7 @@ type pipeBuffer struct {
// ...
// read-9 [d4 p5]
// failed
func (h *Handler) Get(ctx context.Context, w io.Writer, location access.Location, readSize, offset uint64) (func() error, error) {
func (h *Handler) Get(ctx context.Context, w io.Writer, location proto.Location, readSize, offset uint64) (func() error, error) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("get request cluster:%d size:%d offset:%d", location.ClusterID, readSize, offset)
@ -141,6 +143,7 @@ func (h *Handler) Get(ctx context.Context, w io.Writer, location access.Location
getTime := new(timeReadWrite)
defer func() {
span.AppendRPCTrackLog([]string{getTime.String()})
getTime.Report(clusterID.ToString(), h.IDC, false)
}()
// try to read data shard only,
@ -166,6 +169,10 @@ func (h *Handler) Get(ctx context.Context, w io.Writer, location access.Location
}
}
var spanpipe trace.Span
spanpipe, ctx = trace.StartSpanFromContextWithTraceID(context.Background(), "", span.TraceID())
defer spanpipe.Finish()
// data stream flow:
// client <--copy-- pipeline <--swap-- readBlob <--copy-- blobnode
//
@ -185,18 +192,21 @@ func (h *Handler) Get(ctx context.Context, w io.Writer, location access.Location
if blobVolume == nil || blobVolume.Vid != blob.Vid {
blobVolume, err = h.getVolume(ctx, clusterID, blob.Vid, true)
if err != nil {
span.Error("get volume", err)
spanpipe.Error("get volume", err)
ch <- pipeBuffer{err: err}
return
}
// do not use local shards
sortedVuids = genSortedVuidByIDC(ctx, serviceController, h.IDC, blobVolume.Units[:tactic.N+tactic.M])
span.Debugf("to read %s with read-shard-x:%d active-shard-n:%d of data-n:%d party-n:%d",
ordered := h.CodeModesGetOrdered[blobVolume.CodeMode]
ignoreIDC := h.CodeModesGetIgnoreIDC[blobVolume.CodeMode]
sortedVuids = genSortedVuidByIDC(ctx,
serviceController, h.IDC, blobVolume.Units[:tactic.N+tactic.M], ordered, ignoreIDC)
spanpipe.Debugf("to read %s with read-shard-x:%d active-shard-n:%d of data-n:%d party-n:%d",
blob.ID(), h.MinReadShardsX, len(sortedVuids), tactic.N, tactic.M)
if len(sortedVuids) < tactic.N {
err = fmt.Errorf("broken %s", blob.ID())
span.Error(err)
spanpipe.Error(err)
ch <- pipeBuffer{err: err}
return
}
@ -212,7 +222,7 @@ func (h *Handler) Get(ctx context.Context, w io.Writer, location access.Location
err = h.readOneBlob(ctx, getTime, serviceController, blob, sortedVuids, shards)
if err != nil {
span.Error("read one blob", blob.ID(), err)
spanpipe.Error("read one blob", blob.ID(), err)
for _, buf := range shards {
h.memPool.Put(buf)
}
@ -255,7 +265,7 @@ func (h *Handler) Get(ctx context.Context, w io.Writer, location access.Location
continue
}
toRead := minU64(toReadSize, l-off)
toRead := util.Min(toReadSize, l-off)
if _, e := w.Write(buf[off : off+toRead]); e != nil {
err = errors.Info(e, "write to response")
break
@ -301,7 +311,8 @@ func (h *Handler) Get(ctx context.Context, w io.Writer, location access.Location
// 4. Just read essential bytes if the data is a segment of one shard.
func (h *Handler) readOneBlob(ctx context.Context, getTime *timeReadWrite,
serviceController controller.ServiceController,
blob blobGetArgs, sortedVuids []sortedVuid, shards [][]byte) error {
blob blobGetArgs, sortedVuids []sortedVuid, shards [][]byte,
) error {
span := trace.SpanFromContextSafe(ctx)
tactic := blob.CodeMode.Tactic()
@ -369,7 +380,31 @@ func (h *Handler) readOneBlob(ctx context.Context, getTime *timeReadWrite,
startRead := time.Now()
reconstructed := false
got, mostTime := 0, 0
for shard := range shardPipe {
if got++; got == dataN-1 {
mostTime = shard.time
}
var shardSpeed float32
if shard.time > 0 {
shardSpeed = float32(blob.ShardReadSize) / (float32(shard.time) / 1e9) / (1 << 10)
}
// find slow data shard, if it speed greater than index data-1 shard time.
if mostTime > 0 && shard.time/1e6 > h.LogSlowBaseTimeMS &&
shardSpeed < float32(h.LogSlowBaseSpeedKB) &&
float32(shard.time) > h.LogSlowTimeFator*float32(mostTime) {
var logvuid sortedVuid
for idx := range sortedVuids {
if sortedVuids[idx].index == shard.index {
logvuid = sortedVuids[idx]
break
}
}
span.Warnf("slow disk(host:%s diskid:%d) time(most:%dms shard:%dms) speed:%.2fKB/s",
logvuid.host, logvuid.diskID, mostTime/1e6, shard.time/1e6, shardSpeed)
}
// swap shard buffer
if shard.status {
buf := shards[shard.index]
@ -462,7 +497,8 @@ func (h *Handler) readOneBlob(ctx context.Context, getTime *timeReadWrite,
}
func (h *Handler) readOneShard(ctx context.Context, serviceController controller.ServiceController,
blob blobGetArgs, vuid sortedVuid, stopChan <-chan struct{}) shardData {
blob blobGetArgs, vuid sortedVuid, stopChan <-chan struct{},
) shardData {
clusterID, vid := blob.Cid, blob.Vid
shardOffset, shardReadSize := blob.ShardOffset, blob.ShardReadSize
span := trace.SpanFromContextSafe(ctx)
@ -470,12 +506,14 @@ func (h *Handler) readOneShard(ctx context.Context, serviceController controller
index: vuid.index,
status: false,
}
shardStart := time.Now()
args := blobnode.RangeGetShardArgs{
GetShardArgs: blobnode.GetShardArgs{
DiskID: vuid.diskID,
Vuid: vuid.vuid,
Bid: blob.Bid,
Type: blobnode.ReadIO,
},
Offset: int64(shardOffset),
Size: int64(shardReadSize),
@ -484,9 +522,10 @@ func (h *Handler) readOneShard(ctx context.Context, serviceController controller
var (
err error
body io.ReadCloser
crc uint32
)
if hErr := hystrix.Do(rwCommand, func() error {
body, err = h.getOneShardFromHost(ctx, serviceController, vuid.host, vuid.diskID, args,
body, crc, err = h.getOneShardFromHost(ctx, serviceController, vuid.host, vuid.diskID, args,
vuid.index, clusterID, vid, 3, stopChan)
if err != nil && (errorTimeout(err) || rpc.DetectStatusCode(err) == errcode.CodeOverload) {
return err
@ -498,10 +537,13 @@ func (h *Handler) readOneShard(ctx context.Context, serviceController controller
}
if err != nil {
if err == errPunishedDisk || err == errCanceledReadShard {
if err == errPunishedDisk {
span.Warnf("read %s on %s: %s", blob.ID(), vuid.ID(), err.Error())
return shardResult
}
if err == errCanceledReadShard {
return shardResult
}
span.Warnf("rpc read %s on %s: %s", blob.ID(), vuid.ID(), errors.Detail(err))
return shardResult
}
@ -519,14 +561,26 @@ func (h *Handler) readOneShard(ctx context.Context, serviceController controller
span.Warnf("io read %s on %s: %s", blob.ID(), vuid.ID(), err.Error())
return shardResult
}
if h.ShardCrcReadEnable && crc > 0 {
newCrc := crc32.ChecksumIEEE(buf[shardOffset : shardOffset+shardReadSize])
if newCrc != crc {
h.memPool.Put(buf)
reportDownload(clusterID, "Download", "CrcMismatch")
span.Errorf("blob:%+v vuid:%s crc mismatch 0x%x(%d) != 0x%x(%d)",
blob, vuid.ID(), crc, crc, newCrc, newCrc)
return shardResult
}
}
shardResult.status = true
shardResult.buffer = buf
shardResult.time = int(time.Since(shardStart))
return shardResult
}
func (h *Handler) getDataShardOnly(ctx context.Context, getTime *timeReadWrite,
w io.Writer, serviceController controller.ServiceController, blob blobGetArgs) error {
w io.Writer, serviceController controller.ServiceController, blob blobGetArgs,
) error {
span := trace.SpanFromContextSafe(ctx)
if blob.ReadSize == 0 {
return nil
@ -549,6 +603,10 @@ func (h *Handler) getDataShardOnly(ctx context.Context, getTime *timeReadWrite,
firstShardIdx := int(blob.Offset) / shardSize
shardOffset := int(blob.Offset) % shardSize
ctx, cancel := context.WithDeadline(ctx,
time.Now().Add(time.Millisecond*time.Duration(h.ReadDataOnlyTimeoutMS)))
defer cancel()
startRead := time.Now()
remainSize := blob.ReadSize
bufOffset := 0
@ -557,22 +615,30 @@ func (h *Handler) getDataShardOnly(ctx context.Context, getTime *timeReadWrite,
break
}
toReadSize := minU64(remainSize, uint64(shardSize-shardOffset))
diskInfo, err := serviceController.GetDiskHost(ctx, shard.DiskID)
if err != nil {
span.Warnf("get disk host failed: %s", err)
return errNeedReconstructRead
}
host := diskInfo.Host
toReadSize := util.Min(remainSize, uint64(shardSize-shardOffset))
args := blobnode.RangeGetShardArgs{
GetShardArgs: blobnode.GetShardArgs{
DiskID: shard.DiskID,
Vuid: shard.Vuid,
Bid: blob.Bid,
Type: blobnode.ReadIO,
},
Offset: int64(shardOffset),
Size: int64(toReadSize),
}
body, err := h.getOneShardFromHost(ctx, serviceController, shard.Host, shard.DiskID, args,
body, crc, err := h.getOneShardFromHost(ctx, serviceController, host, shard.DiskID, args,
firstShardIdx+i, blob.Cid, blob.Vid, 1, nil)
if err != nil {
span.Warnf("read %s on blobnode(vuid:%d disk:%d host:%s) ecidx(%02d): %s", blob.ID(),
shard.Vuid, shard.DiskID, shard.Host, firstShardIdx+i, errors.Detail(err))
shard.Vuid, shard.DiskID, host, firstShardIdx+i, errors.Detail(err))
return errNeedReconstructRead
}
defer body.Close()
@ -583,6 +649,14 @@ func (h *Handler) getDataShardOnly(ctx context.Context, getTime *timeReadWrite,
span.Warn(err)
return errNeedReconstructRead
}
if h.ShardCrcReadEnable && crc > 0 {
if newCrc := crc32.ChecksumIEEE(buf); newCrc != crc {
reportDownload(blob.Cid, "Download", "CrcMismatch")
span.Errorf("blob:%+v (host:%s diskid:%d vuid:%d) crc mismatch 0x%x(%d) != 0x%x(%d)",
blob, host, shard.DiskID, shard.Vuid, crc, crc, newCrc, newCrc)
return errNeedReconstructRead
}
}
// reset next shard offset
shardOffset = 0
@ -610,20 +684,16 @@ func (h *Handler) getOneShardFromHost(ctx context.Context, serviceController con
host string, diskID proto.DiskID, args blobnode.RangeGetShardArgs, // get shard param with host diskid
index int, clusterID proto.ClusterID, vid proto.Vid, // param to update volume cache
attempts int, cancelChan <-chan struct{}, // do not retry again if cancelChan was closed
) (io.ReadCloser, error) {
) (rbody io.ReadCloser, rcrc uint32, rerr error) {
span := trace.SpanFromContextSafe(ctx)
// skip punished disk
if diskHost, err := serviceController.GetDiskHost(ctx, diskID); err != nil {
return nil, err
return nil, 0, err
} else if diskHost.Punished {
return nil, errPunishedDisk
return nil, 0, errPunishedDisk
}
var (
rbody io.ReadCloser
rerr error
)
rerr = retry.ExponentialBackoff(attempts, 200).RuptOn(func() (bool, error) {
if cancelChan != nil {
select {
@ -633,14 +703,10 @@ func (h *Handler) getOneShardFromHost(ctx context.Context, serviceController con
}
}
// new child span to get from blobnode, we should finish it here.
spanChild, ctxChild := trace.StartSpanFromContextWithTraceID(
context.Background(), "GetFromBlobnode", span.TraceID())
defer spanChild.Finish()
body, _, err := h.blobnodeClient.RangeGetShard(ctxChild, host, &args)
body, crc, err := h.blobnodeClient.RangeGetShard(ctx, host, &args)
if err == nil {
rbody = body
rcrc = crc
return true, nil
}
@ -688,10 +754,12 @@ func (h *Handler) getOneShardFromHost(ctx context.Context, serviceController con
// do not retry on timeout then punish threshold this disk
if errorTimeout(err) {
h.updateVolume(ctx, clusterID, vid)
h.punishDiskWith(ctx, clusterID, diskID, host, "Timeout")
return true, err
}
if errorConnectionRefused(err) {
h.updateVolume(ctx, clusterID, vid)
return true, err
}
span.Debugf("read from disk:%d blobnode/%s", diskID, err.Error())
@ -700,17 +768,17 @@ func (h *Handler) getOneShardFromHost(ctx context.Context, serviceController con
return false, err
})
return rbody, rerr
return
}
func genLocationBlobs(location *access.Location, readSize uint64, offset uint64) ([]blobGetArgs, error) {
if readSize > location.Size || offset > location.Size || offset+readSize > location.Size {
return nil, fmt.Errorf("FileSize:%d ReadSize:%d Offset:%d", location.Size, readSize, offset)
func genLocationBlobs(location *proto.Location, readSize uint64, offset uint64) ([]blobGetArgs, error) {
if readSize > location.Size_ || offset > location.Size_ || offset+readSize > location.Size_ {
return nil, fmt.Errorf("FileSize:%d ReadSize:%d Offset:%d", location.Size_, readSize, offset)
}
blobSize := uint64(location.BlobSize)
blobSize := uint64(location.SliceSize)
if blobSize <= 0 {
return nil, fmt.Errorf("BlobSize:%d", blobSize)
return nil, fmt.Errorf("SliceSize:%d", blobSize)
}
remainSize := readSize
@ -721,8 +789,8 @@ func genLocationBlobs(location *access.Location, readSize uint64, offset uint64)
idx := uint64(0)
blobs := make([]blobGetArgs, 0, 1+(readSize+blobOffset)/blobSize)
for _, blob := range location.Blobs {
currBlobID := blob.MinBid
for _, blob := range location.Slices {
currBlobID := blob.MinSliceID
for ii := uint32(0); ii < blob.Count; ii++ {
if remainSize <= 0 {
@ -730,10 +798,10 @@ func genLocationBlobs(location *access.Location, readSize uint64, offset uint64)
}
if idx >= firstBlobIdx {
toReadSize := minU64(remainSize, blobSize-blobOffset)
toReadSize := util.Min(remainSize, blobSize-blobOffset)
if toReadSize > 0 {
// update the last blob size
fixedBlobSize := minU64(location.Size-idx*blobSize, blobSize)
fixedBlobSize := util.Min(location.Size_-idx*blobSize, blobSize)
sizes, _ := ec.GetBufferSizes(int(fixedBlobSize), tactic)
shardSize := sizes.ShardSize
@ -771,8 +839,10 @@ func genLocationBlobs(location *access.Location, readSize uint64, offset uint64)
return blobs, nil
}
func genSortedVuidByIDC(ctx context.Context, serviceController controller.ServiceController, idc string,
vuidPhys []controller.Unit) []sortedVuid {
func genSortedVuidByIDC(ctx context.Context,
serviceController controller.ServiceController, idc string, vuidPhys []controller.Unit,
ordered bool, ignoreIDC bool,
) []sortedVuid {
span := trace.SpanFromContextSafe(ctx)
vuids := make([]sortedVuid, 0, len(vuidPhys))
@ -792,7 +862,11 @@ func genSortedVuidByIDC(ctx context.Context, serviceController controller.Servic
continue
}
dis := distance(idc, hostIDC.IDC, hostIDC.Punished)
destIDC := hostIDC.IDC
if ignoreIDC {
destIDC = idc
}
dis := distance(idc, destIDC, hostIDC.Punished)
if _, ok := sortMap[dis]; !ok {
sortMap[dis] = make([]sortedVuid, 0, 8)
}
@ -800,7 +874,7 @@ func genSortedVuidByIDC(ctx context.Context, serviceController controller.Servic
index: idx,
vuid: phy.Vuid,
diskID: phy.DiskID,
host: phy.Host,
host: hostIDC.Host,
})
}
@ -812,9 +886,11 @@ func genSortedVuidByIDC(ctx context.Context, serviceController controller.Servic
for _, dis := range keys {
ids := sortMap[dis]
rand.Shuffle(len(ids), func(i, j int) {
ids[i], ids[j] = ids[j], ids[i]
})
if !ordered {
rand.Shuffle(len(ids), func(i, j int) {
ids[i], ids[j] = ids[j], ids[i]
})
}
vuids = append(vuids, ids...)
if dis > 1 {
span.Debugf("distance: %d punished vuids: %+v", dis, ids)
@ -841,7 +917,7 @@ func emptyDataShardIndexes(sizes ec.BufferSizes) map[int]struct{} {
firstEmptyIdx := (sizes.DataSize + sizes.ShardSize - 1) / sizes.ShardSize
n := sizes.ECDataSize / sizes.ShardSize
if firstEmptyIdx >= n {
return make(map[int]struct{})
return nil
}
set := make(map[int]struct{}, n-firstEmptyIdx)

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"bytes"
@ -24,7 +24,6 @@ import (
"github.com/stretchr/testify/require"
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/common/codemode"
"github.com/cubefs/cubefs/blobstore/common/proto"
)
@ -35,7 +34,7 @@ func TestAccessStreamGetBase(t *testing.T) {
{
dataShards.clean()
data := []byte("x")
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(len(data)), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(len(data)), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
buff := bytes.NewBuffer(nil)
@ -48,7 +47,7 @@ func TestAccessStreamGetBase(t *testing.T) {
{
dataShards.clean()
data := []byte("x")
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(len(data)), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(len(data)), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
buff := bytes.NewBuffer(nil)
@ -84,7 +83,7 @@ func TestAccessStreamGetBase(t *testing.T) {
size := cs.size
data := make([]byte, size)
rand.Read(data)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(size), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
buff := bytes.NewBuffer(nil)
@ -118,7 +117,7 @@ func TestAccessStreamGetBroken(t *testing.T) {
rand.Read(data)
// time wait the punished services
time.Sleep(time.Second * time.Duration(punishServiceS))
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(size), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
cases := []struct {
@ -184,7 +183,7 @@ func TestAccessStreamGetOffset(t *testing.T) {
size := cs.size
data := make([]byte, size)
rand.Read(data)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), size, nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), size, nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
buff := bytes.NewBuffer(nil)
@ -211,7 +210,7 @@ func TestAccessStreamGetShardTimeout(t *testing.T) {
size := 1 << 22
buff := make([]byte, size)
rand.Read(buff)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
// no delay when blocking one shard, cos MinReadShardsX = 1
@ -220,13 +219,9 @@ func TestAccessStreamGetShardTimeout(t *testing.T) {
vuidController.Unblock(1001)
}()
{
startTime := time.Now()
transfer, _ := streamer.Get(ctx(), bytes.NewBuffer(nil), *loc, uint64(size), 0)
err := transfer()
require.NoError(t, err)
duration := time.Since(startTime)
require.GreaterOrEqual(t, vuidController.duration, duration, "greater duration: ", duration)
}
// delay one duration when blocking two shard, cos MinReadShardsX = 1
@ -249,6 +244,59 @@ func TestAccessStreamGetShardTimeout(t *testing.T) {
}
}
func TestAccessStreamGetShardSlow(t *testing.T) {
ctx := ctxWithName("TestAccessStreamGetShardSlow")
dataShards.clean()
vuidController.Unbreak(1005)
streamer.MinReadShardsX = 0
defer func() {
vuidController.SetSlowdown(1001, -1)
vuidController.Break(1005)
streamer.MinReadShardsX = minReadShardsX
dataShards.clean()
}()
size := 1 << 20
buff := make([]byte, size)
rand.Read(buff)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
vuidController.SetSlowdown(1001, 500*time.Millisecond)
transfer, err := streamer.Get(ctx(), bytes.NewBuffer(nil), *loc, uint64(size), 0)
require.NoError(t, err)
err = transfer()
require.NoError(t, err)
}
func TestAccessStreamGetShardCrcMismatch(t *testing.T) {
ctx := ctxWithName("TestAccessStreamGetShardCrcMismatch")
vuidController.Unbreak(1005)
streamer.MinReadShardsX = 0
defer func() {
vuidController.SetCrcMismatch(1001, false)
vuidController.SetCrcMismatch(1002, false)
vuidController.Break(1005)
streamer.MinReadShardsX = minReadShardsX
dataShards.clean()
}()
vuidController.SetCrcMismatch(1001, true)
vuidController.SetCrcMismatch(1002, true)
for _, size := range []int{1, 1023, 2048, 1 << 20} {
dataShards.clean()
buff := make([]byte, size)
rand.Read(buff)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
transfer, err := streamer.Get(ctx(), bytes.NewBuffer(nil), *loc, uint64(size), 0)
require.NoError(t, err)
err = transfer()
require.NoError(t, err)
}
}
func TestAccessStreamGetShardBroken(t *testing.T) {
ctx := ctxWithName("TestAccessStreamGetShardBroken")
dataShards.clean()
@ -263,7 +311,7 @@ func TestAccessStreamGetShardBroken(t *testing.T) {
size := 1 << 22
buff := make([]byte, size)
rand.Read(buff)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
// no delay when blocking one shard, cos MinReadShardsX = 1
@ -291,6 +339,39 @@ func TestAccessStreamGetShardBroken(t *testing.T) {
}
}
func TestAccessStreamGetShardOnlyTimeout(t *testing.T) {
ctx := ctxWithName("TestAccessStreamGetShardOnlyTimeout")
dataShards.clean()
oldMs := streamer.ReadDataOnlyTimeoutMS
streamer.ReadDataOnlyTimeoutMS = 100
defer func() {
streamer.ReadDataOnlyTimeoutMS = oldMs
dataShards.clean()
}()
size := 1
buff := make([]byte, size)
rand.Read(buff)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
// blocking the data shard, force to waiting ReadDataOnlyTimeoutMS
vuidController.Block(1001)
defer func() {
vuidController.Unblock(1001)
}()
{
startTime := time.Now()
transfer, err := streamer.Get(ctx(), bytes.NewBuffer(nil), *loc, uint64(size), 0)
require.NoError(t, err)
err = transfer()
require.NoError(t, err)
duration := time.Since(startTime)
require.GreaterOrEqual(t, duration, 100*time.Millisecond, "greater duration:", duration)
}
}
func TestAccessStreamGetLocalIDC(t *testing.T) {
ctx := ctxWithName("TestAccessStreamGetLocalIDC")
dataShards.clean()
@ -303,7 +384,7 @@ func TestAccessStreamGetLocalIDC(t *testing.T) {
size := 1 << 22
buff := make([]byte, size)
rand.Read(buff)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
// no delay when blocking other idc all shards
@ -414,7 +495,7 @@ func TestAccessStreamGetAligned(t *testing.T) {
data := make([]byte, cs.size)
rand.Read(data)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(cs.size), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(data), int64(cs.size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
// cos put shards asynchronously, should wait all shard written
@ -444,21 +525,21 @@ func TestAccessStreamGenLocationBlobs(t *testing.T) {
firstSliceStart := proto.BlobID(100)
secondSliceStart := proto.BlobID(200)
loc := access.Location{
loc := proto.Location{
ClusterID: 0,
CodeMode: codemode.EC6P6,
Size: 1024*4 + 37 + 1024*2, // 5 fine blobs and 2 missing blobs
BlobSize: 1024,
Blobs: []access.SliceInfo{
Size_: 1024*4 + 37 + 1024*2, // 5 fine blobs and 2 missing blobs
SliceSize: 1024,
Slices: []proto.Slice{
{
MinBid: firstSliceStart,
Vid: proto.Vid(1001),
Count: 3,
MinSliceID: firstSliceStart,
Vid: proto.Vid(1001),
Count: 3,
},
{
MinBid: secondSliceStart,
Vid: proto.Vid(2001),
Count: 2,
MinSliceID: secondSliceStart,
Vid: proto.Vid(2001),
Count: 2,
},
},
}
@ -594,7 +675,7 @@ func BenchmarkAccessStreamGet(b *testing.B) {
for _, cs := range cases {
b.ResetTimer()
b.Run(cs.name, func(b *testing.B) {
loc, err := streamer.Put(ctx, newReader(cs.size), int64(cs.size), nil)
loc, err := streamer.Put(ctx, newReader(cs.size), int64(cs.size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(b, err)
b.ResetTimer()

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"context"

View File

@ -12,11 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
// github.com/cubefs/cubefs/blobstore/access/... module access interfaces
//go:generate mockgen -destination=./controller_mock_test.go -package=access -mock_names ClusterController=MockClusterController,ServiceController=MockServiceController,VolumeGetter=MockVolumeGetter github.com/cubefs/cubefs/blobstore/access/controller ClusterController,ServiceController,VolumeGetter
//go:generate mockgen -destination=./access_mock_test.go -package=access -mock_names StreamHandler=MockStreamHandler,Limiter=MockLimiter github.com/cubefs/cubefs/blobstore/access StreamHandler,Limiter
package stream
import (
"bytes"
@ -25,7 +21,6 @@ import (
"fmt"
"hash/crc32"
"io"
"io/ioutil"
"math"
"math/rand"
"strconv"
@ -48,6 +43,7 @@ import (
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/testing/mocks"
_ "github.com/cubefs/cubefs/blobstore/testing/nolog"
"github.com/cubefs/cubefs/blobstore/util/bytespool"
)
var (
@ -82,10 +78,10 @@ var (
cc controller.ClusterController
clusterInfo *clustermgr.ClusterInfo
dataVolume *proxy.VersionVolume
dataVolume *clustermgr.VolumeInfo
dataAllocs []proxy.AllocRet
dataNodes map[string]clustermgr.ServiceInfo
dataDisks map[proto.DiskID]blobnode.DiskInfo
dataDisks map[proto.DiskID]clustermgr.BlobNodeDiskInfo
dataShards *shardsData
vuidController *vuidControl
@ -147,6 +143,8 @@ type vuidControl struct {
mutex sync.Mutex
broken map[proto.Vuid]bool
blocked map[proto.Vuid]bool
slowdown map[proto.Vuid]time.Duration
crc map[proto.Vuid]bool
block func()
duration time.Duration
@ -191,6 +189,36 @@ func (c *vuidControl) Isblocked(id proto.Vuid) bool {
return ok && v
}
func (c *vuidControl) SetSlowdown(id proto.Vuid, t time.Duration) {
c.mutex.Lock()
if t < 0 {
delete(c.slowdown, id)
} else {
c.slowdown[id] = t
}
c.mutex.Unlock()
}
func (c *vuidControl) GetSlowdown(id proto.Vuid) time.Duration {
c.mutex.Lock()
v := c.slowdown[id]
c.mutex.Unlock()
return v
}
func (c *vuidControl) SetCrcMismatch(id proto.Vuid, crc bool) {
c.mutex.Lock()
c.crc[id] = crc
c.mutex.Unlock()
}
func (c *vuidControl) GetCrcMismatch(id proto.Vuid) bool {
c.mutex.Lock()
v := c.crc[id]
c.mutex.Unlock()
return v
}
func (c *vuidControl) SetBNRealError(b bool) {
c.mutex.Lock()
c.isBNRealError = b
@ -209,7 +237,8 @@ func randBlobnodeRealError(errors []errcode.Error) error {
}
var storageAPIRangeGetShard = func(ctx context.Context, host string, args *blobnode.RangeGetShardArgs) (
body io.ReadCloser, shardCrc uint32, err error) {
body io.ReadCloser, shardCrc uint32, err error,
) {
if vuidController.Isbroken(args.Vuid) {
err = errors.New("get shard fake error")
if vuidController.IsBNRealError() {
@ -226,6 +255,9 @@ var storageAPIRangeGetShard = func(ctx context.Context, host string, args *blobn
}
return
}
if slow := vuidController.GetSlowdown(args.Vuid); slow > 0 {
time.Sleep(slow)
}
buff := dataShards.get(args.Vuid, args.Bid)
if len(buff) == 0 {
@ -235,15 +267,21 @@ var storageAPIRangeGetShard = func(ctx context.Context, host string, args *blobn
err = errors.New("get shard concurrently")
return
}
if len(buff) == int(args.Size) {
shardCrc = crc32.ChecksumIEEE(buff)
if vuidController.GetCrcMismatch(args.Vuid) {
shardCrc++
}
}
buff = buff[int(args.Offset):int(args.Offset+args.Size)]
shardCrc = crc32.ChecksumIEEE(buff)
body = ioutil.NopCloser(bytes.NewReader(buff))
body = io.NopCloser(bytes.NewReader(buff))
return
}
var storageAPIPutShard = func(ctx context.Context, host string, args *blobnode.PutShardArgs) (
crc uint32, err error) {
crc uint32, err error,
) {
if vuidController.Isbroken(args.Vuid) {
err = errors.New("put shard fake error")
if vuidController.IsBNRealError() {
@ -256,14 +294,21 @@ var storageAPIPutShard = func(ctx context.Context, host string, args *blobnode.P
err = errors.New("put shard timeout")
return
}
if slow := vuidController.GetSlowdown(args.Vuid); slow > 0 {
time.Sleep(slow)
}
buffer, _ := memPool.Alloc(int(args.Size))
defer memPool.Put(buffer)
buffer = buffer[:int(args.Size)]
_, err = io.ReadFull(args.Body, buffer)
if err != nil {
return
if args.NopData {
bytespool.Zero(buffer)
} else {
_, err = io.ReadFull(args.Body, buffer)
if err != nil {
return
}
}
crc = crc32.ChecksumIEEE(buffer)
@ -284,7 +329,7 @@ func initMockData() {
Vid: volumeID,
}
dataVolume = &proxy.VersionVolume{VolumeInfo: clustermgr.VolumeInfo{
dataVolume = &clustermgr.VolumeInfo{
VolumeInfoBase: clustermgr.VolumeInfoBase{
Vid: volumeID,
CodeMode: codemode.EC6P6,
@ -294,12 +339,11 @@ func initMockData() {
units = append(units, clustermgr.Unit{
Vuid: proto.Vuid(id),
DiskID: proto.DiskID(id),
Host: strconv.Itoa(id),
})
}
return
}(),
}}
}
proxyNodes := make([]clustermgr.ServiceNode, 32)
for idx := range proxyNodes {
@ -316,17 +360,17 @@ func initMockData() {
Nodes: proxyNodes,
}
dataDisks = make(map[proto.DiskID]blobnode.DiskInfo)
dataDisks = make(map[proto.DiskID]clustermgr.BlobNodeDiskInfo)
for _, id := range idcID {
dataDisks[proto.DiskID(id)] = blobnode.DiskInfo{
ClusterID: clusterID, Idc: idc, Host: strconv.Itoa(id),
DiskHeartBeatInfo: blobnode.DiskHeartBeatInfo{DiskID: proto.DiskID(id)},
dataDisks[proto.DiskID(id)] = clustermgr.BlobNodeDiskInfo{
DiskInfo: clustermgr.DiskInfo{ClusterID: clusterID, Idc: idc, Host: strconv.Itoa(id)},
DiskHeartBeatInfo: clustermgr.DiskHeartBeatInfo{DiskID: proto.DiskID(id)},
}
}
for _, id := range idcOtherID {
dataDisks[proto.DiskID(id)] = blobnode.DiskInfo{
ClusterID: clusterID, Idc: idcOther, Host: strconv.Itoa(id),
DiskHeartBeatInfo: blobnode.DiskHeartBeatInfo{DiskID: proto.DiskID(id)},
dataDisks[proto.DiskID(id)] = clustermgr.BlobNodeDiskInfo{
DiskInfo: clustermgr.DiskInfo{ClusterID: clusterID, Idc: idcOther, Host: strconv.Itoa(id)},
DiskHeartBeatInfo: clustermgr.DiskHeartBeatInfo{DiskID: proto.DiskID(id)},
}
}
@ -357,7 +401,7 @@ func initMockData() {
proxycli.EXPECT().GetCacheVolume(gomock.Any(), gomock.Any(), gomock.Any()).
AnyTimes().Return(dataVolume, nil)
proxycli.EXPECT().GetCacheDisk(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
func(_ context.Context, _ string, args *proxy.CacheDiskArgs) (*blobnode.DiskInfo, error) {
func(_ context.Context, _ string, args *proxy.CacheDiskArgs) (*clustermgr.BlobNodeDiskInfo, error) {
if val, ok := dataDisks[args.DiskID]; ok {
return &val, nil
}
@ -366,17 +410,26 @@ func initMockData() {
serviceController, _ = controller.NewServiceController(
controller.ServiceConfig{
ClusterID: clusterID,
IDC: idc,
ReloadSec: 1000,
ClusterID: clusterID,
IDC: idc,
ServiceReloadSecs: 1000,
}, cmcli, proxycli, nil)
volumeGetter, _ = controller.NewVolumeGetter(clusterID, serviceController, proxycli, 0)
volumeGetter, _ = controller.NewVolumeGetter(controller.VolumeConfig{
ClusterID: clusterID,
VolumeMemcacheExpirationMs: -1,
}, serviceController, proxycli, nil)
ctr = gomock.NewController(&testing.T{})
c := NewMockClusterController(ctr)
c.EXPECT().Region().AnyTimes().Return("test-region")
c.EXPECT().ChooseOne().AnyTimes().Return(clusterInfo, nil)
c.EXPECT().GetServiceController(gomock.Any()).AnyTimes().Return(serviceController, nil)
c.EXPECT().GetServiceController(gomock.Any()).AnyTimes().DoAndReturn(
func(needClusterID proto.ClusterID) (controller.ServiceController, error) {
if needClusterID != clusterID {
return nil, fmt.Errorf("no service controller of %d", needClusterID)
}
return serviceController, nil
})
c.EXPECT().GetVolumeGetter(gomock.Any()).AnyTimes().Return(volumeGetter, nil)
c.EXPECT().ChangeChooseAlg(gomock.Any()).AnyTimes().DoAndReturn(
func(alg controller.AlgChoose) error {
@ -393,6 +446,11 @@ func initMockData() {
allocCli.EXPECT().SendShardRepairMsg(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().Return(nil)
allocCli.EXPECT().VolumeAlloc(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes().DoAndReturn(
func(ctx context.Context, host string, args *proxy.AllocVolsArgs) ([]proxy.AllocRet, error) {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
if args.Fsize > allocTimeoutSize {
return nil, errAllocTimeout
}
@ -466,8 +524,10 @@ func initEC() {
func initController() {
vuidController = &vuidControl{
broken: make(map[proto.Vuid]bool),
blocked: make(map[proto.Vuid]bool),
broken: make(map[proto.Vuid]bool),
blocked: make(map[proto.Vuid]bool),
slowdown: make(map[proto.Vuid]time.Duration),
crc: make(map[proto.Vuid]bool),
block: func() {
time.Sleep(200 * time.Millisecond)
},
@ -503,6 +563,8 @@ func init() {
initMockData()
initController()
hystrix.ConfigureCommand(allocCommand, hystrix.CommandConfig{Timeout: defaultAllocatorTimeout})
streamer = &Handler{
memPool: memPool,
encoder: encoder,
@ -521,6 +583,11 @@ func init() {
AllocRetryTimes: 3,
AllocRetryIntervalMS: 3000,
MinReadShardsX: minReadShardsX,
ReadDataOnlyTimeoutMS: 10000,
ShardCrcReadEnable: true,
LogSlowBaseTimeMS: 10,
LogSlowBaseSpeedKB: 1 << 10,
LogSlowTimeFator: 1.3,
},
discardVidChan: make(chan discardVid, 8),
stopCh: make(chan struct{}),

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"bytes"
@ -28,23 +28,24 @@ import (
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/api/blobnode"
"github.com/cubefs/cubefs/blobstore/common/codemode"
"github.com/cubefs/cubefs/blobstore/common/ec"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/util/errors"
"github.com/cubefs/cubefs/blobstore/util/retry"
)
// TODO: To Be Continue
// put empty shard to blobnode if file has been aligned.
// Put put one object
//
// required: size, file size
// optional: hasher map to calculate hash.Hash
func (h *Handler) Put(ctx context.Context, rc io.Reader, size int64,
hasherMap access.HasherMap) (*access.Location, error) {
func (h *Handler) Put(ctx context.Context,
rc io.Reader, size int64, hasherMap access.HasherMap,
assignClusterID proto.ClusterID, codeMode codemode.CodeMode,
) (*proto.Location, error) {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("put request size:%d hashes:b(%b)", size, hasherMap.ToHashAlgorithm())
@ -62,11 +63,20 @@ func (h *Handler) Put(ctx context.Context, rc io.Reader, size int64,
}
// 2.choose cluster and alloc volume from allocator
selectedCodeMode := h.allCodeModes.SelectCodeMode(size)
span.Debugf("select codemode %d", selectedCodeMode)
selectedCodeMode := codeMode
if selectedCodeMode == codemode.CodeModeNone {
selectedCodeMode = h.allCodeModes.SelectCodeMode(size)
} else {
valid := h.allCodeModes.VerifySelectCodeMode(selectedCodeMode)
if !valid {
span.Errorf("specify codemode %d not found in codemode policy", selectedCodeMode)
return nil, errcode.ErrIllegalArguments
}
}
span.Debugf("select codemode %d, specify codemode %d", selectedCodeMode, codeMode)
blobSize := atomic.LoadUint32(&h.MaxBlobSize)
clusterID, blobs, err := h.allocFromAllocatorWithHystrix(ctx, selectedCodeMode, uint64(size), blobSize, 0)
clusterID, blobs, err := h.allocFromAllocatorWithHystrix(ctx, selectedCodeMode, uint64(size), blobSize, assignClusterID)
if err != nil {
span.Error("alloc failed", errors.Detail(err))
return nil, err
@ -75,19 +85,20 @@ func (h *Handler) Put(ctx context.Context, rc io.Reader, size int64,
// 3.read body and split, alloc from mem pool;ec encode and put into data node
limitReader := io.LimitReader(rc, int64(size))
location := &access.Location{
location := &proto.Location{
ClusterID: clusterID,
CodeMode: selectedCodeMode,
Size: uint64(size),
BlobSize: blobSize,
Blobs: blobs,
Size_: uint64(size),
SliceSize: blobSize,
Slices: blobs,
}
uploadSucc := false
defer func() {
if !uploadSucc {
span.Infof("put failed clean location %+v", location)
if err := h.clearGarbage(ctx, location); err != nil {
_, newCtx := trace.StartSpanFromContextWithTraceID(context.Background(), "", span.TraceID())
if err := h.clearGarbage(newCtx, location); err != nil {
span.Warn(errors.Detail(err))
}
}
@ -99,6 +110,7 @@ func (h *Handler) Put(ctx context.Context, rc io.Reader, size int64,
// release ec buffer which have not takeover
buffer.Release()
span.AppendRPCTrackLog([]string{putTime.String()})
putTime.Report(clusterID.ToString(), h.IDC, true)
}()
// concurrent buffer in per request
@ -121,6 +133,7 @@ func (h *Handler) Put(ctx context.Context, rc io.Reader, size int64,
if err != nil {
return nil, err
}
empties := emptyDataShardIndexes(buffer.BufferSizes)
readBuff := buffer.DataBuf[:bsize]
shards, err := encoder.Split(buffer.ECDataBuf)
@ -153,7 +166,7 @@ func (h *Handler) Put(ctx context.Context, rc io.Reader, size int64,
buffer = nil
<-ready
startWrite := time.Now()
err = h.writeToBlobnodesWithHystrix(ctx, blobident, shards, func() {
err = h.writeToBlobnodesWithHystrix(ctx, blobident, shards, empties, func() {
takeoverBuffer.Release()
ready <- struct{}{}
})
@ -168,11 +181,12 @@ func (h *Handler) Put(ctx context.Context, rc io.Reader, size int64,
}
func (h *Handler) writeToBlobnodesWithHystrix(ctx context.Context,
blob blobIdent, shards [][]byte, callback func()) error {
blob blobIdent, shards [][]byte, empties map[int]struct{}, callback func(),
) error {
safe := make(chan struct{}, 1)
err := hystrix.Do(rwCommand, func() error {
safe <- struct{}{}
return h.writeToBlobnodes(ctx, blob, shards, callback)
return h.writeToBlobnodes(ctx, blob, shards, empties, callback)
}, nil)
select {
@ -192,8 +206,8 @@ type shardPutStatus struct {
// takeover ec buffer release by callback.
// return if had quorum successful shards, then wait all shards in background.
func (h *Handler) writeToBlobnodes(ctx context.Context,
blob blobIdent, shards [][]byte, callback func()) (err error) {
span := trace.SpanFromContextSafe(ctx)
blob blobIdent, shards [][]byte, empties map[int]struct{}, callback func(),
) (err error) {
clusterID, vid, bid := blob.cid, blob.vid, blob.bid
wg := &sync.WaitGroup{}
@ -221,6 +235,14 @@ func (h *Handler) writeToBlobnodes(ctx context.Context,
putQuorum = uint32(num)
}
span := trace.SpanFromContextSafe(ctx)
// new context span to write blobnode in background
span, ctx = trace.StartSpanFromContextWithTraceID(context.Background(), "", span.TraceID())
defer span.Finish()
writeStart := time.Now()
writeTime := int32(0)
// writtenNum ONLY apply on data and partiy shards
// TODO: count N and M in each AZ,
// decision ec data is recoverable or not.
@ -238,28 +260,27 @@ func (h *Handler) writeToBlobnodes(ctx context.Context,
wg.Done()
}()
_, empty := empties[index]
diskID := unit.DiskID
args := &blobnode.PutShardArgs{
DiskID: diskID,
Vuid: unit.Vuid,
Bid: bid,
Size: int64(len(shards[index])),
Type: blobnode.NormalIO,
Type: blobnode.WriteIO,
NopData: empty,
}
crcDisabled := h.ShardCrcDisabled
crcDisable := h.ShardCrcWriteDisable
var crcOrigin uint32
if !crcDisabled {
if !crcDisable {
crcOrigin = crc32.ChecksumIEEE(shards[index])
}
// new child span to write to blobnode, we should finish it here.
spanChild, ctxChild := trace.StartSpanFromContextWithTraceID(
context.Background(), "WriteToBlobnode", span.TraceID())
defer spanChild.Finish()
RETRY:
hostInfo, err := serviceController.GetDiskHost(ctxChild, diskID)
hostInfo, err := serviceController.GetDiskHost(ctx, diskID)
if err != nil {
span.Error("get disk host failed", errors.Detail(err))
return
@ -278,14 +299,28 @@ func (h *Handler) writeToBlobnodes(ctx context.Context,
crc uint32
)
writeErr = retry.ExponentialBackoff(3, 200).RuptOn(func() (bool, error) {
args.Body = bytes.NewReader(shards[index])
if !args.NopData {
args.Body = bytes.NewReader(shards[index])
}
crc, err = h.blobnodeClient.PutShard(ctxChild, host, args)
crc, err = h.blobnodeClient.PutShard(ctx, host, args)
if err == nil {
if !crcDisabled && crc != crcOrigin {
if !crcDisable && crc != crcOrigin {
return false, fmt.Errorf("crc mismatch 0x%x != 0x%x", crc, crcOrigin)
}
// slow disk if speed lower and time greater than most shards, also retry.
if mostTime := atomic.LoadInt32(&writeTime); mostTime > 0 {
shardTime := time.Since(writeStart)
shardSpeed := float32(args.Size) / (float32(shardTime) / 1e9) / (1 << 10)
if int(shardTime/1e6) > h.LogSlowBaseTimeMS &&
shardSpeed < float32(h.LogSlowBaseSpeedKB) &&
float32(shardTime) > h.LogSlowTimeFator*float32(mostTime) {
span.Warnf("slow disk(host:%s diskid:%d) time(most:%dms shard:%dms) speed:%.2fKB/s",
host, diskID, mostTime/1e6, shardTime/1e6, shardSpeed)
}
}
needRetry = false
return true, nil
}
@ -304,7 +339,7 @@ func (h *Handler) writeToBlobnodes(ctx context.Context,
switch code {
// EIO and Readonly error, then we need to punish disk in local and no necessary to retry
case errcode.CodeDiskBroken, errcode.CodeVUIDReadonly:
case errcode.CodeVUIDReadonly:
h.punishVolume(ctx, clusterID, vid, host, "BrokenOrRO")
h.punishDisk(ctx, clusterID, diskID, host, "BrokenOrRO")
span.Warnf("punish disk:%d volume:%d cos:blobnode/%d", diskID, vid, code)
@ -316,9 +351,10 @@ func (h *Handler) writeToBlobnodes(ctx context.Context,
span.Warnf("punish volume:%d cos:blobnode/%d", vid, code)
return true, err
// disk broken may be some chunks have repaired
// vuid not found means the reflection between vuid and diskID has change, we should refresh the volume
// disk not found means disk has been repaired or offline
case errcode.CodeDiskNotFound, errcode.CodeVuidNotFound:
case errcode.CodeDiskBroken, errcode.CodeDiskNotFound, errcode.CodeVuidNotFound:
latestVolume, e := h.getVolume(ctx, clusterID, vid, false)
if e != nil {
return true, errors.Base(err, "get volume with no cache failed").Detail(e)
@ -335,8 +371,12 @@ func (h *Handler) writeToBlobnodes(ctx context.Context,
return true, err
}
h.punishVolume(ctx, clusterID, vid, host, "NotFound")
h.punishDisk(ctx, clusterID, diskID, host, "NotFound")
reason := "NotFound"
if code == errcode.CodeDiskBroken {
reason = "Broken"
}
h.punishVolume(ctx, clusterID, vid, host, reason)
h.punishDisk(ctx, clusterID, diskID, host, reason)
span.Warnf("punish disk:%d volume:%d cos:blobnode/%d", diskID, vid, code)
return true, err
default:
@ -344,8 +384,9 @@ func (h *Handler) writeToBlobnodes(ctx context.Context,
// in timeout case and writtenNum is not satisfied with putQuorum, then should retry
if errorTimeout(err) && atomic.LoadUint32(&writtenNum) < putQuorum {
h.updateVolume(ctx, clusterID, vid)
h.punishDiskWith(ctx, clusterID, diskID, host, "Timeout")
span.Warn("connect timeout, need to punish threshold disk", diskID, host)
span.Warn("timeout need to punish threshold disk", diskID, host)
return false, err
}
@ -373,6 +414,11 @@ func (h *Handler) writeToBlobnodes(ctx context.Context,
for len(received) < len(volume.Units) && atomic.LoadUint32(&writtenNum) < putQuorum {
st := <-statusCh
received[st.index] = st
// trace slow disk after written 3/4 shards
if atomic.LoadInt32(&writeTime) == 0 && len(received) > len(volume.Units)*3/4 {
atomic.StoreInt32(&writeTime, int32(time.Since(writeStart)))
}
}
writeDone := make(chan struct{}, 1)

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"bytes"
@ -28,6 +28,7 @@ import (
"github.com/stretchr/testify/require"
"github.com/cubefs/cubefs/blobstore/api/access"
"github.com/cubefs/cubefs/blobstore/common/codemode"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
)
@ -42,41 +43,41 @@ func TestAccessStreamPutBase(t *testing.T) {
// 0
{
size := 0
_, err := streamer.Put(ctx(), newReader(size), int64(size), nil)
_, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.Error(t, err)
}
// 1 byte
{
size := 1
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil)
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
require.Equal(t, 1, len(loc.Blobs))
require.Equal(t, uint32(1), loc.Blobs[0].Count)
require.Equal(t, 1, len(loc.Slices))
require.Equal(t, uint32(1), loc.Slices[0].Count)
// time wait the punished services
time.Sleep(time.Second * time.Duration(punishServiceS))
}
// <4M
{
size := 1 << 18
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil)
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
require.Equal(t, 1, len(loc.Blobs))
require.Equal(t, uint32(1), loc.Blobs[0].Count)
require.Equal(t, 1, len(loc.Slices))
require.Equal(t, uint32(1), loc.Slices[0].Count)
time.Sleep(time.Second * time.Duration(punishServiceS))
}
// 8M + 1k
{
size := (1 << 23) + 1024
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil)
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
require.Equal(t, 2, len(loc.Blobs))
require.Equal(t, uint32(2), loc.Blobs[1].Count)
require.Equal(t, 2, len(loc.Slices))
require.Equal(t, uint32(2), loc.Slices[1].Count)
time.Sleep(time.Second * time.Duration(punishServiceS))
}
// max size + 1
{
size := defaultMaxObjectSize + 1
_, err := streamer.Put(ctx(), nil, int64(size), nil)
_, err := streamer.Put(ctx(), nil, int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.EqualError(t, errcode.ErrAccessExceedSize, err.Error())
}
@ -97,7 +98,7 @@ func TestAccessStreamPutSum(t *testing.T) {
}
hashSumMap := make(access.HashSumMap, len(hasherMap))
_, err := streamer.Put(ctx(), bytes.NewReader(data), int64(len(data)), hasherMap)
_, err := streamer.Put(ctx(), bytes.NewReader(data), int64(len(data)), hasherMap, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
for alg, hasher := range hasherMap {
hashSumMap[alg] = hasher.Sum(nil)
@ -231,7 +232,7 @@ func TestAccessStreamPutShardTimeout(t *testing.T) {
buff := make([]byte, size)
rand.Read(buff)
startTime := time.Now()
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil)
loc, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
// response immediately if had quorum shards
@ -247,7 +248,7 @@ func TestAccessStreamPutShardTimeout(t *testing.T) {
vuidController.Block(1002)
{
startTime := time.Now()
_, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil)
_, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.Error(t, err)
duration := time.Since(startTime)
@ -259,6 +260,25 @@ func TestAccessStreamPutShardTimeout(t *testing.T) {
}
}
func TestAccessStreamPutShardSlow(t *testing.T) {
ctx := ctxWithName("TestAccessStreamPutShardSlow")
dataShards.clean()
vuidController.SetSlowdown(1001, time.Second)
vuidController.Unbreak(1005)
defer func() {
vuidController.SetSlowdown(1001, -1)
vuidController.Break(1005)
dataShards.clean()
}()
size := 3
buff := make([]byte, size)
rand.Read(buff)
_, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
time.Sleep(time.Second)
}
func TestAccessStreamPutQuorum(t *testing.T) {
ctx := ctxWithName("TestAccessStreamPutQuorum")
defer func() {
@ -299,7 +319,7 @@ func TestAccessStreamPutQuorum(t *testing.T) {
vuidController.Break(id)
}
_, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil)
_, err := streamer.Put(ctx(), bytes.NewReader(buff), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
if cs.hasError {
require.NotNil(t, err)
} else {
@ -313,6 +333,49 @@ func TestAccessStreamPutQuorum(t *testing.T) {
}
}
func TestAccessStreamPutWithClusterIDAndCodeMode(t *testing.T) {
ctx := ctxWithName("TestAccessStreamPutWithClusterIDAndCodeMode")
{
size := 1 << 22
_, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(0), codemode.EC16P20L2)
require.Error(t, err)
}
{
size := 1 << 22
_, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(2), codemode.CodeModeNone)
require.Error(t, err)
}
{
size := 1 << 22
_, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(2), codemode.EC15P12)
require.Error(t, err)
}
{
size := 1 << 20
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(0), codemode.EC6P6)
require.NoError(t, err)
require.Equal(t, codemode.EC6P6, loc.CodeMode)
require.Equal(t, 1, len(loc.Slices))
require.Equal(t, uint32(1), loc.Slices[0].Count)
}
{
size := 1 << 22
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(1), codemode.EC6P6)
require.NoError(t, err)
require.Equal(t, codemode.EC6P6, loc.CodeMode)
require.Equal(t, 1, len(loc.Slices))
require.Equal(t, uint32(1), loc.Slices[0].Count)
}
{
size := 1 << 22
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(1), codemode.CodeModeNone)
require.NoError(t, err)
require.Equal(t, codemode.EC6P6, loc.CodeMode)
require.Equal(t, 1, len(loc.Slices))
require.Equal(t, uint32(1), loc.Slices[0].Count)
}
}
func BenchmarkAccessStreamPut(b *testing.B) {
ctx := ctxWithName("BenchmarkAccessStreamPut")()
vuidController.Unbreak(1005)
@ -338,7 +401,7 @@ func BenchmarkAccessStreamPut(b *testing.B) {
b.ResetTimer()
b.Run(cs.name, func(b *testing.B) {
for ii := 0; ii <= b.N; ii++ {
streamer.Put(ctx, bytes.NewReader(buff[:cs.size]), int64(cs.size), nil)
streamer.Put(ctx, bytes.NewReader(buff[:cs.size]), int64(cs.size), nil, proto.ClusterID(0), codemode.CodeModeNone)
}
})
}

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"context"
@ -33,8 +33,9 @@ import (
// required: size, one blob size
// optional: hasherMap, computing hash
func (h *Handler) PutAt(ctx context.Context, rc io.Reader,
clusterID proto.ClusterID, vid proto.Vid, bid proto.BlobID, size int64,
hasherMap access.HasherMap) error {
clusterID proto.ClusterID, vid proto.Vid, bid proto.BlobID,
size int64, hasherMap access.HasherMap,
) error {
span := trace.SpanFromContextSafe(ctx)
span.Debugf("putat request cluster:%d vid:%d bid:%d size:%d hashes:b(%b)",
clusterID, vid, bid, size, hasherMap.ToHashAlgorithm())
@ -55,12 +56,14 @@ func (h *Handler) PutAt(ctx context.Context, rc io.Reader,
if err != nil {
return err
}
empties := emptyDataShardIndexes(buffer.BufferSizes)
putTime := new(timeReadWrite)
putTime.IncA(time.Since(st))
defer func() {
buffer.Release()
span.AppendRPCTrackLog([]string{putTime.String()})
putTime.Report(clusterID.ToString(), h.IDC, true)
}()
shards, err := encoder.Split(buffer.ECDataBuf)
@ -90,7 +93,7 @@ func (h *Handler) PutAt(ctx context.Context, rc io.Reader,
takeoverBuffer := buffer
buffer = nil
startWrite := time.Now()
err = h.writeToBlobnodesWithHystrix(ctx, blobident, shards, func() {
err = h.writeToBlobnodesWithHystrix(ctx, blobident, shards, empties, func() {
takeoverBuffer.Release()
})
putTime.IncW(time.Since(startWrite))

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"bytes"

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"bytes"
@ -24,6 +24,7 @@ import (
"github.com/cubefs/cubefs/blobstore/access/controller"
"github.com/cubefs/cubefs/blobstore/common/codemode"
"github.com/cubefs/cubefs/blobstore/common/proto"
)
func newReader(size int) io.Reader {
@ -44,25 +45,42 @@ func TestAccessStreamConfig(t *testing.T) {
ConsulAgentAddr: "http://127.0.0.1:8500",
},
}
confCheck(&cfg)
err := confCheck(&cfg)
require.NoError(t, err)
require.Equal(t, idcOther, cfg.IDC)
require.Equal(t, map[int]int{1024: 1}, cfg.MemPoolSizeClasses)
require.Equal(t, defaultDiskPunishIntervalS, cfg.DiskPunishIntervalS)
cfg = StreamConfig{
IDC: idcOther,
MemPoolSizeClasses: map[int]int{1024: 1},
CodeModesPutQuorums: map[codemode.CodeMode]int{
codemode.EC15P12: 16,
codemode.EC6P10L2: 18,
},
ClusterConfig: controller.ClusterConfig{
Clusters: []controller.Cluster{
{ClusterID: 1, Hosts: []string{"host1"}},
{ClusterID: 2, Hosts: []string{"host2"}},
},
},
}
err = confCheck(&cfg)
require.NoError(t, err)
}
func TestAccessStreamNew(t *testing.T) {
require.Equal(t, idc, streamer.IDC)
require.Panics(t, func() {
NewStreamHandler(&StreamConfig{IDC: "idc"}, nil)
})
_, err := NewStreamHandler(&StreamConfig{IDC: "idc"}, nil)
require.NotNil(t, err)
}
func TestAccessStreamDelete(t *testing.T) {
ctx := ctxWithName("TestAccessStreamDelete")
size := 1 << 18
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil)
loc, err := streamer.Put(ctx(), newReader(size), int64(size), nil, proto.ClusterID(0), codemode.CodeModeNone)
require.NoError(t, err)
err = streamer.Delete(ctx(), loc)
@ -77,19 +95,19 @@ func TestAccessStreamAdmin(t *testing.T) {
sa := handler.Admin()
require.NotNil(t, sa)
admin := sa.(*streamAdmin)
require.Nil(t, admin.memPool)
require.Nil(t, admin.controller)
admin := sa.(*StreamAdmin)
require.Nil(t, admin.MemPool)
require.Nil(t, admin.Controller)
}
{
sa := streamer.Admin()
require.NotNil(t, sa)
admin := sa.(*streamAdmin)
require.NotNil(t, admin.memPool)
t.Log("mempool status:", admin.memPool.Status())
admin := sa.(*StreamAdmin)
require.NotNil(t, admin.MemPool)
t.Log("mempool status:", admin.MemPool.Status())
ctr := admin.controller
ctr := admin.Controller
require.NotNil(t, ctr)
t.Log("region:", ctr.Region())
require.Error(t, ctr.ChangeChooseAlg(controller.AlgChoose(100)))

View File

@ -12,7 +12,7 @@
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package access
package stream
import (
"fmt"
@ -38,6 +38,16 @@ func (t *timeReadWrite) IncW(dur time.Duration) {
atomic.AddInt64(&t.w, int64(dur))
}
func (t *timeReadWrite) Report(cid, idc string, upload bool) {
if upload {
reportReadwrite(cid, idc, "upload_read", atomic.LoadInt64(&t.r)/1e6)
reportReadwrite(cid, idc, "upload_write", atomic.LoadInt64(&t.w)/1e6)
} else {
reportReadwrite(cid, idc, "download_read", atomic.LoadInt64(&t.r)/1e6)
reportReadwrite(cid, idc, "download_write", atomic.LoadInt64(&t.w)/1e6)
}
}
// String within milliseconds
func (t *timeReadWrite) String() string {
a := atomic.LoadInt64(&t.a) / 1e6

View File

@ -22,12 +22,13 @@ import (
"net/http"
"runtime"
"sort"
"sync"
"sync/atomic"
"time"
"github.com/hashicorp/consul/api"
"gopkg.in/natefinch/lumberjack.v2"
"github.com/cubefs/cubefs/blobstore/api/shardnode"
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/resourcepool"
@ -42,9 +43,7 @@ import (
const (
defaultMaxSizePutOnce int64 = 1 << 28 // 256MB
defaultMaxPartRetry int = 3
defaultMaxHostRetry int = 3
defaultPartConcurrence int = 4
defaultServiceInterval int = 3600 // one hour.
defaultServiceName = "access"
)
@ -52,9 +51,7 @@ const (
type RPCConnectMode uint8
// timeout: [short - - - - - - - - -> long]
//
// quick --> general --> default --> slow --> nolimit
//
// ----- quick --> general --> default --> slow --> nolimit
// speed: 40MB --> 20MB --> 10MB --> 4MB --> nolimit
const (
DefaultConnMode RPCConnectMode = iota
@ -91,9 +88,7 @@ func (mode RPCConnectMode) getConfig(speed float64, timeout, baseTimeout int64)
BodyBaseTimeoutMs: getBaseTimeout(30 * 1000),
Tc: rpc.TransportConfig{
// dial timeout
DialTimeoutMs: 5 * 1000,
// response header timeout after send the request
ResponseHeaderTimeoutMs: 5 * 1000,
DialTimeoutMs: 200,
// IdleConnTimeout is the maximum amount of time an idle
// (keep-alive) connection will remain idle before closing
// itself.Zero means no limit.
@ -111,29 +106,21 @@ func (mode RPCConnectMode) getConfig(speed float64, timeout, baseTimeout int64)
config.ClientTimeoutMs = getTimeout(getSpeed(40))
config.BodyBandwidthMBPs = getSpeed(40)
config.BodyBaseTimeoutMs = getBaseTimeout(3 * 1000)
config.Tc.DialTimeoutMs = 2 * 1000
config.Tc.ResponseHeaderTimeoutMs = 2 * 1000
config.Tc.IdleConnTimeoutMs = 10 * 1000
case GeneralConnMode:
config.ClientTimeoutMs = getTimeout(getSpeed(20))
config.BodyBandwidthMBPs = getSpeed(20)
config.BodyBaseTimeoutMs = getBaseTimeout(10 * 1000)
config.Tc.DialTimeoutMs = 3 * 1000
config.Tc.ResponseHeaderTimeoutMs = 3 * 1000
config.Tc.IdleConnTimeoutMs = 30 * 1000
case SlowConnMode:
config.ClientTimeoutMs = getTimeout(getSpeed(4))
config.BodyBandwidthMBPs = getSpeed(4)
config.BodyBaseTimeoutMs = getBaseTimeout(120 * 1000)
config.Tc.DialTimeoutMs = 10 * 1000
config.Tc.ResponseHeaderTimeoutMs = 10 * 1000
config.Tc.IdleConnTimeoutMs = 60 * 1000
case NoLimitConnMode:
config.ClientTimeoutMs = 0
config.BodyBandwidthMBPs = getSpeed(0)
config.BodyBaseTimeoutMs = getBaseTimeout(0)
config.Tc.DialTimeoutMs = 0
config.Tc.ResponseHeaderTimeoutMs = 0
config.Tc.IdleConnTimeoutMs = 600 * 1000
default:
}
@ -144,61 +131,62 @@ func (mode RPCConnectMode) getConfig(speed float64, timeout, baseTimeout int64)
// Config access client config
type Config struct {
// ConnMode rpc connection timeout setting
ConnMode RPCConnectMode
ConnMode RPCConnectMode `json:"connection_mode"`
// ClientTimeoutMs the whole request and response timeout
ClientTimeoutMs int64
ClientTimeoutMs int64 `json:"client_timeout_ms"`
// BodyBandwidthMBPs reading body timeout, request or response
// timeout = ContentLength/BodyBandwidthMBPs + BodyBaseTimeoutMs
BodyBandwidthMBPs float64
BodyBandwidthMBPs float64 `json:"body_bandwidth_mbps"`
// BodyBaseTimeoutMs base timeout for read body
BodyBaseTimeoutMs int64
BodyBaseTimeoutMs int64 `json:"body_base_timeout_ms"`
// Consul is consul config for discovering service
Consul ConsulConfig
// ServiceIntervalS is interval seconds for discovering service
ServiceIntervalS int
Consul ConsulConfig `json:"consul"`
// ServiceIntervalS is interval seconds for discovering service hosts,
// at least 5 seconds and default is 5 minutes.
ServiceIntervalS int `json:"service_interval_s"`
// PriorityAddrs priority addrs of access service when retry
PriorityAddrs []string
// MaxSizePutOnce max size using once-put object interface
MaxSizePutOnce int64
PriorityAddrs []string `json:"priority_addrs"`
// MaxSizePutOnce max size using once-put object interface, default is 256MB.
MaxSizePutOnce int64 `json:"max_size_put_once"`
// MaxPartRetry max retry times when putting one part, 0 means forever
MaxPartRetry int
// MaxHostRetry max retry hosts of access service
MaxHostRetry int
MaxPartRetry int `json:"max_part_retry"`
// MaxHostRetry max retry hosts of access, default all hosts.
MaxHostRetry int `json:"max_host_retry"`
// PartConcurrence concurrence of put parts
PartConcurrence int
PartConcurrence int `json:"part_concurrence"`
// rpc selector config
// Failure retry interval, default value is -1, if FailRetryIntervalS < 0,
// remove failed hosts will not work.
FailRetryIntervalS int
// Failure retry interval, default value is 300s,
// if FailRetryIntervalS < 0, remove failed hosts will not work.
FailRetryIntervalS int `json:"fail_retry_interval_s"`
// Within MaxFailsPeriodS, if the number of failures is greater than or equal to MaxFails,
// the host is considered disconnected.
MaxFailsPeriodS int
MaxFailsPeriodS int `json:"max_fails_period_s"`
// HostTryTimes Number of host failure retries
HostTryTimes int
HostTryTimes int `json:"host_try_times"`
// RPCConfig user-defined rpc config
// All connections will use the config if it's not nil
// ConnMode will be ignored if rpc config is setting
RPCConfig *rpc.Config
RPCConfig *rpc.Config `json:"rpc_config"`
// LogLevel client output logging level.
LogLevel log.Level
LogLevel log.Level `json:"log_level"`
// Logger trace all logging to the logger if setting.
// It is an io.WriteCloser that writes to the specified filename.
// YOU should CLOSE it after you do not use the client anymore.
Logger *Logger
Logger *Logger `json:"logger"`
}
// ConsulConfig alias of consul api.Config
// Fixup: client and sdk using the same config type
type ConsulConfig = api.Config
// Logger alias of lumberjack Logger
// Logger alias of AsyncLogger
// See more at: https://github.com/natefinch/lumberjack
type Logger = lumberjack.Logger
type Logger = log.AsyncLogger
// client access rpc client
type client struct {
@ -215,12 +203,24 @@ type API interface {
//
// If PutArgs' body is of type *bytes.Buffer, *bytes.Reader, or *strings.Reader,
// GetBody is populated, then the Put once request has retry ability.
Put(ctx context.Context, args *PutArgs) (location Location, hashSumMap HashSumMap, err error)
Put(ctx context.Context, args *PutArgs) (location proto.Location, hashSumMap HashSumMap, err error)
// Get object, range is supported.
Get(ctx context.Context, args *GetArgs) (body io.ReadCloser, err error)
// Delete all blobs in these locations.
// return failed locations which have yet been deleted if error is not nil.
Delete(ctx context.Context, args *DeleteArgs) (failedLocations []Location, err error)
//
// Returns:
// - (nil, nil): all blobs deleted successfully.
// - (nil, ErrIllegalArguments): when args is invalid.
// - (failedLocations, err): returns the list of locations that have not yet been deleted.
Delete(ctx context.Context, args *DeleteArgs) (failedLocations []proto.Location, err error)
}
type Client interface {
API
ListBlob(ctx context.Context, args *ListBlobArgs) (shardnode.ListBlobRet, error)
GetBlob(ctx context.Context, args *GetBlobArgs) (io.ReadCloser, error)
DeleteBlob(ctx context.Context, args *DelBlobArgs) error
PutBlob(ctx context.Context, args *PutBlobArgs) (proto.ClusterID, HashSumMap, error)
}
var _ API = (*client)(nil)
@ -232,28 +232,42 @@ var _ io.ReadCloser = (*noopBody)(nil)
func (rc noopBody) Read(p []byte) (n int, err error) { return 0, io.EOF }
func (rc noopBody) Close() error { return nil }
var memPool *resourcepool.MemPool
var (
memPool *resourcepool.MemPool
poolOnce sync.Once
)
func init() {
memPool = resourcepool.NewMemPool(map[int]int{
1 << 12: -1,
1 << 14: -1,
1 << 18: -1,
1 << 20: -1,
1 << 22: -1,
1 << 23: -1,
1 << 24: -1,
func lazyInitSingletonMemPool() {
poolOnce.Do(func() {
if memPool == nil {
memPool = resourcepool.NewMemPool(map[int]int{
1 << 12: -1,
1 << 14: -1,
1 << 18: -1,
1 << 20: -1,
1 << 22: -1,
1 << 23: -1,
1 << 24: -1,
})
}
})
}
// ResetMemoryPool is thread unsafe, call it on init.
func ResetMemoryPool(sizeClasses map[int]int) {
memPool = resourcepool.NewMemPool(sizeClasses)
}
// New returns an access API
func New(cfg Config) (API, error) {
defaulter.LessOrEqual(&cfg.MaxSizePutOnce, defaultMaxSizePutOnce)
defaulter.Less(&cfg.MaxPartRetry, defaultMaxPartRetry)
defaulter.LessOrEqual(&cfg.MaxHostRetry, defaultMaxHostRetry)
defaulter.LessOrEqual(&cfg.PartConcurrence, defaultPartConcurrence)
if cfg.ServiceIntervalS < 300 { // at least 5 minutes
cfg.ServiceIntervalS = defaultServiceInterval
defaulter.Equal(&cfg.FailRetryIntervalS, 300)
defaulter.LessOrEqual(&cfg.MaxFailsPeriodS, 10)
defaulter.Equal(&cfg.ServiceIntervalS, 300) // 5 minutes
if cfg.ServiceIntervalS < 5 {
cfg.ServiceIntervalS = 5
}
log.SetOutputLevel(cfg.LogLevel)
@ -261,6 +275,8 @@ func New(cfg Config) (API, error) {
log.SetOutput(cfg.Logger)
}
lazyInitSingletonMemPool()
c := &client{
config: cfg,
stop: make(chan struct{}),
@ -322,10 +338,11 @@ func New(cfg Config) (API, error) {
}
c.rpcClient.Store(getClient(&cfg, hosts))
ticker := time.NewTicker(time.Duration(cfg.ServiceIntervalS) * time.Second)
go func() {
ticker := time.NewTicker(time.Duration(cfg.ServiceIntervalS) * time.Second)
defer ticker.Stop()
for {
old := hosts
old := hosts[:]
select {
case <-ticker.C:
hosts, err = hostGetter()
@ -338,10 +355,10 @@ func New(cfg Config) (API, error) {
if ok && oldClient != nil {
oldClient.Close()
}
log.Warnf("update hosts of client (%v) -> (%v)", old, hosts)
c.rpcClient.Store(getClient(&cfg, hosts))
}
case <-c.stop:
ticker.Stop()
return
}
}
@ -387,13 +404,13 @@ func getClient(cfg *Config, hosts []string) rpc.Client {
return rpc.NewLbClient(lbConfig, nil)
}
func (c *client) Put(ctx context.Context, args *PutArgs) (location Location, hashSumMap HashSumMap, err error) {
func (c *client) Put(ctx context.Context, args *PutArgs) (location proto.Location, hashSumMap HashSumMap, err error) {
if args.Size == 0 {
hashSumMap := args.Hashes.ToHashSumMap()
for alg := range hashSumMap {
hashSumMap[alg] = alg.ToHasher().Sum(nil)
}
return Location{Blobs: make([]SliceInfo, 0)}, hashSumMap, nil
return proto.Location{Slices: make([]proto.Slice, 0)}, hashSumMap, nil
}
ctx = withReqidContext(ctx)
@ -403,14 +420,19 @@ func (c *client) Put(ctx context.Context, args *PutArgs) (location Location, has
return c.putParts(ctx, args)
}
func (c *client) putObject(ctx context.Context, args *PutArgs) (location Location, hashSumMap HashSumMap, err error) {
func (c *client) putObject(ctx context.Context, args *PutArgs) (location proto.Location, hashSumMap HashSumMap, err error) {
rpcClient := c.rpcClient.Load().(rpc.Client)
urlStr := fmt.Sprintf("/put?size=%d&hashes=%d", args.Size, args.Hashes)
urlStr := fmt.Sprintf("/put?size=%d&hashes=%d&assign_cluster_id=%d&code_mode=%d",
args.Size, args.Hashes, args.AssignClusterID, args.CodeMode)
req, err := http.NewRequest(http.MethodPut, urlStr, args.Body)
if err != nil {
return
}
if args.GetBody != nil {
req.GetBody = args.GetBody
}
resp := &PutResp{}
if err = rpcClient.DoWith(ctx, req, resp, rpc.WithCrcEncode()); err == nil {
@ -447,7 +469,8 @@ func (c *client) putPartsBatch(ctx context.Context, parts []blobPart) error {
})
}
if err := task.Run(context.Background(), tasks...); err != nil {
newCtx := trace.NewContextFromContext(ctx)
if err := task.Run(ctx, tasks...); err != nil {
for _, part := range parts {
part := part
// asynchronously delete blob
@ -458,7 +481,7 @@ func (c *client) putPartsBatch(ctx context.Context, parts []blobPart) error {
if err != nil {
return
}
rpcClient.DoWith(ctx, req, nil)
rpcClient.DoWith(newCtx, req, nil)
}()
}
return err
@ -467,7 +490,8 @@ func (c *client) putPartsBatch(ctx context.Context, parts []blobPart) error {
}
func (c *client) readerPipeline(span trace.Span, reqBody io.Reader,
closeCh <-chan struct{}, size, blobSize int) <-chan []byte {
closeCh <-chan struct{}, size, blobSize int,
) <-chan []byte {
ch := make(chan []byte, c.config.PartConcurrence-1)
go func() {
for size > 0 {
@ -501,7 +525,7 @@ func (c *client) readerPipeline(span trace.Span, reqBody io.Reader,
return ch
}
func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSumMap, error) {
func (c *client) putParts(ctx context.Context, args *PutArgs) (proto.Location, HashSumMap, error) {
span := trace.SpanFromContextSafe(ctx)
rpcClient := c.rpcClient.Load().(rpc.Client)
@ -517,7 +541,7 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
}
var (
loc Location
loc proto.Location
tokens []string
)
@ -528,16 +552,18 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
return
}
// force to clean up, even canceled context
newCtx := trace.NewContextFromSpan(span)
locations := signArgs.Locations[:]
if len(locations) > 1 {
signArgs.Location = loc.Copy()
signResp := &SignResp{}
if err := rpcClient.PostWith(ctx, "/sign", signResp, signArgs); err == nil {
locations = []Location{signResp.Location.Copy()}
if err := rpcClient.PostWith(newCtx, "/sign", signResp, signArgs); err == nil {
locations = []proto.Location{signResp.Location.Copy()}
}
}
if len(locations) > 0 {
if _, err := c.Delete(ctx, &DeleteArgs{Locations: locations}); err != nil {
if _, err := c.Delete(newCtx, &DeleteArgs{Locations: locations}); err != nil {
span.Warnf("clean location '%+v' failed %s", locations, err.Error())
}
}
@ -545,7 +571,12 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
// alloc
allocResp := &AllocResp{}
if err := rpcClient.PostWith(ctx, "/alloc", allocResp, AllocArgs{Size: uint64(args.Size)}); err != nil {
allocArgs := &AllocArgs{
Size: uint64(args.Size),
AssignClusterID: args.AssignClusterID,
CodeMode: args.CodeMode,
}
if err := rpcClient.PostWith(ctx, "/alloc", allocResp, allocArgs); err != nil {
return allocResp.Location, nil, err
}
loc = allocResp.Location
@ -554,7 +585,7 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
// buffer pipeline
closeCh := make(chan struct{})
bufferPipe := c.readerPipeline(span, reqBody, closeCh, int(loc.Size), int(loc.BlobSize))
bufferPipe := c.readerPipeline(span, reqBody, closeCh, int(loc.Size_), int(loc.SliceSize))
defer func() {
close(closeCh)
// waiting pipeline close if has error
@ -573,17 +604,17 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
currBlobIdx := 0
currBlobCount := uint32(0)
remainSize := loc.Size
remainSize := loc.Size_
restPartsLoc := loc
readSize := 0
for readSize < int(loc.Size) {
for readSize < int(loc.Size_) {
parts := make([]blobPart, 0, c.config.PartConcurrence)
// waiting at least one blob
buf, ok := <-bufferPipe
if !ok && readSize < int(loc.Size) {
return Location{}, nil, errcode.ErrAccessReadRequestBody
if !ok && readSize < int(loc.Size_) {
return proto.Location{}, nil, errcode.ErrAccessReadRequestBody
}
readSize += len(buf)
parts = append(parts, blobPart{size: len(buf), buf: buf})
@ -593,9 +624,9 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
select {
case buf, ok := <-bufferPipe:
if !ok {
if readSize < int(loc.Size) {
if readSize < int(loc.Size_) {
releaseBuffer(parts)
return Location{}, nil, errcode.ErrAccessReadRequestBody
return proto.Location{}, nil, errcode.ErrAccessReadRequestBody
}
more = false
} else {
@ -609,9 +640,9 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
tryTimes := c.config.MaxPartRetry
for {
if len(loc.Blobs) > MaxLocationBlobs {
if len(loc.Slices) > MaxLocationBlobs {
releaseBuffer(parts)
return Location{}, nil, errcode.ErrUnexpected
return proto.Location{}, nil, errcode.ErrUnexpected
}
// feed new params
@ -619,16 +650,16 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
currCount := currBlobCount
for i := range parts {
token := tokens[currIdx]
if restPartsLoc.Size > uint64(loc.BlobSize) && parts[i].size < int(loc.BlobSize) {
token = tokens[currIdx+1]
if restPartsLoc.Size_ > uint64(loc.SliceSize) && parts[i].size < int(loc.SliceSize) {
token = tokens[len(tokens)-1]
}
parts[i].token = token
parts[i].cid = loc.ClusterID
parts[i].vid = loc.Blobs[currIdx].Vid
parts[i].bid = loc.Blobs[currIdx].MinBid + proto.BlobID(currCount)
parts[i].vid = loc.Slices[currIdx].Vid
parts[i].bid = loc.Slices[currIdx].MinSliceID + proto.BlobID(currCount)
currCount++
if loc.Blobs[currIdx].Count == currCount {
if loc.Slices[currIdx].Count == currCount {
currIdx++
currCount = 0
}
@ -640,7 +671,7 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
remainSize -= uint64(part.size)
currBlobCount++
// next blobs
if loc.Blobs[currBlobIdx].Count == currBlobCount {
if loc.Slices[currBlobIdx].Count == currBlobCount {
currBlobIdx++
currBlobCount = 0
}
@ -654,7 +685,7 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
if tryTimes == 1 {
releaseBuffer(parts)
span.Error("exceed the max retry limit", c.config.MaxPartRetry)
return Location{}, nil, errcode.ErrUnexpected
return proto.Location{}, nil, errcode.ErrUnexpected
}
tryTimes--
}
@ -665,14 +696,14 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
resp := &AllocResp{}
if err := rpcClient.PostWith(ctx, "/alloc", resp, AllocArgs{
Size: remainSize,
BlobSize: loc.BlobSize,
BlobSize: loc.SliceSize,
CodeMode: loc.CodeMode,
AssignClusterID: loc.ClusterID,
}); err != nil {
return true, err
}
if len(resp.Location.Blobs) > 0 {
if newVid := resp.Location.Blobs[0].Vid; newVid == loc.Blobs[currBlobIdx].Vid {
if len(resp.Location.Slices) > 0 {
if newVid := resp.Location.Slices[0].Vid; newVid == loc.Slices[currBlobIdx].Vid {
return false, fmt.Errorf("alloc the same vid %d", newVid)
}
}
@ -682,17 +713,17 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
if err != nil {
releaseBuffer(parts)
span.Error("alloc another parts to put", err)
return Location{}, nil, errcode.ErrUnexpected
return proto.Location{}, nil, err
}
restPartsLoc = restPartsResp.Location
signArgs.Locations = append(signArgs.Locations, restPartsLoc.Copy())
if currBlobCount > 0 {
loc.Blobs[currBlobIdx].Count = currBlobCount
loc.Slices[currBlobIdx].Count = currBlobCount
currBlobIdx++
}
loc.Blobs = append(loc.Blobs[:currBlobIdx], restPartsLoc.Blobs...)
loc.Slices = append(loc.Slices[:currBlobIdx], restPartsLoc.Slices...)
tokens = append(tokens[:currBlobIdx], restPartsResp.Tokens...)
currBlobCount = 0
@ -707,7 +738,7 @@ func (c *client) putParts(ctx context.Context, args *PutArgs) (Location, HashSum
signResp := &SignResp{}
if err := rpcClient.PostWith(ctx, "/sign", signResp, signArgs); err != nil {
span.Error("sign location with crc", err)
return Location{}, nil, errcode.ErrUnexpected
return proto.Location{}, nil, err
}
loc = signResp.Location
}
@ -726,7 +757,7 @@ func (c *client) Get(ctx context.Context, args *GetArgs) (body io.ReadCloser, er
rpcClient := c.rpcClient.Load().(rpc.Client)
ctx = withReqidContext(ctx)
if args.Location.Size == 0 || args.ReadSize == 0 {
if args.Location.Size_ == 0 || args.ReadSize == 0 {
return noopBody{}, nil
}
@ -741,7 +772,7 @@ func (c *client) Get(ctx context.Context, args *GetArgs) (body io.ReadCloser, er
return resp.Body, nil
}
func (c *client) Delete(ctx context.Context, args *DeleteArgs) ([]Location, error) {
func (c *client) Delete(ctx context.Context, args *DeleteArgs) ([]proto.Location, error) {
if !args.IsValid() {
if args == nil {
return nil, errcode.ErrIllegalArguments
@ -751,9 +782,9 @@ func (c *client) Delete(ctx context.Context, args *DeleteArgs) ([]Location, erro
rpcClient := c.rpcClient.Load().(rpc.Client)
ctx = withReqidContext(ctx)
locations := make([]Location, 0, len(args.Locations))
locations := make([]proto.Location, 0, len(args.Locations))
for _, loc := range args.Locations {
if loc.Size > 0 {
if loc.Size_ > 0 {
locations = append(locations, loc.Copy())
}
}

View File

@ -31,6 +31,8 @@ const (
reqidKey
)
var ClientWithReqidContext = withReqidContext
// WithRequestID trace request id in full life of the request
// The second parameter rid could be the one of type below:
//

View File

@ -21,7 +21,6 @@ import (
"fmt"
"hash/crc32"
"io"
"io/ioutil"
mrand "math/rand"
"net/http"
"net/http/httptest"
@ -39,8 +38,8 @@ import (
errcode "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/common/security"
"github.com/cubefs/cubefs/blobstore/common/trace"
"github.com/cubefs/cubefs/blobstore/common/uptoken"
_ "github.com/cubefs/cubefs/blobstore/testing/nolog"
"github.com/cubefs/cubefs/blobstore/util/bytespool"
"github.com/cubefs/cubefs/blobstore/util/log"
@ -158,60 +157,60 @@ func handleAlloc(c *rpc.Context) {
return
}
loc := access.Location{
loc := proto.Location{
ClusterID: 1,
Size: args.Size,
BlobSize: blobSize,
Blobs: []access.SliceInfo{
Size_: args.Size,
SliceSize: blobSize,
Slices: []proto.Slice{
{
MinBid: proto.BlobID(mrand.Int()),
Vid: proto.Vid(mrand.Int()),
Count: uint32((args.Size + blobSize - 1) / blobSize),
MinSliceID: proto.BlobID(mrand.Int()),
Vid: proto.Vid(mrand.Int()),
Count: uint32((args.Size + blobSize - 1) / blobSize),
},
},
}
// split to two blobs if large enough
if loc.Blobs[0].Count > 2 {
loc.Blobs[0].Count = 2
loc.Blobs = append(loc.Blobs, []access.SliceInfo{
if loc.Slices[0].Count > 2 {
loc.Slices[0].Count = 2
loc.Slices = append(loc.Slices, []proto.Slice{
{
MinBid: proto.BlobID(mrand.Int()),
Vid: proto.Vid(mrand.Int()),
Count: uint32((args.Size - 2*blobSize + blobSize - 1) / blobSize),
MinSliceID: proto.BlobID(mrand.Int()),
Vid: proto.Vid(mrand.Int()),
Count: uint32((args.Size - 2*blobSize + blobSize - 1) / blobSize),
},
}...)
}
// alloc the rest parts
if args.AssignClusterID > 0 {
loc.Blobs = []access.SliceInfo{
loc.Slices = []proto.Slice{
{
MinBid: proto.BlobID(mrand.Int()),
Vid: proto.Vid(mrand.Int()),
Count: uint32((args.Size + blobSize - 1) / blobSize),
MinSliceID: proto.BlobID(mrand.Int()),
Vid: proto.Vid(mrand.Int()),
Count: uint32((args.Size + blobSize - 1) / blobSize),
},
}
}
tokens := make([]string, 0, len(loc.Blobs)+1)
tokens := make([]string, 0, len(loc.Slices)+1)
hasMultiBlobs := loc.Size >= uint64(loc.BlobSize)
lastSize := uint32(loc.Size % uint64(loc.BlobSize))
for idx, blob := range loc.Blobs {
hasMultiBlobs := loc.Size_ >= uint64(loc.SliceSize)
lastSize := uint32(loc.Size_ % uint64(loc.SliceSize))
for idx, blob := range loc.Slices {
// returns one token if size < blobsize
if hasMultiBlobs {
count := blob.Count
if idx == len(loc.Blobs)-1 && lastSize > 0 {
if idx == len(loc.Slices)-1 && lastSize > 0 {
count--
}
tokens = append(tokens, uptoken.EncodeToken(uptoken.NewUploadToken(loc.ClusterID,
blob.Vid, blob.MinBid, count,
loc.BlobSize, 0, tokenAlloc[:])))
tokens = append(tokens, security.EncodeToken(security.NewUploadToken(loc.ClusterID,
blob.Vid, blob.MinSliceID, count,
loc.SliceSize, 0, tokenAlloc[:])))
}
// token of the last blob
if idx == len(loc.Blobs)-1 && lastSize > 0 {
tokens = append(tokens, uptoken.EncodeToken(uptoken.NewUploadToken(loc.ClusterID,
blob.Vid, blob.MinBid+proto.BlobID(blob.Count)-1, 1,
if idx == len(loc.Slices)-1 && lastSize > 0 {
tokens = append(tokens, security.EncodeToken(security.NewUploadToken(loc.ClusterID,
blob.Vid, blob.MinSliceID+proto.BlobID(blob.Count)-1, 1,
lastSize, 0, tokenAlloc[:])))
}
}
@ -252,7 +251,7 @@ func handlePut(c *rpc.Context) {
hashSumMap[alg] = hasher.Sum(nil)
}
loc := access.Location{Size: uint64(args.Size)}
loc := proto.Location{Size_: uint64(args.Size)}
fillCrc(&loc)
c.RespondJSON(access.PutResp{
Location: loc,
@ -272,7 +271,7 @@ func handlePutAt(c *rpc.Context) {
return
}
token := uptoken.DecodeToken(args.Token)
token := security.DecodeToken(args.Token)
if !token.IsValid(args.ClusterID, args.Vid, args.BlobID, uint32(args.Size), tokenPutat[:]) {
c.RespondStatus(http.StatusForbidden)
return
@ -299,7 +298,7 @@ func handleGet(c *rpc.Context) {
return
}
if args.Location.Size == 100 {
if args.Location.Size_ == 100 {
c.RespondStatus(http.StatusBadRequest)
return
}
@ -360,7 +359,7 @@ func handleSign(c *rpc.Context) {
c.RespondJSON(access.SignResp{Location: args.Location})
}
func calcCrc(loc *access.Location) (uint32, error) {
func calcCrc(loc *proto.Location) (uint32, error) {
crcWriter := crc32.New(crc32.IEEETable)
buf := bytespool.Alloc(1024)
@ -378,7 +377,7 @@ func calcCrc(loc *access.Location) (uint32, error) {
return crcWriter.Sum32(), nil
}
func fillCrc(loc *access.Location) error {
func fillCrc(loc *proto.Location) error {
crc, err := calcCrc(loc)
if err != nil {
return err
@ -387,7 +386,7 @@ func fillCrc(loc *access.Location) error {
return nil
}
func verifyCrc(loc *access.Location) bool {
func verifyCrc(loc *proto.Location) bool {
crc, err := calcCrc(loc)
if err != nil {
return false
@ -395,13 +394,13 @@ func verifyCrc(loc *access.Location) bool {
return loc.Crc == crc
}
func signCrc(loc *access.Location, locs []access.Location) error {
func signCrc(loc *proto.Location, locs []proto.Location) error {
first := locs[0]
bids := make(map[proto.BlobID]struct{}, 64)
if loc.ClusterID != first.ClusterID ||
loc.CodeMode != first.CodeMode ||
loc.BlobSize != first.BlobSize {
loc.SliceSize != first.SliceSize {
return fmt.Errorf("not equal in constant field")
}
@ -413,20 +412,20 @@ func signCrc(loc *access.Location, locs []access.Location) error {
// assert
if l.ClusterID != first.ClusterID ||
l.CodeMode != first.CodeMode ||
l.BlobSize != first.BlobSize {
l.SliceSize != first.SliceSize {
return fmt.Errorf("not equal in constant field")
}
for _, blob := range l.Blobs {
for _, blob := range l.Slices {
for c := 0; c < int(blob.Count); c++ {
bids[blob.MinBid+proto.BlobID(c)] = struct{}{}
bids[blob.MinSliceID+proto.BlobID(c)] = struct{}{}
}
}
}
for _, blob := range loc.Blobs {
for _, blob := range loc.Slices {
for c := 0; c < int(blob.Count); c++ {
bid := blob.MinBid + proto.BlobID(c)
bid := blob.MinSliceID + proto.BlobID(c)
if _, ok := bids[bid]; !ok {
return fmt.Errorf("not equal in blob_id(%d)", bid)
}
@ -501,10 +500,10 @@ func TestAccessClientConnectionMode(t *testing.T) {
if cs.size <= 0 {
continue
}
loc := access.Location{Size: uint64(mrand.Int63n(cs.size))}
loc := proto.Location{Size_: uint64(mrand.Int63n(cs.size))}
fillCrc(&loc)
_, err = cli.Delete(randCtx(), &access.DeleteArgs{
Locations: []access.Location{loc},
Locations: []proto.Location{loc},
})
require.NoError(t, err)
}
@ -546,7 +545,7 @@ func TestAccessClientPutGet(t *testing.T) {
}
// test code 400
_, err := client.Get(randCtx(), &access.GetArgs{Location: access.Location{Size: 100}, ReadSize: uint64(100)})
_, err := client.Get(randCtx(), &access.GetArgs{Location: proto.Location{Size_: 100}, ReadSize: uint64(100)})
require.Error(t, err)
}
@ -691,7 +690,7 @@ func TestAccessClientPutMaxBlobsLength(t *testing.T) {
}
_, _, err := client.Put(randCtx(), &args)
require.ErrorIs(t, cs.err, err)
require.ErrorIs(t, err, cs.err)
}
}
@ -724,17 +723,16 @@ func TestAccessClientPutTimeout(t *testing.T) {
maxMs time.Duration
}
cases := []caseT{
// QuickConnMode 3s + size / 40, dial and response 2s
// QuickConnMode 3s + size / 40
{access.QuickConnMode, mb * -119, ms * 0, ms * 600},
{access.QuickConnMode, mb * -100, ms * 500, ms * 1000},
{access.QuickConnMode, mb * -80, ms * 1000, ms * 1500},
{access.QuickConnMode, mb * -1, ms * 2000, ms * 2500},
{access.QuickConnMode, mb * -1, ms * 2500, ms * 3500},
// DefaultConnMode 30s + size / 10, dial and response 5s
// DefaultConnMode 30s + size / 10
{access.DefaultConnMode, mb * -299, ms * 0, ms * 600},
{access.DefaultConnMode, mb * -280, ms * 2000, ms * 2500},
{access.DefaultConnMode, mb * -270, ms * 3000, ms * 3500},
{access.DefaultConnMode, mb * -1, ms * 5000, ms * 5500},
}
var wg sync.WaitGroup
@ -778,40 +776,40 @@ func TestAccessClientDelete(t *testing.T) {
{
locs, err := client.Delete(randCtx(), nil)
require.Nil(t, locs)
require.ErrorIs(t, errcode.ErrIllegalArguments, err)
require.ErrorIs(t, err, errcode.ErrIllegalArguments)
}
{
locs, err := client.Delete(randCtx(), &access.DeleteArgs{})
require.Nil(t, locs)
require.ErrorIs(t, errcode.ErrIllegalArguments, err)
require.ErrorIs(t, err, errcode.ErrIllegalArguments)
}
{
locs, err := client.Delete(randCtx(), &access.DeleteArgs{
Locations: make([]access.Location, 1),
Locations: make([]proto.Location, 1),
})
require.Nil(t, locs)
require.NoError(t, err)
}
{
args := &access.DeleteArgs{
Locations: make([]access.Location, 1000),
Locations: make([]proto.Location, 1000),
}
_, err := client.Delete(randCtx(), args)
require.NoError(t, err)
}
{
args := &access.DeleteArgs{
Locations: make([]access.Location, access.MaxDeleteLocations+1),
Locations: make([]proto.Location, access.MaxDeleteLocations+1),
}
locs, err := client.Delete(randCtx(), args)
require.Equal(t, args.Locations, locs)
require.ErrorIs(t, errcode.ErrIllegalArguments, err)
require.ErrorIs(t, err, errcode.ErrIllegalArguments)
}
{
loc := access.Location{Size: 100, Blobs: make([]access.SliceInfo, 0)}
loc := proto.Location{Size_: 100, Slices: make([]proto.Slice, 0)}
fillCrc(&loc)
args := &access.DeleteArgs{
Locations: make([]access.Location, 0, access.MaxDeleteLocations),
Locations: make([]proto.Location, 0, access.MaxDeleteLocations),
}
for i := 1; i < access.MaxDeleteLocations/10; i++ {
args.Locations = append(args.Locations, loc)
@ -894,7 +892,7 @@ func TestAccessClientPutAtToken(t *testing.T) {
Body: bytes.NewBuffer(buff),
}
_, _, err := client.Put(randCtx(), &args)
require.ErrorIs(t, errcode.ErrUnexpected, err)
require.ErrorIs(t, err, errcode.ErrUnexpected)
}
}
@ -928,7 +926,7 @@ func TestAccessClientRPCConfig(t *testing.T) {
}
func TestAccessClientLogger(t *testing.T) {
file, err := ioutil.TempFile(os.TempDir(), "TestAccessClientLogger")
file, err := os.CreateTemp(os.TempDir(), "TestAccessClientLogger")
require.NoError(t, err)
require.NoError(t, file.Close())
defer func() {
@ -940,7 +938,7 @@ func TestAccessClientLogger(t *testing.T) {
Logger: &access.Logger{
Filename: file.Name(),
},
PriorityAddrs: []string{"127.0.0.1:9500"},
PriorityAddrs: []string{"127.0.0.1:37173"},
}
client, err := access.New(cfg)
require.NoError(t, err)
@ -956,3 +954,35 @@ func TestAccessClientLogger(t *testing.T) {
_, _, err = client.Put(randCtx(), &args)
require.Error(t, err)
}
func TestAccessClientPutRetryGetBody(t *testing.T) {
refusedAddr := "http://127.0.0.1:37173"
cfg := access.Config{}
cfg.RPCConfig = &rpc.Config{}
cfg.LogLevel = log.Lfatal
cfg.PriorityAddrs = []string{refusedAddr, refusedAddr, mockServer.URL, refusedAddr}
client, err := access.New(cfg)
require.NoError(t, err)
for range [1000]struct{}{} {
retried := false
args := access.PutArgs{
Size: int64(1),
Body: bytes.NewBuffer([]byte{'a'}),
GetBody: func() (io.ReadCloser, error) {
retried = true
return io.NopCloser(bytes.NewBuffer([]byte{'z'})), nil
},
}
loc, _, err := client.Put(randCtx(), &args)
require.NoError(t, err)
rc, err := client.Get(randCtx(), &access.GetArgs{Location: loc, ReadSize: uint64(1)})
require.NoError(t, err)
buff, err := io.ReadAll(rc)
require.NoError(t, err)
if len(buff) > 0 && buff[0] == 'z' {
require.True(t, retried)
return
}
}
require.Fail(t, "retry with get body failed")
}

View File

@ -18,10 +18,7 @@ import (
"crypto/md5"
"crypto/sha1"
"crypto/sha256"
"encoding/base64"
"encoding/binary"
"encoding/hex"
"fmt"
"hash"
"hash/crc32"
"io"
@ -196,298 +193,27 @@ func (h HashSumMap) All() map[string]interface{} {
return m
}
// Location file location, 4 + 1 + 8 + 4 + 4 + len*16 bytes
// | |
// | ClusterID(4) | CodeMode(1) |
// | Size(8) |
// | BlobSize(4) | Crc(4) |
// | len*SliceInfo(16) |
//
// ClusterID which cluster file is in
// CodeMode is ec encode mode, see defined in "common/lib/codemode"
// Size is file size
// BlobSize is every blob's size but the last one which's size=(Size mod BlobSize)
// Crc is the checksum, change anything of the location, crc will mismatch
// Blobs all blob information
type Location struct {
_ [0]byte
ClusterID proto.ClusterID `json:"cluster_id"`
CodeMode codemode.CodeMode `json:"code_mode"`
Size uint64 `json:"size"`
BlobSize uint32 `json:"blob_size"`
Crc uint32 `json:"crc"`
Blobs []SliceInfo `json:"blobs"`
}
// SliceInfo blobs info, 8 + 4 + 4 bytes
//
// MinBid is the first blob id
// Vid is which volume all blobs in
// Count is num of consecutive blob ids, count=1 just has one blob
//
// blob ids = [MinBid, MinBid+count)
type SliceInfo struct {
_ [0]byte
MinBid proto.BlobID `json:"min_bid"`
Vid proto.Vid `json:"vid"`
Count uint32 `json:"count"`
}
// Blob is one piece of data in a location
//
// Bid is the blob id
// Vid is which volume the blob in
// Size is real size of the blob
type Blob struct {
Bid proto.BlobID
Vid proto.Vid
Size uint32
}
// Copy returns a new same Location
func (loc *Location) Copy() Location {
dst := Location{
ClusterID: loc.ClusterID,
CodeMode: loc.CodeMode,
Size: loc.Size,
BlobSize: loc.BlobSize,
Crc: loc.Crc,
Blobs: make([]SliceInfo, len(loc.Blobs)),
}
copy(dst.Blobs, loc.Blobs)
return dst
}
// Encode transfer Location to slice byte
// Returns the buf created by me
//
// (n) means max-n bytes
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// | field | crc | clusterid | codemode | size | blobsize |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// | n-bytes | 4 | uvarint(5) | 1 | uvarint(10) | uvarint(5) |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// 25 + (5){len(blobs)} + len(Blobs) * 20
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// | blobs | minbid | vid | count | ... |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// | n-bytes | (10) | (5) | (5) | (20) | (20) | ... |
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
func (loc *Location) Encode() []byte {
if loc == nil {
return nil
}
n := 25 + 5 + len(loc.Blobs)*20
buf := make([]byte, n)
n = loc.Encode2(buf)
return buf[:n]
}
// Encode2 transfer Location to the buf, the buf reuse by yourself
// Returns the number of bytes read
// If the buffer is too small, Encode2 will panic
func (loc *Location) Encode2(buf []byte) int {
if loc == nil {
return 0
}
n := 0
binary.BigEndian.PutUint32(buf[n:], loc.Crc)
n += 4
n += binary.PutUvarint(buf[n:], uint64(loc.ClusterID))
buf[n] = byte(loc.CodeMode)
n++
n += binary.PutUvarint(buf[n:], uint64(loc.Size))
n += binary.PutUvarint(buf[n:], uint64(loc.BlobSize))
n += binary.PutUvarint(buf[n:], uint64(len(loc.Blobs)))
for _, blob := range loc.Blobs {
n += binary.PutUvarint(buf[n:], uint64(blob.MinBid))
n += binary.PutUvarint(buf[n:], uint64(blob.Vid))
n += binary.PutUvarint(buf[n:], uint64(blob.Count))
}
return n
}
// Decode parse location from buf
// Returns the number of bytes read
// Error is not nil when parsing failed
func (loc *Location) Decode(buf []byte) (int, error) {
if loc == nil {
return 0, fmt.Errorf("location receiver is nil")
}
location, n, err := DecodeLocation(buf)
if err != nil {
return n, err
}
*loc = location
return n, nil
}
// ToString transfer location to hex string
func (loc *Location) ToString() string {
return loc.HexString()
}
// HexString transfer location to hex string
func (loc *Location) HexString() string {
return hex.EncodeToString(loc.Encode())
}
// Base64String transfer location to base64 string
func (loc *Location) Base64String() string {
return base64.StdEncoding.EncodeToString(loc.Encode())
}
// Spread location blobs to slice
func (loc *Location) Spread() []Blob {
count := 0
for _, blob := range loc.Blobs {
count += int(blob.Count)
}
blobs := make([]Blob, 0, count)
for _, blob := range loc.Blobs {
for offset := uint32(0); offset < blob.Count; offset++ {
blobs = append(blobs, Blob{
Bid: blob.MinBid + proto.BlobID(offset),
Vid: blob.Vid,
Size: loc.BlobSize,
})
}
}
if len(blobs) > 0 && loc.BlobSize > 0 {
if lastSize := loc.Size % uint64(loc.BlobSize); lastSize > 0 {
blobs[len(blobs)-1].Size = uint32(lastSize)
}
}
return blobs
}
// DecodeLocation parse location from buf
// Returns Location and the number of bytes read
// Error is not nil when parsing failed
func DecodeLocation(buf []byte) (Location, int, error) {
var (
loc Location
n int
val uint64
nn int
)
next := func() (uint64, int) {
val, nn := binary.Uvarint(buf)
if nn <= 0 {
return 0, nn
}
n += nn
buf = buf[nn:]
return val, nn
}
if len(buf) < 4 {
return loc, n, fmt.Errorf("bytes crc %d", len(buf))
}
loc.Crc = binary.BigEndian.Uint32(buf)
n += 4
buf = buf[4:]
if val, nn = next(); nn <= 0 {
return loc, n, fmt.Errorf("bytes cluster_id %d", nn)
}
loc.ClusterID = proto.ClusterID(val)
if len(buf) < 1 {
return loc, n, fmt.Errorf("bytes codemode %d", len(buf))
}
loc.CodeMode = codemode.CodeMode(buf[0])
n++
buf = buf[1:]
if val, nn = next(); nn <= 0 {
return loc, n, fmt.Errorf("bytes size %d", nn)
}
loc.Size = val
if val, nn = next(); nn <= 0 {
return loc, n, fmt.Errorf("bytes blob_size %d", nn)
}
loc.BlobSize = uint32(val)
if val, nn = next(); nn <= 0 {
return loc, n, fmt.Errorf("bytes length blobs %d", nn)
}
length := int(val)
if length > 0 {
loc.Blobs = make([]SliceInfo, 0, length)
}
for index := 0; index < length; index++ {
var blob SliceInfo
if val, nn = next(); nn <= 0 {
return loc, n, fmt.Errorf("bytes %dth-blob min_bid %d", index, nn)
}
blob.MinBid = proto.BlobID(val)
if val, nn = next(); nn <= 0 {
return loc, n, fmt.Errorf("bytes %dth-blob vid %d", index, nn)
}
blob.Vid = proto.Vid(val)
if val, nn = next(); nn <= 0 {
return loc, n, fmt.Errorf("bytes %dth-blob count %d", index, nn)
}
blob.Count = uint32(val)
loc.Blobs = append(loc.Blobs, blob)
}
return loc, n, nil
}
// DecodeLocationFrom decode location from hex string
func DecodeLocationFrom(s string) (Location, error) {
return DecodeLocationFromHex(s)
}
// DecodeLocationFromHex decode location from hex string
func DecodeLocationFromHex(s string) (Location, error) {
var loc Location
src, err := hex.DecodeString(s)
if err != nil {
return loc, err
}
_, err = loc.Decode(src)
if err != nil {
return loc, err
}
return loc, nil
}
// DecodeLocationFromBase64 decode location from base64 string
func DecodeLocationFromBase64(s string) (Location, error) {
var loc Location
src, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return loc, err
}
_, err = loc.Decode(src)
if err != nil {
return loc, err
}
return loc, nil
}
// PutArgs for service /put
// Hashes means how to calculate check sum,
// HashAlgCRC32 | HashAlgMD5 equal 2 + 4 = 6
// AssignClusterID > 0 means that cluster_id is assigned by the API caller
// AssignClusterID = 0 means that cluster_id is assigned by access cluster controller
// CodeMode > 0 means that codemode is assigned by the API caller
// CodeMode = 0 means that codemode is assigned by code_mode_policies
type PutArgs struct {
Size int64 `json:"size"`
Hashes HashAlgorithm `json:"hashes,omitempty"`
Body io.Reader `json:"-"`
AssignClusterID proto.ClusterID `json:"assign_cluster_id,omitempty"`
CodeMode codemode.CodeMode `json:"code_mode,omitempty"`
// GetBody defines an optional func to return a new copy of Body.
// It is used for client requests when a redirect requires reading
// the body more than once. Use of GetBody still requires setting Body.
//
// There force reset request.GetBody if it is setting.
GetBody func() (io.ReadCloser, error) `json:"-"`
}
// IsValid is valid put args
@ -500,8 +226,8 @@ func (args *PutArgs) IsValid() bool {
// PutResp put response result
type PutResp struct {
Location Location `json:"location"`
HashSumMap HashSumMap `json:"hashsum"`
Location proto.Location `json:"location"`
HashSumMap HashSumMap `json:"hashsum,omitempty"`
}
// PutAtArgs for service /putat
@ -555,15 +281,16 @@ func (args *AllocArgs) IsValid() bool {
// if size mod blobsize == 0, length of tokens equal length of location blobs
// otherwise additional token for the last blob uploading
type AllocResp struct {
Location Location `json:"location"`
Tokens []string `json:"tokens"`
Location proto.Location `json:"location"`
Tokens []string `json:"tokens"`
}
// GetArgs for service /get
type GetArgs struct {
Location Location `json:"location"`
Offset uint64 `json:"offset"`
ReadSize uint64 `json:"read_size"`
Location proto.Location `json:"location"`
Offset uint64 `json:"offset"`
ReadSize uint64 `json:"read_size"`
Writer io.Writer `json:"-"`
}
// IsValid is valid get args
@ -571,14 +298,14 @@ func (args *GetArgs) IsValid() bool {
if args == nil {
return false
}
return args.Offset <= args.Location.Size &&
args.ReadSize <= args.Location.Size &&
args.Offset+args.ReadSize <= args.Location.Size
return args.Offset <= args.Location.Size_ &&
args.ReadSize <= args.Location.Size_ &&
args.Offset+args.ReadSize <= args.Location.Size_
}
// DeleteArgs for service /delete
type DeleteArgs struct {
Locations []Location `json:"locations"`
Locations []proto.Location `json:"locations"`
}
// IsValid is valid delete args
@ -591,7 +318,7 @@ func (args *DeleteArgs) IsValid() bool {
// DeleteResp delete response with failed locations
type DeleteResp struct {
FailedLocations []Location `json:"failed_locations,omitempty"`
FailedLocations []proto.Location `json:"failed_locations,omitempty"`
}
// DeleteBlobArgs for service /deleteblob
@ -618,8 +345,8 @@ func (args *DeleteBlobArgs) IsValid() bool {
// Locations are signed location getting from /alloc
// Location is to be signed location which merged by yourself
type SignArgs struct {
Locations []Location `json:"locations"`
Location Location `json:"location"`
Locations []proto.Location `json:"locations"`
Location proto.Location `json:"location"`
}
// IsValid is valid sign args
@ -632,5 +359,141 @@ func (args *SignArgs) IsValid() bool {
// SignResp sign response location with crc
type SignResp struct {
Location Location `json:"location"`
Location proto.Location `json:"location"`
}
// Shardnode Blob
type GetShardMode int
const (
GetShardModeRandom = GetShardMode(iota)
GetShardModeLeader
)
type CreateBlobArgs struct {
ClusterID proto.ClusterID
CodeMode codemode.CodeMode
BlobName string
Size uint64
SliceSize uint32
}
func (args *CreateBlobArgs) IsValid() bool {
if args == nil {
return false
}
return args.Size != 0 && len(args.BlobName) != 0
}
type CreateBlobRet struct {
Location proto.Location
}
type ListBlobArgs struct {
ClusterID proto.ClusterID
ShardID proto.ShardID
Mode GetShardMode
Prefix string
Marker string
Count uint64
}
func (args *ListBlobArgs) IsValid() bool {
if args == nil {
return false
}
return args.ClusterID != 0
}
type SealBlobArgs struct {
ClusterID proto.ClusterID
BlobName string
Size uint64
Slices []proto.Slice
}
func (args *SealBlobArgs) IsValid() bool {
if args == nil {
return false
}
return args.ClusterID != 0 && len(args.BlobName) != 0
}
type GetBlobArgs struct {
ClusterID proto.ClusterID
Mode GetShardMode
BlobName string
Offset uint64
ReadSize uint64
Writer io.Writer
}
// IsValid is valid get args
func (args *GetBlobArgs) IsValid() bool {
if args == nil {
return false
}
return args.ClusterID != 0 && len(args.BlobName) != 0
}
type DelBlobArgs struct {
ClusterID proto.ClusterID
BlobName string
}
func (args *DelBlobArgs) IsValid() bool {
if args == nil {
return false
}
return args.ClusterID != 0 && len(args.BlobName) != 0
}
type AllocSliceArgs struct {
ClusterID proto.ClusterID
CodeMode codemode.CodeMode
BlobName string
Size uint64
FailSlice proto.Slice
}
func (args *AllocSliceArgs) IsValid() bool {
if args == nil {
return false
}
return args.ClusterID != 0 && args.CodeMode.IsValid() && args.Size != 0 && len(args.BlobName) != 0
}
type PutBlobArgs struct {
CodeMode codemode.CodeMode
BlobName string
NeedSeal bool
Size uint64
Hashes HashAlgorithm
Body io.Reader
}
func (args *PutBlobArgs) IsValid() bool {
if args == nil {
return false
}
return args.CodeMode != 0 && args.Size != 0 && len(args.BlobName) != 0
}
type GetShardCommonArgs struct {
ClusterID proto.ClusterID
ShardID proto.ShardID
Mode GetShardMode
BlobName string
}
func (args *ListBlobEncodeMarker) MarshalToString() (string, error) {
raw, err := args.Marshal()
return string(raw), err
}
func (args *ListBlobEncodeMarker) UnmarshalFromString(marker string) error {
return args.Unmarshal([]byte(marker))
}

View File

@ -259,192 +259,6 @@ func TestHashAlgorithm2HashSumMap(t *testing.T) {
}
}
func TestLocationEncodeDecodeNil(t *testing.T) {
var loc *access.Location
require.Nil(t, loc.Encode())
require.Equal(t, 0, loc.Encode2(nil))
require.Equal(t, "", loc.ToString())
require.Equal(t, "", loc.HexString())
require.Equal(t, "", loc.Base64String())
n, err := loc.Decode(nil)
require.Error(t, err)
require.Equal(t, 0, n)
locx, n, err := access.DecodeLocation(nil)
require.Error(t, err)
require.Equal(t, 0, n)
require.Equal(t, access.Location{}, locx)
locx, err = access.DecodeLocationFrom("")
require.Error(t, err)
require.Equal(t, access.Location{}, locx)
locx, err = access.DecodeLocationFrom("xxx")
require.Error(t, err)
require.Equal(t, access.Location{}, locx)
locx, err = access.DecodeLocationFromHex("xxx")
require.Error(t, err)
require.Equal(t, access.Location{}, locx)
locx, err = access.DecodeLocationFromBase64("xxx")
require.Error(t, err)
require.Equal(t, access.Location{}, locx)
}
func TestLocationEncodeDecode(t *testing.T) {
for ii := 0; ii < 100; ii++ {
loc := &access.Location{
ClusterID: proto.ClusterID(mrand.Uint32()),
CodeMode: codemode.CodeMode(mrand.Intn(0xff)),
Size: mrand.Uint64(),
BlobSize: mrand.Uint32(),
Crc: mrand.Uint32(),
}
num := mrand.Intn(5)
for i := 0; i < num; i++ {
loc.Blobs = append(loc.Blobs, access.SliceInfo{
MinBid: proto.BlobID(mrand.Uint64()),
Vid: proto.Vid(mrand.Uint32()),
Count: mrand.Uint32(),
})
}
buf := loc.Encode()
bufx := make([]byte, len(buf))
n := loc.Encode2(bufx)
require.Equal(t, len(buf), n)
require.Equal(t, buf, bufx)
require.Panics(t, func() { loc.Encode2(nil) })
require.Panics(t, func() { loc.Encode2(bufx[:3]) })
require.Panics(t, func() { loc.Encode2(bufx[:n/2]) })
require.Panics(t, func() { loc.Encode2(bufx[:n-1]) })
locx := access.Location{}
locx.Decode(bufx)
require.Equal(t, loc.ToString(), locx.ToString())
require.Equal(t, loc.HexString(), locx.HexString())
require.Equal(t, loc.Base64String(), locx.Base64String())
str := loc.ToString()
locx, err := access.DecodeLocationFrom(str)
require.NoError(t, err)
require.Equal(t, *loc, locx)
str = loc.HexString()
locx, err = access.DecodeLocationFromHex(str)
require.NoError(t, err)
require.Equal(t, *loc, locx)
str = loc.Base64String()
locx, err = access.DecodeLocationFromBase64(str)
require.NoError(t, err)
require.Equal(t, *loc, locx)
}
}
func TestLocationDecodeError(t *testing.T) {
loc := &access.Location{
ClusterID: proto.ClusterID(math.MaxUint32),
CodeMode: codemode.CodeMode(math.MaxInt8),
Size: math.MaxUint64,
BlobSize: math.MaxUint32,
Crc: math.MaxUint32,
}
buf := loc.Encode()
require.Equal(t, 25+1, len(buf))
for _, n := range []int{3, 8, 9, 19, 24} {
_, _, err := access.DecodeLocation(buf[:n])
require.Error(t, err)
t.Log(err)
}
loc.Blobs = append(loc.Blobs, access.SliceInfo{
MinBid: proto.BlobID(math.MaxUint64),
Vid: proto.Vid(math.MaxUint32),
Count: math.MaxUint32,
})
buf = loc.Encode()
require.Equal(t, 25+1+20, len(buf))
for _, n := range []int{25, 35, 40, 45} {
_, _, err := access.DecodeLocation(buf[:n])
require.Error(t, err)
t.Log(err)
}
}
func TestLocationSpread(t *testing.T) {
{
var loc access.Location
blobs := loc.Spread()
require.NotNil(t, blobs)
require.Equal(t, 0, len(blobs))
}
{
loc := &access.Location{
Size: 10,
BlobSize: 1 << 22,
Blobs: []access.SliceInfo{{
MinBid: 100,
Vid: 4,
Count: 1,
}},
}
blobs := loc.Spread()
require.Equal(t, 1, len(blobs))
require.Equal(t, proto.BlobID(100), blobs[0].Bid)
require.Equal(t, proto.Vid(4), blobs[0].Vid)
require.Equal(t, uint32(10), blobs[0].Size)
}
{
loc := &access.Location{
Size: (1 << 22) + 10,
BlobSize: 1 << 22,
Blobs: []access.SliceInfo{{
MinBid: 100,
Vid: 4,
Count: 2,
}},
}
blobs := loc.Spread()
require.Equal(t, 2, len(blobs))
require.Equal(t, proto.BlobID(100), blobs[0].Bid)
require.Equal(t, proto.Vid(4), blobs[0].Vid)
require.Equal(t, uint32(1<<22), blobs[0].Size)
require.Equal(t, proto.BlobID(101), blobs[1].Bid)
require.Equal(t, proto.Vid(4), blobs[1].Vid)
require.Equal(t, uint32(10), blobs[1].Size)
}
{
loc := &access.Location{
Size: 1 << 23,
BlobSize: 1 << 22,
Blobs: []access.SliceInfo{{
MinBid: 100,
Vid: 4,
Count: 1,
}, {
MinBid: 200,
Vid: 4,
Count: 1,
}},
}
blobs := loc.Spread()
require.Equal(t, 2, len(blobs))
require.Equal(t, proto.BlobID(100), blobs[0].Bid)
require.Equal(t, proto.Vid(4), blobs[0].Vid)
require.Equal(t, uint32(1<<22), blobs[0].Size)
require.Equal(t, proto.BlobID(200), blobs[1].Bid)
require.Equal(t, proto.Vid(4), blobs[1].Vid)
require.Equal(t, uint32(1<<22), blobs[1].Size)
}
}
func TestPutArgs(t *testing.T) {
cases := []struct {
size int64
@ -538,7 +352,7 @@ func TestGetArgs(t *testing.T) {
Offset: cs.offset,
ReadSize: cs.readSize,
}
args.Location.Size = cs.size
args.Location.Size_ = cs.size
require.Equal(t, cs.valid, args.IsValid())
}
}
@ -547,11 +361,11 @@ func TestDeleteArgs(t *testing.T) {
args := access.DeleteArgs{}
require.False(t, args.IsValid())
require.False(t, (*access.DeleteArgs)(nil).IsValid())
args.Locations = []access.Location{{}}
args.Locations = []proto.Location{{}}
require.True(t, args.IsValid())
args.Locations = make([]access.Location, access.MaxDeleteLocations)
args.Locations = make([]proto.Location, access.MaxDeleteLocations)
require.True(t, args.IsValid())
args.Locations = make([]access.Location, access.MaxDeleteLocations+1)
args.Locations = make([]proto.Location, access.MaxDeleteLocations+1)
require.False(t, args.IsValid())
}
@ -573,7 +387,7 @@ func TestSignArgs(t *testing.T) {
args := access.SignArgs{}
require.False(t, args.IsValid())
require.False(t, (*access.DeleteArgs)(nil).IsValid())
args.Locations = []access.Location{{}}
args.Locations = []proto.Location{{}}
require.True(t, args.IsValid())
}

View File

@ -0,0 +1,384 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: stream_blob.proto
package access
import (
fmt "fmt"
sharding "github.com/cubefs/cubefs/blobstore/common/sharding"
_ "github.com/gogo/protobuf/gogoproto"
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
type ListBlobEncodeMarker struct {
Range sharding.Range `protobuf:"bytes,1,opt,name=range,proto3" json:"range"`
Marker string `protobuf:"bytes,2,opt,name=marker,proto3" json:"marker,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ListBlobEncodeMarker) Reset() { *m = ListBlobEncodeMarker{} }
func (m *ListBlobEncodeMarker) String() string { return proto.CompactTextString(m) }
func (*ListBlobEncodeMarker) ProtoMessage() {}
func (*ListBlobEncodeMarker) Descriptor() ([]byte, []int) {
return fileDescriptor_3f58ae6b23694640, []int{0}
}
func (m *ListBlobEncodeMarker) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ListBlobEncodeMarker) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ListBlobEncodeMarker.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ListBlobEncodeMarker) XXX_Merge(src proto.Message) {
xxx_messageInfo_ListBlobEncodeMarker.Merge(m, src)
}
func (m *ListBlobEncodeMarker) XXX_Size() int {
return m.Size()
}
func (m *ListBlobEncodeMarker) XXX_DiscardUnknown() {
xxx_messageInfo_ListBlobEncodeMarker.DiscardUnknown(m)
}
var xxx_messageInfo_ListBlobEncodeMarker proto.InternalMessageInfo
func (m *ListBlobEncodeMarker) GetRange() sharding.Range {
if m != nil {
return m.Range
}
return sharding.Range{}
}
func (m *ListBlobEncodeMarker) GetMarker() string {
if m != nil {
return m.Marker
}
return ""
}
func init() {
proto.RegisterType((*ListBlobEncodeMarker)(nil), "cubefs.blobstore.api.access.ListBlobEncodeMarker")
}
func init() { proto.RegisterFile("stream_blob.proto", fileDescriptor_3f58ae6b23694640) }
var fileDescriptor_3f58ae6b23694640 = []byte{
// 217 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2c, 0x2e, 0x29, 0x4a,
0x4d, 0xcc, 0x8d, 0x4f, 0xca, 0xc9, 0x4f, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x4e,
0x2e, 0x4d, 0x4a, 0x4d, 0x2b, 0xd6, 0x03, 0x09, 0x15, 0x97, 0xe4, 0x17, 0xa5, 0xea, 0x25, 0x16,
0x64, 0xea, 0x25, 0x26, 0x27, 0xa7, 0x16, 0x17, 0x4b, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0xd5,
0xe9, 0x83, 0x58, 0x10, 0x2d, 0x52, 0x3a, 0x10, 0x2d, 0xfa, 0x70, 0x2d, 0xfa, 0xc9, 0xf9, 0xb9,
0xb9, 0xf9, 0x79, 0xfa, 0xc5, 0x19, 0x89, 0x45, 0x29, 0x99, 0x79, 0xe9, 0xfa, 0x45, 0x89, 0x79,
0xe9, 0xa9, 0x10, 0xd5, 0x4a, 0xc5, 0x5c, 0x22, 0x3e, 0x99, 0xc5, 0x25, 0x4e, 0x39, 0xf9, 0x49,
0xae, 0x79, 0xc9, 0xf9, 0x29, 0xa9, 0xbe, 0x89, 0x45, 0xd9, 0xa9, 0x45, 0x42, 0xce, 0x5c, 0xac,
0x60, 0x65, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0xdc, 0x46, 0xea, 0x7a, 0x18, 0x0e, 0x81, 0x98, 0xaa,
0x07, 0x33, 0x55, 0x2f, 0x08, 0xa4, 0xdc, 0x89, 0xe5, 0xc4, 0x3d, 0x79, 0x86, 0x20, 0x88, 0x5e,
0x21, 0x31, 0x2e, 0xb6, 0x5c, 0xb0, 0x71, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x50, 0x9e,
0x93, 0xf8, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x18, 0xc5,
0xa9, 0xa7, 0x6f, 0x0d, 0xf1, 0x51, 0x12, 0x1b, 0xd8, 0x51, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff,
0xff, 0x17, 0x5f, 0xcb, 0x7b, 0x0a, 0x01, 0x00, 0x00,
}
func (m *ListBlobEncodeMarker) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ListBlobEncodeMarker) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ListBlobEncodeMarker) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Marker) > 0 {
i -= len(m.Marker)
copy(dAtA[i:], m.Marker)
i = encodeVarintStreamBlob(dAtA, i, uint64(len(m.Marker)))
i--
dAtA[i] = 0x12
}
{
size, err := m.Range.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintStreamBlob(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
return len(dAtA) - i, nil
}
func encodeVarintStreamBlob(dAtA []byte, offset int, v uint64) int {
offset -= sovStreamBlob(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func (m *ListBlobEncodeMarker) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.Range.Size()
n += 1 + l + sovStreamBlob(uint64(l))
l = len(m.Marker)
if l > 0 {
n += 1 + l + sovStreamBlob(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovStreamBlob(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozStreamBlob(x uint64) (n int) {
return sovStreamBlob(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (m *ListBlobEncodeMarker) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStreamBlob
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ListBlobEncodeMarker: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ListBlobEncodeMarker: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Range", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStreamBlob
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthStreamBlob
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthStreamBlob
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if err := m.Range.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Marker", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStreamBlob
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthStreamBlob
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthStreamBlob
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Marker = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipStreamBlob(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthStreamBlob
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipStreamBlob(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowStreamBlob
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowStreamBlob
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowStreamBlob
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthStreamBlob
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupStreamBlob
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthStreamBlob
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthStreamBlob = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowStreamBlob = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupStreamBlob = fmt.Errorf("proto: unexpected end of group")
)

View File

@ -0,0 +1,31 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
syntax = "proto3";
package cubefs.blobstore.api.access;
option go_package = "./;access";
option (gogoproto.sizer_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true;
import "gogoproto/gogo.proto";
import "cubefs/blobstore/common/sharding/range.proto";
message ListBlobEncodeMarker {
cubefs.blobstore.common.sharding.Range range = 1 [(gogoproto.nullable) = false];
string marker = 2;
}

View File

@ -16,157 +16,24 @@ package blobnode
import (
"context"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"time"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
bloberr "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
)
const (
ChunkStatusDefault ChunkStatus = iota // 0
ChunkStatusNormal // 1
ChunkStatusReadOnly // 2
ChunkStatusRelease // 3
ChunkNumStatus // 4
)
const (
ReleaseForUser = "release for user"
ReleaseForCompact = "release for compact"
)
// Chunk ID
// vuid + timestamp
const (
chunkVuidLen = 8
chunkTimestmapLen = 8
ChunkIdLength = chunkVuidLen + chunkTimestmapLen
)
var InvalidChunkId ChunkId = [ChunkIdLength]byte{}
var (
_vuidHexLen = hex.EncodedLen(chunkVuidLen)
_timestampHexLen = hex.EncodedLen(chunkTimestmapLen)
// ${vuid_hex}-${tiemstamp_hex}
// |-- 8 Bytes --|-- 1 Bytes --|-- 8 Bytes --|
delimiter = []byte("-")
ChunkIdEncodeLen = _vuidHexLen + _timestampHexLen + len(delimiter)
)
type (
ChunkId [ChunkIdLength]byte
ChunkStatus uint8
)
func (c ChunkId) UnixTime() uint64 {
return binary.BigEndian.Uint64(c[chunkVuidLen:ChunkIdLength])
}
func (c ChunkId) VolumeUnitId() proto.Vuid {
return proto.Vuid(binary.BigEndian.Uint64(c[:chunkVuidLen]))
}
func (c *ChunkId) Marshal() ([]byte, error) {
buf := make([]byte, ChunkIdEncodeLen)
var i int
hex.Encode(buf[i:_vuidHexLen], c[:chunkVuidLen])
i += _vuidHexLen
copy(buf[i:i+len(delimiter)], delimiter)
i += len(delimiter)
hex.Encode(buf[i:], c[chunkVuidLen:ChunkIdLength])
return buf, nil
}
func (c *ChunkId) Unmarshal(data []byte) error {
if len(data) != ChunkIdEncodeLen {
panic(errors.New("chunk buf size not match"))
}
var i int
_, err := hex.Decode(c[:chunkVuidLen], data[i:_vuidHexLen])
if err != nil {
return err
}
i += _vuidHexLen
i += len(delimiter)
_, err = hex.Decode(c[chunkVuidLen:], data[i:])
if err != nil {
return err
}
return nil
}
func (c ChunkId) String() string {
buf, _ := c.Marshal()
return string(buf[:])
}
func (c ChunkId) MarshalJSON() ([]byte, error) {
b := make([]byte, ChunkIdEncodeLen+2)
b[0], b[ChunkIdEncodeLen+1] = '"', '"'
buf, _ := c.Marshal()
copy(b[1:], buf)
return b, nil
}
func (c *ChunkId) UnmarshalJSON(data []byte) (err error) {
if len(data) != ChunkIdEncodeLen+2 {
return errors.New("failed unmarshal json")
}
return c.Unmarshal(data[1 : ChunkIdEncodeLen+1])
}
func EncodeChunk(id ChunkId) string {
return id.String()
}
func NewChunkId(vuid proto.Vuid) (chunkId ChunkId) {
binary.BigEndian.PutUint64(chunkId[:chunkVuidLen], uint64(vuid))
binary.BigEndian.PutUint64(chunkId[chunkVuidLen:ChunkIdLength], uint64(time.Now().UnixNano()))
return
}
func IsValidDiskID(id proto.DiskID) bool {
return id != proto.InvalidDiskID
}
func IsValidChunkId(id ChunkId) bool {
return id != InvalidChunkId
func IsValidChunkID(id clustermgr.ChunkID) bool {
return id != clustermgr.InvalidChunkID
}
func IsValidChunkStatus(status ChunkStatus) bool {
return status < ChunkNumStatus
}
func DecodeChunk(name string) (id ChunkId, err error) {
buf := []byte(name)
if len(buf) != ChunkIdEncodeLen {
return InvalidChunkId, errors.New("invalid chunk name")
}
if err = id.Unmarshal(buf); err != nil {
return InvalidChunkId, errors.New("chunk unmarshal failed")
}
return
func IsValidChunkStatus(status clustermgr.ChunkStatus) bool {
return status < clustermgr.ChunkNumStatus
}
type CreateChunkArgs struct {
@ -193,14 +60,14 @@ type StatChunkArgs struct {
Vuid proto.Vuid `json:"vuid"`
}
func (c *client) StatChunk(ctx context.Context, host string, args *StatChunkArgs) (ci *ChunkInfo, err error) {
func (c *client) StatChunk(ctx context.Context, host string, args *StatChunkArgs) (ci *clustermgr.ChunkInfo, err error) {
if !IsValidDiskID(args.DiskID) {
err = bloberr.ErrInvalidDiskId
return
}
urlStr := fmt.Sprintf("%v/chunk/stat/diskid/%v/vuid/%v", host, args.DiskID, args.Vuid)
ci = new(ChunkInfo)
ci = new(clustermgr.ChunkInfo)
err = c.GetWith(ctx, urlStr, ci)
return
}
@ -255,10 +122,10 @@ type ListChunkArgs struct {
}
type ListChunkRet struct {
ChunkInfos []*ChunkInfo `json:"chunk_infos"`
ChunkInfos []*clustermgr.ChunkInfo `json:"chunk_infos"`
}
func (c *client) ListChunks(ctx context.Context, host string, args *ListChunkArgs) (ret []*ChunkInfo, err error) {
func (c *client) ListChunks(ctx context.Context, host string, args *ListChunkArgs) (ret []*clustermgr.ChunkInfo, err error) {
if !IsValidDiskID(args.DiskID) {
err = bloberr.ErrInvalidDiskId
return
@ -288,4 +155,5 @@ type BadShard struct {
DiskID proto.DiskID
Vuid proto.Vuid
Bid proto.BlobID
Err error
}

View File

@ -21,58 +21,59 @@ import (
"github.com/stretchr/testify/require"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/util/log"
)
func TestIsValidChunkId(t *testing.T) {
id := InvalidChunkId
require.Equal(t, false, IsValidChunkId(id))
id := clustermgr.InvalidChunkID
require.Equal(t, false, IsValidChunkID(id))
id = ChunkId{0x1}
require.Equal(t, true, IsValidChunkId(id))
id = clustermgr.ChunkID{0x1}
require.Equal(t, true, IsValidChunkID(id))
}
func TestChunkIdNew(t *testing.T) {
chunkid := NewChunkId(101)
require.Equal(t, ChunkIdLength, len(chunkid))
require.NotEqual(t, InvalidChunkId, chunkid)
chunkid := clustermgr.NewChunkID(101)
require.Equal(t, clustermgr.ChunkIDLength, len(chunkid))
require.NotEqual(t, clustermgr.InvalidChunkID, chunkid)
expectedVuid := chunkid.VolumeUnitId()
require.Equal(t, expectedVuid, proto.Vuid(101))
chunkname := chunkid.String()
require.Equal(t, ChunkIdEncodeLen, len(chunkname))
require.Equal(t, clustermgr.ChunkIDEncodeLen, len(chunkname))
arrs := strings.Split(chunkname, string(delimiter))
arrs := strings.Split(chunkname, "-")
require.Equal(t, 2, len(arrs))
require.Equal(t, "0000000000000065", arrs[0])
}
func TestChunkId_Marshal(t *testing.T) {
chunkid := NewChunkId(101)
chunkid := clustermgr.NewChunkID(101)
data, err := chunkid.Marshal()
require.NoError(t, err)
require.Equal(t, ChunkIdEncodeLen, len(data))
require.Equal(t, clustermgr.ChunkIDEncodeLen, len(data))
log.Infof("data:%s", data)
var newchunk ChunkId
var newchunk clustermgr.ChunkID
err = newchunk.Unmarshal(data)
require.NoError(t, err)
require.Equal(t, chunkid, newchunk)
}
func TestChunkId_MarshalJSON(t *testing.T) {
chunkid := NewChunkId(101)
chunkid := clustermgr.NewChunkID(101)
data, err := json.Marshal(chunkid)
require.NoError(t, err)
require.Equal(t, ChunkIdEncodeLen+2, len(data))
require.Equal(t, clustermgr.ChunkIDEncodeLen+2, len(data))
log.Infof("data:%s", data)
var newchunk ChunkId
var newchunk clustermgr.ChunkID
err = json.Unmarshal(data, &newchunk)
require.NoError(t, err)
require.Equal(t, chunkid, newchunk)

View File

@ -19,6 +19,7 @@ import (
"fmt"
"io"
"github.com/cubefs/cubefs/blobstore/api/clustermgr"
"github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
@ -48,9 +49,9 @@ func (c *client) Close(ctx context.Context, host string) (err error) {
return nil
}
func (c *client) Stat(ctx context.Context, host string) (dis []*DiskInfo, err error) {
func (c *client) Stat(ctx context.Context, host string) (dis []*clustermgr.BlobNodeDiskInfo, err error) {
urlStr := fmt.Sprintf("%v/stat", host)
dis = make([]*DiskInfo, 0)
dis = make([]*clustermgr.BlobNodeDiskInfo, 0)
err = c.GetWith(ctx, urlStr, &dis)
return
}
@ -64,17 +65,46 @@ type InspectRateArgs struct {
Rate int `json:"rate"`
}
type InspectCleanMetricArgs struct {
DiskID proto.DiskID `json:"diskid"`
}
// LimiterStat single limiter using counter
type LimiterStat struct {
Running int `json:"running"`
Capacity int `json:"capacity"`
Remaining int `json:"remaining"`
}
// IoLimiterStats single level qos type limiter stats
type IoLimiterStats struct {
Concurrency LimiterStat `json:"concurrency"`
BidConcurrency LimiterStat `json:"bid_concurrency"`
Bandwidth LimiterStat `json:"bandwidth"`
}
type QosStatArgs struct {
DiskID proto.DiskID `json:"diskid"`
}
func (c *client) QosStat(ctx context.Context, host string, args *QosStatArgs) (stat map[proto.DiskID]map[string]IoLimiterStats, err error) {
urlStr := fmt.Sprintf("%s/disk/stat/diskid/%d", host, args.DiskID)
stat = make(map[proto.DiskID]map[string]IoLimiterStats)
err = c.GetWith(ctx, urlStr, stat)
return
}
type DiskStatArgs struct {
DiskID proto.DiskID `json:"diskid"`
}
func (c *client) DiskInfo(ctx context.Context, host string, args *DiskStatArgs) (di *DiskInfo, err error) {
func (c *client) DiskInfo(ctx context.Context, host string, args *DiskStatArgs) (di *clustermgr.BlobNodeDiskInfo, err error) {
if !IsValidDiskID(args.DiskID) {
return nil, errors.ErrInvalidDiskId
}
urlStr := fmt.Sprintf("%v/disk/stat/diskid/%v", host, args.DiskID)
di = new(DiskInfo)
di = new(clustermgr.BlobNodeDiskInfo)
err = c.GetWith(ctx, urlStr, di)
return
}
@ -83,20 +113,22 @@ type StorageAPI interface {
String(ctx context.Context, host string) string
IsOnline(ctx context.Context, host string) bool
Close(ctx context.Context, host string) error
Stat(ctx context.Context, host string) (infos []*DiskInfo, err error)
DiskInfo(ctx context.Context, host string, args *DiskStatArgs) (di *DiskInfo, err error)
Stat(ctx context.Context, host string) (infos []*clustermgr.BlobNodeDiskInfo, err error)
DiskInfo(ctx context.Context, host string, args *DiskStatArgs) (di *clustermgr.BlobNodeDiskInfo, err error)
QosStat(ctx context.Context, host string, args *QosStatArgs) (stat map[proto.DiskID]map[string]IoLimiterStats, err error)
// chunks
CreateChunk(ctx context.Context, host string, args *CreateChunkArgs) (err error)
StatChunk(ctx context.Context, host string, args *StatChunkArgs) (ci *ChunkInfo, err error)
StatChunk(ctx context.Context, host string, args *StatChunkArgs) (ci *clustermgr.ChunkInfo, err error)
ReleaseChunk(ctx context.Context, host string, args *ChangeChunkStatusArgs) (err error)
SetChunkReadonly(ctx context.Context, host string, args *ChangeChunkStatusArgs) (err error)
SetChunkReadwrite(ctx context.Context, host string, args *ChangeChunkStatusArgs) (err error)
ListChunks(ctx context.Context, host string, args *ListChunkArgs) (cis []*ChunkInfo, err error)
ListChunks(ctx context.Context, host string, args *ListChunkArgs) (cis []*clustermgr.ChunkInfo, err error)
// shard
GetShard(ctx context.Context, host string, args *GetShardArgs) (body io.ReadCloser, shardCrc uint32, err error)
RangeGetShard(ctx context.Context, host string, args *RangeGetShardArgs) (body io.ReadCloser, shardCrc uint32, err error)
GetShards(ctx context.Context, host string, args *GetShardsArgs) (getter ShardGetter, err error)
PutShard(ctx context.Context, host string, args *PutShardArgs) (crc uint32, err error)
StatShard(ctx context.Context, host string, args *StatShardArgs) (si *ShardInfo, err error)
MarkDeleteShard(ctx context.Context, host string, args *DeleteShardArgs) (err error)

View File

@ -17,7 +17,7 @@ package blobnode
import (
"bytes"
"context"
"io/ioutil"
"io"
"net/http"
"net/http/httptest"
"testing"
@ -108,7 +108,7 @@ func TestNewBlobNodeClient(t *testing.T) {
body, _, err := cli.RangeGetShard(ctx, mockServer.URL, getShardArgs)
require.NoError(t, err)
if body != nil {
b, _ := ioutil.ReadAll(body)
b, _ := io.ReadAll(body)
span.Infof("body: %s\n", b)
}

View File

@ -1,65 +0,0 @@
// Copyright 2022 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package blobnode
import (
"time"
"github.com/cubefs/cubefs/blobstore/common/proto"
)
type DiskHeartBeatInfo struct {
DiskID proto.DiskID `json:"disk_id"`
Used int64 `json:"used"` // disk used space
Free int64 `json:"free"` // remaining free space on the disk
Size int64 `json:"size"` // total physical disk space
MaxChunkCnt int64 `json:"max_chunk_cnt"` // note: maintained by clustermgr
FreeChunkCnt int64 `json:"free_chunk_cnt"` // note: maintained by clustermgr
UsedChunkCnt int64 `json:"used_chunk_cnt"` // current number of chunks on the disk
}
type DiskInfo struct {
ClusterID proto.ClusterID `json:"cluster_id"`
Idc string `json:"idc"`
Rack string `json:"rack"`
Host string `json:"host"`
Path string `json:"path"`
Status proto.DiskStatus `json:"status"` // normal、broken、repairing、repaired、dropped
Readonly bool `json:"readonly"`
CreateAt time.Time `json:"create_time"`
LastUpdateAt time.Time `json:"last_update_time"`
DiskHeartBeatInfo
}
type ChunkInfo struct {
Id ChunkId `json:"id"`
Vuid proto.Vuid `json:"vuid"`
DiskID proto.DiskID `json:"diskid"`
Total uint64 `json:"total"` // ChunkSize
Used uint64 `json:"used"` // user data size
Free uint64 `json:"free"` // ChunkSize - Used
Size uint64 `json:"size"` // Chunk File Size (logic size)
Status ChunkStatus `json:"status"` // normal、readOnly
Compacting bool `json:"compacting"`
}
type ShardInfo struct {
Vuid proto.Vuid `json:"vuid"`
Bid proto.BlobID `json:"bid"`
Size int64 `json:"size"`
Crc uint32 `json:"crc"`
Flag ShardStatus `json:"flag"` // 1:normal,2:markDelete
Inline bool `json:"inline"`
}

View File

@ -28,35 +28,48 @@ const (
type IOType uint64
const (
NormalIO IOType = iota // From: external: user io: read/write
BackgroundIO // From: external: background io: shard repair;disk repair, delete, compact;balance, drop, manual migrate; internal, inspect
IOTypeMax // 2
IOTypeOldMax = 8 // For compatibility with previous versions
WriteIO IOType = iota // From: external: user io: write
BackgroundIO // From: external: background io: shard repair; disk repair, compact;balance, drop, manual migrate
ReadIO
DeleteIO
IOTypeMax // 4
)
var IOtypemap = [...]string{
"normal",
"background",
var (
ioTypeArray = [...]string{
"write",
"background",
"read",
"delete",
}
revertIOMap = make(map[string]IOType, IOTypeMax)
)
var _ = ioTypeArray[IOTypeMax-1]
func init() {
for id, str := range ioTypeArray {
revertIOMap[str] = IOType(id)
}
}
var _ = IOtypemap[IOTypeMax-1]
func (it IOType) IsValid() bool {
return it >= NormalIO && it < IOTypeOldMax
return it >= WriteIO && it < IOTypeMax
}
func (it IOType) String() string {
return IOtypemap[it]
return ioTypeArray[it]
}
func (it IOType) IsHighLevel() bool {
return it == NormalIO
return it == WriteIO || it == ReadIO
}
func GetIoType(ctx context.Context) IOType {
v := ctx.Value(_ioFlowStatKey)
if v == nil {
return NormalIO
return IOTypeMax
}
return v.(IOType)
}
@ -64,3 +77,15 @@ func GetIoType(ctx context.Context) IOType {
func SetIoType(ctx context.Context, iot IOType) context.Context {
return context.WithValue(ctx, _ioFlowStatKey, iot)
}
func StringToIOType(str string) IOType {
tp, exist := revertIOMap[str]
if exist {
return tp
}
return IOTypeMax
}
func GetAllIOType() [IOTypeMax]string {
return ioTypeArray
}

View File

@ -24,14 +24,104 @@ import (
func TestGetIoType(t *testing.T) {
ctx := context.TODO()
// nil ctx, should return IOTypeMax/invalid
iotype := GetIoType(ctx)
require.Equal(t, NormalIO, iotype)
require.Equal(t, IOTypeMax, iotype)
ctx0 := context.WithValue(ctx, _ioFlowStatKey, BackgroundIO)
iotype = GetIoType(ctx0)
require.Equal(t, BackgroundIO, iotype)
ctx1 := context.WithValue(ctx0, _ioFlowStatKey, BackgroundIO)
ctx1 := SetIoType(ctx, ReadIO)
iotype = GetIoType(ctx1)
require.Equal(t, BackgroundIO, iotype)
require.Equal(t, ReadIO, iotype)
ctx = SetIoType(ctx, DeleteIO)
iotype = GetIoType(ctx)
require.Equal(t, DeleteIO, iotype)
}
func TestIOType_IsValid(t *testing.T) {
tests := []struct {
name string
ioType IOType
expected bool
}{
{name: "WriteIO is valid", ioType: WriteIO, expected: true},
{name: "BackgroundIO is valid", ioType: BackgroundIO, expected: true},
{name: "ReadIO is valid", ioType: ReadIO, expected: true},
{name: "DeleteIO is valid", ioType: DeleteIO, expected: true},
{name: "IOTypeMax is invalid", ioType: IOTypeMax, expected: false},
{name: "IOTypeMax+1 is invalid", ioType: IOTypeMax + 1, expected: false},
{name: "IOTypeMax-1 is valid", ioType: IOTypeMax - 1, expected: true},
{name: "Zero value is valid (WriteIO)", ioType: 0, expected: true},
{name: "Large value is invalid", ioType: 100, expected: false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := tt.ioType.IsValid()
require.Equal(t, tt.expected, result)
})
}
}
func TestIOType_String(t *testing.T) {
tests := []struct {
name string
ioType IOType
expected string
}{
{name: "WriteIO string", ioType: WriteIO, expected: "write"},
{name: "BackgroundIO string", ioType: BackgroundIO, expected: "background"},
{name: "ReadIO string", ioType: ReadIO, expected: "read"},
{name: "DeleteIO string", ioType: DeleteIO, expected: "delete"},
{name: "IOTypeMax string (should panic or return empty)", ioType: IOTypeMax, expected: ""},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.ioType >= IOTypeMax {
// Test that it doesn't panic
require.Panics(t, func() {
_ = tt.ioType.String()
})
} else {
result := tt.ioType.String()
require.Equal(t, tt.expected, result)
}
})
}
}
func TestIOtypemap(t *testing.T) {
t.Run("ioTypeArray contains correct values", func(t *testing.T) {
require.Len(t, ioTypeArray, int(IOTypeMax))
require.Equal(t, "write", ioTypeArray[WriteIO])
require.Equal(t, "background", ioTypeArray[BackgroundIO])
require.Equal(t, "read", ioTypeArray[ReadIO])
require.Equal(t, "delete", ioTypeArray[DeleteIO])
})
t.Run("ioTypeArray index validation", func(t *testing.T) {
// Test that all valid IO types have corresponding strings
for i := WriteIO; i < IOTypeMax; i++ {
require.NotEmpty(t, ioTypeArray[i])
}
})
}
func TestRevertIOtypeMap(t *testing.T) {
t.Run("revertIOMap contains correct values", func(t *testing.T) {
require.Len(t, revertIOMap, int(IOTypeMax))
require.Equal(t, revertIOMap["write"], WriteIO)
require.Equal(t, revertIOMap["background"], BackgroundIO)
require.Equal(t, revertIOMap["read"], ReadIO)
require.Equal(t, revertIOMap["delete"], DeleteIO)
require.Equal(t, revertIOMap[WriteIO.String()], WriteIO)
require.Equal(t, revertIOMap[BackgroundIO.String()], BackgroundIO)
require.Equal(t, revertIOMap[ReadIO.String()], ReadIO)
require.Equal(t, revertIOMap[DeleteIO.String()], DeleteIO)
})
}

View File

@ -16,12 +16,14 @@ package blobnode
import (
"context"
"encoding/binary"
"fmt"
"io"
"math"
"net/http"
"strconv"
"github.com/cubefs/cubefs/blobstore/blobnode/base"
bloberr "github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
@ -29,9 +31,29 @@ import (
)
const (
MaxShardSize = math.MaxUint32
MaxShardSize = math.MaxUint32
GetShardsHeaderSize = 4
)
type ShardInfo struct {
Vuid proto.Vuid `json:"vuid"`
Bid proto.BlobID `json:"bid"`
Size int64 `json:"size"`
Crc uint32 `json:"crc"`
Offset int64 `json:"offset"`
Flag ShardStatus `json:"flag"` // 1:normal,2:markDelete
Inline bool `json:"inline"`
NopData bool `json:"nopdata"` // data all zero
}
type BidInfo struct {
Bid proto.BlobID `json:"bid"`
Size int64 `json:"size"`
Offset int64 `json:"offset"`
Crc uint32 `json:"crc"`
}
type ShardStatus uint8
const (
@ -42,8 +64,11 @@ const (
const (
ShardDataInline = 0x80 // 1000 0000
ShardDataNop = 0x40 // 0100 0000
)
var putWithCrcOption = []rpc.Option{rpc.WithCrcEncode()}
type PutShardArgs struct {
DiskID proto.DiskID `json:"diskid"`
Vuid proto.Vuid `json:"vuid"`
@ -51,6 +76,8 @@ type PutShardArgs struct {
Size int64 `json:"size"`
Type IOType `json:"iotype,omitempty"`
Body io.Reader `json:"-"`
NopData bool `json:"nopdata,omitempty"`
}
type PutShardRet struct {
@ -77,13 +104,20 @@ func (c *client) PutShard(ctx context.Context, host string, args *PutShardArgs)
}
urlStr := fmt.Sprintf("%v/shard/put/diskid/%v/vuid/%v/bid/%v/size/%v?iotype=%d",
host, args.DiskID, args.Vuid, args.Bid, args.Size, args.Type)
if args.NopData {
urlStr += "&nopdata=true"
}
req, err := http.NewRequest(http.MethodPost, urlStr, args.Body)
if err != nil {
err = convertEIO(err)
return
}
req.ContentLength = args.Size
err = c.DoWith(ctx, req, ret, rpc.WithCrcEncode())
if err == nil {
var opts []rpc.Option
if !args.NopData {
req.ContentLength = args.Size
opts = putWithCrcOption
}
if err = c.DoWith(ctx, req, ret, opts...); err == nil {
crc = ret.Crc
}
@ -115,6 +149,7 @@ func (c *client) GetShard(ctx context.Context, host string, args *GetShardArgs)
resp, err := c.Get(ctx, urlStr)
if err != nil {
err = convertEIO(err)
return nil, 0, err
}
@ -161,6 +196,7 @@ func (c *client) RangeGetShard(ctx context.Context, host string, args *RangeGetS
req, err := http.NewRequest(http.MethodGet, urlStr, nil)
if err != nil {
err = convertEIO(err)
span.Errorf("Failed new req. urlStr:%s, err:%v", urlStr, err)
return
}
@ -207,7 +243,8 @@ func (c *client) MarkDeleteShard(ctx context.Context, host string, args *DeleteS
urlStr := fmt.Sprintf("%v/shard/markdelete/diskid/%v/vuid/%v/bid/%v", host, args.DiskID, args.Vuid, args.Bid)
err = c.PostWith(ctx, urlStr, nil, rpc.NoneBody)
return
return convertEIO(err)
}
func (c *client) DeleteShard(ctx context.Context, host string, args *DeleteShardArgs) (err error) {
@ -218,13 +255,15 @@ func (c *client) DeleteShard(ctx context.Context, host string, args *DeleteShard
urlStr := fmt.Sprintf("%v/shard/delete/diskid/%v/vuid/%v/bid/%v", host, args.DiskID, args.Vuid, args.Bid)
err = c.PostWith(ctx, urlStr, nil, rpc.NoneBody)
return
return convertEIO(err)
}
type StatShardArgs struct {
DiskID proto.DiskID `json:"diskid"`
Vuid proto.Vuid `json:"vuid"`
Bid proto.BlobID `json:"bid"`
Type IOType `json:"iotype,omitempty"`
}
func (c *client) StatShard(ctx context.Context, host string, args *StatShardArgs) (si *ShardInfo, err error) {
@ -233,11 +272,12 @@ func (c *client) StatShard(ctx context.Context, host string, args *StatShardArgs
return
}
urlStr := fmt.Sprintf("%v/shard/stat/diskid/%v/vuid/%v/bid/%v",
host, args.DiskID, args.Vuid, args.Bid)
urlStr := fmt.Sprintf("%v/shard/stat/diskid/%v/vuid/%v/bid/%v?iotype=%d",
host, args.DiskID, args.Vuid, args.Bid, args.Type)
si = &ShardInfo{}
err = c.GetWith(ctx, urlStr, si)
return
return si, convertEIO(err)
}
type ListShardsArgs struct {
@ -265,8 +305,129 @@ func (c *client) ListShards(ctx context.Context, host string, args *ListShardsAr
listRet := ListShardsRet{}
err = c.GetWith(ctx, urlStr, &listRet)
if err != nil {
err = convertEIO(err)
return nil, proto.InValidBlobID, err
}
return listRet.ShardInfos, listRet.Next, nil
}
func convertEIO(err error) error {
if base.IsEIO(err) {
return bloberr.ErrDiskBroken
}
return err
}
type GetShardsArgs struct {
DiskID proto.DiskID `json:"diskid"`
Vuid proto.Vuid `json:"vuid" `
Bids []BidInfo `json:"bids"`
Type IOType `json:"type"`
}
func (c *client) GetShards(ctx context.Context, host string, args *GetShardsArgs) (getter ShardGetter, err error) {
if !args.Type.IsValid() {
err = bloberr.ErrInvalidParam
return
}
if !IsValidDiskID(args.DiskID) {
err = bloberr.ErrInvalidDiskId
return
}
urlStr := fmt.Sprintf("%v/shards/get", host)
resp, err := c.Post(ctx, urlStr, args)
if err != nil {
err = convertEIO(err)
return
}
if resp.StatusCode/100 != 2 {
defer resp.Body.Close()
err = rpc.ParseResponseErr(resp)
return
}
return &shardGetter{bids: args.Bids, body: resp.Body}, nil
}
type ShardGetter interface {
// NextShard before read next shard must read all data of last shard, if not will get unexpect error
NextShard(ctx context.Context) (body io.ReadCloser, err error, ok bool)
Close() error
}
type shardGetter struct {
body io.ReadCloser
bids []BidInfo
idx int
}
func (b *shardGetter) NextShard(ctx context.Context) (io.ReadCloser, error, bool) {
span := trace.SpanFromContextSafe(ctx)
if b.idx >= len(b.bids) {
return nil, nil, false
}
var header ShardsHeader
_, err := io.ReadFull(b.body, header[:])
if err != nil {
return nil, err, true
}
code := header.Get()
if code != 200 {
span.Errorf("download shard failed, errCode: %s", code)
return nil, bloberr.ErrBidNotMatch, true
}
bid := b.bids[b.idx]
b.idx++
return io.NopCloser(io.LimitReader(b.body, bid.Size)), nil, true
}
func (b *shardGetter) Close() error {
return b.body.Close()
}
type shardWriter struct {
header int
headerWritten bool
shard io.WriterTo
}
func NewShardWriter(header int, shard io.WriterTo) io.WriterTo {
return &shardWriter{header: header, shard: shard}
}
func (s *shardWriter) WriteTo(w io.Writer) (int64, error) {
if s.headerWritten {
return s.shard.WriteTo(w)
}
// write header
var header ShardsHeader
header.Set(s.header)
start := int64(0)
for start < int64(len(header)) {
n, err := w.Write(header[start:])
if err != nil {
return start, err
}
start += int64(n)
}
s.headerWritten = true
if s.header != http.StatusOK {
return int64(len(header)), bloberr.ErrBidNotMatch
}
// write data
n, err := s.shard.WriteTo(w)
return n + start, err
}
type ShardsHeader [GetShardsHeaderSize]byte
func (s *ShardsHeader) Set(code int) {
binary.BigEndian.PutUint32(s[:], uint32(code))
}
func (s *ShardsHeader) Get() int {
return int(binary.BigEndian.Uint32(s[:]))
}

View File

@ -15,13 +15,26 @@
package blobnode
import (
"syscall"
"testing"
"github.com/cubefs/cubefs/util/errors"
"github.com/stretchr/testify/require"
bloberr "github.com/cubefs/cubefs/blobstore/common/errors"
)
func TestShardStatus(t *testing.T) {
require.Equal(t, ShardStatusDefault, ShardStatus(0))
require.Equal(t, ShardStatusNormal, ShardStatus(1))
require.Equal(t, ShardStatusMarkDelete, ShardStatus(2))
var err error
require.Nil(t, convertEIO(err))
err = syscall.EIO
require.ErrorIs(t, convertEIO(err), bloberr.ErrDiskBroken)
err = errors.New("input/output error")
require.ErrorIs(t, convertEIO(err), bloberr.ErrDiskBroken)
}

View File

@ -0,0 +1,108 @@
package clustermgr
import (
"bytes"
"context"
"crypto/md5"
"encoding/base64"
"encoding/binary"
"fmt"
"time"
)
const (
hashBytesLength = 16
authVersionV1 uint8 = 1
)
func (c *Client) CreateSpace(ctx context.Context, args *CreateSpaceArgs) (err error) {
err = c.PostWith(ctx, "/space/create", nil, args)
return
}
func (c *Client) GetSpaceByName(ctx context.Context, args *GetSpaceByNameArgs) (ret *Space, err error) {
ret = &Space{}
err = c.GetWith(ctx, "/space/get?name="+args.Name, ret)
return
}
func (c *Client) GetSpaceByID(ctx context.Context, args *GetSpaceByIDArgs) (ret *Space, err error) {
ret = &Space{}
err = c.GetWith(ctx, "/space/get?space_id="+args.SpaceID.ToString(), ret)
return
}
func (c *Client) AuthSpace(ctx context.Context, args *AuthSpaceArgs) (err error) {
err = c.GetWith(ctx, fmt.Sprintf("/space/auth?name=%s&token=%s", args.Name, args.Token), nil)
return
}
func (c *Client) ListSpace(ctx context.Context, args *ListSpaceArgs) (ret ListSpaceRet, err error) {
err = c.GetWith(ctx, fmt.Sprintf("/space/list?marker=%d&count=%d", args.Marker, args.Count), &ret)
return
}
type AuthInfo struct {
AccessKey string
SecretKey string
}
// EncodeAuthInfo SDK generates token based on ak/sk
func EncodeAuthInfo(auth *AuthInfo) (token string, err error) {
timeStamp := time.Now().Unix()
hashBytes := CalculateHash(auth, timeStamp)
w := bytes.NewBuffer([]byte{})
if err = binary.Write(w, binary.LittleEndian, authVersionV1); err != nil {
return
}
if err = binary.Write(w, binary.LittleEndian, &timeStamp); err != nil {
return
}
if err = binary.Write(w, binary.LittleEndian, &hashBytes); err != nil {
return
}
return base64.URLEncoding.EncodeToString(w.Bytes()), nil
}
// DecodeAuthInfo server parses token
func DecodeAuthInfo(token string) (timestamp int64, hashBytes []byte, err error) {
b, err := base64.URLEncoding.DecodeString(token)
if err != nil {
return
}
var authVersion uint8
hashBytes = make([]byte, hashBytesLength)
r := bytes.NewBuffer(b)
if err = binary.Read(r, binary.LittleEndian, &authVersion); err != nil {
return
}
if authVersion == authVersionV1 {
if err = binary.Read(r, binary.LittleEndian, &timestamp); err != nil {
return
}
if err = binary.Read(r, binary.LittleEndian, &hashBytes); err != nil {
return
}
}
return
}
// CalculateHash server caculates hash based on ak/sk and timeStamp
func CalculateHash(auth *AuthInfo, timeStamp int64) (hashBytes []byte) {
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, uint64(timeStamp))
hash := md5.New()
hash.Write(b)
hash.Write([]byte(auth.AccessKey))
hash.Write([]byte(auth.SecretKey))
hashBytes = hash.Sum(nil)
return hashBytes
}
func (c *Client) GetCatalogChanges(ctx context.Context, args *GetCatalogChangesArgs) (ret *GetCatalogChangesRet, err error) {
ret = &GetCatalogChangesRet{}
err = c.GetWith(ctx, fmt.Sprintf("/catalogchanges/get?route_version=%d&node_id=%d", args.RouteVersion, args.NodeID), ret)
return
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,96 @@
syntax = "proto3";
package cubefs.blobstore.api.clustermgr;
option go_package = "./;clustermgr";
option (gogoproto.sizer_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.goproto_unkeyed_all) = true;
option (gogoproto.goproto_unrecognized_all) = true;
option (gogoproto.goproto_sizecache_all) = true;
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = true;
option (gogoproto.gostring_all) = true;
import "gogoproto/gogo.proto";
import "google/protobuf/any.proto";
import "cubefs/blobstore/api/clustermgr/shard.proto";
message Space {
uint32 space_id = 1 [(gogoproto.customname) = "SpaceID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.SpaceID"];
string name = 2;
uint32 status = 3[(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.SpaceStatus"];
repeated FieldMeta field_metas = 4 [(gogoproto.nullable) = false];
string acc_key = 5;
string sec_key = 6;
}
message FieldMeta {
uint32 id = 1 [(gogoproto.customname) = "ID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.FieldID"];
string name = 2;
uint32 field_type = 3 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.FieldType"];
uint32 index_option = 4 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.IndexOption"];
}
message CreateSpaceArgs {
string name = 1;
repeated FieldMeta field_metas = 2 [(gogoproto.nullable) = false];
}
message GetSpaceByNameArgs {
string name = 1;
}
message GetSpaceByIDArgs {
uint32 space_id = 1 [(gogoproto.customname) = "SpaceID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.SpaceID"];
}
message GetSpaceArgs {
string name = 1;
uint32 space_id = 2 [(gogoproto.customname) = "SpaceID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.SpaceID"];
}
message AuthSpaceArgs {
string name = 1;
string token = 2;
}
message CatalogChangeShardAdd {
uint32 shard_id = 1 [(gogoproto.customname) = "ShardID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.ShardID"];
uint64 route_version = 2 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
repeated ShardUnitInfo units = 3 [(gogoproto.nullable) = false];
}
message CatalogChangeShardUpdate {
uint32 shard_id = 1 [(gogoproto.customname) = "ShardID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.ShardID"];
uint64 route_version = 2 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
ShardUnitInfo unit = 3 [(gogoproto.nullable) = false];
}
message CatalogChangeItem {
uint64 route_version = 1 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
uint32 type = 2 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.CatalogChangeItemType"];
google.protobuf.Any item =3;
}
message GetCatalogChangesArgs {
uint64 route_version = 1 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
uint32 node_id = 2 [(gogoproto.customname) = "NodeID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.NodeID"];
}
message GetCatalogChangesRet {
uint64 route_version = 1 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
repeated CatalogChangeItem items = 2 [(gogoproto.nullable) = false];
}
message ListSpaceArgs {
uint32 marker = 1 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.SpaceID"];
uint32 count = 2;
}
message ListSpaceRet {
repeated Space spaces = 1;
uint32 marker = 2 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.SpaceID"];
}

View File

@ -0,0 +1,181 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package clustermgr
import (
"encoding/binary"
"encoding/hex"
"errors"
"time"
"github.com/cubefs/cubefs/blobstore/common/proto"
)
type ChunkInfo struct {
Id ChunkID `json:"id"`
Vuid proto.Vuid `json:"vuid"`
DiskID proto.DiskID `json:"diskid"`
Total uint64 `json:"total"` // ChunkSize
Used uint64 `json:"used"` // user data size
Free uint64 `json:"free"` // ChunkSize - Used
Size uint64 `json:"size"` // Chunk File Size (logic size)
Status ChunkStatus `json:"status"` // normal、readOnly
Compacting bool `json:"compacting"`
}
const (
ChunkStatusDefault ChunkStatus = iota // 0
ChunkStatusNormal // 1
ChunkStatusReadOnly // 2
ChunkStatusRelease // 3
ChunkNumStatus // 4
)
const (
ReleaseForUser = "release for user"
ReleaseForCompact = "release for compact"
)
// Chunk ID
// vuid + timestamp
const (
chunkVuidLen = 8
chunkTimestmapLen = 8
ChunkIDLength = chunkVuidLen + chunkTimestmapLen
)
var InvalidChunkID ChunkID = [ChunkIDLength]byte{}
var (
_vuidHexLen = hex.EncodedLen(chunkVuidLen)
_timestampHexLen = hex.EncodedLen(chunkTimestmapLen)
// ${vuid_hex}-${tiemstamp_hex}
// |-- 8 Bytes --|-- 1 Bytes --|-- 8 Bytes --|
delimiter = []byte("-")
ChunkIDEncodeLen = _vuidHexLen + _timestampHexLen + len(delimiter)
)
type (
ChunkID [ChunkIDLength]byte
ChunkStatus uint8
)
func (c ChunkID) UnixTime() uint64 {
return binary.BigEndian.Uint64(c[chunkVuidLen:ChunkIDLength])
}
func (c ChunkID) VolumeUnitId() proto.Vuid {
return proto.Vuid(binary.BigEndian.Uint64(c[:chunkVuidLen]))
}
func (c *ChunkID) Marshal() ([]byte, error) {
buf := make([]byte, ChunkIDEncodeLen)
var i int
hex.Encode(buf[i:_vuidHexLen], c[:chunkVuidLen])
i += _vuidHexLen
copy(buf[i:i+len(delimiter)], delimiter)
i += len(delimiter)
hex.Encode(buf[i:], c[chunkVuidLen:ChunkIDLength])
return buf, nil
}
func (c *ChunkID) Unmarshal(data []byte) error {
if len(data) != ChunkIDEncodeLen {
panic(errors.New("chunk buf size not match"))
}
var i int
_, err := hex.Decode(c[:chunkVuidLen], data[i:_vuidHexLen])
if err != nil {
return err
}
i += _vuidHexLen
i += len(delimiter)
_, err = hex.Decode(c[chunkVuidLen:], data[i:])
if err != nil {
return err
}
return nil
}
func (c ChunkID) String() string {
buf, _ := c.Marshal()
return string(buf[:])
}
func (c ChunkID) MarshalJSON() ([]byte, error) {
b := make([]byte, ChunkIDEncodeLen+2)
b[0], b[ChunkIDEncodeLen+1] = '"', '"'
buf, _ := c.Marshal()
copy(b[1:], buf)
return b, nil
}
func (c *ChunkID) UnmarshalJSON(data []byte) (err error) {
if len(data) != ChunkIDEncodeLen+2 {
return errors.New("failed unmarshal json")
}
return c.Unmarshal(data[1 : ChunkIDEncodeLen+1])
}
func EncodeChunk(id ChunkID) string {
return id.String()
}
func NewChunkID(vuid proto.Vuid) (chunkId ChunkID) {
binary.BigEndian.PutUint64(chunkId[:chunkVuidLen], uint64(vuid))
binary.BigEndian.PutUint64(chunkId[chunkVuidLen:ChunkIDLength], uint64(time.Now().UnixNano()))
return
}
func DecodeChunk(name string) (id ChunkID, err error) {
buf := []byte(name)
if len(buf) != ChunkIDEncodeLen {
return InvalidChunkID, errors.New("invalid chunk name")
}
if err = id.Unmarshal(buf); err != nil {
return InvalidChunkID, errors.New("chunk unmarshal failed")
}
return
}
func (s *ChunkStatus) String() string {
switch *s {
case ChunkStatusDefault:
return "default"
case ChunkStatusNormal:
return "normal"
case ChunkStatusReadOnly:
return "readOnly"
case ChunkStatusRelease:
return "release"
default:
return "unkown"
}
}

View File

@ -22,6 +22,7 @@ import (
"github.com/cubefs/cubefs/blobstore/common/errors"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
"github.com/cubefs/cubefs/blobstore/util"
)
const (
@ -134,3 +135,12 @@ func (c *Client) Stat(ctx context.Context) (ret *StatInfo, err error) {
func (c *Client) Snapshot(ctx context.Context) (*http.Response, error) {
return c.Get(ctx, "/snapshot/dump")
}
type SetClusterReadonlyArgs struct {
Readonly bool `json:"readonly"`
}
func (c *Client) SetClusterReadonly(ctx context.Context, args *SetClusterReadonlyArgs) (err error) {
err = c.PostWith(ctx, "/cluster/set?readonly="+util.Any2String(args.Readonly), nil, nil)
return
}

View File

@ -16,7 +16,10 @@ package clustermgr
import (
"context"
"encoding/json"
"github.com/cubefs/cubefs/blobstore/common/codemode"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
)
@ -38,8 +41,8 @@ func (c *Client) GetConfig(ctx context.Context, key string) (ret string, err err
return
}
func (c *Client) SetConfig(ctx context.Context, args *ConfigSetArgs) (err error) {
err = c.PostWith(ctx, "/config/set", nil, args)
func (c *Client) SetConfig(ctx context.Context, key, value string) (err error) {
err = c.PostWith(ctx, "/config/set", nil, &ConfigSetArgs{Key: key, Value: value})
return
}
@ -47,3 +50,19 @@ func (c *Client) DeleteConfig(ctx context.Context, key string) (err error) {
err = c.PostWith(ctx, "/config/delete?key="+key, nil, rpc.NoneBody)
return
}
func LoadExtendCodemode(ctx context.Context, configer interface {
GetConfig(context.Context, string) (string, error)
},
) error {
extend, err := configer.GetConfig(ctx, proto.CodeModeExtendKey)
if err != nil {
return err
}
extends := make([]codemode.ExtendCodeMode, 0)
if err = json.Unmarshal([]byte(extend), &extends); err != nil {
return err
}
codemode.Extend(extends...)
return nil
}

View File

@ -16,14 +16,69 @@ package clustermgr
import (
"context"
"encoding/json"
"errors"
"fmt"
"time"
"github.com/cubefs/cubefs/blobstore/api/blobnode"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
)
type ShardNodeDiskInfo struct {
DiskInfo
ShardNodeDiskHeartbeatInfo
}
func (s *ShardNodeDiskInfo) Marshal() ([]byte, error) {
return json.Marshal(s)
}
func (s *ShardNodeDiskInfo) Unmarshal(raw []byte) error {
return json.Unmarshal(raw, s)
}
type ShardNodeDiskHeartbeatInfo struct {
DiskID proto.DiskID `json:"disk_id"`
Used int64 `json:"used"` // disk used space
Free int64 `json:"free"` // remaining free space on the disk
Size int64 `json:"size"` // total physical disk space
MaxShardCnt int32 `json:"max_shard_cnt"` // note: maintained by clustermgr
FreeShardCnt int32 `json:"free_shard_cnt"` // note: maintained by clustermgr
UsedShardCnt int32 `json:"used_shard_cnt"` // current number of shards on the disk
}
type BlobNodeDiskInfo struct {
DiskInfo
DiskHeartBeatInfo
}
type DiskHeartBeatInfo struct {
DiskID proto.DiskID `json:"disk_id"`
Used int64 `json:"used"` // disk used space
Free int64 `json:"free"` // remaining free space on the disk
Size int64 `json:"size"` // total physical disk space
MaxChunkCnt int64 `json:"max_chunk_cnt"` // note: maintained by clustermgr
FreeChunkCnt int64 `json:"free_chunk_cnt"` // note: maintained by clustermgr
UsedChunkCnt int64 `json:"used_chunk_cnt"` // current number of chunks on the disk
OversoldFreeChunkCnt int64 `json:"oversold_free_chunk_cnt"` // note: maintained by clustermgr
}
type DiskInfo struct {
ClusterID proto.ClusterID `json:"cluster_id"`
Idc string `json:"idc"`
Rack string `json:"rack"`
Host string `json:"host"`
Path string `json:"path"`
Status proto.DiskStatus `json:"status"` // normal、broken、repairing、repaired、dropped
Readonly bool `json:"readonly"`
CreateAt time.Time `json:"create_time"`
LastUpdateAt time.Time `json:"last_update_time"`
DiskSetID proto.DiskSetID `json:"disk_set_id"`
NodeID proto.NodeID `json:"node_id"`
}
type DiskInfoArgs struct {
DiskID proto.DiskID `json:"disk_id"`
}
@ -49,12 +104,21 @@ type ListOptionArgs struct {
}
type ListDiskRet struct {
Disks []*blobnode.DiskInfo `json:"disks"`
Disks []*BlobNodeDiskInfo `json:"disks"`
Marker proto.DiskID `json:"marker"`
}
type ListShardNodeDiskRet struct {
Disks []*ShardNodeDiskInfo `json:"disks"`
Marker proto.DiskID `json:"marker"`
}
type DisksHeartbeatArgs struct {
Disks []*blobnode.DiskHeartBeatInfo `json:"disks"`
Disks []*DiskHeartBeatInfo `json:"disks"`
}
type ShardNodeDisksHeartbeatArgs struct {
Disks []ShardNodeDiskHeartbeatInfo `json:"disks"`
}
type DisksHeartbeatRet struct {
@ -68,26 +132,32 @@ type DiskHeartbeatRet struct {
}
type DiskStatInfo struct {
IDC string `json:"idc"`
Total int `json:"total"`
TotalChunk int64 `json:"total_chunk"`
TotalFreeChunk int64 `json:"total_free_chunk"`
Available int `json:"available"`
Readonly int `json:"readonly"`
Expired int `json:"expired"`
Broken int `json:"broken"`
Repairing int `json:"repairing"`
Repaired int `json:"repaired"`
Dropping int `json:"dropping"`
Dropped int `json:"dropped"`
IDC string `json:"idc"`
Total int `json:"total"`
TotalChunk int64 `json:"total_chunk,omitempty"`
TotalFreeChunk int64 `json:"total_free_chunk,omitempty"`
TotalOversoldFreeChunk int64 `json:"total_oversold_free_chunk,omitempty"`
TotalShard int64 `json:"total_shard,omitempty"`
TotalFreeShard int64 `json:"total_free_shard,omitempty"`
Available int `json:"available"`
Readonly int `json:"readonly"`
Expired int `json:"expired"`
Broken int `json:"broken"`
Repairing int `json:"repairing"`
Repaired int `json:"repaired"`
Dropping int `json:"dropping"`
Dropped int `json:"dropped"`
}
type SpaceStatInfo struct {
TotalSpace int64 `json:"total_space"`
FreeSpace int64 `json:"free_space"`
UsedSpace int64 `json:"used_space"`
WritableSpace int64 `json:"writable_space"`
TotalBlobNode int64 `json:"total_blob_node"`
TotalSpace int64 `json:"total_space"` // total physical space
FreeSpace int64 `json:"free_space"` // free physical space which is writable
ReadOnlySpace int64 `json:"readonly_space"` // free physical space which is readonly
UsedSpace int64 `json:"used_space"` // used physical space
ReservedSpace int64 `json:"reserved_space"` // reserved logical space
WritableSpace int64 `json:"writable_space"` // writable logical space
TotalBlobNode int64 `json:"total_blob_node,omitempty"`
TotalShardNode int64 `json:"total_shard_node,omitempty"`
TotalDisk int64 `json:"total_disk"`
DisksStatInfos []DiskStatInfo `json:"disk_stat_infos"`
}
@ -108,14 +178,14 @@ func (c *Client) AllocDiskID(ctx context.Context) (proto.DiskID, error) {
}
// DiskInfo get disk info from cluster manager
func (c *Client) DiskInfo(ctx context.Context, id proto.DiskID) (ret *blobnode.DiskInfo, err error) {
ret = &blobnode.DiskInfo{}
func (c *Client) DiskInfo(ctx context.Context, id proto.DiskID) (ret *BlobNodeDiskInfo, err error) {
ret = &BlobNodeDiskInfo{}
err = c.GetWith(ctx, "/disk/info?disk_id="+id.ToString(), ret)
return
}
// AddDisk add/register a new disk into cluster manager
func (c *Client) AddDisk(ctx context.Context, info *blobnode.DiskInfo) (err error) {
func (c *Client) AddDisk(ctx context.Context, info *BlobNodeDiskInfo) (err error) {
err = c.PostWith(ctx, "/disk/add", nil, info)
return
}
@ -129,7 +199,7 @@ func (c *Client) SetDisk(ctx context.Context, id proto.DiskID, status proto.Disk
}
// ListHostDisk list specified host disk info from cluster manager
func (c *Client) ListHostDisk(ctx context.Context, host string) (ret []*blobnode.DiskInfo, err error) {
func (c *Client) ListHostDisk(ctx context.Context, host string) (ret []*BlobNodeDiskInfo, err error) {
listRet := ListDiskRet{}
opt := &ListOptionArgs{Host: host, Count: 200}
for {
@ -158,7 +228,7 @@ func (c *Client) ListDisk(ctx context.Context, options *ListOptionArgs) (ret Lis
}
// HeartbeatDisk report blobnode disk latest capacity info to cluster manager
func (c *Client) HeartbeatDisk(ctx context.Context, infos []*blobnode.DiskHeartBeatInfo) (ret []*DiskHeartbeatRet, err error) {
func (c *Client) HeartbeatDisk(ctx context.Context, infos []*DiskHeartBeatInfo) (ret []*DiskHeartbeatRet, err error) {
result := &DisksHeartbeatRet{}
args := &DisksHeartbeatArgs{Disks: infos}
err = c.PostWith(ctx, "/disk/heartbeat", result, args)
@ -176,7 +246,7 @@ func (c *Client) DroppedDisk(ctx context.Context, id proto.DiskID) (err error) {
return
}
func (c *Client) ListDroppingDisk(ctx context.Context) (ret []*blobnode.DiskInfo, err error) {
func (c *Client) ListDroppingDisk(ctx context.Context) (ret []*BlobNodeDiskInfo, err error) {
result := &ListDiskRet{}
err = c.GetWith(ctx, "/disk/droppinglist", result)
ret = result.Disks
@ -187,3 +257,56 @@ func (c *Client) SetReadonlyDisk(ctx context.Context, id proto.DiskID, readonly
err = c.PostWith(ctx, "/disk/access", nil, &DiskAccessArgs{DiskID: id, Readonly: readonly})
return
}
// AddShardNodeDisk add/register a new disk of shardnode into cluster manager
func (c *Client) AddShardNodeDisk(ctx context.Context, info *ShardNodeDiskInfo) (err error) {
err = c.PostWith(ctx, "/shardnode/disk/add", nil, info)
return
}
// HeartbeatShardNodeDisk report shardnode disk latest capacity info to cluster manager
func (c *Client) HeartbeatShardNodeDisk(ctx context.Context, infos []ShardNodeDiskHeartbeatInfo) (err error) {
args := &ShardNodeDisksHeartbeatArgs{Disks: infos}
err = c.PostWith(ctx, "/shardnode/disk/heartbeat", nil, args)
return
}
// AllocShardNodeDiskID alloc shardnode diskID from cluster manager
func (c *Client) AllocShardNodeDiskID(ctx context.Context) (proto.DiskID, error) {
ret := &DiskIDAllocRet{}
err := c.PostWith(ctx, "/shardnode/diskid/alloc", ret, rpc.NoneBody)
if err != nil {
return 0, err
}
return ret.DiskID, nil
}
// ListShardNodeDisk list disk info from cluster manager
// when ListOptionArgs is default value, defalut return 10 diskInfos
func (c *Client) ListShardNodeDisk(ctx context.Context, options *ListOptionArgs) (ret ListShardNodeDiskRet, err error) {
err = c.GetWith(ctx, fmt.Sprintf(
"/shardnode/disk/list?idc=%s&rack=%s&host=%s&status=%d&marker=%d&count=%d",
options.Idc,
options.Rack,
options.Host,
options.Status,
options.Marker,
options.Count,
), &ret)
return
}
// ShardNodeDiskInfo get shardnode disk info from cluster manager
func (c *Client) ShardNodeDiskInfo(ctx context.Context, id proto.DiskID) (ret *ShardNodeDiskInfo, err error) {
ret = &ShardNodeDiskInfo{}
err = c.GetWith(ctx, "/shardnode/disk/info?disk_id="+id.ToString(), ret)
return
}
// SetShardNodeDisk set shardnode disk status
func (c *Client) SetShardNodeDisk(ctx context.Context, id proto.DiskID, status proto.DiskStatus) (err error) {
if !status.IsValid() {
return errors.New("invalid status")
}
return c.PostWith(ctx, "/shardnode/disk/set", nil, &DiskSetArgs{DiskID: id, Status: status})
}

View File

@ -0,0 +1,121 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package clustermgr
import (
"context"
"github.com/cubefs/cubefs/blobstore/common/proto"
)
type BlobNodeInfo struct {
NodeInfo
}
type ShardNodeInfo struct {
NodeInfo
ShardNodeExtraInfo
}
type ShardNodeExtraInfo struct {
RaftHost string `json:"raft_host"`
}
type NodeInfo struct {
NodeID proto.NodeID `json:"node_id"`
NodeSetID proto.NodeSetID `json:"node_set_id"`
ClusterID proto.ClusterID `json:"cluster_id"`
DiskType proto.DiskType `json:"disk_type"` // one node only manages one diskType disk
Idc string `json:"idc"`
Rack string `json:"rack"`
Host string `json:"host"`
Role proto.NodeRole `json:"role"`
Status proto.NodeStatus `json:"status"`
}
type NodeInfoArgs struct {
NodeID proto.NodeID `json:"node_id"`
}
type NodeIDAllocRet struct {
NodeID proto.NodeID `json:"node_id"`
}
type NodeSetInfo struct {
ID proto.NodeSetID `json:"id"`
Number int `json:"number"`
Nodes []proto.NodeID `json:"nodes"`
DiskSets map[proto.DiskSetID][]proto.DiskID `json:"disk_sets"`
}
type TopoInfo struct {
CurNodeSetID proto.NodeSetID `json:"cur_node_set_id"`
CurDiskSetID proto.DiskSetID `json:"cur_disk_set_id"`
AllNodeSets map[string]map[proto.NodeSetID]*NodeSetInfo `json:"all_node_sets"`
}
// AddNode add a new node into cluster manager and return allocated nodeID
func (c *Client) AddNode(ctx context.Context, info *BlobNodeInfo) (proto.NodeID, error) {
ret := &NodeIDAllocRet{}
err := c.PostWith(ctx, "/node/add", ret, info)
if err != nil {
return 0, err
}
return ret.NodeID, nil
}
// DropNode drop a node from cluster manager
func (c *Client) DropNode(ctx context.Context, id proto.NodeID) (err error) {
err = c.PostWith(ctx, "/node/drop", nil, &NodeInfoArgs{NodeID: id})
return
}
// NodeInfo get node info from cluster manager
func (c *Client) NodeInfo(ctx context.Context, id proto.NodeID) (ret *BlobNodeInfo, err error) {
ret = &BlobNodeInfo{}
err = c.GetWith(ctx, "/node/info?node_id="+id.ToString(), ret)
return
}
// TopoInfo get nodeset and diskset topo info from cluster manager
func (c *Client) TopoInfo(ctx context.Context) (ret *TopoInfo, err error) {
ret = &TopoInfo{}
err = c.GetWith(ctx, "/topo/info", ret)
return
}
// AddShardNode add a new shardnode into cluster manager and return allocated nodeID
func (c *Client) AddShardNode(ctx context.Context, info *ShardNodeInfo) (proto.NodeID, error) {
ret := &NodeIDAllocRet{}
err := c.PostWith(ctx, "/shardnode/add", ret, info)
if err != nil {
return 0, err
}
return ret.NodeID, nil
}
// ShardNodeInfo get shardnode info from cluster manager
func (c *Client) ShardNodeInfo(ctx context.Context, id proto.NodeID) (ret *ShardNodeInfo, err error) {
ret = &ShardNodeInfo{}
err = c.GetWith(ctx, "/shardnode/info?node_id="+id.ToString(), ret)
return
}
// ShardNodeTopoInfo get shardnode nodeset and diskset topo info from cluster manager
func (c *Client) ShardNodeTopoInfo(ctx context.Context) (ret *TopoInfo, err error) {
ret = &TopoInfo{}
err = c.GetWith(ctx, "/shardnode/topo/info", ret)
return
}

View File

@ -18,9 +18,7 @@ import (
"context"
"fmt"
"github.com/cubefs/cubefs/blobstore/api/blobnode"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/raftserver"
)
const (
@ -39,11 +37,12 @@ type ClusterInfo struct {
}
type StatInfo struct {
LeaderHost string `json:"leader_host"`
ReadOnly bool `json:"read_only"`
RaftStatus raftserver.Status `json:"raft_status"`
SpaceStat SpaceStatInfo `json:"space_stat"`
VolumeStat VolumeStatInfo `json:"volume_stat"`
LeaderHost string `json:"leader_host"`
ReadOnly bool `json:"read_only"`
RaftStatus interface{} `json:"raft_status"`
BlobNodeSpaceStat SpaceStatInfo `json:"space_stat"`
ShardNodeSpaceStat SpaceStatInfo `json:"shard_node_space_stat"`
VolumeStat VolumeStatInfo `json:"volume_stat"`
}
func GetConsulClusterPath(region string) string {
@ -54,6 +53,7 @@ func GetConsulClusterPath(region string) string {
type ClientAPI interface {
APIAccess
APIProxy
APIBlobnode
}
// APIAccess sub of cluster manager api for access
@ -61,13 +61,19 @@ type APIAccess interface {
GetConfig(ctx context.Context, key string) (string, error)
GetService(ctx context.Context, args GetServiceArgs) (ServiceInfo, error)
ListDisk(ctx context.Context, options *ListOptionArgs) (ListDiskRet, error)
AuthSpace(ctx context.Context, args *AuthSpaceArgs) (err error)
GetSpaceByName(ctx context.Context, args *GetSpaceByNameArgs) (ret *Space, err error)
GetCatalogChanges(ctx context.Context, args *GetCatalogChangesArgs) (ret *GetCatalogChangesRet, err error)
ShardNodeDiskInfo(ctx context.Context, id proto.DiskID) (ret *ShardNodeDiskInfo, err error)
ListShardNodeDisk(ctx context.Context, options *ListOptionArgs) (ret ListShardNodeDiskRet, err error)
}
// APIProxy sub of cluster manager api for allocator
type APIProxy interface {
GetConfig(ctx context.Context, key string) (string, error)
GetVolumeInfo(ctx context.Context, args *GetVolumeArgs) (*VolumeInfo, error)
DiskInfo(ctx context.Context, id proto.DiskID) (*blobnode.DiskInfo, error)
GetVolumeRoutes(ctx context.Context, args *GetVolumeRoutesArgs) (*GetVolumeRoutesRet, error)
DiskInfo(ctx context.Context, id proto.DiskID) (*BlobNodeDiskInfo, error)
AllocVolume(ctx context.Context, args *AllocVolumeArgs) (AllocatedVolumeInfos, error)
AllocBid(ctx context.Context, args *BidScopeArgs) (*BidScopeRet, error)
RetainVolume(ctx context.Context, args *RetainVolumeArgs) (RetainVolumes, error)
@ -77,4 +83,23 @@ type APIProxy interface {
// APIService sub of cluster manager api for service
type APIService interface {
GetService(ctx context.Context, args GetServiceArgs) (ServiceInfo, error)
RegisterService(ctx context.Context, node ServiceNode, tickInterval, heartbeatTicks, expiresTicks uint32) (err error)
}
type APIBlobnode interface {
APIService
GetConfig(ctx context.Context, key string) (value string, err error)
SetConfig(ctx context.Context, key, value string) error
AddNode(ctx context.Context, info *BlobNodeInfo) (proto.NodeID, error)
ListHostDisk(ctx context.Context, host string) (ret []*BlobNodeDiskInfo, err error)
ListDisk(ctx context.Context, options *ListOptionArgs) (ret ListDiskRet, err error)
AddDisk(ctx context.Context, info *BlobNodeDiskInfo) (err error)
DiskInfo(ctx context.Context, id proto.DiskID) (ret *BlobNodeDiskInfo, err error)
SetDisk(ctx context.Context, id proto.DiskID, status proto.DiskStatus) (err error)
AllocDiskID(ctx context.Context) (proto.DiskID, error)
SetCompactChunk(ctx context.Context, args *SetCompactChunkArgs) (err error)
ListVolumeUnit(ctx context.Context, args *ListVolumeUnitArgs) ([]*VolumeUnitInfo, error)
GetVolumeInfo(ctx context.Context, args *GetVolumeArgs) (ret *VolumeInfo, err error)
ReportChunk(ctx context.Context, args *ReportChunkArgs) (err error)
HeartbeatDisk(ctx context.Context, infos []*DiskHeartBeatInfo) (ret []*DiskHeartbeatRet, err error)
}

View File

@ -0,0 +1,64 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package clustermgr
import (
"context"
"fmt"
)
func (c *Client) AllocShardUnit(ctx context.Context, args *AllocShardUnitArgs) (ret *AllocShardUnitRet, err error) {
ret = &AllocShardUnitRet{}
err = c.PostWith(ctx, "/shard/unit/alloc", ret, args)
return
}
func (c *Client) UpdateShard(ctx context.Context, args *UpdateShardArgs) (err error) {
err = c.PostWith(ctx, "/shard/update", nil, args)
return
}
func (c *Client) ReportShard(ctx context.Context, args *ShardReportArgs) (ret []ShardTask, err error) {
result := &ShardReportRet{}
err = c.PostWith(ctx, "/shard/report", result, args)
return result.ShardTasks, err
}
func (c *Client) GetShardInfo(ctx context.Context, args *GetShardArgs) (ret *Shard, err error) {
ret = &Shard{}
err = c.GetWith(ctx, "/shard/get?shard_id="+args.ShardID.ToString(), ret)
return
}
func (c *Client) ListShardUnit(ctx context.Context, args *ListShardUnitArgs) ([]ShardUnitInfo, error) {
ret := &ListShardUnitRet{}
err := c.GetWith(ctx, "/shard/unit/list?disk_id="+args.DiskID.ToString(), ret)
return ret.ShardUnitInfos, err
}
func (c *Client) ListShard(ctx context.Context, args *ListShardArgs) (ret ListShardRet, err error) {
err = c.GetWith(ctx, fmt.Sprintf("/shard/list?marker=%d&count=%d", args.Marker, args.Count), &ret)
return
}
func (c *Client) AdminUpdateShard(ctx context.Context, args *Shard) (err error) {
err = c.PostWith(ctx, "/admin/update/shard", nil, args)
return
}
func (c *Client) AdminUpdateShardUnit(ctx context.Context, args *AdminUpdateShardUnitArgs) (err error) {
err = c.PostWith(ctx, "/admin/update/shard/unit", nil, args)
return
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,108 @@
syntax = "proto3";
package cubefs.blobstore.api.clustermgr;
option go_package = "./;clustermgr";
option (gogoproto.sizer_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.goproto_unkeyed_all) = true;
option (gogoproto.goproto_unrecognized_all) = true;
option (gogoproto.goproto_sizecache_all) = true;
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = true;
option (gogoproto.gostring_all) = true;
import "gogoproto/gogo.proto";
import "cubefs/blobstore/common/sharding/range.proto";
message Shard {
uint32 shard_id = 1 [(gogoproto.customname) = "ShardID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.ShardID"];
uint64 applied_index = 2;
uint32 leader_disk_id = 3 [(gogoproto.customname) = "LeaderDiskID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
cubefs.blobstore.common.sharding.Range range = 4 [(gogoproto.nullable) = false];
repeated ShardUnit units = 5 [(gogoproto.nullable) = false];
uint64 route_version = 6 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
}
message ShardUnit {
uint64 suid = 1 [(gogoproto.customname) = "Suid", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.Suid"];
uint32 disk_id = 2 [(gogoproto.customname) = "DiskID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
bool learner = 3;
string host = 4;
uint32 status = 5 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.ShardUnitStatus"];
}
message ShardUnitInfo {
uint64 suid = 1 [(gogoproto.customname) = "Suid", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.Suid"];
uint32 disk_id = 2 [(gogoproto.customname) = "DiskID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
uint64 applied_index = 3;
uint32 leader_disk_id = 4 [(gogoproto.customname) = "LeaderDiskID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
cubefs.blobstore.common.sharding.Range range = 5 [(gogoproto.nullable) = false];
uint64 route_version = 6 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
string host = 7;
bool learner = 8;
}
message ShardTask {
uint32 task_type = 1 [(gogoproto.customname) = "TaskType", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.ShardTaskType"];
uint32 disk_id = 2 [(gogoproto.customname) = "DiskID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
uint32 suid = 3 [(gogoproto.customname) = "Suid", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.Suid"];
uint64 old_route_version = 4 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
uint64 route_version = 5 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.RouteVersion"];
}
message ShardReportArgs {
repeated ShardUnitInfo shards = 1 [(gogoproto.nullable) = false];
}
message ShardReportRet {
repeated ShardTask shard_tasks = 1 [(gogoproto.nullable) = false];
}
message AllocShardUnitArgs{
uint64 suid = 1 [(gogoproto.customname) = "Suid", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.Suid"];
repeated uint32 exclude_disk_ids = 2 [(gogoproto.customname) = "ExcludeDiskIDs", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
}
message AllocShardUnitRet {
uint64 suid = 1 [(gogoproto.customname) = "Suid", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.Suid"];
uint32 disk_id = 2 [(gogoproto.customname) = "DiskID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
string host = 3;
}
message UpdateShardArgs {
uint64 new_suid = 1 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.Suid"];
uint32 new_disk_id = 2 [(gogoproto.customname) = "NewDiskID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
bool new_is_leaner = 3;
uint64 old_suid = 4 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.Suid"];
bool old_is_leaner = 5;
}
message GetShardArgs {
uint32 shard_id = 1 [(gogoproto.customname) = "ShardID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.ShardID"];
}
message ListShardUnitArgs {
uint32 disk_id = 1 [(gogoproto.customname) = "DiskID", (gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.DiskID"];
}
message ListShardUnitRet {
repeated ShardUnitInfo shard_unit_infos = 1 [(gogoproto.nullable) = false];
}
message ListShardArgs {
uint32 marker = 1 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.ShardID"];
uint32 count = 2;
}
message ListShardRet {
repeated Shard shards = 1 [(gogoproto.nullable) = false];
uint32 marker = 2 [(gogoproto.casttype) = "github.com/cubefs/cubefs/blobstore/common/proto.ShardID"];
}
message AdminUpdateShardUnitArgs {
uint32 epoch = 1;
uint32 next_epoch = 2;
ShardUnit unit = 3 [(gogoproto.embed) = true, (gogoproto.nullable) = false];
}

View File

@ -24,7 +24,6 @@ import (
"net/http"
"unsafe"
"github.com/cubefs/cubefs/blobstore/api/blobnode"
"github.com/cubefs/cubefs/blobstore/common/codemode"
"github.com/cubefs/cubefs/blobstore/common/proto"
"github.com/cubefs/cubefs/blobstore/common/rpc"
@ -62,16 +61,7 @@ func (v *VolumeInfo) Equal(expected *VolumeInfo) bool {
return true
}
type VolumeInfoBase struct {
Vid proto.Vid `json:"vid"`
CodeMode codemode.CodeMode `json:"code_mode"`
Status proto.VolumeStatus `json:"status"`
HealthScore int `json:"health_score"`
Total uint64 `json:"total"`
Free uint64 `json:"free"`
Used uint64 `json:"used"`
CreateByNodeID uint64 `json:"create_by_node_id"`
}
type VolumeInfoBase VolumeInfoBasePB
type AllocVolumeInfo struct {
VolumeInfo
@ -157,7 +147,8 @@ func (c *Client) RetainVolume(ctx context.Context, args *RetainVolumeArgs) (ret
}
type LockVolumeArgs struct {
Vid proto.Vid `json:"vid"`
Vid proto.Vid `json:"vid"`
Epoch uint32 `json:"epoch"`
}
func (c *Client) LockVolume(ctx context.Context, args *LockVolumeArgs) (err error) {
@ -166,7 +157,9 @@ func (c *Client) LockVolume(ctx context.Context, args *LockVolumeArgs) (err erro
}
type UnlockVolumeArgs struct {
Vid proto.Vid `json:"vid"`
Vid proto.Vid `json:"vid"`
Epoch uint32 `json:"epoch"`
Force bool `json:"force"`
}
func (c *Client) UnlockVolume(ctx context.Context, args *UnlockVolumeArgs) (err error) {
@ -175,7 +168,8 @@ func (c *Client) UnlockVolume(ctx context.Context, args *UnlockVolumeArgs) (err
}
type AllocVolumeUnitArgs struct {
Vuid proto.Vuid `json:"vuid"`
Vuid proto.Vuid `json:"vuid"`
IsBalance bool `json:"is_balance"`
}
type AllocVolumeUnit struct {
@ -202,15 +196,8 @@ type ListVolumeUnitArgs struct {
DiskID proto.DiskID `json:"disk_id"`
}
type VolumeUnitInfo struct {
Vuid proto.Vuid `json:"vuid"`
DiskID proto.DiskID `json:"disk_id"`
Total uint64 `json:"total"`
Free uint64 `json:"free"`
Used uint64 `json:"used"`
Compacting bool `json:"compact"`
Host string `json:"host"`
}
// VolumeUnitInfoBase is used to maintain the VolumeUnitInfo marshal method after existing structs are defined in pb.
type VolumeUnitInfo VolumeUnitInfoBase
type ListVolumeUnitInfos struct {
VolumeUnitInfos []*VolumeUnitInfo `json:"volume_unit_infos"`
@ -223,7 +210,7 @@ func (c *Client) ListVolumeUnit(ctx context.Context, args *ListVolumeUnitArgs) (
}
type ReportChunkArgs struct {
ChunkInfos []blobnode.ChunkInfo `json:"chunk_infos"`
ChunkInfos []ChunkInfo `json:"chunk_infos"`
}
func (r *ReportChunkArgs) Encode() ([]byte, error) {
@ -274,16 +261,16 @@ func (r *ReportChunkArgs) Decode(reader io.Reader) error {
}
read(&count)
r.ChunkInfos = make([]blobnode.ChunkInfo, count)
if count > 1<<20 {
return fmt.Errorf("chunks is too much %d, limit: %d", count, 1<<20)
}
r.ChunkInfos = make([]ChunkInfo, count)
for i := range r.ChunkInfos {
raw := make([]byte, blobnode.ChunkIdEncodeLen)
raw := make([]byte, ChunkIDEncodeLen)
n, err := io.ReadFull(reader, raw)
if n != blobnode.ChunkIdEncodeLen || err != nil {
if n != ChunkIDEncodeLen || err != nil {
return fmt.Errorf("invalid source reader, err: %v", err)
}
if err != nil {
return err
}
r.ChunkInfos[i].Id.Unmarshal(raw)
read(&r.ChunkInfos[i].Vuid)
read(&r.ChunkInfos[i].DiskID)
@ -344,12 +331,13 @@ func (c *Client) ListAllocatedVolumes(ctx context.Context, args *ListAllocatedVo
}
type VolumeStatInfo struct {
TotalVolume int `json:"total_volume"`
IdleVolume int `json:"idle_volume"`
AllocatableVolume int `json:"can_alloc_volume"`
ActiveVolume int `json:"active_volume"`
LockVolume int `json:"lock_volume"`
UnlockingVolume int `json:"unlocking_volume"`
TotalVolume int `json:"total_volume"`
IdleVolume int `json:"idle_volume"`
AllocatableVolume int `json:"can_alloc_volume"`
ActiveVolume int `json:"active_volume"`
LockVolume int `json:"lock_volume"`
UnlockingVolume int `json:"unlocking_volume"`
WritableSpace uint64 `json:"writable_space"`
}
type AdminUpdateUnitArgs struct {
@ -357,3 +345,17 @@ type AdminUpdateUnitArgs struct {
NextEpoch uint32 `json:"next_epoch"`
VolumeUnitInfo
}
func (c *Client) GetVolumeRoutes(ctx context.Context, args *GetVolumeRoutesArgs) (ret *GetVolumeRoutesRet, err error) {
ret = &GetVolumeRoutesRet{}
err = c.GetWith(ctx, fmt.Sprintf("/volumeroutes/get?route_version=%d", args.RouteVersion), ret)
return
}
func (m *VolumeUnitInfoBase) Convert2Unit() Unit {
return Unit{
Vuid: m.GetVuid(),
DiskID: m.GetDiskID(),
Host: m.GetHost(),
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More