提交 83539326 编写于 作者: Z ZhaoMing 提交者: 奏之章

Fix IntTblPropCollectorFactory ttl options bug

上级 bad886ba
......@@ -104,26 +104,6 @@ const Comparator* ColumnFamilyHandleImpl::GetComparator() const {
return cfd()->user_comparator();
}
void GetIntTblPropCollectorFactory(
const ImmutableCFOptions& ioptions, const MutableCFOptions& moptions,
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>*
int_tbl_prop_collector_factories,
bool with_ttl_extractor) {
auto& collector_factories = ioptions.table_properties_collector_factories;
for (size_t i = 0; i < ioptions.table_properties_collector_factories.size();
++i) {
assert(collector_factories[i]);
int_tbl_prop_collector_factories->emplace_back(
new UserKeyTablePropertiesCollectorFactory(collector_factories[i]));
}
if (with_ttl_extractor && ioptions.ttl_extractor_factory != nullptr) {
int_tbl_prop_collector_factories->emplace_back(
NewTtlIntTblPropCollectorFactory(ioptions.ttl_extractor_factory,
ioptions.env, moptions.ttl_gc_ratio,
moptions.ttl_max_scan_gap));
}
}
Status CheckCompressionSupported(const ColumnFamilyOptions& cf_options) {
if (!cf_options.compression_per_level.empty()) {
for (size_t level = 0; level < cf_options.compression_per_level.size();
......@@ -447,7 +427,7 @@ ColumnFamilyData::ColumnFamilyData(
internal_comparator_(cf_options.comparator),
initial_cf_options_(SanitizeOptions(db_options, cf_options)),
ioptions_(db_options, initial_cf_options_),
mutable_cf_options_(initial_cf_options_),
mutable_cf_options_(initial_cf_options_, db_options.env),
is_delete_range_supported_(
cf_options.table_factory->IsDeleteRangeSupported()),
write_buffer_manager_(write_buffer_manager),
......@@ -470,16 +450,6 @@ ColumnFamilyData::ColumnFamilyData(
last_memtable_id_(0) {
Ref();
// Convert user defined table properties collector factories to internal ones.
GetIntTblPropCollectorFactory(ioptions_, mutable_cf_options_,
&int_tbl_prop_collector_factories_,
true /* with_ttl_extractor */);
if (ioptions_.ttl_extractor_factory != nullptr) {
GetIntTblPropCollectorFactory(ioptions_, mutable_cf_options_,
&int_tbl_prop_collector_factories_for_blob_,
false /* with_ttl_extractor */);
}
// if _dummy_versions is nullptr, then this is a dummy column family.
if (_dummy_versions != nullptr) {
internal_stats_.reset(
......
......@@ -147,14 +147,6 @@ extern Status CheckCFPathsSupported(const DBOptions& db_options,
extern ColumnFamilyOptions SanitizeOptions(const ImmutableDBOptions& db_options,
const ColumnFamilyOptions& src);
// Wrap user defined table proproties collector factories `from cf_options`
// into internal ones in int_tbl_prop_collector_factories. Add a system internal
// one too.
extern void GetIntTblPropCollectorFactory(
const ImmutableCFOptions& ioptions, const MutableCFOptions& moptions,
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>*
int_tbl_prop_collector_factories,
bool with_ttl_extractor);
class ColumnFamilySet;
......@@ -328,14 +320,15 @@ class ColumnFamilyData {
}
const std::vector<std::unique_ptr<IntTblPropCollectorFactory>>*
int_tbl_prop_collector_factories() const {
return &int_tbl_prop_collector_factories_;
int_tbl_prop_collector_factories(const MutableCFOptions& moptions) const {
return moptions.int_tbl_prop_collector_factories.get();
}
const std::vector<std::unique_ptr<IntTblPropCollectorFactory>>*
int_tbl_prop_collector_factories_for_blob() const {
return int_tbl_prop_collector_factories_for_blob_.empty()
? &int_tbl_prop_collector_factories_
: &int_tbl_prop_collector_factories_for_blob_;
int_tbl_prop_collector_factories_for_blob(
const MutableCFOptions& moptions) const {
return ioptions_.int_tbl_prop_collector_factories_for_blob == nullptr
? moptions.int_tbl_prop_collector_factories.get()
: ioptions_.int_tbl_prop_collector_factories_for_blob.get();
}
SuperVersion* GetSuperVersion() { return super_version_; }
......@@ -439,11 +432,6 @@ class ColumnFamilyData {
std::atomic<bool> dropped_; // true if client dropped it
const InternalKeyComparator internal_comparator_;
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
int_tbl_prop_collector_factories_;
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
int_tbl_prop_collector_factories_for_blob_;
const ColumnFamilyOptions initial_cf_options_;
const ImmutableCFOptions ioptions_;
MutableCFOptions mutable_cf_options_;
......
......@@ -793,7 +793,8 @@ Status CompactionJob::Run() {
context.compaction_filter_context.column_family_id;
collector_context.smallest_user_key = context.smallest_user_key;
collector_context.largest_user_key = context.largest_user_key;
for (auto& collector : *cfd->int_tbl_prop_collector_factories()) {
for (auto& collector :
*cfd->int_tbl_prop_collector_factories(*c->mutable_cf_options())) {
std::string param;
if (collector->NeedSerialize()) {
collector->Serialize(&param, collector_context);
......@@ -1026,10 +1027,8 @@ Status CompactionJob::VerifyFiles() {
// Verify that the table is usable
// We set for_compaction to false and don't OptimizeForCompactionTableRead
// here because this is a special case after we finish the table building
// No matter whether use_direct_io_for_flush_and_compaction is true,
// we
// will regard this verification as user reads since the goal is
// to cache
// No matter whether use_direct_io_for_flush_and_compaction is true, we
// will regard this verification as user reads since the goal is to cache
// it here for further user reads
auto output_level = compact_->compaction->output_level();
InternalIterator* iter = cfd->table_cache()->NewIterator(
......@@ -2619,10 +2618,12 @@ Status CompactionJob::OpenCompactionOutputFile(
}
auto c = sub_compact->compaction;
auto& moptions = *c->mutable_cf_options();
sub_compact->builder.reset(NewTableBuilder(
*cfd->ioptions(), *c->mutable_cf_options(), cfd->internal_comparator(),
cfd->int_tbl_prop_collector_factories(), cfd->GetID(), cfd->GetName(),
sub_compact->outfile.get(), sub_compact->compaction->output_compression(),
*cfd->ioptions(), moptions, cfd->internal_comparator(),
cfd->int_tbl_prop_collector_factories(moptions), cfd->GetID(),
cfd->GetName(), sub_compact->outfile.get(),
sub_compact->compaction->output_compression(),
sub_compact->compaction->output_compression_opts(),
sub_compact->compaction->output_level(), c->compaction_load(),
&sub_compact->compression_dict, skip_filters, output_file_creation_time,
......@@ -2706,10 +2707,11 @@ Status CompactionJob::OpenCompactionOutputBlob(
}
auto c = sub_compact->compaction;
auto& moptions = *c->mutable_cf_options();
// skip_filters always false, Blob all hits
sub_compact->blob_builder.reset(NewTableBuilder(
*cfd->ioptions(), *c->mutable_cf_options(), cfd->internal_comparator(),
cfd->int_tbl_prop_collector_factories_for_blob(), cfd->GetID(),
*cfd->ioptions(), moptions, cfd->internal_comparator(),
cfd->int_tbl_prop_collector_factories_for_blob(moptions), cfd->GetID(),
cfd->GetName(), sub_compact->blob_outfile.get(),
sub_compact->compaction->output_compression(),
sub_compact->compaction->output_compression_opts(), -1 /* level */,
......
......@@ -2147,8 +2147,8 @@ Status DBImpl::CreateColumnFamilyImpl(const ColumnFamilyOptions& cf_options,
write_thread_.EnterUnbatched(&w, &mutex_);
// LogAndApply will both write the creation in MANIFEST and create
// ColumnFamilyData object
s = versions_->LogAndApply(nullptr, MutableCFOptions(cf_options), &edit,
&mutex_, directories_.GetDbDir(), false,
s = versions_->LogAndApply(nullptr, MutableCFOptions(cf_options, env_),
&edit, &mutex_, directories_.GetDbDir(), false,
&cf_options);
write_thread_.ExitUnbatched(&w);
}
......
......@@ -1694,10 +1694,6 @@ class DBImpl : public DB {
// Only to be set during initialization
std::unique_ptr<PreReleaseCallback> recoverable_state_pre_release_callback_;
// handle for scheduling jobs at fixed intervals
// REQUIRES: mutex locked
std::unique_ptr<TERARKDB_NAMESPACE::RepeatableThread> thread_dump_stats_;
// No copying allowed
DBImpl(const DBImpl&);
void operator=(const DBImpl&);
......
......@@ -1171,10 +1171,10 @@ Status DBImpl::WriteLevel0TableForRecovery(int job_id, ColumnFamilyData* cfd,
c_style_callback(get_arena_input_iter), &get_arena_input_iter,
c_style_callback(get_range_del_iters), &get_range_del_iters,
&meta_vec, cfd->internal_comparator(),
cfd->int_tbl_prop_collector_factories(),
cfd->int_tbl_prop_collector_factories_for_blob(), cfd->GetID(),
cfd->GetName(), snapshot_seqs, earliest_write_conflict_snapshot,
snapshot_checker,
cfd->int_tbl_prop_collector_factories(mutable_cf_options),
cfd->int_tbl_prop_collector_factories_for_blob(mutable_cf_options),
cfd->GetID(), cfd->GetName(), snapshot_seqs,
earliest_write_conflict_snapshot, snapshot_checker,
GetCompressionFlush(*cfd->ioptions(), mutable_cf_options),
cfd->ioptions()->compression_opts, paranoid_file_checks,
cfd->internal_stats(), TableFileCreationReason::kRecovery,
......
......@@ -376,9 +376,10 @@ Status FlushJob::WriteLevel0Table() {
mutable_cf_options_, env_options_, cfd_->table_cache(),
c_style_callback(get_arena_input_iter), &get_arena_input_iter,
c_style_callback(get_range_del_iters), &get_range_del_iters, &meta_,
cfd_->internal_comparator(), cfd_->int_tbl_prop_collector_factories(),
cfd_->int_tbl_prop_collector_factories_for_blob(), cfd_->GetID(),
cfd_->GetName(), existing_snapshots_,
cfd_->internal_comparator(),
cfd_->int_tbl_prop_collector_factories(mutable_cf_options_),
cfd_->int_tbl_prop_collector_factories_for_blob(mutable_cf_options_),
cfd_->GetID(), cfd_->GetName(), existing_snapshots_,
earliest_write_conflict_snapshot_, snapshot_checker_,
output_compression_, cfd_->ioptions()->compression_opts,
mutable_cf_options_.paranoid_file_checks, cfd_->internal_stats(),
......
......@@ -434,15 +434,16 @@ class Repairer {
}
return range_del_iters;
};
auto& moptions = *cfd->GetLatestMutableCFOptions();
status = BuildTable(
dbname_, &vset_, env_, *cfd->ioptions(),
*cfd->GetLatestMutableCFOptions(), env_options_, table_cache_,
c_style_callback(get_arena_input_iter), &get_arena_input_iter,
c_style_callback(get_range_del_iters), &get_range_del_iters, &meta,
cfd->internal_comparator(), cfd->int_tbl_prop_collector_factories(),
cfd->int_tbl_prop_collector_factories_for_blob(), cfd->GetID(),
cfd->GetName(), {}, kMaxSequenceNumber, snapshot_checker,
kNoCompression, CompressionOptions(), false,
dbname_, &vset_, env_, *cfd->ioptions(), moptions, env_options_,
table_cache_, c_style_callback(get_arena_input_iter),
&get_arena_input_iter, c_style_callback(get_range_del_iters),
&get_range_del_iters, &meta, cfd->internal_comparator(),
cfd->int_tbl_prop_collector_factories(moptions),
cfd->int_tbl_prop_collector_factories_for_blob(moptions),
cfd->GetID(), cfd->GetName(), {}, kMaxSequenceNumber,
snapshot_checker, kNoCompression, CompressionOptions(), false,
nullptr /* internal_stats */, TableFileCreationReason::kRecovery,
nullptr /* event_logger */, 0 /* job_id */, Env::IO_HIGH,
nullptr /* table_properties */, -1 /* level */, current_time,
......
......@@ -154,7 +154,7 @@ class UserKeyTablePropertiesCollectorFactory
};
extern IntTblPropCollectorFactory* NewTtlIntTblPropCollectorFactory(
TtlExtractorFactory* ttl_extractor_factory, Env* env, double ttl_gc_ratio,
size_t ttl_max_scan_cap);
const TtlExtractorFactory* ttl_extractor_factory, Env* env,
double ttl_gc_ratio, size_t ttl_max_scan_cap);
} // namespace TERARKDB_NAMESPACE
......@@ -255,18 +255,21 @@ void TestCustomizedTablePropertiesCollector(
std::unique_ptr<WritableFileWriter> writer;
const ImmutableCFOptions ioptions(options);
const MutableCFOptions moptions(options);
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>*
int_tbl_prop_collector_factories;
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
int_tbl_prop_collector_factories_storage;
if (test_int_tbl_prop_collector) {
int_tbl_prop_collector_factories.emplace_back(
int_tbl_prop_collector_factories =
&int_tbl_prop_collector_factories_storage;
int_tbl_prop_collector_factories->emplace_back(
new RegularKeysStartWithAFactory(backward_mode));
} else {
GetIntTblPropCollectorFactory(ioptions, moptions,
&int_tbl_prop_collector_factories,
false /* with_ttl_extractor */);
int_tbl_prop_collector_factories =
moptions.int_tbl_prop_collector_factories.get();
}
MakeBuilder(options, ioptions, moptions, internal_comparator,
&int_tbl_prop_collector_factories, &writer, &builder);
int_tbl_prop_collector_factories, &writer, &builder);
SequenceNumber seqNum = 0U;
for (const auto& kv : kvs) {
......@@ -385,7 +388,7 @@ void TestInternalKeyPropertiesCollector(
Options options;
test::PlainInternalKeyComparator pikc(options.comparator);
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>*
int_tbl_prop_collector_factories;
options.table_factory = table_factory;
if (sanitized) {
......@@ -401,9 +404,8 @@ void TestInternalKeyPropertiesCollector(
options);
ImmutableCFOptions ioptions(options);
MutableCFOptions moptions(options);
GetIntTblPropCollectorFactory(ioptions, moptions,
&int_tbl_prop_collector_factories,
false /* with_ttl_extractor */);
int_tbl_prop_collector_factories =
moptions.int_tbl_prop_collector_factories.get();
options.comparator = comparator;
}
const ImmutableCFOptions ioptions(options);
......@@ -411,7 +413,7 @@ void TestInternalKeyPropertiesCollector(
for (int iter = 0; iter < 2; ++iter) {
MakeBuilder(options, ioptions, moptions, pikc,
&int_tbl_prop_collector_factories, &writable, &builder);
int_tbl_prop_collector_factories, &writable, &builder);
for (const auto& k : keys) {
ASSERT_OK(builder->Add(k.Encode(), LazyBuffer("val")));
}
......
......@@ -84,7 +84,16 @@ ImmutableCFOptions::ImmutableCFOptions(const ImmutableDBOptions& db_options,
row_cache(db_options.row_cache),
memtable_insert_with_hint_prefix_extractor(
cf_options.memtable_insert_with_hint_prefix_extractor.get()),
cf_paths(cf_options.cf_paths) {}
cf_paths(cf_options.cf_paths) {
if (ttl_extractor_factory != nullptr) {
int_tbl_prop_collector_factories_for_blob = std::make_shared<
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>>();
for (auto& f : table_properties_collector_factories) {
int_tbl_prop_collector_factories_for_blob->emplace_back(
new UserKeyTablePropertiesCollectorFactory(f));
}
}
}
// Multiple two operands. If they overflow, return op1.
uint64_t MultiplyCheckOverflow(uint64_t op1, double op2) {
......@@ -241,7 +250,63 @@ void MutableCFOptions::Dump(Logger* log) const {
compaction_options_fifo.allow_compaction);
}
MutableCFOptions::MutableCFOptions(const ColumnFamilyOptions& options, Env* env)
: write_buffer_size(options.write_buffer_size),
max_write_buffer_number(options.max_write_buffer_number),
arena_block_size(options.arena_block_size),
memtable_factory(options.memtable_factory),
memtable_prefix_bloom_size_ratio(
options.memtable_prefix_bloom_size_ratio),
memtable_huge_page_size(options.memtable_huge_page_size),
max_successive_merges(options.max_successive_merges),
inplace_update_num_locks(options.inplace_update_num_locks),
prefix_extractor(options.prefix_extractor),
disable_auto_compactions(options.disable_auto_compactions),
max_subcompactions(options.max_subcompactions),
blob_size(options.blob_size),
blob_large_key_ratio(options.blob_large_key_ratio),
blob_gc_ratio(options.blob_gc_ratio),
soft_pending_compaction_bytes_limit(
options.soft_pending_compaction_bytes_limit),
hard_pending_compaction_bytes_limit(
options.hard_pending_compaction_bytes_limit),
level0_file_num_compaction_trigger(
options.level0_file_num_compaction_trigger),
level0_slowdown_writes_trigger(options.level0_slowdown_writes_trigger),
level0_stop_writes_trigger(options.level0_stop_writes_trigger),
max_compaction_bytes(options.max_compaction_bytes),
target_file_size_base(options.target_file_size_base),
target_file_size_multiplier(options.target_file_size_multiplier),
max_bytes_for_level_base(options.max_bytes_for_level_base),
max_bytes_for_level_multiplier(options.max_bytes_for_level_multiplier),
ttl(options.ttl),
max_bytes_for_level_multiplier_additional(
options.max_bytes_for_level_multiplier_additional),
compaction_options_fifo(options.compaction_options_fifo),
compaction_options_universal(options.compaction_options_universal),
max_sequential_skip_in_iterations(
options.max_sequential_skip_in_iterations),
paranoid_file_checks(options.paranoid_file_checks),
report_bg_io_stats(options.report_bg_io_stats),
compression(options.compression),
ttl_gc_ratio(options.ttl_gc_ratio),
ttl_max_scan_gap(options.ttl_max_scan_gap) {
RefreshDerivedOptions(options.num_levels);
int_tbl_prop_collector_factories = std::make_shared<
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>>();
for (auto& f : options.table_properties_collector_factories) {
int_tbl_prop_collector_factories->emplace_back(
new UserKeyTablePropertiesCollectorFactory(f));
}
if (options.ttl_extractor_factory != nullptr) {
int_tbl_prop_collector_factories->emplace_back(
NewTtlIntTblPropCollectorFactory(options.ttl_extractor_factory.get(),
env, ttl_gc_ratio, ttl_max_scan_gap));
}
}
MutableCFOptions::MutableCFOptions(const Options& options)
: MutableCFOptions(ColumnFamilyOptions(options)) {}
: MutableCFOptions(ColumnFamilyOptions(options), options.env) {}
} // namespace TERARKDB_NAMESPACE
......@@ -9,6 +9,7 @@
#include <vector>
#include "db/dbformat.h"
#include "db/table_properties_collector.h"
#include "options/db_options.h"
#include "rocksdb/options.h"
#include "rocksdb/terark_namespace.h"
......@@ -131,6 +132,9 @@ struct ImmutableCFOptions {
const SliceTransform* memtable_insert_with_hint_prefix_extractor;
std::vector<DbPath> cf_paths;
std::shared_ptr<std::vector<std::unique_ptr<IntTblPropCollectorFactory>>>
int_tbl_prop_collector_factories_for_blob;
};
struct BlobConfig {
......@@ -139,49 +143,7 @@ struct BlobConfig {
};
struct MutableCFOptions {
explicit MutableCFOptions(const ColumnFamilyOptions& options)
: write_buffer_size(options.write_buffer_size),
max_write_buffer_number(options.max_write_buffer_number),
arena_block_size(options.arena_block_size),
memtable_factory(options.memtable_factory),
memtable_prefix_bloom_size_ratio(
options.memtable_prefix_bloom_size_ratio),
memtable_huge_page_size(options.memtable_huge_page_size),
max_successive_merges(options.max_successive_merges),
inplace_update_num_locks(options.inplace_update_num_locks),
prefix_extractor(options.prefix_extractor),
disable_auto_compactions(options.disable_auto_compactions),
max_subcompactions(options.max_subcompactions),
blob_size(options.blob_size),
blob_large_key_ratio(options.blob_large_key_ratio),
blob_gc_ratio(options.blob_gc_ratio),
soft_pending_compaction_bytes_limit(
options.soft_pending_compaction_bytes_limit),
hard_pending_compaction_bytes_limit(
options.hard_pending_compaction_bytes_limit),
level0_file_num_compaction_trigger(
options.level0_file_num_compaction_trigger),
level0_slowdown_writes_trigger(options.level0_slowdown_writes_trigger),
level0_stop_writes_trigger(options.level0_stop_writes_trigger),
max_compaction_bytes(options.max_compaction_bytes),
target_file_size_base(options.target_file_size_base),
target_file_size_multiplier(options.target_file_size_multiplier),
max_bytes_for_level_base(options.max_bytes_for_level_base),
max_bytes_for_level_multiplier(options.max_bytes_for_level_multiplier),
ttl(options.ttl),
max_bytes_for_level_multiplier_additional(
options.max_bytes_for_level_multiplier_additional),
compaction_options_fifo(options.compaction_options_fifo),
compaction_options_universal(options.compaction_options_universal),
max_sequential_skip_in_iterations(
options.max_sequential_skip_in_iterations),
paranoid_file_checks(options.paranoid_file_checks),
report_bg_io_stats(options.report_bg_io_stats),
compression(options.compression),
ttl_gc_ratio(options.ttl_gc_ratio),
ttl_max_scan_gap(options.ttl_max_scan_gap) {
RefreshDerivedOptions(options.num_levels);
}
explicit MutableCFOptions(const ColumnFamilyOptions& options, Env* env);
MutableCFOptions()
: write_buffer_size(0),
......@@ -283,6 +245,9 @@ struct MutableCFOptions {
double ttl_gc_ratio;
size_t ttl_max_scan_gap;
std::shared_ptr<std::vector<std::unique_ptr<IntTblPropCollectorFactory>>>
int_tbl_prop_collector_factories;
};
uint64_t MultiplyCheckOverflow(uint64_t op1, double op2);
......
......@@ -29,7 +29,7 @@ struct SstFileReader::Rep {
: options(opts),
soptions(options),
ioptions(options),
moptions(ColumnFamilyOptions(options)) {}
moptions(options) {}
};
SstFileReader::SstFileReader(const Options& options) : rep_(new Rep(options)) {}
......
......@@ -59,7 +59,7 @@ SstFileDumper::SstFileDumper(const std::string& file_path, bool verify_checksum,
verify_checksum_(verify_checksum),
output_hex_(output_hex),
ioptions_(options_),
moptions_(ColumnFamilyOptions(options_)),
moptions_(options_),
internal_comparator_(BytewiseComparator()) {
fprintf(stdout, "Process %s\n", file_path.c_str());
init_result_ = GetTableReader(file_name_);
......@@ -215,7 +215,7 @@ int SstFileDumper::ShowAllCompressionSizes(
Options opts;
const ImmutableCFOptions imoptions(opts);
const ColumnFamilyOptions cfo(opts);
const MutableCFOptions moptions(cfo);
const MutableCFOptions moptions(opts);
TERARKDB_NAMESPACE::InternalKeyComparator ikc(opts.comparator);
std::vector<std::unique_ptr<IntTblPropCollectorFactory>>
block_based_table_factories;
......
......@@ -22,6 +22,7 @@
#include "rocksdb/env.h"
#include "rocksdb/terark_namespace.h"
#include "util/logging.h"
#include "util/sync_point.h"
namespace TERARKDB_NAMESPACE {
......
......@@ -12,6 +12,7 @@
#pragma once
#include <string>
#include <vector>
#include "redis_list_exception.h"
#include "redis_list_iterator.h"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册