Skip to content

Commit 686572f

Browse files
author
shuwen5
committed
block_desc add ts_range and ref_num
1 parent 3c041bb commit 686572f

File tree

4 files changed

+184
-15
lines changed

4 files changed

+184
-15
lines changed

ectypes/block_desc.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,53 @@ def _mtime(ts=None):
4141
return int(ts)
4242

4343

44+
def _ts_range(ts_range=None):
45+
if ts_range is None:
46+
return ts_range
47+
48+
if ts_range[0] is not None:
49+
ts_range[0] = str(ts_range[0])
50+
51+
if ts_range[1] is not None:
52+
ts_range[1] = str(ts_range[1])
53+
54+
return ts_range
55+
56+
4457
class BlockDesc(FixedKeysDict):
4558

4659
keys_default = dict(
4760
block_id=_block_id,
4861
size=int,
4962
range=_range,
63+
ts_range=_ts_range,
5064
is_del=_is_del,
5165
mtime=_mtime,
66+
ref_num=int,
5267
)
5368

5469
def mark_del(self):
70+
if self['ref_num'] != 0:
71+
raise ValueError("cannot mark del block with ref_num:{n} > 0".format(
72+
n=self['ref_num']))
73+
5574
self["is_del"] = 1
5675
self.mtime = int(time.time())
76+
77+
def is_mark_del(self):
78+
return self['is_del'] == 1
79+
80+
def add_ref(self):
81+
if self['is_del'] != 0:
82+
raise ValueError("reference a block marked delete")
83+
84+
self['ref_num'] += 1
85+
86+
def rm_ref(self):
87+
if self['ref_num'] < 1:
88+
raise ValueError("ref_num:{n} < 1".format(n=self['ref_num']))
89+
90+
self['ref_num'] -= 1
91+
92+
def can_del(self):
93+
return self['ref_num'] == 0

ectypes/block_group.py

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,27 +100,55 @@ def make_type_map(self):
100100

101101
def mark_delete_block(self, block_index):
102102
block = self.get_block(block_index, raise_error=True)
103-
block.mark_del()
104103

105-
return block
104+
block.rm_ref()
106105

107-
def delete_block(self, block_index):
108-
block = self.get_block(block_index, raise_error=True)
109-
del self['blocks'][str(block_index)]
106+
if block.can_del():
107+
block.mark_del()
108+
return block
110109

111-
return block
110+
return None
112111

113112
def mark_delete_block_byid(self, block_id):
114113
block = self.get_block_byid(block_id, raise_error=True)
115-
block.mark_del()
116114

117-
return block
115+
block.rm_ref()
118116

119-
def delete_block_byid(self, block_id):
117+
if block.can_del():
118+
block.mark_del()
119+
return block
120+
121+
return None
122+
123+
def unlink_block(self, block_index):
124+
block = self.get_block(block_index, raise_error=True)
125+
126+
if not block.is_mark_del():
127+
block.rm_ref()
128+
129+
if block.can_del():
130+
del self['blocks'][str(block_index)]
131+
return block
132+
133+
return None
134+
135+
def unlink_block_byid(self, block_id):
120136
block = self.get_block_byid(block_id, raise_error=True)
121-
del self['blocks'][block_id.block_index]
122137

123-
return block
138+
if not block.is_mark_del():
139+
block.rm_ref()
140+
141+
if block.can_del():
142+
del self['blocks'][block_id.block_index]
143+
return block
144+
145+
return None
146+
147+
def delete_block(self, block_index):
148+
return self.unlink_block(block_index)
149+
150+
def delete_block_byid(self, block_id):
151+
return self.unlink_block_byid(block_id)
124152

125153
def has(self, block):
126154
bid = block['block_id']
@@ -129,6 +157,18 @@ def has(self, block):
129157
existent = self['blocks'].get(bidx)
130158
return existent == block
131159

160+
def link_block(self, block_index):
161+
block = self.get_block(block_index, raise_error=True)
162+
163+
block.add_ref()
164+
return block
165+
166+
def link_block_byid(self, block_id):
167+
block = self.get_block_byid(block_id, raise_error=True)
168+
169+
block.add_ref()
170+
return block
171+
132172
def add_block(self, new_block, replace=False, allow_exist=False):
133173

