1368 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			1368 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/**
 | 
						|
 * Copyright (c) 2021 OceanBase
 | 
						|
 * OceanBase CE is licensed under Mulan PubL v2.
 | 
						|
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | 
						|
 * You may obtain a copy of Mulan PubL v2 at:
 | 
						|
 *          http://license.coscl.org.cn/MulanPubL-2.0
 | 
						|
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | 
						|
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | 
						|
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | 
						|
 * See the Mulan PubL v2 for more details.
 | 
						|
 */
 | 
						|
 | 
						|
#define USING_LOG_PREFIX SHARE_PT
 | 
						|
 | 
						|
#include <gtest/gtest.h>
 | 
						|
#include <gmock/gmock.h>
 | 
						|
#include "lib/stat/ob_session_stat.h"
 | 
						|
#include "share/config/ob_server_config.h"
 | 
						|
#include "share/schema/db_initializer.h"
 | 
						|
// TODO : rename .cpp to .h
 | 
						|
#include "share/schema/ob_schema_test_utils.cpp"
 | 
						|
#include "share/schema/ob_multi_version_schema_service.h"
 | 
						|
#include "share/schema/ob_schema_getter_guard.h"
 | 
						|
#include "share/schema/ob_table_iter.h"
 | 
						|
#include "share/partition_table/ob_partition_table_operator.h"
 | 
						|
#include "share/partition_table/ob_partition_table_iterator.h"
 | 
						|
#include "lib/allocator/page_arena.h"
 | 
						|
#include "lib/container/ob_array.h"
 | 
						|
#include "lib/container/ob_array_iterator.h"
 | 
						|
#include "fake_part_property_getter.h"
 | 
						|
#include "../mock_ob_rs_mgr.h"
 | 
						|
#include "rpc/mock_ob_common_rpc_proxy.h"
 | 
						|
#include "../../rootserver/fake_rs_list_change_cb.h"
 | 
						|
#include "rootserver/ob_root_service.h"
 | 
						|
