~didrocks/ubuntuone-client/use_result_var

« back to all changes in this revision

Viewing changes to tests/syncdaemon/test_tritcask.py

  • Committer: Bazaar Package Importer
  • Author(s): Rodney Dawes
  • Date: 2011-02-11 16:18:11 UTC
  • mto: This revision was merged to the branch mainline in revision 67.
  • Revision ID: james.westby@ubuntu.com-20110211161811-n18dj9lde7dxqjzr
Tags: upstream-1.5.4
ImportĀ upstreamĀ versionĀ 1.5.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
919
919
        self.assertEqual(old_keydir, db._keydir)
920
920
        db.shutdown()
921
921
 
 
922
    def test_build_keydir_build_hint_with_dead_rows(self):
 
923
        """Test that _build_keydir build the hint with TOMBSTONE rows."""
 
924
        db = Tritcask(self.base_dir, dead_bytes_threshold=0.1)
 
925
        # create some stuff.
 
926
        for i in range(100):
 
927
            db.put(i, 'foo%d' % (i,), 'bar%s' % (i,))
 
928
        # create a inactive file with all the items
 
929
        db.rotate()
 
930
        db.shutdown()
 
931
        # delete half of the items
 
932
        db = Tritcask(self.base_dir, dead_bytes_threshold=0.01)
 
933
        for i in range(50):
 
934
            db.delete(i, 'foo%d' % (i,))
 
935
        # add one item so the hint file have at leats one
 
936
        db.put(100, 'foo%d' % (100,), 'bar%s' % (100,))
 
937
        assert len(db._keydir.keys()) == 51, len(db._keydir.keys())
 
938
        old_keydir = db._keydir
 
939
        db.shutdown()
 
940
        # trigger a rotate and a hint build
 
941
        db = Tritcask(self.base_dir, dead_bytes_threshold=0.01)
 
942
        db.rotate()
 
943
        db.shutdown()
 
944
        # trigger a hint build of the last rotated file
 
945
        Tritcask(self.base_dir, dead_bytes_threshold=0.01).shutdown()
 
946
        db = Tritcask(self.base_dir, dead_bytes_threshold=0.01)
 
947
        self.assertEqual(sorted(old_keydir.keys()), sorted(db._keydir.keys()))
 
948
        db.shutdown()
 
949
 
922
950
    def test_should_rotate(self):
923
951
        """Test should_rotate method."""
924
952
        db = Tritcask(self.base_dir)
949
977
        self.assertTrue(db.should_merge(db._immutable))
950
978
        db.shutdown()
951
979
 
 
980
    def test_should_merge_max_files(self):
 
981
        """Test should_merge method based on max_im files ."""
 
982
        db = Tritcask(self.base_dir)
 
983
        # add some data
 
984
        # create 10 immutable files
 
985
        for j in range(10):
 
986
            for i in range(2):
 
987
                db.put(i*j, 'foo%d' % (i*j+i,), 'bar%s' % (i,))
 
988
            db.rotate()
 
989
        self.assertFalse(db.should_merge(db._immutable))
 
990
        # create the 11th immutable file
 
991
        db.put(200, 'foo%d' % (200,), 'bar%s' % (200,))
 
992
        db.rotate()
 
993
        self.assertTrue(db.should_merge(db._immutable))
 
994
        db.shutdown()
 
995
 
 
996
    def test__rotate_and_not_merge(self):
 
997
        """Test _rotate_and_merge method."""
 
998
        db = Tritcask(self.base_dir)
 
999
        # add the same data in 5 different data files
 
1000
        for i in range(5):
 
1001
            for i in range(10):
 
1002
                db.put(i, 'foo%d' % (i,), 'bar%s' % (i,))
 
1003
            db.rotate()
 
1004
        for i in range(5):
 
1005
            for i in range(10):
 
1006
                db.put(i, 'foo%d' % (i,), 'bar%s' % (i,))
 
1007
        called = []
 
1008
        db.shutdown()
 
1009
        self.patch(Tritcask, 'rotate', lambda *a, **k: called.append('rotate'))
 
