595 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			595 lines
		
	
	
		
			20 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.
 | |
|  */
 | |
| 
 | |
| #ifndef OCEANBASE_SLOG_SIMPLE_OB_PARTITION_IMAGE_H_
 | |
| #define OCEANBASE_SLOG_SIMPLE_OB_PARTITION_IMAGE_H_
 | |
| 
 | |
| #include "lib/list/ob_list.h"
 | |
| #include "lib/file/file_directory_utils.h"
 | |
| #include "lib/file/ob_file.h"
 | |
| #include "lib/random/ob_random.h"
 | |
| #include "lib/allocator/ob_mod_define.h"
 | |
| #include "storage/blocksstable/slog/ob_base_storage_logger.h"
 | |
| #include "storage/blocksstable/ob_block_sstable_struct.h"
 | |
| 
 | |
| namespace oceanbase {
 | |
| using namespace common;
 | |
| using namespace lib;
 | |
| namespace blocksstable {
 | |
| struct SimpleObPartition : public ObIBaseStorageLogEntry {
 | |
|   int64_t table_id_;
 | |
|   int64_t partition_id_;
 | |
|   int64_t log_seq_num_;
 | |
|   int64_t macro_block_cnt_;
 | |
|   int64_t macro_blocks_[1024];
 | |
|   bool operator==(const SimpleObPartition& partition);
 | |
|   bool operator!=(const SimpleObPartition& partition);
 | |
|   bool is_valid() const;
 | |
|   static void build(int64_t table_id, int64_t partition_id, int64_t macro_block_cnt, SimpleObPartition& partition);
 | |
|   TO_STRING_EMPTY();
 | |
| 
 | |
| public:
 | |
|   NEED_SERIALIZE_AND_DESERIALIZE;
 | |
| };
 | |
| 
 | |
| struct SimpleObPartitionNode {
 | |
|   SimpleObPartitionNode() : partition_(), next_(NULL)
 | |
|   {}
 | |
|   SimpleObPartition partition_;
 | |
|   SimpleObPartitionNode* next_;
 | |
| };
 | |
| 
 | |
| enum SimpleObPartitionOperation { ADD_PARTITION = 0, REMOVE_PARTITION = 1 };
 | |
| 
 | |
| class SimpleObPartitionImage : public ObIRedoModule {
 | |
| public:
 | |
|   SimpleObPartitionImage();
 | |
|   virtual ~SimpleObPartitionImage();
 | |
|   int init(const char* data_dir, ObBaseStorageLogger* redo_log);
 | |
|   virtual int read_check_point();
 | |
|   virtual int do_check_point();
 | |
|   // replay the redo log.
 | |
|   virtual int replay(const ObRedoModuleReplayParam& param) override;
 | |
|   virtual int parse(const int64_t subcmd, const char* buf, const int64_t len, FILE* stream) override;
 | |
|   virtual int enable_write_log() override
 | |
|   {
 | |
|     return common::OB_SUCCESS;
 | |
|   }
 | |
|   int add_partition(SimpleObPartition& partition);
 | |
|   int add_partition_no_commit(SimpleObPartition& partition);
 | |
|   int remove_partition(const int64_t table_id, const int64_t partition_id);
 | |
|   bool exist_partition(const int64_t table_id, const int64_t partition_id, int64_t* log_seq_num = NULL);
 | |
|   bool operator==(SimpleObPartitionImage& image);
 | |
|   bool operator!=(SimpleObPartitionImage& image);
 | |
| 
 | |
| public:
 | |
|   static const int64_t BUCKET_NUM = 1523;
 | |
|   static int64_t hash(const int64_t table_id, const int64_t partition_id);
 | |
|   int do_add_partition(const SimpleObPartition& partition);
 | |
|   void do_remove_partition(const int64_t table_id, const int64_t partition_id);
 | |
|   bool inited_;
 | |
|   common::ObArenaAllocator allocator_;
 | |
|   common::ObConcurrentFIFOAllocator pt_allocator_;
 | |
|   common::ObBucketLock buckets_lock_;
 | |
|   SimpleObPartitionNode** buckets_;
 | |
|   char data_file_[OB_MAX_FILE_NAME_LENGTH];
 | |
|   ObBaseStorageLogger* redo_log_;
 | |
| };
 | |
| 
 | |
| bool SimpleObPartition::operator==(const SimpleObPartition& partition)
 | |
| {
 | |
|   bool bret = true;
 | |
| 
 | |
|   if (table_id_ != partition.table_id_) {
 | |
|     bret = false;
 | |
|   } else if (partition_id_ != partition.partition_id_) {
 | |
|     bret = false;
 | |
|   } else if (macro_block_cnt_ != partition.macro_block_cnt_) {
 | |
|     bret = false;
 | |
|   } else {
 | |
|     for (int64_t i = 0; bret && i < macro_block_cnt_; i++) {
 | |
|       if (macro_blocks_[i] != partition.macro_blocks_[i]) {
 | |
|         bret = false;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return bret;
 | |
| }
 | |
| 
 | |
| bool SimpleObPartition::operator!=(const SimpleObPartition& partition)
 | |
| {
 | |
|   return !(*this == partition);
 | |
| }
 | |
| 
 | |
| bool SimpleObPartition::is_valid() const
 | |
| {
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| DEFINE_SERIALIZE(SimpleObPartition)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
| 
 | |
|   if (OB_SUCCESS != (ret = serialization::encode_vi64(buf, buf_len, pos, table_id_))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to encode ", "table_id_", table_id_, "ret", ret);
 | |
|   } else if (OB_SUCCESS != (ret = serialization::encode_vi64(buf, buf_len, pos, partition_id_))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to encode ", "partition_id_", partition_id_, "ret", ret);
 | |
|   } else if (OB_SUCCESS != (ret = serialization::encode_vi64(buf, buf_len, pos, log_seq_num_))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to encode ", "log_seq_num_", log_seq_num_, "ret", ret);
 | |
|   } else if (OB_SUCCESS != (ret = serialization::encode_vi64(buf, buf_len, pos, macro_block_cnt_))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to encode ", "macro_block_cnt_", macro_block_cnt_, "ret", ret);
 | |
|   } else {
 | |
|     for (int64_t i = 0; OB_SUCC(ret) && i < macro_block_cnt_; ++i) {
 | |
|       if (OB_SUCCESS != (ret = serialization::encode_vi64(buf, buf_len, pos, macro_blocks_[i]))) {
 | |
|         STORAGE_REDO_LOG(WARN, "Fail to encode ", "macro_block", macro_blocks_[i], "ret", ret);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| DEFINE_DESERIALIZE(SimpleObPartition)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
| 
 | |
|   if (OB_SUCCESS != (ret = serialization::decode_vi64(buf, data_len, pos, &table_id_))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to decode table_id_", "ret", ret);
 | |
|   } else if (OB_SUCCESS != (ret = serialization::decode_vi64(buf, data_len, pos, &partition_id_))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to decode partition_id_", "ret", ret);
 | |
|   } else if (OB_SUCCESS != (ret = serialization::decode_vi64(buf, data_len, pos, &log_seq_num_))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to decode log_seq_num_", "ret", ret);
 | |
|   } else if (OB_SUCCESS != (ret = serialization::decode_vi64(buf, data_len, pos, ¯o_block_cnt_))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to decode macro_block_cnt_", "ret", ret);
 | |
|   } else {
 | |
|     for (int64_t i = 0; OB_SUCC(ret) && i < macro_block_cnt_; ++i) {
 | |
|       if (OB_SUCCESS != (ret = serialization::decode_vi64(buf, data_len, pos, ¯o_blocks_[i]))) {
 | |
|         STORAGE_REDO_LOG(WARN, "Fail to decode macro_block", "ret", ret);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| DEFINE_GET_SERIALIZE_SIZE(SimpleObPartition)
 | |
| {
 | |
|   int64_t len = 0;
 | |
|   len += serialization::encoded_length(table_id_);
 | |
|   len += serialization::encoded_length(partition_id_);
 | |
|   len += serialization::encoded_length(log_seq_num_);
 | |
|   len += serialization::encoded_length(macro_block_cnt_);
 | |
| 
 | |
|   for (int64_t i = 0; i < macro_block_cnt_; ++i) {
 | |
|     len += serialization::encoded_length(macro_blocks_[i]);
 | |
|   }
 | |
| 
 | |
|   len += ObRandom::rand(0, 100);
 | |
| 
 | |
|   return len;
 | |
| }
 | |
| 
 | |
| void SimpleObPartition::build(
 | |
|     int64_t table_id, int64_t partition_id, int64_t macro_block_cnt, SimpleObPartition& partition)
 | |
| {
 | |
|   partition.table_id_ = table_id;
 | |
|   partition.partition_id_ = partition_id;
 | |
|   partition.macro_block_cnt_ = macro_block_cnt;
 | |
|   for (int64_t i = 0; i < partition.macro_block_cnt_; ++i) {
 | |
|     partition.macro_blocks_[i] = (table_id % (partition_id * macro_block_cnt + 1) + i);
 | |
|   }
 | |
| }
 | |
| 
 | |
| SimpleObPartitionImage::SimpleObPartitionImage()
 | |
|     : inited_(false), allocator_(ObModIds::TEST), buckets_(NULL), redo_log_(NULL)
 | |
| {}
 | |
| 
 | |
| SimpleObPartitionImage::~SimpleObPartitionImage()
 | |
| {
 | |
|   if (NULL != buckets_) {
 | |
|     SimpleObPartitionNode* iter = NULL;
 | |
|     SimpleObPartitionNode* tmp = NULL;
 | |
| 
 | |
|     for (int64_t pos = 0; pos < BUCKET_NUM; ++pos) {
 | |
|       for (iter = buckets_[pos]; iter != NULL; iter = tmp) {
 | |
|         tmp = iter->next_;
 | |
|         pt_allocator_.free(iter);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::init(const char* data_dir, ObBaseStorageLogger* redo_log)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   void* tmp = NULL;
 | |
| 
 | |
|   if (inited_) {
 | |
|     ret = OB_INIT_TWICE;
 | |
|     STORAGE_REDO_LOG(WARN, "Init twice.");
 | |
|   } else if (NULL == data_dir || NULL == redo_log) {
 | |
|     ret = OB_INVALID_ARGUMENT;
 | |
|     STORAGE_REDO_LOG(WARN, "Invalid arguments, ", "data_dir", data_dir, "redo_log", redo_log);
 | |
|   } else if (OB_FAIL(redo_log->register_redo_module(OB_REDO_LOG_PARTITION, this))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to register redo log, ", "ret", ret);
 | |
|   } else if (OB_FAIL(buckets_lock_.init(BUCKET_NUM))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to init buckets lock, ", K(ret));
 | |
|   } else if (NULL == (tmp = allocator_.alloc(sizeof(SimpleObPartitionNode*) * BUCKET_NUM))) {
 | |
|     ret = OB_ALLOCATE_MEMORY_FAILED;
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to allocate memory, ", K(ret));
 | |
|   } else if (OB_FAIL(pt_allocator_.init(1024 * 1024 * 1024, 16 * 1024 * 1024, 64 * 1024))) {
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to init pt allocator, ", K(ret));
 | |
|   } else {
 | |
|     buckets_ = new (tmp) SimpleObPartitionNode*[BUCKET_NUM];
 | |
|     MEMSET(buckets_, 0, sizeof(SimpleObPartitionNode*) * BUCKET_NUM);
 | |
|     snprintf(data_file_, OB_MAX_FILE_NAME_LENGTH, "%s/data", data_dir);
 | |
|     redo_log_ = redo_log;
 | |
|     inited_ = true;
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::read_check_point()
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   bool exist = false;
 | |
|   if (OB_SUCCESS == FileDirectoryUtils::is_exists(data_file_, exist) && exist) {
 | |
|     ObString str;
 | |
|     ModuleArena allocator;
 | |
|     SimpleObPartition partition;
 | |
|     int64_t pos = 0;
 | |
| 
 | |
|     if (OB_SUCCESS != (ret = load_file_to_string(data_file_, allocator, str))) {
 | |
|       STORAGE_REDO_LOG(WARN, "Fail to load file to string, ", "ret", ret);
 | |
|     } else {
 | |
|       while (OB_SUCCESS == ret && pos < str.length()) {
 | |
|         if (OB_SUCCESS != (ret = partition.deserialize(str.ptr(), str.length(), pos))) {
 | |
|           STORAGE_REDO_LOG(WARN, "Fail to deserialize partition, ", "ret", ret);
 | |
|         } else if (OB_SUCCESS != (ret = do_add_partition(partition))) {
 | |
|           STORAGE_REDO_LOG(WARN, "Fail to add partition, ", "ret", ret);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::do_check_point()
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   ObFileAppender data_file;
 | |
|   int64_t pos = 0;
 | |
|   const int64_t len = 1024 * 16;
 | |
|   char buf[len];
 | |
| 
 | |
|   if (OB_SUCCESS != (ret = data_file.open(ObString(0, (int32_t)strlen(data_file_), data_file_), false, true, true))) {
 | |
|     ret = OB_IO_ERROR;
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to open checkpoint file, ", "ret", ret);
 | |
|   } else {
 | |
|     for (int64_t i = 0; OB_SUCC(ret) && i < BUCKET_NUM; ++i) {
 | |
|       common::ObBucketWLockGuard guard(buckets_lock_, i);
 | |
|       SimpleObPartitionNode* iter = NULL;
 | |
|       for (iter = buckets_[i]; OB_SUCC(ret) && iter != NULL; iter = iter->next_) {
 | |
|         pos = 0;
 | |
|         if (OB_SUCCESS != (ret = iter->partition_.serialize(buf, len, pos))) {
 | |
|           STORAGE_REDO_LOG(WARN, "Fail to serialize, ", "ret", ret);
 | |
|         } else if (OB_SUCCESS != (ret = data_file.append(buf, pos, true))) {
 | |
|           STORAGE_REDO_LOG(WARN, "Fail to append to data file, ", "ret", ret);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     data_file.close();
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::replay(const ObRedoModuleReplayParam& param)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   const int64_t log_seq_num = param.log_seq_num_;
 | |
|   const int64_t subcmd = param.subcmd_;
 | |
|   const char* buf = param.buf_;
 | |
|   const int64_t len = param.buf_len_;
 | |
|   enum ObRedoLogMainType main_type;
 | |
|   int32_t sub_type = 0;
 | |
|   ObIRedoModule::parse_subcmd(param.subcmd_, main_type, sub_type);
 | |
|   UNUSED(log_seq_num);
 | |
| 
 | |
|   if (OB_REDO_LOG_PARTITION != main_type) {
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|   } else {
 | |
|     switch (static_cast<enum SimpleObPartitionOperation>(sub_type)) {
 | |
|       case ADD_PARTITION: {
 | |
|         SimpleObPartition partition;
 | |
|         int64_t pos = 0;
 | |
|         if (OB_SUCCESS != (ret = partition.deserialize(buf, len, pos))) {
 | |
|           STORAGE_REDO_LOG(WARN, "Fail to deserialize partition, ", "ret", ret);
 | |
|         } else if (!exist_partition(partition.table_id_, partition.partition_id_)) {
 | |
|           partition.log_seq_num_ = log_seq_num;
 | |
|           if (OB_SUCCESS != (ret = do_add_partition(partition))) {
 | |
|             STORAGE_REDO_LOG(WARN, "Fail to do add partition, ", "ret", ret);
 | |
|           }
 | |
|         } else {
 | |
|           STORAGE_REDO_LOG(DEBUG,
 | |
|               "Recovery add partition: ",
 | |
|               "table_id",
 | |
|               partition.table_id_,
 | |
|               "partition_id",
 | |
|               partition.partition_id_);
 | |
|         }
 | |
|         break;
 | |
|       }
 | |
|       case REMOVE_PARTITION: {
 | |
|         int64_t pos = 0;
 | |
|         int64_t table_id = 0;
 | |
|         int64_t partition_id = 0;
 | |
|         int64_t plog_seq_num = 0;
 | |
|         if (OB_SUCCESS != (ret = serialization::decode_vi64(buf, len, pos, &table_id))) {
 | |
|           STORAGE_REDO_LOG(WARN, "Fail to decode table_id, ", "ret", ret);
 | |
|         } else if (OB_SUCCESS != (ret = serialization::decode_vi64(buf, len, pos, &partition_id))) {
 | |
|           STORAGE_REDO_LOG(WARN, "Fail to decode partition_id, ", "ret", ret);
 | |
|         } else if (exist_partition(table_id, partition_id, &plog_seq_num)) {
 | |
|           if (log_seq_num > plog_seq_num) {
 | |
|             do_remove_partition(table_id, partition_id);
 | |
|           }
 | |
|         } else {
 | |
|           STORAGE_REDO_LOG(DEBUG, "recovery remove partition: ", "table_id", table_id, "partition_id", partition_id);
 | |
|         }
 | |
| 
 | |
|         break;
 | |
|       }
 | |
|       default: {
 | |
|         ret = OB_ERR_UNEXPECTED;
 | |
|         STORAGE_REDO_LOG(WARN, "Can not recognize the subcmd.");
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::parse(const int64_t subcmd, const char* buf, const int64_t len, FILE* stream)
 | |
| {
 | |
|   int ret = OB_NOT_SUPPORTED;
 | |
|   UNUSED(subcmd);
 | |
|   UNUSED(buf);
 | |
|   UNUSED(len);
 | |
|   UNUSED(stream);
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::add_partition(SimpleObPartition& partition)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   int64_t subcmd = ObIRedoModule::gen_subcmd(OB_REDO_LOG_PARTITION, ADD_PARTITION);
 | |
|   int64_t log_seq_num = 0;
 | |
| 
 | |
|   if (!inited_) {
 | |
|     ret = OB_NOT_INIT;
 | |
|     STORAGE_REDO_LOG(WARN, "Not init.");
 | |
|   } else {
 | |
|     int64_t pos = hash(partition.table_id_, partition.partition_id_) % BUCKET_NUM;
 | |
|     const ObStorageLogAttribute log_attr(OB_SYS_TENANT_ID, OB_VIRTUAL_DATA_FILE_ID);
 | |
|     common::ObBucketWLockGuard guard(buckets_lock_, pos);
 | |
| 
 | |
|     if (!exist_partition(partition.table_id_, partition.partition_id_)) {
 | |
|       if (OB_SUCCESS != (ret = redo_log_->begin(OB_LOG_CS_CREATE_PARTITION))) {
 | |
|         STORAGE_REDO_LOG(WARN, "Fail to start transaction, ", "ret", ret);
 | |
|       } else if (OB_SUCCESS != (ret = redo_log_->write_log(subcmd, log_attr, partition))) {
 | |
|         STORAGE_REDO_LOG(WARN, "Fail to write log, ", "ret", ret);
 | |
|       } else if (OB_SUCCESS != (ret = redo_log_->commit(log_seq_num))) {
 | |
|         STORAGE_REDO_LOG(WARN, "Fail to commit, ", "ret", ret);
 | |
|       } else {
 | |
|         partition.log_seq_num_ = log_seq_num;
 | |
|         if (OB_SUCCESS != (ret = do_add_partition(partition))) {
 | |
|           STORAGE_REDO_LOG(ERROR, "Fail to add partition, ", "ret", ret);
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       if (OB_FAIL(ret)) {
 | |
|         redo_log_->abort();
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::add_partition_no_commit(SimpleObPartition& partition)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   int64_t subcmd = ObIRedoModule::gen_subcmd(OB_REDO_LOG_PARTITION, ADD_PARTITION);
 | |
|   if (!inited_) {
 | |
|     ret = OB_NOT_INIT;
 | |
|     STORAGE_REDO_LOG(WARN, "Not init.");
 | |
|   } else {
 | |
|     const ObStorageLogAttribute log_attr(OB_SYS_TENANT_ID, OB_VIRTUAL_DATA_FILE_ID);
 | |
|     if (OB_SUCCESS != (ret = redo_log_->write_log(subcmd, log_attr, partition))) {
 | |
|       STORAGE_REDO_LOG(WARN, "Fail to write log, ", "ret", ret);
 | |
|     } else {
 | |
|       if (OB_SUCCESS != (ret = do_add_partition(partition))) {
 | |
|         STORAGE_REDO_LOG(WARN, "Fail to add partition, ", "ret", ret);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::remove_partition(const int64_t table_id, const int64_t partition_id)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   int64_t subcmd = ObIRedoModule::gen_subcmd(OB_REDO_LOG_PARTITION, REMOVE_PARTITION);
 | |
| 
 | |
|   int64_t log_seq_num = 0;
 | |
| 
 | |
|   if (!inited_) {
 | |
|     ret = OB_NOT_INIT;
 | |
|     STORAGE_REDO_LOG(WARN, "Not init.");
 | |
|   } else {
 | |
|     SimpleObPartition partition;
 | |
|     SimpleObPartition::build(table_id, partition_id, 1, partition);
 | |
|     const ObStorageLogAttribute log_attr(OB_SYS_TENANT_ID, OB_VIRTUAL_DATA_FILE_ID);
 | |
|     if (OB_SUCCESS != (ret = redo_log_->begin(OB_LOG_CS_DEL_PARTITION))) {
 | |
|       STORAGE_REDO_LOG(WARN, "Fail to start transaction, ", "ret", ret);
 | |
|     } else if (OB_SUCCESS != (ret = redo_log_->write_log(subcmd, log_attr, partition))) {
 | |
|       STORAGE_REDO_LOG(WARN, "Fail to write log, ", "ret", ret);
 | |
|     } else {
 | |
|       int64_t pos = hash(table_id, partition_id) % BUCKET_NUM;
 | |
|       common::ObBucketWLockGuard guard(buckets_lock_, pos);
 | |
| 
 | |
|       if (!exist_partition(table_id, partition_id)) {
 | |
|         ret = OB_ENTRY_NOT_EXIST;
 | |
|       } else if (OB_SUCCESS != (ret = redo_log_->commit(log_seq_num))) {
 | |
|         STORAGE_REDO_LOG(WARN, "Fail to commit trans, ", "ret", ret);
 | |
|       } else {
 | |
|         do_remove_partition(table_id, partition_id);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (OB_FAIL(ret)) {
 | |
|       redo_log_->abort();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| bool SimpleObPartitionImage::exist_partition(const int64_t table_id, const int64_t partition_id, int64_t* log_seq_num)
 | |
| {
 | |
|   bool bret = false;
 | |
|   int64_t pos = hash(table_id, partition_id) % BUCKET_NUM;
 | |
|   SimpleObPartitionNode* iter = NULL;
 | |
| 
 | |
|   for (iter = buckets_[pos]; iter != NULL; iter = iter->next_) {
 | |
|     if (iter->partition_.table_id_ == table_id && iter->partition_.partition_id_ == partition_id) {
 | |
|       bret = true;
 | |
|       if (NULL != log_seq_num) {
 | |
|         *log_seq_num = iter->partition_.log_seq_num_;
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return bret;
 | |
| }
 | |
| 
 | |
| bool SimpleObPartitionImage::operator==(SimpleObPartitionImage& image)
 | |
| {
 | |
|   bool bret = true;
 | |
|   int64_t i = 0;
 | |
|   SimpleObPartitionNode* iter1 = NULL;
 | |
|   SimpleObPartitionNode* iter2 = NULL;
 | |
| 
 | |
|   for (i = 0; bret && i < BUCKET_NUM; ++i) {
 | |
|     for (iter1 = buckets_[i], iter2 = image.buckets_[i]; bret && iter1 != NULL && iter2 != NULL;
 | |
|          iter1 = iter1->next_, iter2 = iter2->next_) {
 | |
|       if ((iter1->partition_) != (iter2->partition_)) {
 | |
|         bret = false;
 | |
|         STORAGE_LOG(ERROR,
 | |
|             "iter different, ",
 | |
|             K(iter1->partition_.partition_id_),
 | |
|             K(iter2->partition_.partition_id_),
 | |
|             K(iter1->partition_.macro_block_cnt_),
 | |
|             K(iter2->partition_.macro_block_cnt_));
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (iter1 != NULL || iter2 != NULL) {
 | |
|       bret = false;
 | |
|     }
 | |
|     OB_ASSERT(bret);
 | |
|   }
 | |
| 
 | |
|   return bret;
 | |
| }
 | |
| 
 | |
| bool SimpleObPartitionImage::operator!=(SimpleObPartitionImage& image)
 | |
| {
 | |
|   return !(*this == image);
 | |
| }
 | |
| 
 | |
| int64_t SimpleObPartitionImage::hash(const int64_t table_id, const int64_t partition_id)
 | |
| {
 | |
|   return table_id + (partition_id << 16);
 | |
| }
 | |
| 
 | |
| int SimpleObPartitionImage::do_add_partition(const SimpleObPartition& partition)
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   int64_t pos = hash(partition.table_id_, partition.partition_id_) % BUCKET_NUM;
 | |
|   SimpleObPartitionNode* iter = NULL;
 | |
|   SimpleObPartitionNode* node = NULL;
 | |
|   void* tmp = NULL;
 | |
| 
 | |
|   for (iter = buckets_[pos]; iter != NULL; iter = iter->next_) {
 | |
|     if (iter->partition_.table_id_ == partition.table_id_ &&
 | |
|         iter->partition_.partition_id_ == partition.partition_id_) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (iter != NULL) {
 | |
|     ret = OB_ENTRY_EXIST;
 | |
|   } else if (NULL == (tmp = pt_allocator_.alloc(sizeof(SimpleObPartitionNode)))) {
 | |
|     ret = OB_ALLOCATE_MEMORY_FAILED;
 | |
|     STORAGE_REDO_LOG(WARN, "Fail to allocate memory, ", K(ret));
 | |
|   } else {
 | |
|     node = new (tmp) SimpleObPartitionNode();
 | |
|     node->partition_ = partition;
 | |
|     node->next_ = NULL;
 | |
|     for (iter = buckets_[pos]; iter != NULL && iter->next_ != NULL; iter = iter->next_) {}
 | |
|     if (NULL == iter) {
 | |
|       buckets_[pos] = node;
 | |
|     } else {
 | |
|       iter->next_ = node;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| void SimpleObPartitionImage::do_remove_partition(const int64_t table_id, const int64_t partition_id)
 | |
| {
 | |
|   int64_t pos = hash(table_id, partition_id) % BUCKET_NUM;
 | |
|   SimpleObPartitionNode* iter = NULL;
 | |
|   SimpleObPartitionNode* prev = NULL;
 | |
| 
 | |
|   for (iter = buckets_[pos]; iter != NULL; iter = iter->next_) {
 | |
|     if (iter->partition_.table_id_ == table_id && iter->partition_.partition_id_ == partition_id) {
 | |
|       break;
 | |
|     } else {
 | |
|       prev = iter;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (iter != NULL) {
 | |
|     if (NULL == prev) {
 | |
|       buckets_[pos] = iter->next_;
 | |
|     } else {
 | |
|       prev->next_ = iter->next_;
 | |
|     }
 | |
|     pt_allocator_.free(iter);
 | |
|   }
 | |
| }
 | |
| 
 | |
| }  // namespace blocksstable
 | |
| }  // end namespace oceanbase
 | |
| 
 | |
| #endif  // OCEANBASE_SLOG_SIMPLE_OB_PARTITION_IMAGE_H_
 | 
