def verify_and_fetch_shard(shard_id): """Find out if the shard_id exists and return the sharding specification for it. If it does not exist throw an exception. :param shard_id: The ID for the shard whose specification needs to be fetched. :return: The sharding specification class representing the shard ID. :raises: ShardingError if the shard ID is not found. """ #Here the underlying sharding specification might be a RANGE #or a HASH. The type of sharding specification is obtained from the #shard mapping. range_sharding_spec = RangeShardingSpecification.fetch(shard_id) if range_sharding_spec is None: raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, )) #Fetch the shard mappings and use them to find the type of sharding #scheme. shard_mappings = ShardMapping.fetch_by_id( range_sharding_spec.shard_mapping_id ) if shard_mappings is None: raise _errors.ShardingError( SHARD_MAPPING_NOT_FOUND % ( range_sharding_spec.shard_mapping_id, ) ) #Fetch the shard mapping definition. There is only one shard mapping #definition associated with all of the shard mappings. shard_mapping_defn = ShardMapping.fetch_shard_mapping_defn( range_sharding_spec.shard_mapping_id ) if shard_mapping_defn is None: raise _errors.ShardingError( SHARD_MAPPING_DEFN_NOT_FOUND % ( range_sharding_spec.shard_mapping_id, ) ) shard = Shards.fetch(shard_id) if shard is None: raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, )) #Both of the shard_mappings retrieved will be of the same sharding #type. Hence it is safe to use one of them to retireve the sharding type. if shard_mappings[0].type_name == "HASH": return HashShardingSpecification.fetch(shard_id), \ shard, shard_mappings, shard_mapping_defn else: return range_sharding_spec, shard, shard_mappings, shard_mapping_defn
def verify_and_fetch_shard(shard_id): """Find out if the shard_id exists and return the sharding specification for it. If it does not exist throw an exception. :param shard_id: The ID for the shard whose specification needs to be fetched. :return: The sharding specification class representing the shard ID. :raises: ShardingError if the shard ID is not found. """ #Here the underlying sharding specification might be a RANGE #or a HASH. The type of sharding specification is obtained from the #shard mapping. range_sharding_spec = RangeShardingSpecification.fetch(shard_id) if range_sharding_spec is None: raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, )) #Fetch the shard mappings and use them to find the type of sharding #scheme. shard_mappings = ShardMapping.fetch_by_id( range_sharding_spec.shard_mapping_id) if shard_mappings is None: raise _errors.ShardingError(SHARD_MAPPING_NOT_FOUND % (range_sharding_spec.shard_mapping_id, )) #Fetch the shard mapping definition. There is only one shard mapping #definition associated with all of the shard mappings. shard_mapping_defn = ShardMapping.fetch_shard_mapping_defn( range_sharding_spec.shard_mapping_id) if shard_mapping_defn is None: raise _errors.ShardingError(SHARD_MAPPING_DEFN_NOT_FOUND % (range_sharding_spec.shard_mapping_id, )) shard = Shards.fetch(shard_id) if shard is None: raise _errors.ShardingError(SHARD_NOT_FOUND % (shard_id, )) #Both of the shard_mappings retrieved will be of the same sharding #type. Hence it is safe to use one of them to retireve the sharding type. if shard_mappings[0].type_name == "HASH": return HashShardingSpecification.fetch(shard_id), \ shard, shard_mappings, shard_mapping_defn else: return range_sharding_spec, shard, shard_mappings, shard_mapping_defn
def test_shard_split(self): status = self.proxy.sharding.split_shard("1", "GROUPID3", "600") self.assertStatus(status, _executor.Job.SUCCESS) self.assertEqual(status[1][-1]["state"], _executor.Job.COMPLETE) self.assertEqual(status[1][-1]["description"], "Executed action (_prune_shard_tables_after_split).") status = self.proxy.sharding.lookup_servers("db1.t1", 500, "LOCAL") self.assertEqual(status[0], True) self.assertEqual(status[1], "") obtained_server_list = status[2] for idx in range(0, 2): server_uuid = obtained_server_list[idx][0] shard_server = MySQLServer.fetch(server_uuid) shard_server.connect() rows = shard_server.exec_stmt( "SELECT NAME FROM db1.t1", {"fetch" : True}) self.assertEqual(len(rows), 3) self.assertEqual(rows[0][0], 'TEST 1') self.assertEqual(rows[1][0], 'TEST 2') self.assertEqual(rows[2][0], 'TEST 3') status = self.proxy.sharding.lookup_servers("db1.t1", 800, "LOCAL") self.assertEqual(status[0], True) self.assertEqual(status[1], "") obtained_server_list = status[2] for idx in range(0, 2): server_uuid = obtained_server_list[idx][0] shard_server = MySQLServer.fetch(server_uuid) shard_server.connect() rows = shard_server.exec_stmt( "SELECT NAME FROM db1.t1", {"fetch" : True}) self.assertEqual(len(rows), 4) self.assertEqual(rows[0][0], 'TEST 4') self.assertEqual(rows[1][0], 'TEST 5') self.assertEqual(rows[2][0], 'TEST 6') self.assertEqual(rows[3][0], 'TEST 7') status = self.proxy.sharding.lookup_servers("1", 500, "GLOBAL") self.assertEqual(status[0], True) self.assertEqual(status[1], "") obtained_server_list = status[2] for idx in range(0, 2): if obtained_server_list[idx][2]: global_master_uuid = obtained_server_list[idx][0] break global_master = MySQLServer.fetch(global_master_uuid) global_master.connect() global_master.exec_stmt("DROP DATABASE IF EXISTS global_db") global_master.exec_stmt("CREATE DATABASE global_db") global_master.exec_stmt("CREATE TABLE global_db.global_table" "(userID INT, name VARCHAR(30))") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(101, 'TEST 1')") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(202, 'TEST 2')") status = self.proxy.group.promote("GROUPID1") self.assertStatus(status, _executor.Job.SUCCESS) self.assertEqual(status[1][-1]["state"], _executor.Job.COMPLETE) self.assertEqual(status[1][-1]["description"], "Executed action (_change_to_candidate).") sleep(5) status = self.proxy.sharding.lookup_servers("1", 500, "GLOBAL") self.assertEqual(status[0], True) self.assertEqual(status[1], "") obtained_server_list = status[2] for idx in range(0, 2): if obtained_server_list[idx][2]: global_master_uuid = obtained_server_list[idx][0] break global_master = MySQLServer.fetch(global_master_uuid) global_master.connect() global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(303, 'TEST 3')") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(404, 'TEST 4')") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(505, 'TEST 5')") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(606, 'TEST 6')") sleep(5) status = self.proxy.sharding.lookup_servers("db1.t1", 500, "LOCAL") self.assertEqual(status[0], True) self.assertEqual(status[1], "") obtained_server_list = status[2] for idx in range(0, 2): if obtained_server_list[idx][2]: shard_uuid = obtained_server_list[idx][0] shard_server = MySQLServer.fetch(shard_uuid) shard_server.connect() rows = shard_server.exec_stmt( "SELECT NAME FROM global_db.global_table", {"fetch" : True} ) self.assertEqual(len(rows), 6) self.assertEqual(rows[0][0], 'TEST 1') self.assertEqual(rows[1][0], 'TEST 2') self.assertEqual(rows[2][0], 'TEST 3') self.assertEqual(rows[3][0], 'TEST 4') self.assertEqual(rows[4][0], 'TEST 5') self.assertEqual(rows[5][0], 'TEST 6') #Ensure tha two new shard_ids have been generated. range_sharding_specifications = RangeShardingSpecification.list(1) self.assertTrue(ShardingUtils.compare_range_specifications( range_sharding_specifications[0], RangeShardingSpecification.fetch(2))) self.assertTrue(ShardingUtils.compare_range_specifications( range_sharding_specifications[1], RangeShardingSpecification.fetch(3)))
def test_shard_split(self): status = self.proxy.sharding.split_shard("1", "GROUPID3", "600") self.check_xmlrpc_command_result(status) status = self.proxy.sharding.lookup_servers("db1.t1", 500, "LOCAL") for info in self.check_xmlrpc_iter(status): server_uuid = info['server_uuid'] shard_server = fetch_test_server(server_uuid) shard_server.connect() rows = shard_server.exec_stmt( "SELECT NAME FROM db1.t1", {"fetch" : True}) self.assertEqual(len(rows), 3) self.assertEqual(rows[0][0], 'TEST 1') self.assertEqual(rows[1][0], 'TEST 2') self.assertEqual(rows[2][0], 'TEST 3') status = self.proxy.sharding.lookup_servers("db1.t1", 800, "LOCAL") for info in self.check_xmlrpc_iter(status): server_uuid = info['server_uuid'] shard_server = fetch_test_server(server_uuid) shard_server.connect() rows = shard_server.exec_stmt( "SELECT NAME FROM db1.t1", {"fetch" : True}) self.assertEqual(len(rows), 4) self.assertEqual(rows[0][0], 'TEST 4') self.assertEqual(rows[1][0], 'TEST 5') self.assertEqual(rows[2][0], 'TEST 6') self.assertEqual(rows[3][0], 'TEST 7') status = self.proxy.sharding.lookup_servers("1", 500, "GLOBAL") for info in self.check_xmlrpc_iter(status): if info['status'] == MySQLServer.PRIMARY: global_master = fetch_test_server(info['server_uuid']) global_master.connect() global_master.exec_stmt("DROP DATABASE IF EXISTS global_db") global_master.exec_stmt("CREATE DATABASE global_db") global_master.exec_stmt("CREATE TABLE global_db.global_table" "(userID INT, name VARCHAR(30))") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(101, 'TEST 1')") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(202, 'TEST 2')") status = self.proxy.group.promote("GROUPID1") self.check_xmlrpc_command_result(status) sleep(5) status = self.proxy.sharding.lookup_servers("1", 500, "GLOBAL") for info in self.check_xmlrpc_iter(status): if info['status'] == MySQLServer.PRIMARY: global_master = fetch_test_server(info['server_uuid']) global_master.connect() global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(303, 'TEST 3')") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(404, 'TEST 4')") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(505, 'TEST 5')") global_master.exec_stmt("INSERT INTO global_db.global_table " "VALUES(606, 'TEST 6')") sleep(5) status = self.proxy.sharding.lookup_servers("db1.t1", 500, "LOCAL") for info in self.check_xmlrpc_iter(status): if info['status'] == MySQLServer.PRIMARY: shard_server = fetch_test_server(info['server_uuid']) shard_server.connect() rows = shard_server.exec_stmt( "SELECT NAME FROM global_db.global_table", {"fetch" : True} ) self.assertEqual(len(rows), 6) self.assertEqual(rows[0][0], 'TEST 1') self.assertEqual(rows[1][0], 'TEST 2') self.assertEqual(rows[2][0], 'TEST 3') self.assertEqual(rows[3][0], 'TEST 4') self.assertEqual(rows[4][0], 'TEST 5') self.assertEqual(rows[5][0], 'TEST 6') #Ensure tha two new shard_ids have been generated. range_sharding_specifications = RangeShardingSpecification.list(1) self.assertTrue(ShardingUtils.compare_range_specifications( range_sharding_specifications[0], RangeShardingSpecification.fetch(2))) self.assertTrue(ShardingUtils.compare_range_specifications( range_sharding_specifications[1], RangeShardingSpecification.fetch(3)))