1010
        self.patch(Tritcask, 'merge', lambda *args: called.append('merge'))
 
1011
        Tritcask(self.base_dir).shutdown()
 
1012
        self.assertIn('rotate', called)
 
1013
        self.assertNotIn('merge', called)
 
1014
 
952
1015
    def test__rotate_and_merge(self):
953
1016
        """Test _rotate_and_merge method."""
954
1017
        db = Tritcask(self.base_dir)
955
 
        # add the same data in 5 different data files
956
 
        for i in range(5):
957
 
            for i in range(10):
 
1018
        # add the slightly different data in 5 different data files
 
1019
        for j in range(5):
 
1020
            for i in range(20):
958
1021
                db.put(i, 'foo%d' % (i,), 'bar%s' % (i,))
959
1022
            db.rotate()
960
 
        for i in range(5):
961
 
            for i in range(10):
 
1023
        for j in range(5):
 
1024
            for i in range(15):
962
1025
                db.put(i, 'foo%d' % (i,), 'bar%s' % (i,))
963
1026
        called = []
964
1027
        db.shutdown()
965
 
        self.patch(Tritcask, 'rotate', lambda _: called.append('rotate'))
 
1028
        self.patch(Tritcask, 'rotate', lambda *a, **k: called.append('rotate'))
966
1029
        self.patch(Tritcask, 'merge', lambda *args: called.append('merge'))
967
1030
        Tritcask(self.base_dir).shutdown()
968
1031
        self.assertIn('rotate', called)
981
1044
        db.live_file.fd.flush()
982
1045
        db.shutdown()
983
1046
        called = []
984
 
        self.patch(Tritcask, 'rotate', lambda _: called.append('rotate'))
 
1047
        self.patch(Tritcask, 'rotate', lambda *a, **k: called.append('rotate'))
985
1048
        Tritcask(self.base_dir).shutdown()
986
1049
        self.assertIn('rotate', called)
987
1050
 
1097
1160
        self.assertTrue((0, key1) in self.db._keydir)
1098
1161
        self.assertTrue((0, key1) in self.db)
1099
1162
 
 
1163
 
1100
1164
class MergeTests(BaseTestCase):
1101
1165
 
1102
1166
    def _add_data(self, db, size=100):
1211
1275
        self.assertIn(old_live_file_1.file_id, db._immutable)
1212
1276
        db.shutdown()
1213
1277
 
1214
 
    def test_merge_all_dead_entries_single_file(self):
1215
 
        """Test merge of a immutable file with 100% dead data.
 
1278
    def test_merge_do_nothing_all_dead_entries_single_file(self):
 
1279
        """Test possible merge of a immutable file with 100% dead data.
1216
1280
 
1217
 
        The expected side effect is that the file should be marked as dead."""
 
1281
        The expected side effect is that the file should be marked as immutable,
 
1282
        then merged and marked as dead. And on the next startup deleted.
 
1283
        """
1218
1284
        db = Tritcask(self.base_dir)
1219
1285
        self._add_data(db, 100)
1220
1286
        # delete almost all entrie to trigger a merge
1221
1287
        for i, k in enumerate(db._keydir.keys()):
1222
 
            if i <= 100:
 
1288
            if i < 100:
1223
1289
                db.delete(*k)
1224
1290
        db.shutdown()
1225
 
        # at this moment we only have the live file
 
1291
        # start tritcask without automerge and check
 
1292
        db = Tritcask(self.base_dir, auto_merge=False)
 
1293
        files = sorted(os.listdir(db.base_path))
 
1294
        self.assertEqual(2, len(files))
 
1295
        self.assertIn(INACTIVE, files[0])
 
1296
        self.assertIn(LIVE, files[1])
 
1297
        db.shutdown()
 
1298
        # trigger the rotation
 
1299
        # now we should have a single immutable_file (previous live one)
 
1300
        db = Tritcask(self.base_dir)
 
1301
        self.assertEqual(0, len(db._immutable))
 
1302
        files = sorted(os.listdir(db.base_path))
 
1303
        self.assertEqual(3, len(files))
 