134174
if self.has(new_block) and allow_exist:
@@ -251,7 +291,7 @@ def classify_blocks(self, idc_index, only_primary=True):
251291
if blk is None:
252292
continue
253293

254-
if blk['is_del'] == 1:
294+
if blk.is_mark_del():
255295
mark_del.append(blk)
256296
continue
257297

ectypes/test/test_block_desc.py

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,34 @@ def test_blockdesc(self):
1919
{'block_id': None,
2020
'size': 0,
2121
'range': None,
22+
'ts_range': None,
23+
'ref_num': 0,
2224
'is_del': 0}),
2325

2426
({'block_id': block_id,
2527
'range': ['a', 'b'],
28+
'ts_range': ["124", None],
29+
'ref_num': 0,
2630
'size': 34,
2731
'mtime': 1,
2832
'is_del': 0},
2933
{'block_id': BlockID(block_id),
3034
'range': rangeset.Range('a', 'b'),
35+
'ts_range': ["124", None],
36+
'ref_num': 0,
3137
'size': 34,
3238
'mtime': 1,
3339
'is_del': 0}),
3440

3541
({'block_id': BlockID(block_id),
3642
'range': rangeset.Range('b', 'bb'),
43+
'ts_range': ["1235", "456"],
44+
'ref_num': 0,
3745
'mtime': 1},
3846
{'block_id': BlockID(block_id),
3947
'range': rangeset.Range('b', 'bb'),
48+
'ts_range': ["1235", "456"],
49+
'ref_num': 0,
4050
'size': 0,
4151
'mtime': 1,
4252
'is_del': 0, })
@@ -61,15 +71,48 @@ def test_json(self):
6171
DriveID('idc000' 'c62d8736c7280002'), 1),
6272
'size': 1000,
6373
'range': ['0a', '0b'],
74+
'ts_range': ["1235", "456"],
75+
'ref_num': 1,
6476
'is_del': 0,
6577
'mtime': 1,
6678

6779
})
6880

6981
rst = utfjson.dump(blk)
70-
expected = ('{"is_del": 0, "range": ["0a", "0b"], "mtime": 1, "block_id": '
71-
'"d0g0006400000001230000idc000c62d8736c72800020000000001", "size": 1000}')
82+
83+
expected = ('{"block_id": "d0g0006400000001230000idc000c62d8736c72800020000000001", "is_del": 0, "ref_num": 1, "range": ["0a", "0b"], "mtime": 1, "ts_range": ["1235", "456"], "size": 1000}')
7284

7385
self.assertEqual(expected, rst)
7486
loaded = BlockDesc(utfjson.load(rst))
7587
self.assertEqual(blk, loaded)
88+
89+
def test_ref(self):
90+
block_id = 'd1g0006300000001230101idc000c62d8736c72800020000000001'
91+
blk = BlockDesc({
92+
'block_id': block_id,
93+
'size': 1000,
94+
'range': ['0a', '0b'],
95+
'ts_range': ["1235", "456"],
96+
'ref_num': 1,
97+
'is_del': 0,
98+
'mtime': 1,
99+
100+
})
101+
102+
blk.add_ref()
103+
blk.add_ref()
104+
self.assertEqual(blk['ref_num'], 3)
105+
106+
blk.rm_ref()
107+
self.assertEqual(blk['ref_num'], 2)
108+
109+
self.assertRaises(ValueError, blk.mark_del)
110+
111+
blk.rm_ref()
112+
blk.rm_ref()
113+
self.assertEqual(blk['ref_num'], 0)
114+
self.assertTrue(blk.can_del())
115+
116+
self.assertRaises(ValueError, blk.rm_ref)
117+
118+
blk.mark_del()

ectypes/test/test_block_group.py

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ def setUp(self):
7777
DriveID('idc000' 'c62d8736c7280002'), 1),
7878
'size': 1000,
7979
'range': ['0a', '0b'],
80+
'ts_range': None,
81+
'ref_num': 1,
8082
'is_del': 0
8183
})
8284

@@ -150,6 +152,12 @@ def test_mark_delete_block(self):
150152
g = BlockGroup(block_group_id='g000640000000123', idcs=['a', 'b', 'c'], config=_ec_config)
151153