namespace oceanbase {
 | 
						|
namespace share {
 | 
						|
 | 
						|
using namespace common;
 | 
						|
using namespace schema;
 | 
						|
using namespace host;
 | 
						|
using namespace obrpc;
 | 
						|
using namespace std;
 | 
						|
 | 
						|
static uint64_t& TEN = FakePartPropertyGetter::TEN();
 | 
						|
 | 
						|
using testing::_;
 | 
						|
using ::testing::Invoke;
 | 
						|
using ::testing::Return;
 | 
						|
ObServerConfig& config = ObServerConfig::get_instance();
 | 
						|
class TestPartitionTableIterator : public ::testing::Test {
 | 
						|
public:
 | 
						|
  TestPartitionTableIterator() : operator_(prop_getter_)
 | 
						|
  {}
 | 
						|
 | 
						|
  int gen_tenant_schema(const uint64_t tenant_id, ObTenantSchema& tenant_schema);
 | 
						|
  virtual void SetUp();
 | 
						|
  virtual void TearDown();
 | 
						|
  virtual int gen_table_schema(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id,
 | 
						|
      const uint64_t pure_tg_id, ObTableSchema& table_schema);
 | 
						|
  void gen_schema_lack_partition_level_two(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id,
 | 
						|
      const uint64_t pure_tg_id, const int64_t lack_position, bool create_tanent, ObMetaTableMode mode);
 | 
						|
 | 
						|
  void gen_schema_lack_partition_level_one(const uint64_t tenant_id, const uint64_t pure_id, const uint64_t pure_db_id,
 | 
						|
      const uint64_t pure_tg_id, const int64_t lack_position, bool create_tenant, ObMetaTableMode mode);
 | 
						|
 | 
						|
  void gen_partition_table_level_one(const uint64_t tenant_id, const uint64_t pure_id, const vector<int64_t>& part_ids,
 | 
						|
      const vector<int64_t>& meta_part_projector);
 | 
						|
  void gen_table_schema_with_specified_part_id(const uint64_t tenant_id, const uint64_t pure_id,
 | 
						|
      const uint64_t pure_db_id, const uint64_t pure_tg_id_, const vector<int64_t>& part_ids);
 | 
						|
  int gen_tenant_space_schema(uint64_t tenant_id);
 | 
						|
  int release_tenant_space_schema(uint64_t tenant_id);
 | 
						|
 | 
						|
protected:
 | 
						|
  DBInitializer db_initer_;
 | 
						|
  FakePartPropertyGetter prop_getter_;
 | 
						|
  MockObCommonRpcProxy rpc_proxy_;
 | 
						|
  MockObRsMgr rs_mgr_;
 | 
						|
  ObPartitionTableOperator operator_;
 | 
						|
  // FakeSchemaService schema_service_;
 | 
						|
  ObMultiVersionSchemaService multi_schema_service_;
 | 
						|
  FakeRsListChangeCb cb_;
 | 
						|
  FakeMergeErrorCb merge_error_cb_;
 | 
						|
};
 | 
						|
 | 
						|
int TestPartitionTableIterator::gen_table_schema(const uint64_t tenant_id, const uint64_t pure_id,
 | 
						|
    const uint64_t pure_db_id, const uint64_t pure_tg_id, ObTableSchema& table_schema)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  table_schema.reset();
 | 
						|
  ObInnerTableSchema::all_core_table_schema(table_schema);
 | 
						|
  char table_name[64];
 | 
						|
  if (snprintf(table_name, 64, "table_%lu", combine_id(tenant_id, pure_id)) >= 64) {
 | 
						|
    ret = OB_BUF_NOT_ENOUGH;
 | 
						|
    SHARE_SCHEMA_LOG(WARN, "buf not enough", K(ret));
 | 
						|
  } else {
 | 
						|
    table_schema.set_table_name(table_name);
 | 
						|
    table_schema.set_tenant_id(tenant_id);
 | 
						|
    table_schema.set_table_id(combine_id(tenant_id, pure_id));
 | 
						|
    table_schema.set_database_id(combine_id(tenant_id, pure_db_id));
 | 
						|
    table_schema.set_tablegroup_id(combine_id(tenant_id, pure_tg_id));
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
int TestPartitionTableIterator::gen_tenant_schema(const uint64_t tenant_id, ObTenantSchema& tenant_schema)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  char tenant_name[64];
 | 
						|
  if (snprintf(tenant_name, 64, "tenant_%lu", tenant_id) >= 64) {
 | 
						|
    ret = OB_BUF_NOT_ENOUGH;
 | 
						|
  } else {
 | 
						|
    tenant_schema.reset();
 | 
						|
    tenant_schema.set_tenant_id(tenant_id);
 | 
						|
    tenant_schema.set_tenant_name(tenant_name);
 | 
						|
    tenant_schema.set_comment("this is a test tenant");
 | 
						|
    tenant_schema.add_zone("zone");
 | 
						|
    tenant_schema.set_primary_zone("zone");
 | 
						|
    tenant_schema.set_locality("");
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
void TestPartitionTableIterator::gen_table_schema_with_specified_part_id(const uint64_t tenant_id,
 | 
						|
    const uint64_t pure_id, const uint64_t pure_db_id, const uint64_t pure_tg_id, const vector<int64_t>& part_ids)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObTableSchema table_schema;
 | 
						|
  if (OB_FAIL(gen_table_schema(tenant_id, pure_id, pure_db_id, pure_tg_id, table_schema))) {
 | 
						|
    LOG_WARN("fail to gen table schema", K(ret), K(tenant_id), K(pure_id));
 | 
						|
  }
 | 
						|
 | 
						|
  for (int i = 0; i < part_ids.size(); ++i) {
 | 
						|
    ObPartition partition;
 | 
						|
    int64_t value = i + 10;
 | 
						|
    ObObj key(value);
 | 
						|
    ObRowkey rowkey(&key, 1);
 | 
						|
    partition.set_high_bound_val(rowkey);
 | 
						|
    char part_name[50];
 | 
						|
    memset(part_name, '\0', 50);
 | 
						|
    snprintf(part_name, 50, "range%d", i);
 | 
						|
    ObString name = ObString::make_string(part_name);
 | 
						|
    partition.set_part_id(part_ids[i]);
 | 
						|
    partition.set_part_name(name);
 | 
						|
    table_schema.add_partition(partition);
 | 
						|
  }
 | 
						|
  table_schema.set_table_type(USER_TABLE);
 | 
						|
  table_schema.set_part_level(PARTITION_LEVEL_ONE);
 | 
						|
  table_schema.get_part_option().set_part_num(part_ids.size());
 | 
						|
  table_schema.get_part_option().set_part_func_type(PARTITION_FUNC_TYPE_RANGE);
 | 
						|
  table_schema.get_part_option().set_part_expr(ObString::make_string("table_id mod 111"));
 | 
						|
 | 
						|
  CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  // ObMySQLTransaction trans;
 | 
						|
  // ret = trans.start(&db_initer_.get_sql_proxy());
 | 
						|
  // ret = multi_schema_service_.get_schema_service()->get_table_sql_service().create_table(table_schema, trans);
 | 
						|
  // const bool commit = true;
 | 
						|
  // ret = trans.end(commit);
 | 
						|
  multi_schema_service_.refresh_and_add_schema();
 | 
						|
}
 | 
						|
 | 
						|
void TestPartitionTableIterator::gen_schema_lack_partition_level_two(const uint64_t tenant_id, const uint64_t pure_id,
 | 
						|
    const uint64_t pure_db_id, const uint64_t pure_tg_id, const int64_t lack_position, bool create_tenant,
 | 
						|
    ObMetaTableMode mode)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObTenantSchema tenant_schema;
 | 
						|
  ObTableSchema table_schema;
 | 
						|
  if (create_tenant) {
 | 
						|
    if (OB_FAIL(gen_tenant_schema(tenant_id, tenant_schema))) {
 | 
						|
      LOG_WARN("fail to gen tenant schema", K(ret), K(tenant_id));
 | 
						|
    }
 | 
						|
 | 
						|
    CREATE_TENANT(ret, tenant_schema);
 | 
						|
    if (mode >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant_schema.get_tenant_id()));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (OB_SUCC(ret) && OB_FAIL(gen_table_schema(tenant_id, pure_id, pure_db_id, pure_tg_id, table_schema))) {
 | 
						|
    LOG_WARN("fail to gen table schema", K(ret), K(tenant_id), K(pure_id));
 | 
						|
  }
 | 
						|
 | 
						|
  table_schema.set_table_type(USER_TABLE);
 | 
						|
  table_schema.set_part_level(PARTITION_LEVEL_TWO);
 | 
						|
  table_schema.get_part_option().set_part_num(2);
 | 
						|
  table_schema.get_sub_part_option().set_part_func_type(PARTITION_FUNC_TYPE_RANGE);
 | 
						|
  table_schema.get_sub_part_option().set_part_expr(ObString::make_string("table_id mod 111"));
 | 
						|
  table_schema.get_sub_part_option().set_part_num(3);
 | 
						|
  ObSubPartition subpartition;
 | 
						|
  subpartition.set_part_id(0);
 | 
						|
  subpartition.set_sub_part_id(0);
 | 
						|
  ObString name1 = ObString::make_string("range1");
 | 
						|
  subpartition.set_part_name(name1);
 | 
						|
  int64_t value = 5;
 | 
						|
  ObObj key1(value);
 | 
						|
  ObRowkey rowkey1(&key1, 1);
 | 
						|
  subpartition.set_high_bound_val(rowkey1);
 | 
						|
  table_schema.add_partition(subpartition);
 | 
						|
  subpartition.reset();
 | 
						|
  ObString name2 = ObString::make_string("range2");
 | 
						|
  subpartition.set_part_id(0);
 | 
						|
  subpartition.set_sub_part_id(1);
 | 
						|
  subpartition.set_part_name(name2);
 | 
						|
  value = 15;
 | 
						|
  ObObj key2(value);
 | 
						|
  ObRowkey rowkey2(&key2, 1);
 | 
						|
  subpartition.set_high_bound_val(rowkey2);
 | 
						|
  table_schema.add_partition(subpartition);
 | 
						|
  subpartition.reset();
 | 
						|
  ObString name3 = ObString::make_string("range2");
 | 
						|
  subpartition.set_part_id(0);
 | 
						|
  subpartition.set_sub_part_id(2);
 | 
						|
  subpartition.set_part_name(name3);
 | 
						|
  value = 150;
 | 
						|
  ObObj key3(value);
 | 
						|
  ObRowkey rowkey3(&key3, 1);
 | 
						|
  subpartition.set_high_bound_val(rowkey3);
 | 
						|
  table_schema.add_partition(subpartition);
 | 
						|
 | 
						|
  CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  prop_getter_.clear();
 | 
						|
  // generate two level partitions 2 * 3
 | 
						|
  // 13 patterns
 | 
						|
  // nothing                                                   --0
 | 
						|
  //      <0,1>,<0,2>,      <1,0>,<1,1>,<1,2> //lack of front   --1
 | 
						|
  //<0,0>,      <0,2>,      <1,0>,<1,1>,<1,2> //lack of middle ---2
 | 
						|
  //<0,0>,<0,1>,     ,      <1,0>,<1,1>,<1,2> //lack of middle ---3
 | 
						|
  //<0,0>,<0,1>,<0,2>,<0,3>,<1,0>,<1,1>,<1,2> //more in middle ---4
 | 
						|
  //<0,0>,<0,1>,<0,2>,      <1,0>,<1,1>,<1,2> //normal         ---5
 | 
						|
  //<0,0>,<0,1>,<0,2>,<0,3>,      <1,1>,<1,2> //more in middle ---6
 | 
						|
  //<0,0>,<0,1>,<0,2>,            <1,1>,<1,2> //lack of front  ---7
 | 
						|
  //<0,0>,<0,1>,<0,2>,                                ---8
 | 
						|
  //<0,0>,<0,1>,                  <1,1>,<1,2> //lack of middle ---9
 | 
						|
  //<0,0>,<0,1>,<0,2>,      <1,0>             //the back is missing ----10
 | 
						|
  //<0,0>,<0,1>,<0,2>,      <1,0>,<1,1>,<1,2><1,3>,<1,4> more in back  ---11
 | 
						|
  //                        <1,0>,<1,1>,<1,2>                  ----12
 | 
						|
  //<0,0>,<0,1>,<0,2>,<0,3>,  <0,5>    <1,1>,<1,2> //more in middle----13
 | 
						|
  // for (int64_t i = 0; i < 13; i++) {
 | 
						|
  int64_t i = lack_position;
 | 
						|
  int64_t phy_part_id = 0;
 | 
						|
  if (i == 0) {
 | 
						|
    // nothing to do
 | 
						|
  } else {
 | 
						|
    if (i != 1 && i != 12) {
 | 
						|
      phy_part_id = generate_phy_part_id(0, 0, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
    }
 | 
						|
    if (i != 2 && i != 12) {
 | 
						|
      phy_part_id = generate_phy_part_id(0, 1, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
    }
 | 
						|
    if (i != 3 && i != 9 && i != 12) {
 | 
						|
      phy_part_id = generate_phy_part_id(0, 2, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
    }
 | 
						|
    if (i == 4 || i == 6 || i == 13) {
 | 
						|
      phy_part_id = generate_phy_part_id(0, 3, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
    }
 | 
						|
    if (i == 13) {
 | 
						|
      phy_part_id = generate_phy_part_id(0, 5, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
    }
 | 
						|
    if (i != 6 && i != 7 && i != 8 && i != 9 && i != 13) {
 | 
						|
      phy_part_id = generate_phy_part_id(1, 0, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
    }
 | 
						|
    if (i != 8 && i != 10) {
 | 
						|
      phy_part_id = generate_phy_part_id(1, 1, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
      phy_part_id = generate_phy_part_id(1, 2, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
    }
 | 
						|
    if (i == 11) {
 | 
						|
      phy_part_id = generate_phy_part_id(1, 3, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
      phy_part_id = generate_phy_part_id(1, 4, PARTITION_LEVEL_TWO);
 | 
						|
      prop_getter_.add(combine_id(tenant_id, pure_id), phy_part_id, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), phy_part_id, B, FOLLOWER);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //}
 | 
						|
  for (int64_t i = 0; i < prop_getter_.get_replicas().count(); i++) {
 | 
						|
    GCONF.self_addr_ = prop_getter_.get_replicas().at(i).server_;
 | 
						|
    operator_.update(prop_getter_.get_replicas().at(i));
 | 
						|
  }
 | 
						|
  multi_schema_service_.refresh_and_add_schema();
 | 
						|
}
 | 
						|
 | 
						|
void TestPartitionTableIterator::gen_partition_table_level_one(const uint64_t tenant_id, const uint64_t pure_id,
 | 
						|
    const vector<int64_t>& part_ids, const vector<int64_t>& meta_part_projector)
 | 
						|
{
 | 
						|
  prop_getter_.clear();
 | 
						|
  for (int i = 0; i < meta_part_projector.size(); ++i) {
 | 
						|
    int64_t part_id = meta_part_projector[i];
 | 
						|
    if (meta_part_projector[i] < part_ids.size()) {
 | 
						|
      part_id = part_ids[meta_part_projector[i]];
 | 
						|
    }
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), part_id, A, LEADER)
 | 
						|
        .add(combine_id(tenant_id, pure_id), part_id, B, FOLLOWER);
 | 
						|
  }
 | 
						|
  for (int64_t i = 0; i < prop_getter_.get_replicas().count(); i++) {
 | 
						|
    operator_.update(prop_getter_.get_replicas().at(i));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void TestPartitionTableIterator::gen_schema_lack_partition_level_one(const uint64_t tenant_id, const uint64_t pure_id,
 | 
						|
    const uint64_t pure_db_id, const uint64_t pure_tg_id, const int64_t lack_position, bool create_tenant,
 | 
						|
    ObMetaTableMode mode)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  ObTenantSchema tenant_schema;
 | 
						|
  ObTableSchema table_schema;
 | 
						|
  if (create_tenant) {
 | 
						|
    if (OB_FAIL(gen_tenant_schema(tenant_id, tenant_schema))) {
 | 
						|
      LOG_WARN("fail to gen tenant schema", K(ret), K(tenant_id));
 | 
						|
    }
 | 
						|
 | 
						|
    CREATE_TENANT(ret, tenant_schema);
 | 
						|
    if (mode >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant_schema.get_tenant_id()));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  if (OB_SUCC(ret) && OB_FAIL(gen_table_schema(tenant_id, pure_id, pure_db_id, pure_tg_id, table_schema))) {
 | 
						|
    LOG_WARN("fail to gen table schema", K(ret), K(tenant_id), K(pure_id));
 | 
						|
  }
 | 
						|
 | 
						|
  // five replicas, five pattern
 | 
						|
  // 1234 \ 0234 \ 0123 \ 01234 \ 0123456 \ empty\012367
 | 
						|
  table_schema.set_table_type(USER_TABLE);
 | 
						|
  table_schema.set_part_level(PARTITION_LEVEL_ONE);
 | 
						|
  table_schema.get_part_option().set_part_num(5);
 | 
						|
  CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  prop_getter_.clear();
 | 
						|
  if (lack_position != 0 && lack_position != 5) {
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 0, A, LEADER).add(combine_id(tenant_id, pure_id), 0, B, FOLLOWER);
 | 
						|
  }
 | 
						|
  if (lack_position != 1 && lack_position != 5) {
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 1, A, LEADER).add(combine_id(tenant_id, pure_id), 1, B, FOLLOWER);
 | 
						|
  }
 | 
						|
  if (lack_position != 5) {
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 2, A, LEADER).add(combine_id(tenant_id, pure_id), 2, B, FOLLOWER);
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 3, A, LEADER).add(combine_id(tenant_id, pure_id), 3, B, FOLLOWER);
 | 
						|
  }
 | 
						|
  if (lack_position != 2 && lack_position != 5 && lack_position != 6) {
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 4, A, LEADER).add(combine_id(tenant_id, pure_id), 4, B, FOLLOWER);
 | 
						|
  }
 | 
						|
  if (lack_position == 4) {
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 5, A, LEADER).add(combine_id(tenant_id, pure_id), 5, B, FOLLOWER);
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 6, A, LEADER).add(combine_id(tenant_id, pure_id), 6, B, FOLLOWER);
 | 
						|
  }
 | 
						|
  if (lack_position == 6) {
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 6, A, LEADER).add(combine_id(tenant_id, pure_id), 6, B, FOLLOWER);
 | 
						|
    prop_getter_.add(combine_id(tenant_id, pure_id), 7, A, LEADER).add(combine_id(tenant_id, pure_id), 7, B, FOLLOWER);
 | 
						|
  }
 | 
						|
  for (int64_t i = 0; i < prop_getter_.get_replicas().count(); i++) {
 | 
						|
    GCONF.self_addr_ = prop_getter_.get_replicas().at(i).server_;
 | 
						|
    operator_.update(prop_getter_.get_replicas().at(i));
 | 
						|
  }
 | 
						|
  multi_schema_service_.refresh_and_add_schema();
 | 
						|
}
 | 
						|
 | 
						|
int TestPartitionTableIterator::gen_tenant_space_schema(uint64_t tenant_id)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  int idx = 0;
 | 
						|
  std::string db = db_initer_.get_db_name();
 | 
						|
  common::ObMySQLProxy& sql_proxy = db_initer_.get_sql_proxy();
 | 
						|
  ObSqlString sql;
 | 
						|
  int64_t affect_rows = 0;
 | 
						|
  LOG_INFO("create db", K(db.c_str()), K(tenant_id));
 | 
						|
  if (OB_FAIL(sql.assign_fmt("drop database if exists %s_%lu", db.c_str(), tenant_id))) {
 | 
						|
    LOG_WARN("assign sql failed", K(ret));
 | 
						|
  } else if (OB_FAIL(sql_proxy.write(sql.ptr(), affect_rows))) {
 | 
						|
    LOG_WARN("execute create database sql failed", K(ret), K(sql));
 | 
						|
  } else if (OB_FAIL(sql.assign_fmt("create database %s_%lu", db.c_str(), tenant_id))) {
 | 
						|
    LOG_WARN("assign sql failed", K(ret));
 | 
						|
  } else if (OB_FAIL(sql_proxy.write(sql.ptr(), affect_rows))) {
 | 
						|
    LOG_WARN("execute create database sql failed", K(ret), K(sql));
 | 
						|
  } else {
 | 
						|
    const schema_create_func* creator_ptr_array[] = {
 | 
						|
        share::core_table_schema_creators, share::sys_table_schema_creators};
 | 
						|
    ObTableSchema tables[ARRAYSIZEOF(core_table_schema_creators) + ARRAYSIZEOF(sys_table_schema_creators)];
 | 
						|
    // build system table schema to %tables
 | 
						|
    for (int64_t i = 0; common::OB_SUCCESS == ret && i < ARRAYSIZEOF(creator_ptr_array); i++) {
 | 
						|
      for (const schema_create_func* creator_ptr = creator_ptr_array[i];
 | 
						|
           common::OB_SUCCESS == ret && NULL != *creator_ptr;
 | 
						|
           ++creator_ptr) {
 | 
						|
        if (OB_FAIL((*creator_ptr)(tables[idx++]))) {
 | 
						|
          LOG_WARN("create table schema fialed", K(ret));
 | 
						|
          ret = common::OB_SCHEMA_ERROR;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    ObTableSchema table_schema;
 | 
						|
    char csql[common::OB_MAX_SQL_LENGTH];
 | 
						|
    memset(csql, 0, sizeof(csql));
 | 
						|
    for (int64_t i = 0; OB_SUCC(ret) && i < ARRAYSIZEOF(tenant_space_tables); i++) {
 | 
						|
      if (!is_virtual_table(tenant_space_tables[i])) {
 | 
						|
        uint64_t tid = tenant_space_tables[i];
 | 
						|
        // found table schema
 | 
						|
        for (idx = 0; idx < ARRAYSIZEOF(tables); ++idx) {
 | 
						|
          if (extract_pure_id(tables[idx].get_table_id()) == tid) {
 | 
						|
            LOG_INFO("", K(tid));
 | 
						|
            if (OB_FAIL(table_schema.assign(tables[idx]))) {
 | 
						|
              LOG_WARN("fail to assign schema", K(ret));
 | 
						|
            } else {
 | 
						|
              ObSchemaTestUtils::table_set_tenant(table_schema, tenant_id);
 | 
						|
              CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
            }
 | 
						|
            if (OB_FAIL(ret)) {
 | 
						|
            } else if (tables[idx].is_view_table()) {
 | 
						|
              // skip
 | 
						|
            } else if (OB_FAIL(rootserver::ObSchema2DDLSql::convert(table_schema, csql, sizeof(csql)))) {
 | 
						|
              LOG_WARN("convert table schema to create table sql failed", K(ret));
 | 
						|
            } else if (OB_FAIL(sql_proxy.write(tenant_id, csql, affect_rows))) {
 | 
						|
              ret = OB_SUCCESS;
 | 
						|
              LOG_WARN("execute sql failed", K(ret), K(csql));
 | 
						|
            }
 | 
						|
            break;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
int TestPartitionTableIterator::release_tenant_space_schema(uint64_t tenant_id)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  std::string db = db_initer_.get_db_name();
 | 
						|
  common::ObMySQLProxy& sql_proxy = db_initer_.get_sql_proxy();
 | 
						|
  ObSqlString sql;
 | 
						|
  int64_t affect_rows = 0;
 | 
						|
  if (OB_FAIL(sql.assign_fmt("drop database if exists %s_%lu", db.c_str(), tenant_id))) {
 | 
						|
    LOG_WARN("assign sql failed", K(ret));
 | 
						|
  } else if (OB_FAIL(sql_proxy.write(sql.ptr(), affect_rows))) {
 | 
						|
    LOG_WARN("execute create database sql failed", K(ret), K(sql));
 | 
						|
  }
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
void TestPartitionTableIterator::TearDown()
 | 
						|
{
 | 
						|
  ObKVGlobalCache::get_instance().destroy();
 | 
						|
}
 | 
						|
 | 
						|
void TestPartitionTableIterator::SetUp()
 | 
						|
{
 | 
						|
  int ret = db_initer_.init();
 | 
						|
  ASSERT_EQ(OB_SUCCESS, ret);
 | 
						|
  ObKVGlobalCache::get_instance().init();
 | 
						|
 | 
						|
  GCONF.meta_table_read_write_mode = ObMetaTableMode::METATABLE_MODE_SYS_ONLY;
 | 
						|
  GCONF.min_observer_version.set_value("2.0.0");
 | 
						|
 | 
						|
  const bool only_core_tables = false;
 | 
						|
  ret = db_initer_.create_system_table(only_core_tables);
 | 
						|
  ASSERT_EQ(OB_SUCCESS, ret);
 | 
						|
 | 
						|
  ret = operator_.init(db_initer_.get_sql_proxy(), NULL);
 | 
						|
  ASSERT_EQ(OB_SUCCESS, ret);
 | 
						|
  ASSERT_EQ(OB_SUCCESS, operator_.set_callback_for_rs(cb_, merge_error_cb_));
 | 
						|
  // init schema service
 | 
						|
  // ASSERT_EQ(OB_SUCCESS, schema_service_.init());
 | 
						|
  ret = multi_schema_service_.init(&db_initer_.get_sql_proxy(),
 | 
						|
      &db_initer_.get_config(),
 | 
						|
      OB_MAX_VERSION_COUNT,
 | 
						|
      OB_MAX_VERSION_COUNT_FOR_MERGE,
 | 
						|
      false);
 | 
						|
  ASSERT_EQ(OB_SUCCESS, ret);
 | 
						|
  TEN = 1;
 | 
						|
  // create sys tenant
 | 
						|
  ObTenantSchema tenant_schema;
 | 
						|
  tenant_schema.set_tenant_id(OB_SYS_TENANT_ID);
 | 
						|
  tenant_schema.set_tenant_name(OB_SYS_TENANT_NAME);
 | 
						|
  tenant_schema.set_locality("");
 | 
						|
  CREATE_TENANT(ret, tenant_schema);
 | 
						|
  ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(TEN));
 | 
						|
  ObTableSchema table_schema;
 | 
						|
  for (int64_t i = 0; OB_SUCC(ret) && NULL != share::sys_table_schema_creators[i]; ++i) {
 | 
						|
    table_schema.reset();
 | 
						|
    ASSERT_EQ(OB_SUCCESS, (*share::sys_table_schema_creators[i])(table_schema));
 | 
						|
    ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID);
 | 
						|
    CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  }
 | 
						|
 | 
						|
  for (int64_t i = 0; OB_SUCC(ret) && NULL != share::core_table_schema_creators[i]; ++i) {
 | 
						|
    table_schema.reset();
 | 
						|
    ASSERT_EQ(OB_SUCCESS, (*share::core_table_schema_creators[i])(table_schema));
 | 
						|
    ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID);
 | 
						|
    CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  }
 | 
						|
  for (int64_t i = 0; OB_SUCC(ret) && NULL != share::virtual_table_schema_creators[i]; ++i) {
 | 
						|
    table_schema.reset();
 | 
						|
    ASSERT_EQ(OB_SUCCESS, (*share::virtual_table_schema_creators[i])(table_schema));
 | 
						|
    ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID);
 | 
						|
    CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  }
 | 
						|
 | 
						|
  for (int64_t i = 0; OB_SUCC(ret) && NULL != share::sys_view_schema_creators[i]; ++i) {
 | 
						|
    table_schema.reset();
 | 
						|
    ASSERT_EQ(OB_SUCCESS, (*share::sys_view_schema_creators[i])(table_schema));
 | 
						|
    ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID);
 | 
						|
    CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  }
 | 
						|
 | 
						|
  for (int64_t i = 0; OB_SUCC(ret) && NULL != share::information_schema_table_schema_creators[i]; ++i) {
 | 
						|
    table_schema.reset();
 | 
						|
    ASSERT_EQ(OB_SUCCESS, (*share::information_schema_table_schema_creators[i])(table_schema));
 | 
						|
    ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID);
 | 
						|
    CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  }
 | 
						|
 | 
						|
  for (int64_t i = 0; OB_SUCC(ret) && NULL != share::mysql_table_schema_creators[i]; ++i) {
 | 
						|
    table_schema.reset();
 | 
						|
    ASSERT_EQ(OB_SUCCESS, (*share::mysql_table_schema_creators[i])(table_schema));
 | 
						|
    ObSchemaTestUtils::table_set_tenant(table_schema, OB_SYS_TENANT_ID);
 | 
						|
    CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  }
 | 
						|
  TEN = 2;
 | 
						|
  ASSERT_EQ(OB_SUCCESS, gen_tenant_schema(2, tenant_schema));
 | 
						|
  CREATE_TENANT(ret, tenant_schema);
 | 
						|
  ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(TEN));
 | 
						|
  ASSERT_EQ(OB_SUCCESS, gen_table_schema(TEN, 50001, 1, 1, table_schema));
 | 
						|
  table_schema.set_table_type(USER_TABLE);
 | 
						|
  table_schema.set_part_level(PARTITION_LEVEL_ONE);
 | 
						|
  table_schema.get_part_option().set_part_num(2);
 | 
						|
  CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
  ASSERT_EQ(OB_SUCCESS, gen_table_schema(TEN, 50002, 1, 1, table_schema));
 | 
						|
  table_schema.set_part_level(PARTITION_LEVEL_ZERO);
 | 
						|
  CREATE_USER_TABLE_SCHEMA(ret, table_schema);
 | 
						|
 | 
						|
  // init partition table
 | 
						|
  TEN = 1;
 | 
						|
  prop_getter_.clear().add(combine_id(TEN, 1), 0, A, LEADER);
 | 
						|
  GCONF.self_addr_ = prop_getter_.get_replicas().at(0).server_;
 | 
						|
  ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(0)));
 | 
						|
 | 
						|
  prop_getter_.clear().add(combine_id(TEN, 2), 0, A, LEADER);
 | 
						|
  GCONF.self_addr_ = prop_getter_.get_replicas().at(0).server_;
 | 
						|
  ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(0)));
 | 
						|
 | 
						|
  TEN = 2;
 | 
						|
  prop_getter_.clear()
 | 
						|
      .add(combine_id(TEN, 50001), 0, A, LEADER)
 | 
						|
      .add(combine_id(TEN, 50001), 0, B, FOLLOWER)
 | 
						|
      .add(combine_id(TEN, 50001), 1, A, LEADER)
 | 
						|
      .add(combine_id(TEN, 50001), 1, B, FOLLOWER);
 | 
						|
  for (int64_t i = 0; i < prop_getter_.get_replicas().count(); i++) {
 | 
						|
    GCONF.self_addr_ = prop_getter_.get_replicas().at(i).server_;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(i)));
 | 
						|
  }
 | 
						|
  ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema());
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(TestPartitionTableIterator, table_partition_iterator_v2)
 | 
						|
{
 | 
						|
  const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_TENANT_ONLY};
 | 
						|
  for (int idx = 0; idx < ARRAYSIZEOF(modes); idx++) {
 | 
						|
    LOG_INFO("case table_partition_iterator_v2: use mode ", K(modes[idx]));
 | 
						|
    GCONF.meta_table_read_write_mode = modes[idx];
 | 
						|
 | 
						|
    ObTablePartitionIterator iter;
 | 
						|
    GCONF.partition_table_scan_batch_count = 4;
 | 
						|
    ObSchemaGetterGuard schema_guard;
 | 
						|
    EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(schema_guard));
 | 
						|
    ObPartitionInfo partition;
 | 
						|
    // not init
 | 
						|
    ASSERT_NE(OB_SUCCESS, iter.next(partition));
 | 
						|
    ASSERT_NE(OB_SUCCESS, iter.init(OB_INVALID_ID, schema_guard, operator_));
 | 
						|
 | 
						|
    if (ObMetaTableMode::METATABLE_MODE_SYS_ONLY == modes[idx]) {
 | 
						|
      // during setup, tenant 1,2 are created according to ObMetaTableRWMode::TENANT_RW
 | 
						|
      // only verified in this mode
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(2, 50001), schema_guard, operator_));
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(2, partition.replica_count());
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(2, partition.replica_count());
 | 
						|
 | 
						|
      ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
      ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
 | 
						|
      // init again
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(2, 50001), schema_guard, operator_));
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(2, partition.replica_count());
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(2, partition.replica_count());
 | 
						|
 | 
						|
      ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
    }
 | 
						|
 | 
						|
    LOG_INFO("table_iterator", K(iter));
 | 
						|
    // test exception, there is a hole in the partition table
 | 
						|
    TEN = 20005 + idx * 10000;
 | 
						|
    uint64_t table_id = 50005;
 | 
						|
    // five replcias, 6 error pattern
 | 
						|
    // 1234 \ 0234 \ 0123 \  01234 \ 0123456 \ empty \012367
 | 
						|
    for (int64_t i = 0; i < 7; i++) {
 | 
						|
      LOG_INFO("round", K(i));
 | 
						|
      ObSchemaGetterGuard tmp_schema_guard;
 | 
						|
      gen_schema_lack_partition_level_one(TEN, table_id, 1, 1, i, true, modes[idx]);
 | 
						|
      gen_schema_lack_partition_level_one(TEN, table_id + 1, 1, 1, i, false, modes[idx]);
 | 
						|
      EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(tmp_schema_guard));
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(TEN, table_id), tmp_schema_guard, operator_));
 | 
						|
      partition.reuse();
 | 
						|
      // 1
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(0, partition.get_partition_id());
 | 
						|
      if (0 == i || 5 == i) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      partition.reuse();
 | 
						|
      // 2
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(1, partition.get_partition_id());
 | 
						|
      if (1 == i || 5 == i) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 3
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(2, partition.get_partition_id());
 | 
						|
      if (i == 5) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        if (partition.replica_count() != 2)
 | 
						|
          OB_ASSERT(0);
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 4
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(3, partition.get_partition_id());
 | 
						|
      if (i == 5) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 5
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(4, partition.get_partition_id());
 | 
						|
      if (2 == i || 5 == i || 6 == i) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
      table_id += 2;
 | 
						|
      TEN++;
 | 
						|
    }
 | 
						|
 | 
						|
    // generate two level partitions 2 * 3
 | 
						|
    // 13 patterns
 | 
						|
    // nothing                                                   --0
 | 
						|
    //      <0,1>,<0,2>,      <1,0>,<1,1>,<1,2> //lack of front   --1
 | 
						|
    //<0,0>,      <0,2>,      <1,0>,<1,1>,<1,2> //lack of middle ---2
 | 
						|
    //<0,0>,<0,1>,     ,      <1,0>,<1,1>,<1,2> //lack of middle ---3
 | 
						|
    //<0,0>,<0,1>,<0,2>,<0,3>,<1,0>,<1,1>,<1,2> //more in middle ---4
 | 
						|
    //<0,0>,<0,1>,<0,2>,      <1,0>,<1,1>,<1,2> //normal         ---5
 | 
						|
    //<0,0>,<0,1>,<0,2>,<0,3>,      <1,1>,<1,2> //more in middle ---6
 | 
						|
    //<0,0>,<0,1>,<0,2>,            <1,1>,<1,2> //lack of front  ---7
 | 
						|
    //<0,0>,<0,1>,<0,2>,                                ---8
 | 
						|
    //<0,0>,<0,1>,                  <1,1>,<1,2> //lack of middle ---9
 | 
						|
    //<0,0>,<0,1>,<0,2>,      <1,0>             //the back is missing ----10
 | 
						|
    //<0,0>,<0,1>,<0,2>,      <1,0>,<1,1>,<1,2><1,3>,<1,4> more in back  ---11
 | 
						|
    //                        <1,0>,<1,1>,<1,2>                  ----12
 | 
						|
    //<0,0>,<0,1>,<0,2>,<0,3>,  <0,5>    <1,1>,<1,2> //more in middle----13
 | 
						|
 | 
						|
    for (int64_t i = 0; i < 14; i++) {
 | 
						|
      ObSchemaGetterGuard tmp_schema_guard;
 | 
						|
      gen_schema_lack_partition_level_two(TEN, table_id, 1, 1, i, true, modes[idx]);
 | 
						|
      gen_schema_lack_partition_level_two(TEN, table_id + 1, 1, 1, i, false, modes[idx]);
 | 
						|
      EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(tmp_schema_guard));
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(TEN, table_id), tmp_schema_guard, operator_));
 | 
						|
      // 1
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(generate_phy_part_id(0, 0, PARTITION_LEVEL_TWO), partition.get_partition_id());
 | 
						|
      if (i == 0 || i == 1 || i == 12) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 2
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(generate_phy_part_id(0, 1, PARTITION_LEVEL_TWO), partition.get_partition_id());
 | 
						|
      if (i == 2 || i == 12 || i == 0) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 3
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(generate_phy_part_id(0, 2, PARTITION_LEVEL_TWO), partition.get_partition_id());
 | 
						|
      if (i == 3 || i == 9 || i == 12 || i == 0) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 4
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(generate_phy_part_id(1, 0, PARTITION_LEVEL_TWO), partition.get_partition_id());
 | 
						|
      if (i == 0 || i == 6 || i == 7 || i == 8 || i == 9 || i == 13) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 5
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(generate_phy_part_id(1, 1, PARTITION_LEVEL_TWO), partition.get_partition_id());
 | 
						|
      if (i == 0 || i == 8 || i == 10) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 6
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(generate_phy_part_id(1, 2, PARTITION_LEVEL_TWO), partition.get_partition_id());
 | 
						|
      if (i == 0 || i == 8 || i == 10) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
      table_id += 2;
 | 
						|
      TEN++;
 | 
						|
    }
 | 
						|
 | 
						|
    int ret = OB_SUCCESS;
 | 
						|
    for (uint64_t i = 20005 + idx * 10000; i < TEN; i++) {
 | 
						|
      if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
        ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(i));
 | 
						|
      }
 | 
						|
      DROP_TENANT(ret, i);
 | 
						|
      ASSERT_EQ(OB_SUCCESS, ret);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(TestPartitionTableIterator, tenant_partition_iterator_for_non_continuous_partition_id)
 | 
						|
{
 | 
						|
  const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_TENANT_ONLY};
 | 
						|
  for (int idx = 0; idx < ARRAYSIZEOF(modes); idx++) {
 | 
						|
    LOG_INFO("case tenant_partition_iterator_for_non_continuous_partition_id: use mode ", K(modes[idx]));
 | 
						|
    GCONF.meta_table_read_write_mode = modes[idx];
 | 
						|
 | 
						|
    int ret = OB_SUCCESS;
 | 
						|
    int64_t tenant_id = 1001 + idx;
 | 
						|
    uint64_t table_id = 50005;
 | 
						|
    vector<int64_t> part_ids = {1, 3, 6, 7, 13};
 | 
						|
    vector<vector<int64_t>> meta_part_projectors = {{0, 1, 2, 3, 4}};
 | 
						|
    ObTenantSchema tenant_schema;
 | 
						|
    if (OB_FAIL(gen_tenant_schema(tenant_id, tenant_schema))) {
 | 
						|
      LOG_WARN("fail to gen tenant schema", K(ret), K(tenant_id));
 | 
						|
    }
 | 
						|
    CREATE_TENANT(ret, tenant_schema);
 | 
						|
    if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant_schema.get_tenant_id()));
 | 
						|
    }
 | 
						|
 | 
						|
    gen_table_schema_with_specified_part_id(tenant_id, table_id, 1, 1, part_ids);
 | 
						|
    gen_partition_table_level_one(tenant_id, table_id, part_ids, meta_part_projectors[0]);
 | 
						|
 | 
						|
    ObSchemaGetterGuard tmp_schema_guard;
 | 
						|
    EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(tmp_schema_guard));
 | 
						|
    ObTenantPartitionIterator iter;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, tenant_id, false));
 | 
						|
    ObPartitionInfo partition;
 | 
						|
    int i = 0;
 | 
						|
    while (OB_SUCC(iter.next(partition))) {
 | 
						|
      const uint64_t tid = combine_id(tenant_id, table_id);
 | 
						|
      if (partition.get_table_id() != tid) {
 | 
						|
        continue;
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(part_ids[i], partition.get_partition_id());
 | 
						|
        ASSERT_EQ(2, partition.get_replicas_v2().count());
 | 
						|
        ++i;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ASSERT_EQ(OB_ITER_END, ret);
 | 
						|
    ASSERT_EQ(5, i);
 | 
						|
    if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant_schema.get_tenant_id()));
 | 
						|
    }
 | 
						|
    DROP_TENANT(ret, tenant_id);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(TestPartitionTableIterator, table_partition_iterator_for_non_continuous_partition_id)
 | 
						|
{
 | 
						|
  const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_TENANT_ONLY};
 | 
						|
  for (int idx = 0; idx < ARRAYSIZEOF(modes); idx++) {
 | 
						|
    LOG_INFO("case table_partition_iterator_for_non_continuous_partition_id: use mode ", K(modes[idx]));
 | 
						|
    GCONF.meta_table_read_write_mode = modes[idx];
 | 
						|
 | 
						|
    int ret = OB_SUCCESS;
 | 
						|
    int64_t tenant_id = 2001 + idx;
 | 
						|
    uint64_t table_id = 50005;
 | 
						|
    vector<int64_t> part_ids = {1, 3, 6, 7, 13};
 | 
						|
    vector<vector<int64_t>> meta_part_projectors = {
 | 
						|
        {1, 2, 3, 4},
 | 
						|
        {0, 2, 3, 4},
 | 
						|
        {0, 1, 2, 3},
 | 
						|
        {0, 1, 2, 3, 4},
 | 
						|
        {0, 1, 2, 3, 4, 14, 15},
 | 
						|
        {},
 | 
						|
        {0, 1, 2, 3, 15, 16},
 | 
						|
    };
 | 
						|
    ObTenantSchema tenant_schema;
 | 
						|
    if (OB_FAIL(gen_tenant_schema(tenant_id, tenant_schema))) {
 | 
						|
      LOG_WARN("fail to gen tenant schema", K(ret), K(tenant_id));
 | 
						|
    }
 | 
						|
    CREATE_TENANT(ret, tenant_schema);
 | 
						|
    if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant_id));
 | 
						|
    }
 | 
						|
    // test exception. there is a hole in the partition_table
 | 
						|
    // 5 replicas, 6 error pattern
 | 
						|
    // 1234 \ 0234 \ 0123 \  01234 \ 0123456 \ empty \ 012367
 | 
						|
    for (int64_t i = 0; i < 7; i++) {
 | 
						|
      LOG_INFO("round", K(i));
 | 
						|
      ObSchemaGetterGuard tmp_schema_guard;
 | 
						|
      gen_table_schema_with_specified_part_id(tenant_id, table_id, 1, 1, part_ids);
 | 
						|
      gen_partition_table_level_one(tenant_id, table_id, part_ids, meta_part_projectors[i]);
 | 
						|
 | 
						|
      EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(tmp_schema_guard));
 | 
						|
      ObTablePartitionIterator iter;
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(tenant_id, table_id), tmp_schema_guard, operator_));
 | 
						|
      ObPartitionInfo partition;
 | 
						|
      // 1
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(part_ids[0], partition.get_partition_id());
 | 
						|
      if (0 == i || 5 == i) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 2
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(part_ids[1], partition.get_partition_id());
 | 
						|
      if (1 == i || 5 == i) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 3
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(part_ids[2], partition.get_partition_id());
 | 
						|
      if (i == 5) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        if (partition.replica_count() != 2)
 | 
						|
          OB_ASSERT(0);
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 4
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(part_ids[3], partition.get_partition_id());
 | 
						|
      if (i == 5) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      // 5
 | 
						|
      partition.reuse();
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(part_ids[4], partition.get_partition_id());
 | 
						|
      if (2 == i || 5 == i || 6 == i) {
 | 
						|
        LOG_INFO("expect error", K(partition.get_partition_id()));
 | 
						|
        ASSERT_EQ(0, partition.replica_count());
 | 
						|
      } else {
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
      }
 | 
						|
      ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
      table_id += 2;
 | 
						|
    }
 | 
						|
    if (modes[idx] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant_id));
 | 
						|
    }
 | 
						|
    DROP_TENANT(ret, tenant_id);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(TestPartitionTableIterator, all_table_partition)
 | 
						|
{
 | 
						|
  LOG_INFO("case TestPartitionTableIterator.all_table_partition");
 | 
						|
  GCONF.meta_table_read_write_mode = ObMetaTableMode::METATABLE_MODE_TENANT_ONLY;
 | 
						|
  ObPartitionInfo partition;
 | 
						|
  {
 | 
						|
    ObPartitionTableIterator iter;
 | 
						|
    LOG_INFO("partition table iterator", K(iter));
 | 
						|
    // not init
 | 
						|
    ASSERT_NE(OB_SUCCESS, iter.next(partition));
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true));
 | 
						|
    // init twice
 | 
						|
    ASSERT_NE(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true));
 | 
						|
 | 
						|
    // tid: 1
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
    ASSERT_EQ(1, partition.replica_count());
 | 
						|
    ASSERT_EQ(1UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_));
 | 
						|
 | 
						|
    // tid: 2
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
    ASSERT_EQ(1, partition.replica_count());
 | 
						|
    ASSERT_EQ(2UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_));
 | 
						|
 | 
						|
    // ignore non exist table (tid: 3), virtual table (tid: 5)
 | 
						|
 | 
						|
    // tid: OB_ALL_META_TABLE, no replica
 | 
						|
    for (int64_t i = 0; i < 16; ++i) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(0, partition.replica_count());
 | 
						|
    }
 | 
						|
 | 
						|
    // tid: 50001
 | 
						|
    while (OB_SUCCESS == iter.next(partition)) {
 | 
						|
      if (partition.get_table_id() == combine_id(2, 50001)) {
 | 
						|
        // ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
        LOG_INFO("xx", K(partition));
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
        ASSERT_EQ(50001UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_));
 | 
						|
        ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
        ASSERT_EQ(2, partition.replica_count());
 | 
						|
        ASSERT_EQ(50001UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_));
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
    while (OB_SUCCESS == iter.next(partition)) {
 | 
						|
      LOG_INFO("tingting", K(partition.get_table_id()));
 | 
						|
    }
 | 
						|
    // ignore non exist table (tid: 50002)
 | 
						|
    ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
    ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
  }
 | 
						|
  {
 | 
						|
 | 
						|
    // iterator with filter
 | 
						|
    {
 | 
						|
      ObPartitionTableIterator iter;
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_valid_version());
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_server(A));
 | 
						|
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true));
 | 
						|
 | 
						|
      // tid: 1
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(1, partition.replica_count());
 | 
						|
 | 
						|
      // tid: 2
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(1, partition.replica_count());
 | 
						|
 | 
						|
      // tid: 50001
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(1, partition.replica_count());
 | 
						|
      ASSERT_EQ(50001UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_));
 | 
						|
      ASSERT_EQ(A, partition.get_replicas_v2().at(0).server_);
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(1, partition.replica_count());
 | 
						|
      ASSERT_EQ(50001UL, extract_pure_id(partition.get_replicas_v2().at(0).table_id_));
 | 
						|
      ASSERT_EQ(A, partition.get_replicas_v2().at(0).server_);
 | 
						|
    }
 | 
						|
 | 
						|
    // iter empty partition
 | 
						|
    {
 | 
						|
      ObPartitionTableIterator iter;
 | 
						|
      iter.get_filters().set_zone("1024");  // non exist zone
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true));
 | 
						|
 | 
						|
      // tid: 1
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(0, partition.replica_count());
 | 
						|
      ASSERT_EQ(1UL, extract_pure_id(partition.get_table_id()));
 | 
						|
 | 
						|
      // tid: 2
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(0, partition.replica_count());
 | 
						|
      ASSERT_EQ(2UL, extract_pure_id(partition.get_table_id()));
 | 
						|
 | 
						|
      // tid: 50001 ...
 | 
						|
    }
 | 
						|
 | 
						|
    // fitler empty partition
 | 
						|
    {
 | 
						|
      ObPartitionTableIterator iter;
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_valid_version());
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_server(B));
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true));
 | 
						|
      // tid: 50001
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(1, partition.replica_count());
 | 
						|
      ASSERT_EQ(50001UL, extract_pure_id(partition.get_table_id()));
 | 
						|
      ASSERT_EQ(B, partition.get_replicas_v2().at(0).server_);
 | 
						|
    }
 | 
						|
 | 
						|
    {
 | 
						|
      ObPartitionTableIterator iter;
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_valid_version());
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.get_filters().set_server(E));  // non exist server
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, false));
 | 
						|
      ASSERT_EQ(OB_ITER_END, iter.next(partition));
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
class MockPartitionInfo : public ObPartitionInfo {
 | 
						|
public:
 | 
						|
  MOCK_METHOD1(filter, int(const ObIReplicaFilter&));
 | 
						|
};
 | 
						|
 | 
						|