1304
        self.assertIn(DEAD, files[0])
 
1305
        self.assertIn(DEAD, files[1])
 
1306
        self.assertIn(LIVE, files[2])
 
1307
        db.shutdown()
 
1308
        # at this moment we have the live + imm_file files
1226
1309
        # start a new Tritcask instance.
1227
1310
        db = Tritcask(self.base_dir)
1228
 
        self.assertEqual(1, len(db._immutable))
1229
 
        imm_file = db._immutable.values()[0]
 
1311
        files = sorted(os.path.join(self.base_dir,f ) \
 
1312
                       for f in os.listdir(db.base_path))
 
1313
        #self.assertIn(imm_file.filename.replace(INACTIVE, DEAD), files)
1230
1314
        # the immutable_file should be dead as there are no live entries
1231
 
        self.assertIn(DEAD, imm_file.filename)
1232
1315
        # there should be only 2 files, the dead and the live
 
1316
        # dead + dead_hint + live
1233
1317
        files = sorted(os.listdir(db.base_path))
1234
 
        self.assertEqual(2, len(files), files)
1235
 
        self.assertIn(DEAD, files[0])
1236
 
        self.assertIn(LIVE, files[1])
 
1318
        self.assertEqual(1, len(files), files)
 
1319
        #self.assertIn(DEAD, files[0])
 
1320
        #self.assertIn(DEAD, files[1])
 
1321
        #self.assertIn(HINT, files[1])
 
1322
        self.assertIn(LIVE, files[0])
1237
1323
        db.shutdown()
1238
1324
        # start a new Tritcask to check everything is ok after the
1239
1325
        # merge.
1245
1331
    def test_merge_mixed_dead_entries(self):
1246
1332
        """Test merge of 2 immutable files one with 100% dead data.
1247
1333
 
1248
 
        The expected side effect is that the file should be marked as dead."""
 
1334
        The expected side effect is that the file should be marked as dead.
 
1335
        """
1249
1336
        db = Tritcask(self.base_dir)
1250
1337
        self._add_data(db, 100)
1251
1338
        # delete almost all entrie to trigger a merge
1252
1339
        for i, k in enumerate(db._keydir.keys()):
1253
1340
            if i <= 100:
1254
1341
                db.delete(*k)
1255
 
        db.rotate()
 
1342
        db = Tritcask(self.base_dir, auto_merge=False)
1256
1343
        self.assertEqual(1, len(db._immutable))
1257
1344
        imm_file_1 = db._immutable.values()[0]
1258
 
        self._add_data(db, 100)
1259
 
        for i, k in enumerate(db._keydir.keys()):
1260
 
            if i % 2:
1261
 
                db.delete(*k)
1262
1345
        db.shutdown()
1263
 
        # at this moment we only have the live file
1264
 
        # start a new Tritcask instance.
1265
1346
        db = Tritcask(self.base_dir)
1266
1347
        # the "empty" immutable_file should be dead as there are no live entries
1267
 
        self.assertIn(DEAD, db._immutable[imm_file_1.file_id].filename)
1268
 
        # there should be 6 files:
1269
 
        #    - the empty immutable as "dead"
1270
 
        #    - the immutable file just merged
 
1348
        # but it's also removed from the _immutable dict
 
1349
        files = sorted(os.path.join(self.base_dir,f ) \
 
1350
                       for f in os.listdir(db.base_path))
 
1351
        self.assertIn(imm_file_1.filename.replace(INACTIVE, DEAD), files)
 
1352
        self._add_data(db, 100)
 
1353
        for i, k in enumerate(db._keydir.keys()):
 
1354
            if i % 2:
 
1355
                db.delete(*k)
 
1356
        db.shutdown()
 
1357
        # at this moment we only have the live file
 
1358
        # start a new Tritcask instance.
 
1359
        db = Tritcask(self.base_dir)
 
1360
        # there should be 5 files:
 
1361
        #    - the immutable file just merged as a DEAD file.
1271
1362
        #    - the new immutable_file
1272
1363
        #    - the current live file
1273
1364
        files = sorted(os.listdir(db.base_path))
1274
 
        self.assertEqual(6, len(files), files)
 
1365
        self.assertEqual(4, len(files), files)
1275
1366
        self.assertIn(DEAD, files[0])
1276
 
        self.assertIn(DEAD, files[1])
1277
 
        self.assertIn(HINT, files[1])
1278
 
        self.assertIn(DEAD, files[2])
 
1367
        self.assertIn(INACTIVE, files[1])
 
1368
        self.assertIn(INACTIVE, files[2])
 
1369
        self.assertIn(HINT, files[2])
1279
1370
        self.assertIn(LIVE, files[3])
1280
 
        self.assertIn(INACTIVE, files[4])
1281
 
        self.assertIn(INACTIVE, files[5])
1282
 
        self.assertIn(HINT, files[5])
1283
1371
        db.shutdown()
1284
1372
        # start a new Tritcask to check everything is ok after the
1285
1373
        # merge.
1287
1375
        # check that the dead files were deleted
1288
1376
        files = sorted(os.listdir(db.base_path))
1289
1377
        self.assertEqual(3, len(files), files)
1290
 
        self.assertIn(LIVE, files[0])
1291
 
        self.assertIn(INACTIVE, files[1])
1292
 
        self.assertIn(INACTIVE, files[2])
 
1378
        self.assertIn(INACTIVE, files[0])
 
1379
        self.assertIn(INACTIVE, files[1])
 
1380
        self.assertIn(HINT, files[1])
 
1381
        self.assertIn(LIVE, files[2])
 
1382
 
 
1383
    def test_merged_file_is_older_than_live(self):
 
1384
        """Test that merge creates and live file newer than the merge result.
 