152154
g.add_block(self.foo_block)
155+
156+
self.foo_block.add_ref()
157+
self.assertIsNone(g.mark_delete_block('0000'))
158+
self.assertEqual(self.foo_block['ref_num'], 1)
159+
self.assertEqual(0, self.foo_block['is_del'])
160+
153161
del_blk = g.mark_delete_block('0000')
154162
self.assertDictEqual(del_blk, g.get_block('0000'))
155163

@@ -161,6 +169,12 @@ def test_mark_delete_block_byid(self):
161169
g = BlockGroup(block_group_id='g000640000000123', idcs=['a', 'b', 'c'], config=_ec_config)
162170

163171
g.add_block(self.foo_block)
172+
173+
self.foo_block.add_ref()
174+
self.assertIsNone(g.mark_delete_block_byid(self.foo_block['block_id']))
175+
self.assertDictEqual(self.foo_block, g.get_block_byid(self.foo_block['block_id']))
176+
self.assertEqual(self.foo_block['ref_num'], 1)
177+
164178
del_blk = g.mark_delete_block_byid(self.foo_block['block_id'])
165179
self.assertDictEqual(del_blk, g.get_block_byid(self.foo_block['block_id']))
166180

@@ -181,6 +195,10 @@ def test_delete_block(self):
181195
g.add_block(self.foo_block)
182196
self.assertIsNotNone(g.get_block('0000'))
183197

198+
self.foo_block.add_ref()
199+
del_blk = g.delete_block('0000')
200+
self.assertIsNotNone(g.get_block('0000', raise_error=False))
201+
184202
del_blk = g.delete_block('0000')
185203
self.assertIsNone(g.get_block('0000', raise_error=False))
186204
self.assertDictEqual(self.foo_block, del_blk)
@@ -397,6 +415,8 @@ def make_test_block_group(self, blk_idxes, config=None):
397415
base_blk = BlockDesc({
398416
'size': 1000,
399417
'range': ['0a', '0b'],
418+
'ts_range': ["123", "456"],
419+
'ref_num': 1,
400420
'is_del': 0
401421
})
402422

@@ -541,7 +561,7 @@ def test_get_block_byid(self):
541561
self.assertRaises(BlockNotFoundError, bg.get_block_byid, fake_bid, True)
542562
self.assertRaises(BlockNotFoundError, bg.get_block_byid, fake_bid)
543563

544-
def test_delete_block_byid(self):
564+
def test_unlink_block_byid(self):
545565

546566
blk_idxes = ['0000', '0001', '0002', '0003', '0008', '0012']
547567

@@ -550,6 +570,14 @@ def test_delete_block_byid(self):
550570
blks = bg.indexes_to_blocks(blk_idxes)
551571
bids = [blk['block_id'] for blk in blks]
552572

573+
bg.link_block_byid(bids[1])
574+
self.assertEqual(blks[1]['ref_num'], 2)
575+
576+
self.assertIsNone(bg.delete_block_byid(bids[1]))
577+
578+
del_blk = bg.mark_delete_block_byid(bids[1])
579+
self.assertEqual(del_blk["is_del"], 1)
580+
553581
del_blk = bg.delete_block_byid(bids[1])
554582
self.assertDictEqual(del_blk, blks[1])
555583

@@ -562,6 +590,27 @@ def test_delete_block_byid(self):
562590

563591
self.assertListEqual(blks, act_blks)
564592

593+
def test_link_block(self):
594+
595+
blk_idxes = ['0000', '0001', '0002', '0003', '0008', '0012']
596+
597+
bg = self.make_test_block_group(blk_idxes)
598+
blks = bg.indexes_to_blocks(blk_idxes)
599+
600+
args = [blks[1], False, False]
601+
self.assertRaises(BlockExists, bg.add_block, *args)
602+
act_blks = bg.indexes_to_blocks(blk_idxes)
603+
self.assertListEqual(blks, act_blks)
604+
605+
bg.link_block(blk_idxes[1])
606+
self.assertEqual(blks[1]['ref_num'], 2)
607+
608+
bg.unlink_block(blk_idxes[1])
609+
self.assertDictEqual(blks[1], bg.add_block(blks[1], allow_exist=True))
610+
611+
act_blks = bg.indexes_to_blocks(blk_idxes)
612+
self.assertListEqual(blks, act_blks)
613+
565614
def test_add_block(self):
566615

567616
blk_idxes = ['0000', '0001', '0002', '0003', '0008', '0012']

0 commit comments

Comments
 (0)