33 #include <boost/algorithm/string.hpp>
40 using namespace Property;
46 bool desc_inited =
false;
49 compressor_desc(
" bmz|lzo|quicklz|zlib|snappy|none [compressor_options]\n\n"
50 "compressor_options"),
51 bloomfilter_desc(
" rows|rows+cols|none [bloomfilter_options]\n\n"
52 " Default bloom filter is defined by the config property:\n"
53 " Hypertable.RangeServer.CellStore.DefaultBloomFilter.\n\n"
54 "bloomfilter_options");
59 void init_schema_options_desc() {
60 lock_guard<mutex> lock(desc_mutex);
65 compressor_desc.add_options()
66 (
"best,9",
"Highest setting (probably slower) for zlib")
67 (
"normal",
"Normal setting for zlib")
68 (
"fp-len",
i16()->default_value(19),
"Minimum fingerprint length for bmz")
69 (
"offset",
i16()->default_value(0),
"Starting fingerprint offset for bmz")
71 compressor_hidden_desc.add_options()
72 (
"compressor-type",
str(),
73 "Compressor type (bmz|lzo|quicklz|zlib|snappy|none)")
75 compressor_pos_desc.add(
"compressor-type", 1);
77 bloomfilter_desc.add_options()
78 (
"bits-per-item",
f64(),
"Number of bits to use per item "
79 "for the Bloom filter")
80 (
"num-hashes",
i32(),
"Number of hash functions to use "
81 "for the Bloom filter")
82 (
"false-positive",
f64()->default_value(0.01),
"Expected false positive "
83 "probability for the Bloom filter")
84 (
"max-approx-items",
i32()->default_value(1000),
"Number of cell store "
85 "items used to guess the number of actual Bloom filter entries")
87 bloomfilter_hidden_desc.add_options()
88 (
"bloom-filter-mode",
str(),
"Bloom filter mode (rows|rows+cols|none)")
90 bloomfilter_pos_desc.add(
"bloom-filter-mode", 1);
94 void validate_compressor(
const std::string &compressor) {
95 if (compressor.empty())
99 init_schema_options_desc();
101 vector<std::string> args;
102 boost::split(args, compressor, boost::is_any_of(
" \t"));
103 HT_TRY(
"parsing compressor spec",
104 props->parse_args(args, compressor_desc, &compressor_hidden_desc,
105 &compressor_pos_desc));
113 void validate_bloomfilter(
const std::string &bloomfilter) {
114 if (bloomfilter.empty())
118 init_schema_options_desc();
120 vector<std::string> args;
122 boost::split(args, bloomfilter, boost::is_any_of(
" \t"));
123 HT_TRY(
"parsing bloom filter spec",
124 props->parse_args(args, bloomfilter_desc, &bloomfilter_hidden_desc,
125 &bloomfilter_pos_desc));
129 bloomfilter.c_str());
137 m_replication = replication;
138 m_isset.set(REPLICATION);
142 return m_isset.test(REPLICATION);
146 m_blocksize = blocksize;
147 m_isset.set(BLOCKSIZE);
151 return m_isset.test(BLOCKSIZE);
155 validate_compressor(compressor);
156 m_compressor = compressor;
157 m_isset.set(COMPRESSOR);
161 return m_isset.test(COMPRESSOR);
165 validate_bloomfilter(bloomfilter);
166 m_bloomfilter = bloomfilter;
167 m_isset.set(BLOOMFILTER);
171 return m_isset.test(BLOOMFILTER);
176 m_isset.set(IN_MEMORY);
180 return m_isset.test(IN_MEMORY);
198 class XmlParserAccessGroupOptions :
public XmlParser {
201 int len) :
XmlParser(s,len), m_options(ops) {}
203 void end_element(
const XML_Char *name,
const string &content)
override {
204 if (!strcasecmp(name,
"Replication"))
205 m_options->set_replication(content_to_i16(name, content));
206 else if (!strcasecmp(name,
"BlockSize"))
207 m_options->set_blocksize(content_to_i32(name, content));
208 else if (!strcasecmp(name,
"Compressor"))
209 m_options->set_compressor(content);
210 else if (!strcasecmp(name,
"BloomFilter"))
211 m_options->set_bloom_filter(content);
212 else if (!strcasecmp(name,
"InMemory"))
213 m_options->set_in_memory(content_to_bool(name, content));
214 else if (!m_element_stack.empty())
216 "Unrecognized AccessGroup option element (%s)", name);
225 XmlParserAccessGroupOptions parser(
this, s, len);
231 if (is_set_replication())
232 xstr +=
format(
"%s<Replication>%d</Replication>\n",
233 line_prefix.c_str(), m_replication);
234 if (is_set_blocksize())
235 xstr +=
format(
"%s<BlockSize>%d</BlockSize>\n",
236 line_prefix.c_str(), m_blocksize);
237 if (is_set_compressor())
238 xstr +=
format(
"%s<Compressor>%s</Compressor>\n",
239 line_prefix.c_str(), m_compressor.c_str());
240 if (is_set_bloom_filter())
241 xstr +=
format(
"%s<BloomFilter>%s</BloomFilter>\n",
242 line_prefix.c_str(), m_bloomfilter.c_str());
243 if (is_set_in_memory())
244 xstr +=
format(
"%s<InMemory>%s</InMemory>\n",
245 line_prefix.c_str(), m_in_memory ?
"true" :
"false");
251 if (is_set_replication())
252 hstr +=
format(
" REPLICATION %d", m_replication);
253 if (is_set_blocksize())
254 hstr +=
format(
" BLOCKSIZE %d", m_blocksize);
255 if (is_set_compressor())
256 hstr +=
format(
" COMPRESSOR \"%s\"", m_compressor.c_str());
257 if (is_set_bloom_filter())
258 hstr +=
format(
" BLOOMFILTER \"%s\"", m_bloomfilter.c_str());
259 if (is_set_in_memory())
260 hstr +=
format(
" IN_MEMORY %s", m_in_memory ?
"true" :
"false");
265 return (m_isset == other.
m_isset &&
276 init_schema_options_desc();
278 vector<std::string> args;
280 HT_TRY(
"parsing bloom filter spec",
281 props->parse_args(args, bloomfilter_desc, &bloomfilter_hidden_desc,
282 &bloomfilter_pos_desc));
284 std::string mode = props->get_str(
"bloom-filter-mode");
286 if (mode ==
"none" || mode ==
"disabled")
288 else if (mode ==
"rows" || mode ==
"row")
290 else if (mode ==
"rows+cols" || mode ==
"row+col"
291 || mode ==
"rows-cols" || mode ==
"row-col"
292 || mode ==
"rows_cols" || mode ==
"row_col")
300 for (
auto cf_spec : m_columns)
311 for (
auto cf : m_columns) {
312 auto orig_cf = original.
get_column(cf->get_name());
313 if (orig_cf ==
nullptr) {
317 else if (*cf != *orig_cf) {
318 if (cf->get_option_time_order_desc() != orig_cf->get_option_time_order_desc())
320 "Modificaton of TIME ORDER option for column '%s' is not allowed.",
321 cf->get_name().c_str());
322 if (cf->get_option_counter() != orig_cf->get_option_counter())
324 "Modificaton of COUNTER option for column '%s' is not allowed.",
325 cf->get_name().c_str());
332 for (
auto cf : original.
columns()) {
333 if (get_column(cf->get_name()) ==
nullptr) {
342 "of access group '%s' is not allowed.", m_name.c_str());
355 if (!m_options.is_set_replication() ||
356 m_options.get_replication() != replication)
358 m_options.set_replication(replication);
362 return m_options.get_replication();
366 if (!m_options.is_set_blocksize() ||
367 m_options.get_blocksize() != blocksize)
369 m_options.set_blocksize(blocksize);
373 return m_options.get_blocksize();
377 if (!m_options.is_set_compressor() ||
378 m_options.get_compressor() != compressor)
380 m_options.set_compressor(compressor);
384 return m_options.get_compressor();
388 if (!m_options.is_set_bloom_filter() ||
389 m_options.get_bloom_filter() != bloomfilter)
391 m_options.set_bloom_filter(bloomfilter);
395 return m_options.get_bloom_filter();
399 if (!m_options.is_set_in_memory() ||
400 m_options.get_in_memory() != value)
402 m_options.set_in_memory(value);
406 return m_options.get_in_memory();
410 if (!m_defaults.is_set_max_versions() ||
411 m_defaults.get_max_versions() != max_versions)
413 m_defaults.set_max_versions(max_versions);
417 return m_defaults.get_max_versions();
421 if (!m_defaults.is_set_ttl() || m_defaults.get_ttl() != ttl)
423 m_defaults.set_ttl(ttl);
427 return m_defaults.get_ttl();
431 if (!m_defaults.is_set_time_order_desc() ||
432 m_defaults.get_time_order_desc() != value)
434 m_defaults.set_time_order_desc(value);
438 return m_defaults.get_time_order_desc();
442 if (!m_defaults.is_set_counter() || m_defaults.get_counter() != value)
444 m_defaults.set_counter(value);
448 return m_defaults.get_counter();
456 m_columns.push_back(cf);
463 for (
auto cf : m_columns) {
464 if (cf->get_name() == new_cf->
get_name()) {
466 new_columns.push_back(new_cf);
469 new_columns.push_back(cf);
472 m_columns.swap(new_columns);
479 for (
auto cf : m_columns) {
480 if (cf->get_name() == name)
483 new_columns.push_back(cf);
485 m_columns.swap(new_columns);
490 for (
auto cf : m_columns) {
491 if (cf->get_name() == name) {
492 cf->set_generation(0);
493 cf->set_deleted(
true);
494 cf->set_name(
format(
"!%d", cf->get_id()));
501 for (
auto cf : m_columns)
502 if (cf->get_name() == name)
508 return (m_name == other.
m_name &&
511 m_columns.size() == other.
m_columns.size());
517 class XmlParserAccessGroupSpec :
public XmlParser {
519 XmlParserAccessGroupSpec(
AccessGroupSpec *spec,
const char *s,
int len) :
520 XmlParser(s,len,{
"Options",
"ColumnFamilyDefaults",
"ColumnFamily"}),
523 void start_element(
const XML_Char *name,
const XML_Char **atts)
override {
524 if (m_element_stack.empty()) {
525 for (
int i=0; atts[i] != 0; i+=2) {
526 if (!strcasecmp(atts[i],
"name"))
527 m_spec->set_name(atts[i+1]);
529 else if (!strcasecmp(atts[i],
"inMemory"))
530 m_spec->set_option_in_memory(content_to_bool(atts[i], atts[i+1]));
531 else if (!strcasecmp(atts[i],
"counter"))
532 m_spec->set_default_counter(content_to_bool(atts[i], atts[i+1]));
533 else if (!strcasecmp(atts[i],
"replication"))
534 m_spec->set_option_replication(content_to_i16(atts[i], atts[i+1]));
535 else if (!strcasecmp(atts[i],
"blksz"))
536 m_spec->set_option_blocksize(content_to_i32(atts[i], atts[i+1]));
537 else if (!strcasecmp(atts[i],
"compressor"))
538 m_spec->set_option_compressor(atts[i+1]);
539 else if (!strcasecmp(atts[i],
"bloomFilter"))
540 m_spec->set_option_bloom_filter(atts[i+1]);
544 "Unrecognized attribute (%s) in AccessGroup element", atts[i]);
549 void end_element(
const XML_Char *name,
const string &content)
override {
550 if (!strcasecmp(name,
"Generation"))
551 m_spec->set_generation(content_to_i64(name, content));
552 else if (!m_element_stack.empty())
554 "Unrecognized AccessGroup element (%s)", name);
557 void sub_parse(
const XML_Char *name,
const char *s,
int len)
override {
558 if (!strcasecmp(name,
"Options")) {
561 m_spec->merge_options(options);
563 else if (!strcasecmp(name,
"ColumnFamilyDefaults")) {
566 m_spec->merge_defaults(defaults);
568 else if (!strcasecmp(name,
"ColumnFamily")) {
571 m_spec->add_column(cf_spec);
582 XmlParserAccessGroupSpec parser(
this, base, len);
588 bool with_ids)
const {
590 stack<string> prefix;
591 prefix.push(line_prefix);
592 output += prefix.top() +
format(
"<AccessGroup name=\"%s\">\n",
594 prefix.push(prefix.top() +
" ");
596 output += prefix.top() +
597 format(
"<Generation>%lld</Generation>\n", (
Lld)m_generation);
598 output += prefix.top() +
"<Options>\n";
599 prefix.push(prefix.top() +
" ");
600 output += m_options.render_xml(prefix.top());
602 output += prefix.top() +
"</Options>\n";
603 output += prefix.top() +
"<ColumnFamilyDefaults>\n";
604 prefix.push(prefix.top() +
" ");
605 output += m_defaults.render_xml(prefix.top());
607 output += prefix.top() +
"</ColumnFamilyDefaults>\n";
608 for (
auto cf_spec : m_columns)
609 output += cf_spec->render_xml(prefix.top(), with_ids);
611 output += prefix.top() +
"</AccessGroup>\n";
616 const std::string maybe_quote(
const string &name) {
617 auto valid_char = [](
char c) {
return isalnum(c); };
618 if (!isalpha(name[0]) ||
619 find_if_not(name.begin(), name.end(), valid_char) != name.end())
620 return String(
"'") + name +
"'";
628 output =
" ACCESS GROUP ";
629 output += maybe_quote(m_name);
632 for (
auto cf_spec : m_columns) {
633 if (cf_spec->get_deleted())
639 output += maybe_quote(cf_spec->get_name());
642 output += m_options.render_hql();
643 output += m_defaults.render_hql();
std::string m_bloomfilter
Bloom filter specification.
int32_t m_blocksize
Block size.
void set_default_max_versions(int32_t max_versions)
Sets default max versions column family option.
void set_name(const std::string &name)
Sets access group name.
int32_t get_blocksize() const
Gets blocksize option.
void parse_xml(const char *base, int len)
Parses XML options document.
bool is_set_bloom_filter() const
Checks if bloom filter option is set.
void set_default_ttl(time_t ttl)
Sets default ttl column family option.
void set_bloom_filter(const std::string &bloomfilter)
Sets bloom filter option.
bool get_default_time_order_desc() const
Gets default time order desc column family option.
std::string String
A String is simply a typedef to std::string.
Po::positional_options_description PositionalDesc
String format(const char *fmt,...)
Returns a String using printf like format facilities Vanilla snprintf is about 1.5x faster than this...
void set_default_counter(bool value)
Sets default counter column family option.
void parse_xml(const char *base, int len)
Parses XML options specification.
void set_option_bloom_filter(const std::string &bloomfilter)
Sets bloom filter option.
Po::typed_value< uint16_t > * i16(uint16_t *v=0)
Po::typed_value< String > * str(String *v=0)
ColumnFamilySpec * get_column(const std::string &name)
Gets column family specification.
void set_replication(int16_t replication)
Sets replication option.
void set_option_compressor(const std::string &compressor)
Sets compressor option.
Column family specification.
static void parse_bloom_filter(const std::string &spec, PropertiesPtr &props)
Parsers a bloom filter specification and sets properties.
bool is_set_in_memory() const
Checks if in memory option is set.
int16_t m_replication
Replication.
ColumnFamilyOptions m_defaults
Column family defaults.
Specification for column family options.
bool clear_generation_if_changed(AccessGroupSpec &original)
Clears generation if different than original.
bool get_default_counter() const
Gets default counter column family option.
AccessGroupOptions m_options
Options.
Specification for access group options.
int16_t get_option_replication() const
Gets replication option.
bool is_set_replication() const
Checks if replication option is set.
const std::string render_xml(const std::string &line_prefix, bool with_ids=false) const
Renders access group specification in XML format.
bool m_in_memory
In memory.
bool operator==(const AccessGroupSpec &other) const
Equality operator.
void parse_xml(const char *base, int len)
Parses XML access group specification.
std::bitset< MAX > m_isset
Bit mask describing which options are set.
ColumnFamilySpec * remove_column(const std::string &name)
Removes column family specification.
void merge_options(const ColumnFamilyOptions &other)
Merges options from another ColumnFamilyOptions object.
~AccessGroupSpec()
Destructor.
Definitions for XmlParser.
bool get_option_in_memory() const
Gets in memory option.
Po::typed_value< int32_t > * i32(int32_t *v=0)
const std::string render_xml(const std::string &line_prefix) const
Renders options in XML format.
bool get_in_memory() const
Gets in memory option.
void parse_xml(const char *base, int len)
Parses XML options document.
std::shared_ptr< Properties > PropertiesPtr
Compatibility Macros for C/C++.
Po::options_description PropertiesDesc
const std::string & get_access_group() const
Gets access group name.
void drop_column(const std::string &name)
Drops column family.
bool is_set_compressor() const
Checks if compressor option is set.
const std::string render_hql() const
Renders options in HQL format.
Access group specification.
int32_t get_option_blocksize() const
Gets blocksize option.
int16_t get_replication() const
Gets replication option.
const std::string & get_name() const
Gets column family name.
long long int Lld
Shortcut for printf formats.
ColumnFamilySpecs m_columns
Member column family specifications.
Declarations for AccessGroupSpec.
int32_t get_default_max_versions() const
Gets default max versions column family option.
Base class for XML document parsers.
bool operator==(const AccessGroupOptions &other) const
Equality operator.
time_t get_default_ttl() const
Gets default ttl column family option.
void set_access_group(const std::string &ag)
Sets access group.
ColumnFamilySpecs & columns()
Returns reference to column specifications.
void set_option_in_memory(bool value)
Sets in memory option.
void set_blocksize(int32_t blocksize)
Sets blocksize option.
#define HT_THROWF(_code_, _fmt_,...)
bool split(int flags)
Tests the SPLIT bit of flags
This is a generic exception class for Hypertable.
const std::string & get_option_bloom_filter() const
Gets bloom filter option.
void set_in_memory(bool value)
Sets in memory option.
bool is_set_blocksize() const
Checks if blocksize option is set.
std::string m_compressor
Compressor specification.
std::vector< ColumnFamilySpec * > ColumnFamilySpecs
Vector of ColumnFamilySpec pointers.
void set_compressor(const std::string &compressor)
Sets compressor option.
#define HT_TRY(_s_, _code_)
Po::typed_value< double > * f64(double *v=0)
void set_default_time_order_desc(bool value)
Sets default time order desc column family option.
ColumnFamilySpec * replace_column(ColumnFamilySpec *new_cf)
Replaces column family specification.
void set_option_replication(int16_t replication)
Sets replication option.
void add_column(ColumnFamilySpec *cf)
Adds column family specification.
const std::string get_option_compressor() const
Gets compressor option.
const std::string & get_compressor() const
Gets compressor option.
void merge(const AccessGroupOptions &other)
Merges options from another AccessGroupOptions object.
const std::string & get_bloom_filter() const
Gets bloom filter option.
void set_option_blocksize(int32_t blocksize)
Sets blocksize option.
const std::string render_hql() const
Renders access group specification in HQL format.