1385
 
 
1386
        The expected side effect is that the live file should be newer than the
 
1387
        merged immutable file.
 
1388
        """
 
1389
        db = Tritcask(self.base_dir)
 
1390
        self._add_data(db, 100)
 
1391
        # delete almost all entrie to trigger a merge
 
1392
        for i, k in enumerate(db._keydir.keys()):
 
1393
            if i <= 60:
 
1394
                db.delete(*k)
 
1395
        db.shutdown()
 
1396
        # trigger the rotation
 
1397
        # now we should have a single immutable_file (previous live one)
 
1398
        db = Tritcask(self.base_dir)
 
1399
        self.assertEqual(1, len(db._immutable))
 
1400
        dead_file = db._immutable.values()[0]
 
1401
        self.assertIn(DEAD, dead_file.filename)
 
1402
        files = sorted(os.listdir(db.base_path))
 
1403
        self.assertEqual(4, len(files))
 
1404
        self.assertIn(DEAD, files[0])
 
1405
        self.assertIn(INACTIVE, files[1])
1293
1406
        self.assertIn(HINT, files[2])
1294
 
 
 
1407
        self.assertIn(LIVE, files[3])
 
1408
        self.assertEqual(db.live_file.size, 0)
 
1409
        db.shutdown()
 
1410
        # at this moment we have the live + imm_file files
 
1411
        # start a new Tritcask instance.
 
1412
        db = Tritcask(self.base_dir)
 
1413
        # the dead file should be fone
 
1414
        # there should be only 2 files, the immutable and the live
 
1415
        # immutable + hint + live
 
1416
        files = sorted(os.listdir(db.base_path))
 
1417
        self.assertEqual(3, len(files), files)
 
1418
        self.assertIn(INACTIVE, files[0])
 
1419
        self.assertIn(HINT, files[1])
 
1420
        self.assertIn(LIVE, files[2])
 
1421
        assert len(db._immutable) == 1, "More than 1 immutable file."
 
1422
        live_id = int(db.live_file.file_id)
 
1423
        imm_id = int(db._immutable.keys()[0])
 
1424
        self.assertTrue(live_id > imm_id, "%d <= %d" % (live_id, imm_id))
 
1425
        db.shutdown()
1295
1426
 
1296
1427
class KeydirStatsTests(BaseTestCase):
1297
1428
    """Tests for the Keydir stats handling."""