Skip to content

Commit 971a241

Browse files
author
shuwen5
committed
block_desc add ts_range and ref_num
1 parent 3c041bb commit 971a241

File tree

4 files changed

+178
-13
lines changed

4 files changed

+178
-13
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: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,35 +100,69 @@ 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
106-
107-
def delete_block(self, block_index):
108-
block = self.get_block(block_index, raise_error=True)
109-
del self['blocks'][str(block_index)]
104+
block.rm_ref()
105+
if block.can_del():
106+
block.mark_del()
110107

111108
return block
112109

113110
def mark_delete_block_byid(self, block_id):
114111
block = self.get_block_byid(block_id, raise_error=True)
115-
block.mark_del()
112+
113+
block.rm_ref()
114+
if block.can_del():
115+
block.mark_del()
116116

117117
return block
118118

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

123139
return block
124140

141+
def delete_block(self, block_index):
142+
return self.unlink_block(block_index)
143+
144+
def delete_block_byid(self, block_id):
145+
return self.unlink_block_byid(block_id)
146+
125147
def has(self, block):
126148
bid = block['block_id']
127149
bidx = bid.block_index
128150

129151
existent = self['blocks'].get(bidx)
130152
return existent == block
131153

154+
def link_block(self, block_index):
155+
block = self.get_block(block_index, raise_error=True)
156+
157+
block.add_ref()
158+
return block
159+
160+
def link_block_byid(self, block_id):
161+
block = self.get_block_byid(block_id, raise_error=True)
162+
163+
block.add_ref()
164+
return block
165+
132166
def add_block(self, new_block, replace=False, allow_exist=False):
133167

134168
if self.has(new_block) and allow_exist:
@@ -251,7 +285,7 @@ def classify_blocks(self, idc_index, only_primary=True):
251285
if blk is None:
252286
continue
253287

254-
if blk['is_del'] == 1:
288+
if blk.is_mark_del():
255289
mark_del.append(blk)
256290
continue
257291

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: 52 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,13 @@ 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+
del_blk = g.mark_delete_block('0000')
158+
self.assertDictEqual(del_blk, g.get_block('0000'))
159+
self.assertEqual(del_blk['ref_num'], 1)
160+
self.assertEqual(0, del_blk['is_del'])
161+
153162
del_blk = g.mark_delete_block('0000')
154163
self.assertDictEqual(del_blk, g.get_block('0000'))
155164

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

163172
g.add_block(self.foo_block)
173+
174+
self.foo_block.add_ref()
175+
del_blk = g.mark_delete_block_byid(self.foo_block['block_id'])
176+
self.assertDictEqual(del_blk, g.get_block_byid(self.foo_block['block_id']))
177+
self.assertEqual(del_blk['ref_num'], 1)
178+
164179
del_blk = g.mark_delete_block_byid(self.foo_block['block_id'])
165180
self.assertDictEqual(del_blk, g.get_block_byid(self.foo_block['block_id']))
166181

@@ -181,6 +196,10 @@ def test_delete_block(self):
181196
g.add_block(self.foo_block)
182197
self.assertIsNotNone(g.get_block('0000'))
183198

199+
self.foo_block.add_ref()
200+
del_blk = g.delete_block('0000')
201+
self.assertIsNotNone(g.get_block('0000', raise_error=False))
202+
184203
del_blk = g.delete_block('0000')
185204
self.assertIsNone(g.get_block('0000', raise_error=False))
186205
self.assertDictEqual(self.foo_block, del_blk)
@@ -397,6 +416,8 @@ def make_test_block_group(self, blk_idxes, config=None):
397416
base_blk = BlockDesc({
398417
'size': 1000,
399418
'range': ['0a', '0b'],
419+
'ts_range': ["123", "456"],
420+
'ref_num': 1,
400421
'is_del': 0
401422
})
402423

@@ -541,7 +562,7 @@ def test_get_block_byid(self):
541562
self.assertRaises(BlockNotFoundError, bg.get_block_byid, fake_bid, True)
542563
self.assertRaises(BlockNotFoundError, bg.get_block_byid, fake_bid)
543564

544-
def test_delete_block_byid(self):
565+
def test_unlink_block_byid(self):
545566

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

@@ -550,6 +571,15 @@ def test_delete_block_byid(self):
550571
blks = bg.indexes_to_blocks(blk_idxes)
551572
bids = [blk['block_id'] for blk in blks]
552573

574+
bg.link_block_byid(bids[1])
575+
self.assertEqual(blks[1]['ref_num'], 2)
576+
577+
del_blk = bg.delete_block_byid(bids[1])
578+
self.assertDictEqual(del_blk, blks[1])
579+
580+
del_blk = bg.mark_delete_block_byid(bids[1])
581+
self.assertEqual(del_blk["is_del"], 1)
582+
553583
del_blk = bg.delete_block_byid(bids[1])
554584
self.assertDictEqual(del_blk, blks[1])
555585

@@ -562,6 +592,27 @@ def test_delete_block_byid(self):
562592

563593
self.assertListEqual(blks, act_blks)
564594

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

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

0 commit comments

Comments
 (0)