Merge lp:~verterok/ubuntuone-client/tritcask-fix-825366-stable-2-0 into lp:ubuntuone-client/stable-2-0

Proposed by Guillermo Gonzalez
Status: Merged
Approved by: Guillermo Gonzalez
Approved revision: 1144
Merged at revision: 1145
Proposed branch: lp:~verterok/ubuntuone-client/tritcask-fix-825366-stable-2-0
Merge into: lp:ubuntuone-client/stable-2-0
Diff against target: 149 lines (+74/-6)
2 files modified
tests/syncdaemon/test_tritcask.py (+61/-1)
ubuntuone/syncdaemon/tritcask.py (+13/-5)
To merge this branch: bzr merge lp:~verterok/ubuntuone-client/tritcask-fix-825366-stable-2-0
Reviewer Review Type Date Requested Status
Roberto Alsina (community) Approve
Curtis Caravone (community) Approve
Review via email: mp+86770@code.launchpad.net

Commit message

Make sure we never use or create a hint file with size 0.

Description of the change

Make sure we never use or create a hint file with size 0.

To post a comment you must log in.
Revision history for this message
Curtis Caravone (caravone) :
review: Approve
Revision history for this message
Roberto Alsina (ralsina) wrote :

+1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/syncdaemon/test_tritcask.py'
2--- tests/syncdaemon/test_tritcask.py 2011-09-26 20:22:12 +0000
3+++ tests/syncdaemon/test_tritcask.py 2011-12-23 04:16:28 +0000
4@@ -140,6 +140,16 @@
5 new_file.fd.flush()
6 self.assertEqual(len('foo'), new_file.size)
7
8+ def test_has_hint(self):
9+ """Test that has_hint works as expetced."""
10+ new_file = self.file_class(self.base_dir)
11+ self.assertFalse(new_file.has_hint)
12+
13+ def test_hint_size(self):
14+ """Test that hint_size work as expected."""
15+ new_file = self.file_class(self.base_dir)
16+ self.assertEqual(new_file.hint_size, 0)
17+
18 def test__open(self):
19 """Test the _open private method."""
20 new_file = self.file_class(self.base_dir)
21@@ -523,6 +533,26 @@
22 self.assertEqual(len('bar')+len('foo')+header_size+crc32_size,
23 data_file.size)
24
25+ def test_has_hint(self):
26+ """Test that has_hint works as expetced."""
27+ rw_file = DataFile(self.base_dir)
28+ tstamp, value_pos, value_sz = rw_file.write(0, 'foo', 'bar')
29+ data_file = rw_file.make_immutable()
30+ self.assertFalse(data_file.has_hint)
31+ data_file.get_hint_file().close()
32+ self.assertTrue(data_file.has_hint)
33+
34+ def test_hint_size(self):
35+ """Test that hint_size work as expected."""
36+ rw_file = DataFile(self.base_dir)
37+ tstamp, value_pos, value_sz = rw_file.write(0, 'foo', 'bar')
38+ data_file = rw_file.make_immutable()
39+ self.assertEqual(data_file.hint_size, 0)
40+ hint_file = data_file.get_hint_file()
41+ hint_file.fd.write("some data")
42+ hint_file.close()
43+ self.assertEqual(data_file.hint_size, len("some data"))
44+
45
46 class DeadDataFileTest(ImmutableDataFileTest):
47 """Tests for DeadDataFile."""
48@@ -617,13 +647,22 @@
49 self.assertEqual('w+b', hint_file.fd.mode)
50
51 def test_init_existing(self):
52- """Test initialization."""
53+ """Test initialization with existing file."""
54 path = os.path.join(self.base_dir, 'test_hint_existing')
55 hint_file = HintFile(path)
56+ hint_file.fd.write("some data")
57 hint_file.close()
58 hint_file = HintFile(path)
59 self.assertEqual('rb', hint_file.fd.mode)
60
61+ def test_init_existing_empty(self):
62+ """Test initialization with existing file."""
63+ path = os.path.join(self.base_dir, 'test_hint_existing')
64+ hint_file = HintFile(path)
65+ hint_file.close()
66+ hint_file = HintFile(path)
67+ self.assertEqual('w+b', hint_file.fd.mode)
68+
69 def test_close(self):
70 """Test for the close method."""
71 path = os.path.join(self.base_dir, 'test_hint_close')
72@@ -1032,6 +1071,27 @@
73 self.assertEqual(6, len(hint_entry))
74 self.assertTrue(db.get(hint_entry[2], hint_entry[-1]) is not None)
75
76+ def test_build_keydir_with_empty_hint(self):
77+ """Test _build_keydir using a hint file."""
78+ db = Tritcask(self.base_dir)
79+ # create some stuff.
80+ for i in range(10):
81+ db.put(i, 'foo%d' % (i,), 'bar%s' % (i,))
82+ # make the data file inactive and generate the hint.
83+ db.live_file.make_immutable()
84+ old_keydir = db._keydir
85+ db.shutdown()
86+ db = Tritcask(self.base_dir)
87+ hint_filename = db._immutable.values()[0].hint_filename
88+ # truncate the hint file
89+ open(hint_filename, 'w').close()
90+ db.shutdown()
91+ # open the tritcask and make sure it regenerates the hint file
92+ db = Tritcask(self.base_dir)
93+ self.addCleanup(db.shutdown)
94+ self.assertTrue(os.path.exists(hint_filename), os.listdir(db.base_path))
95+ self.assertEqual(old_keydir, db._keydir)
96+
97 def test_build_keydir(self):
98 """Test _build_keydir method."""
99 db = Tritcask(self.base_dir)
100
101=== modified file 'ubuntuone/syncdaemon/tritcask.py'
102--- ubuntuone/syncdaemon/tritcask.py 2011-09-26 20:22:12 +0000
103+++ ubuntuone/syncdaemon/tritcask.py 2011-12-23 04:16:28 +0000
104@@ -202,6 +202,13 @@
105 """Return true if there is a hint file on-disk."""
106 return os.path.exists(self.hint_filename)
107
108+ @property
109+ def hint_size(self):
110+ """Return the hint file size."""
111+ if self.has_hint:
112+ return os.stat(self.hint_filename).st_size
113+ return 0
114+
115 def exists(self):
116 return os.path.exists(self.filename)
117
118@@ -433,8 +440,8 @@
119 """Create the instance."""
120 self.path = path
121 self.tempfile = None
122- if os.path.exists(self.path):
123- # if it's there open only for read
124+ if os.path.exists(self.path) and os.stat(self.path).st_size > 0:
125+ # if it's there and size > 0, open only for read
126 self.fd = open(self.path, 'rb')
127 else:
128 # this is a new hint file, lets create it as a tempfile.
129@@ -755,8 +762,8 @@
130 # sort the files by name, in order to load from older -> newest
131 for data_file in sorted(self._immutable.values(),
132 key=attrgetter('filename')):
133- if data_file.has_hint:
134- # load directly from the hint file.
135+ if data_file.has_hint and data_file.hint_size > 0:
136+ # load directly from the hint file, only if the size > 0
137 self._load_from_hint(data_file)
138 elif data_file.exists() and data_file.size > 0:
139 self._load_from_data(data_file)
140@@ -808,7 +815,8 @@
141 if build_hint:
142 hint_entry = HintEntry.from_tritcask_entry(entry)
143 hint_idx[hint_entry.key] = hint_entry
144- if build_hint:
145+ if build_hint and hint_idx:
146+ # only build the hint file if hint_idx contains data
147 with data_file.get_hint_file() as hint_file:
148 for key, hint_entry in hint_idx.iteritems():
149 hint_file.write(hint_entry)

Subscribers

People subscribed via source and target branches