class MockPartitionTableOperator : public ObPartitionTableOperator {
 | 
						|
public:
 | 
						|
  MockPartitionTableOperator(ObIPartPropertyGetter& prop_getter, ObPartitionTableOperator& pt_operator)
 | 
						|
      : ObPartitionTableOperator(prop_getter), pt_operator_(pt_operator), return_error_(false)
 | 
						|
  {}
 | 
						|
 | 
						|
  MOCK_METHOD3(get, int(const uint64_t, const int64_t, ObPartitionInfo&));
 | 
						|
  int prefetch(const uint64_t tenant_id, const uint64_t start_table_id, const int64_t start_partition_id,
 | 
						|
      ObIArray<ObPartitionInfo>& partition_infos, bool ignore_row_checksum, bool use_sys_tenant)
 | 
						|
  {
 | 
						|
    UNUSED(ignore_row_checksum);
 | 
						|
    if (return_error_) {
 | 
						|
      return OB_ERR_UNEXPECTED;
 | 
						|
    } else {
 | 
						|
      return pt_operator_.prefetch(
 | 
						|
          tenant_id, start_table_id, start_partition_id, partition_infos, false, use_sys_tenant);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void set_return_error(const bool return_error)
 | 
						|
  {
 | 
						|
    return_error_ = return_error;
 | 
						|
  }
 | 
						|
 | 
						|
private:
 | 
						|
  ObPartitionTableOperator& pt_operator_;
 | 
						|
  bool return_error_;
 | 
						|
};
 | 
						|
 | 
						|
TEST_F(TestPartitionTableIterator, fail)
 | 
						|
{
 | 
						|
  LOG_INFO("case TestPartitionTableIterator.fail");
 | 
						|
  GCONF.meta_table_read_write_mode = ObMetaTableMode::METATABLE_MODE_TENANT_ONLY;
 | 
						|
  ObPartitionInfo partition;
 | 
						|
  ObSchemaGetterGuard schema_guard;
 | 
						|
  EXPECT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(schema_guard));
 | 
						|
  // table partition iterator
 | 
						|
  {
 | 
						|
    ObTablePartitionIterator iter;
 | 
						|
 | 
						|
    ASSERT_NE(OB_SUCCESS, iter.init(combine_id(1, OB_INVALID_ID), schema_guard, operator_));
 | 
						|
 | 
						|
    ObPartitionTableOperator opt(prop_getter_);
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.init(combine_id(1, 1), schema_guard, opt));
 | 
						|
    ASSERT_NE(OB_SUCCESS, iter.next(partition));  // fail: opt not init
 | 
						|
  }
 | 
						|
  // partition table iterator init
 | 
						|
  {
 | 
						|
    ObPartitionTableIterator iter;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true));
 | 
						|
    ASSERT_EQ(OB_INIT_TWICE, iter.init(operator_, multi_schema_service_, true));
 | 
						|
  }
 | 
						|
  // partition operator get fail
 | 
						|
  {
 | 
						|
    MockPartitionTableOperator opt(prop_getter_, operator_);
 | 
						|
    ASSERT_EQ(OB_SUCCESS, opt.init(db_initer_.get_sql_proxy(), NULL));
 | 
						|
    // first call fail
 | 
						|
    {
 | 
						|
      opt.set_return_error(true);
 | 
						|
      ObPartitionTableIterator iter;
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(opt, multi_schema_service_, true));
 | 
						|
      ASSERT_NE(OB_SUCCESS, iter.next(partition));
 | 
						|
    }
 | 
						|
    // second call fail
 | 
						|
    {
 | 
						|
      opt.set_return_error(false);
 | 
						|
      ObPartitionTableIterator iter;
 | 
						|
      rootserver::ObRootService rs;
 | 
						|
      rootserver::ObRootService::RsListChangeCb cb(rs);
 | 
						|
      opt.set_callback_for_rs(cb, merge_error_cb_);
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.init(opt, multi_schema_service_, true));
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
      opt.set_return_error(true);
 | 
						|
      ASSERT_NE(OB_SUCCESS, iter.next(partition));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  // partition filter fail
 | 
						|
  {
 | 
						|
    MockPartitionInfo p;
 | 
						|
    ObPartitionTableIterator iter;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.init(operator_, multi_schema_service_, true));
 | 
						|
    EXPECT_CALL(p, filter(_)).WillOnce(Return(OB_ERR_UNEXPECTED));
 | 
						|
    ASSERT_NE(OB_SUCCESS, iter.next(p));
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(TestPartitionTableIterator, tenant)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_TENANT_ONLY};
 | 
						|
  for (int i = 0; i < ARRAYSIZEOF(modes); i++) {
 | 
						|
    LOG_INFO("case tenant: use mode ", K(modes[i]));
 | 
						|
    GCONF.meta_table_read_write_mode = modes[i];
 | 
						|
 | 
						|
    const uint64_t tenant_id = 3001 + i;
 | 
						|
    const int64_t table_count = 100;
 | 
						|
    ObTenantSchema tenant;
 | 
						|
    ObTableSchema table;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, gen_tenant_schema(tenant_id, tenant));
 | 
						|
    // ASSERT_EQ(OB_SUCCESS, schema_service_.add_tenant(tenant));
 | 
						|
 | 
						|
    CREATE_TENANT(ret, tenant);
 | 
						|
    if (modes[i] >= ObMetaTableMode::METATABLE_MODE_SYS_ONLY) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant.get_tenant_id()));
 | 
						|
    }
 | 
						|
    // replica count is 200
 | 
						|
    for (int64_t i = 0; i < table_count; ++i) {
 | 
						|
      const uint64_t pure_id = 50001 + static_cast<uint64_t>(i);
 | 
						|
      ASSERT_EQ(OB_SUCCESS, gen_table_schema(tenant_id, pure_id, 1, 1, table));
 | 
						|
      table.set_part_level(PARTITION_LEVEL_ZERO);
 | 
						|
      table.set_table_type(USER_TABLE);
 | 
						|
      CREATE_USER_TABLE_SCHEMA(ret, table);
 | 
						|
      // ASSERT_EQ(OB_SUCCESS, schema_service_.add_table(table));
 | 
						|
      prop_getter_.clear()
 | 
						|
          .add(combine_id(tenant_id, pure_id), 0, A, LEADER)
 | 
						|
          .add(combine_id(tenant_id, pure_id), 0, B, FOLLOWER);
 | 
						|
      for (int64_t j = 0; j < prop_getter_.get_replicas().count(); j++) {
 | 
						|
        GCONF.self_addr_ = prop_getter_.get_replicas().at(j).server_;
 | 
						|
        ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(j)));
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema());
 | 
						|
 | 
						|
    // case 1: one prefetch get all replicas
 | 
						|
    // case 2: one prefetch can just get all replicas, but we don't konw whether last partition
 | 
						|
    // is complete, trim last partition, prefetch again
 | 
						|
    // case 3: one prefetch can't not get all replicas
 | 
						|
    const int64_t prefetch_counts[] = {400, 200, 80};
 | 
						|
    for (int64_t idx = 0; idx < ARRAYSIZEOF(prefetch_counts); ++idx) {
 | 
						|
      GCONF.partition_table_scan_batch_count = prefetch_counts[idx];
 | 
						|
      ObTenantPartitionIterator tenant_partition_iter;
 | 
						|
      ASSERT_EQ(OB_SUCCESS, tenant_partition_iter.init(operator_, multi_schema_service_, tenant_id, false));
 | 
						|
      ObPartitionInfo partition;
 | 
						|
      while (OB_SUCC(tenant_partition_iter.next(partition))) {
 | 
						|
        if (partition.get_table_id() == combine_id(tenant_id, 50001)) {
 | 
						|
          ASSERT_EQ(2, partition.get_replicas_v2().count());
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      for (int64_t i = 1; i < table_count; ++i) {
 | 
						|
        const uint64_t pure_id = 50001 + static_cast<uint64_t>(i);
 | 
						|
        ASSERT_EQ(OB_SUCCESS, tenant_partition_iter.next(partition));
 | 
						|
        ASSERT_EQ(combine_id(tenant_id, pure_id), partition.get_table_id());
 | 
						|
        ASSERT_EQ(2, partition.get_replicas_v2().count());
 | 
						|
      }
 | 
						|
      ASSERT_EQ(OB_ITER_END, tenant_partition_iter.next(partition));
 | 
						|
    }
 | 
						|
 | 
						|
    // iterator all partition
 | 
						|
    ObPartitionTableIterator pt_iter;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, pt_iter.init(operator_, multi_schema_service_, true));
 | 
						|
    ret = OB_SUCCESS;
 | 
						|
    while (OB_SUCC(ret)) {
 | 
						|
      ObPartitionInfo partition;
 | 
						|
      ret = pt_iter.next(partition);
 | 
						|
    }
 | 
						|
    ASSERT_EQ(OB_ITER_END, ret);
 | 
						|
    if (modes[i] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant.get_tenant_id()));
 | 
						|
    }
 | 
						|
    DROP_TENANT(ret, tenant_id);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(TestPartitionTableIterator, by_partition)
 | 
						|
{
 | 
						|
  LOG_INFO("case by_partition");
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  GCONF.meta_table_read_write_mode = ObMetaTableMode::METATABLE_MODE_TENANT_ONLY;
 | 
						|
  // partition not in schema, full partition table iterator can still get them
 | 
						|
  const uint64_t tenant_id = 1001;
 | 
						|
  ObTenantSchema tenant;
 | 
						|
  ObTableSchema table;
 | 
						|
  ASSERT_EQ(OB_SUCCESS, gen_tenant_schema(tenant_id, tenant));
 | 
						|
  // ASSERT_EQ(OB_SUCCESS, schema_service_.add_tenant(tenant));
 | 
						|
  CREATE_TENANT(ret, tenant);
 | 
						|
  ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant.get_tenant_id()));
 | 
						|
  ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema());
 | 
						|
 | 
						|
  const int64_t table_count = 100;
 | 
						|
  // replica count is 200
 | 
						|
  for (int64_t i = 0; i < table_count; ++i) {
 | 
						|
    const uint64_t pure_id = 50001 + static_cast<uint64_t>(i);
 | 
						|
    prop_getter_.clear()
 | 
						|
        .add(combine_id(tenant_id, pure_id), 0, A, LEADER)
 | 
						|
        .add(combine_id(tenant_id, pure_id), 0, B, FOLLOWER);
 | 
						|
    for (int64_t j = 0; j < prop_getter_.get_replicas().count(); j++) {
 | 
						|
      GCONF.self_addr_ = prop_getter_.get_replicas().at(j).server_;
 | 
						|
      ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(j)));
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // iterator all partition
 | 
						|
  const int64_t prefetch_counts[] = {400, 200, 80};
 | 
						|
  for (int64_t idx = 0; idx < ARRAYSIZEOF(prefetch_counts); ++idx) {
 | 
						|
    int ret = OB_SUCCESS;
 | 
						|
    GCONF.partition_table_scan_batch_count = prefetch_counts[idx];
 | 
						|
    ObFullPartitionTableIterator pt_iter;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, pt_iter.init(operator_, multi_schema_service_));
 | 
						|
    ObPartitionInfo partition;
 | 
						|
    int64_t sys_tenant_part_cnt = 0;
 | 
						|
    int64_t normal_tenant_part_cnt = 0;
 | 
						|
    while (OB_SUCC(ret)) {
 | 
						|
      ObPartitionInfo partition;
 | 
						|
      ret = pt_iter.next(partition);
 | 
						|
      LOG_INFO("xx", K(partition));
 | 
						|
      if (OB_SUCC(ret)) {
 | 
						|
        if (OB_SYS_TENANT_ID == partition.get_tenant_id()) {
 | 
						|
          ++sys_tenant_part_cnt;
 | 
						|
        } else {
 | 
						|
          ++normal_tenant_part_cnt;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    ASSERT_EQ(OB_ITER_END, ret);
 | 
						|
    ASSERT_EQ(2, sys_tenant_part_cnt);
 | 
						|
    ASSERT_EQ(2 + table_count, normal_tenant_part_cnt);
 | 
						|
  }
 | 
						|
  ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant.get_tenant_id()));
 | 
						|
  DROP_TENANT(ret, tenant_id);
 | 
						|
}
 | 
						|
 | 
						|
TEST_F(TestPartitionTableIterator, prefetch_second_fail)
 | 
						|
{
 | 
						|
  int ret = OB_SUCCESS;
 | 
						|
  GCONF.partition_table_scan_batch_count = 300;
 | 
						|
  const ObMetaTableMode modes[] = {ObMetaTableMode::METATABLE_MODE_SYS_ONLY,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE,
 | 
						|
      ObMetaTableMode::METATABLE_MODE_TENANT_ONLY};
 | 
						|
  for (int i = 0; i < ARRAYSIZEOF(modes); i++) {
 | 
						|
    LOG_INFO("case prefetch_second_fail: use mode ", K(modes[i]));
 | 
						|
    GCONF.meta_table_read_write_mode = modes[i];
 | 
						|
 | 
						|
    const uint64_t tenant_id = 1001;
 | 
						|
    const int64_t table_count = 3;
 | 
						|
    for (int64_t i = 0; i < table_count; ++i) {
 | 
						|
      const uint64_t pure_id = 50001 + static_cast<uint64_t>(i);
 | 
						|
      const int64_t part_num = 100;
 | 
						|
      for (int64_t j = 0; j < part_num; ++j) {
 | 
						|
        prop_getter_.clear()
 | 
						|
            .add(combine_id(tenant_id, pure_id), j, A, LEADER)
 | 
						|
            .add(combine_id(tenant_id, pure_id), j, B, FOLLOWER);
 | 
						|
        for (int64_t k = 0; k < prop_getter_.get_replicas().count(); k++) {
 | 
						|
          GCONF.self_addr_ = prop_getter_.get_replicas().at(k).server_;
 | 
						|
          ASSERT_EQ(OB_SUCCESS, operator_.update(prop_getter_.get_replicas().at(k)));
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    ObTenantSchema tenant;
 | 
						|
    ObTableSchema table;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, gen_tenant_schema(tenant_id, tenant));
 | 
						|
    // ASSERT_EQ(OB_SUCCESS, schema_service_.add_tenant(tenant));
 | 
						|
 | 
						|
    CREATE_TENANT(ret, tenant);
 | 
						|
    if (modes[i] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, gen_tenant_space_schema(tenant.get_tenant_id()));
 | 
						|
    }
 | 
						|
 | 
						|
    for (int64_t i = 0; i < table_count; ++i) {
 | 
						|
      const uint64_t pure_id = 50001 + static_cast<uint64_t>(i);
 | 
						|
      ASSERT_EQ(OB_SUCCESS, gen_table_schema(tenant_id, pure_id, 1, 1, table));
 | 
						|
      table.set_table_type(USER_TABLE);
 | 
						|
      table.set_part_level(PARTITION_LEVEL_ONE);
 | 
						|
      table.get_part_option().set_part_num(100);
 | 
						|
      CREATE_USER_TABLE_SCHEMA(ret, table);
 | 
						|
      // ASSERT_EQ(OB_SUCCESS, schema_service.add_table(table)); // user table
 | 
						|
    }
 | 
						|
    ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema());
 | 
						|
    common::ObMySQLProxy sql_proxy;
 | 
						|
    MockPartitionTableOperator pt(prop_getter_, operator_);
 | 
						|
    pt.init(sql_proxy, NULL);
 | 
						|
    ObTenantPartitionIterator iter;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.init(pt, multi_schema_service_, tenant_id, false));
 | 
						|
    for (int64_t i = 0; i < 100; ++i) {
 | 
						|
      ObPartitionInfo partition;
 | 
						|
      ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
    }
 | 
						|
 | 
						|
    // ASSERT_EQ(OB_SUCCESS, schema_service.del_table(combine_id(tenant_id, 50002)));
 | 
						|
    const ObTableSchema* table_schema = NULL;
 | 
						|
    ObSchemaGetterGuard schema_guard;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, multi_schema_service_.get_schema_guard(schema_guard));
 | 
						|
    ASSERT_EQ(OB_SUCCESS, schema_guard.get_table_schema(combine_id(tenant_id, 50002), table_schema));
 | 
						|
    DROP_USER_TABLE_SCHEMA(ret, *table_schema);
 | 
						|
    ASSERT_EQ(OB_SUCCESS, multi_schema_service_.refresh_and_add_schema());
 | 
						|
    ObPartitionInfo partition;
 | 
						|
    ASSERT_EQ(OB_SUCCESS, iter.next(partition));
 | 
						|
    if (modes[i] >= ObMetaTableMode::METATABLE_MODE_DOUBLE_WRITE) {
 | 
						|
      ASSERT_EQ(OB_SUCCESS, release_tenant_space_schema(tenant.get_tenant_id()));
 | 
						|
    }
 | 
						|
    DROP_TENANT(ret, tenant_id);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
}  // end namespace share
 | 
						|
}  // end namespace oceanbase
 | 
						|
 | 
						|
int main(int argc, char** argv)
 | 
						|
{
 | 
						|
  system("rm -f test_partition_table_iterator.log");
 | 
						|
  oceanbase::common::ObLogger::get_logger().set_log_level("INFO");
 | 
						|
  OB_LOGGER.set_log_level("INFO");
 | 
						|
  OB_LOGGER.set_file_name("test_partition_table_iterator.log", true);
 | 
						|
  testing::InitGoogleTest(&argc, argv);
 | 
						|
  return RUN_ALL_TESTS();
 | 
						|
}
 |