0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ColumnFamilySpec.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2007-2015 Hypertable, Inc.
3  *
4  * This file is part of Hypertable.
5  *
6  * Hypertable is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; version 3 of the
9  * License, or any later version.
10  *
11  * Hypertable is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 
26 
27 #include <Common/Compat.h>
28 #include "ColumnFamilySpec.h"
29 
30 #include <Common/Error.h>
31 #include <Common/XmlParser.h>
32 
33 #include <algorithm>
34 #include <stack>
35 
36 using namespace Hypertable;
37 using namespace std;
38 
39 bool ColumnFamilyOptions::set_max_versions(int32_t max_versions) {
40 
41  if (max_versions < 0)
43  "Invalid value for MAX VERSIONS (%d), must be non-negative",
44  (int)max_versions);
45 
46  if (m_counter && max_versions != 0)
48  "COUNTER and MAX VERSIONS are incompatible");
49 
50  m_isset.set(MAX_VERSIONS);
51 
52  if (m_max_versions != max_versions) {
53  m_max_versions = max_versions;
54  return true;
55  }
56  return false;
57 }
58 
60  return m_isset.test(MAX_VERSIONS);
61 }
62 
63 
64 bool ColumnFamilyOptions::set_ttl(time_t ttl) {
65  if (ttl < 0)
67  "Invalid value for TTL (%d), must be non-negative", (int)ttl);
68  m_isset.set(TTL);
69  if (m_ttl != ttl) {
70  m_ttl = ttl;
71  return true;
72  }
73  return false;
74 }
75 
77  return m_isset.test(TTL);
78 }
79 
80 
82  if (value) {
83  if (m_counter)
85  "COUNTER and TIME_ORDER_DESC are incompatible");
86  }
87  m_isset.set(TIME_ORDER_DESC);
88  if (m_time_order_desc != value) {
89  m_time_order_desc = value;
90  return true;
91  }
92  return false;
93 }
94 
95 
97  return m_isset.test(TIME_ORDER_DESC);
98 }
99 
100 
102  if (value) {
103  if (m_max_versions)
105  "COUNTER and MAX_VERSIONS are incompatible");
106  if (m_time_order_desc)
108  "COUNTER and TIME_ORDER_DESC are incompatible");
109  }
110  m_isset.set(COUNTER);
111  if (m_counter != value) {
112  m_counter = value;
113  return true;
114  }
115  return false;
116 }
117 
119  return m_isset.test(COUNTER);
120 }
121 
122 
124  if (!is_set_max_versions() && other.is_set_max_versions())
125  set_max_versions(other.get_max_versions());
126  if (!is_set_ttl() && other.is_set_ttl())
127  set_ttl(other.get_ttl());
128  if (!is_set_time_order_desc() && other.is_set_time_order_desc())
129  set_time_order_desc(other.get_time_order_desc());
130  if (!is_set_counter() && other.is_set_counter())
131  set_counter(other.get_counter());
132 }
133 
134 namespace {
135 
136  class XmlParserColumnFamilyOptions : public XmlParser {
137  public:
138  XmlParserColumnFamilyOptions(ColumnFamilyOptions *ops, const char *s,
139  int len) : XmlParser(s,len), m_options(ops) {}
140 
141  void end_element(const XML_Char *name, const string &content) override {
142  if (!strcasecmp(name, "MaxVersions"))
143  m_options->set_max_versions(content_to_i32(name, content));
144  else if (!strcasecmp(name, "TTL"))
145  m_options->set_ttl((time_t)content_to_i32(name, content));
146  else if (!strcasecmp(name, "TimeOrder"))
147  m_options->set_time_order_desc(content_to_text(name, content,
148  {"asc","desc"})=="desc");
149  else if (!strcasecmp(name, "Counter"))
150  m_options->set_counter(content_to_bool(name, content));
151  else if (!m_element_stack.empty())
153  "Unrecognized ColumnFamily option element (%s)", name);
154  }
155  private:
156  ColumnFamilyOptions *m_options;
157  };
158 
159 }
160 
161 void ColumnFamilyOptions::parse_xml(const char *base, int len) {
162  XmlParserColumnFamilyOptions parser(this, base, len);
163  parser.parse();
164 }
165 
166 const std::string ColumnFamilyOptions::render_xml(const std::string &line_prefix) const {
167  std::string xstr;
168  if (is_set_max_versions())
169  xstr += format("%s<MaxVersions>%d</MaxVersions>\n",
170  line_prefix.c_str(), (int)m_max_versions);
171  if (is_set_ttl())
172  xstr += format("%s<TTL>%d</TTL>\n", line_prefix.c_str(), (int)m_ttl);
173  if (is_set_time_order_desc())
174  xstr += format("%s<TimeOrder>%s</TimeOrder>\n", line_prefix.c_str(),
175  m_time_order_desc ? "desc" : "asc");
176  if (is_set_counter())
177  xstr += format("%s<Counter>%s</Counter>\n", line_prefix.c_str(),
178  m_counter ? "true" : "false");
179  return xstr;
180 }
181 
182 const std::string ColumnFamilyOptions::render_hql() const {
183  std::string hstr;
184  if (is_set_max_versions())
185  hstr += format(" MAX_VERSIONS %d", (int)m_max_versions);
186  if (is_set_ttl())
187  hstr += format(" TTL %d", (int)m_ttl);
188  if (is_set_time_order_desc())
189  hstr += format(" TIME_ORDER %s", m_time_order_desc ? "desc" : "asc");
190  if (is_set_counter())
191  hstr += format(" COUNTER %s", m_counter ? "true" : "false");
192  return hstr;
193 }
194 
196  return (m_isset == other.m_isset &&
197  m_max_versions == other.m_max_versions &&
198  m_ttl == other.m_ttl &&
199  m_time_order_desc == other.m_time_order_desc &&
200  m_counter == other.m_counter);
201 }
202 
203 void ColumnFamilySpec::set_name(const std::string &name) {
204  m_name = name;
205 }
206 
207 void ColumnFamilySpec::set_access_group(const std::string &ag) {
208  m_ag = ag;
209 }
210 
211 void ColumnFamilySpec::set_generation(int64_t generation) {
212  m_generation = generation;
213 }
214 
215 void ColumnFamilySpec::set_id(int32_t id) {
216  m_id = id;
217 }
218 
220  if (m_deleted != value) {
221  m_deleted = value;
222  m_generation = 0;
223  }
224 }
225 
226 void ColumnFamilySpec::set_option_max_versions(int32_t max_versions) {
227  if (m_options.set_max_versions(max_versions))
228  m_generation = 0;
229 }
230 
232  if (m_options.set_ttl(ttl))
233  m_generation = 0;
234 }
235 
237  if (m_options.set_time_order_desc(value))
238  m_generation = 0;
239 }
240 
242 
243  if (value) {
244  if (m_value_index)
246  "COUNTER and INDEX are incompatible");
247  if (m_qualifier_index)
249  "COUNTER and QUALIFIER INDEX are incompatible");
250  }
251 
252  if (m_options.set_counter(value))
253  m_generation = 0;
254 }
255 
257  if (value && m_options.get_counter())
259  "COUNTER and INDEX are incompatible");
260  if (m_value_index != value) {
261  m_value_index = value;
262  m_generation = 0;
263  }
264 }
265 
267  if (value && m_options.get_counter())
269  "COUNTER and QUALIFIER INDEX are incompatible");
270  if (m_qualifier_index != value) {
271  m_qualifier_index = value;
272  m_generation = 0;
273  }
274 }
275 
277  m_options.merge(other);
278 }
279 
281  return (m_name == other.m_name &&
282  m_ag == other.m_ag &&
283  m_generation == other.m_generation &&
284  m_id == other.m_id &&
285  m_options == other.m_options &&
286  m_value_index == other.m_value_index &&
287  m_qualifier_index == other.m_qualifier_index &&
288  m_deleted == other.m_deleted);
289 }
290 
291 
292 namespace {
293 
294  class XmlParserColumnFamilySpec : public XmlParser {
295  public:
296  XmlParserColumnFamilySpec(ColumnFamilySpec *spec, const char *s, int len) :
297  XmlParser(s,len,{"Options"}), m_spec(spec) {}
298 
299  void start_element(const XML_Char *name, const XML_Char **atts) override {
300  if (m_element_stack.empty()) {
301  for (int i=0; atts[i] != 0; i+=2) {
302  if (!strcasecmp(atts[i], "id"))
303  m_spec->set_id(content_to_i32("id", atts[i+1]));
304  else
306  "Unrecognized attribute (%s) in ColumnFamily element", atts[i]);
307  }
308  }
309  }
310 
311  void end_element(const XML_Char *name, const string &content) override {
312  if (!strcasecmp(name, "Name"))
313  m_spec->set_name(content);
314  else if (!strcasecmp(name, "AccessGroup"))
315  m_spec->set_access_group(content);
316  else if (!strcasecmp(name, "Generation"))
317  m_generation = content_to_i64(name, content);
318  else if (!strcasecmp(name, "Deleted"))
319  m_spec->set_deleted(content_to_bool(name, content));
320  else if (!strcasecmp(name, "Index"))
321  m_spec->set_value_index(content_to_bool(name, content));
322  else if (!strcasecmp(name, "QualifierIndex"))
323  m_spec->set_qualifier_index(content_to_bool(name, content));
324  else if (m_element_stack.empty())
325  m_spec->set_generation(m_generation);
326  else {
327  // backward compatibility
328  if (!strcasecmp(name, "MaxVersions"))
329  m_spec->set_option_max_versions(content_to_i32(name, content));
330  else if (!strcasecmp(name, "TTL"))
331  m_spec->set_option_ttl((time_t)content_to_i32(name, content));
332  else if (!strcasecmp(name, "TimeOrder")) {
333  bool val = content_to_text(name, content, {"asc","desc"}) == "desc";
334  m_spec->set_option_time_order_desc(val);
335  }
336  else if (!strcasecmp(name, "Counter"))
337  m_spec->set_option_counter(content_to_bool(name, content));
338  else if (!strcasecmp(name, "Renamed") || !strcasecmp(name, "NewName"))
339  ;
340  else
342  "Unrecognized ColumnFamily element (%s)", name);
343  }
344  }
345 
346  void sub_parse(const XML_Char *name, const char *s, int len) override {
347  ColumnFamilyOptions options;
348  XmlParserColumnFamilyOptions parser(&options, s, len);
349  parser.parse();
350  m_spec->merge_options(options);
351  }
352 
353  private:
354  ColumnFamilySpec *m_spec;
355  int64_t m_generation {};
356  };
357 
358 }
359 
360 void ColumnFamilySpec::parse_xml(const char *base, int len) {
361  XmlParserColumnFamilySpec parser(this, base, len);
362  parser.parse();
363 }
364 
365 const std::string ColumnFamilySpec::render_xml(const std::string &line_prefix,
366  bool with_ids) const {
367  string output;
368  stack<string> prefix;
369  prefix.push(line_prefix);
370  output += prefix.top() + "<ColumnFamily";
371  prefix.push(prefix.top() + " ");
372  if (with_ids) {
373  output += format(" id=\"%u\"", get_id());
374  output += ">\n";
375  output += prefix.top() + format("<Generation>%lld</Generation>\n", (Lld)get_generation());
376  }
377  else
378  output += ">\n";
379  output += prefix.top() + format("<Name>%s</Name>\n", get_name().c_str());
380  output += prefix.top() + format("<AccessGroup>%s</AccessGroup>\n", get_access_group().c_str());
381  output += prefix.top() + format("<Deleted>%s</Deleted>\n",
382  get_deleted() ? "true" : "false");
383  if (get_value_index())
384  output += prefix.top() + format("<Index>true</Index>\n");
385  if (get_qualifier_index())
386  output += prefix.top() + format("<QualifierIndex>true</QualifierIndex>\n");
387  output += prefix.top() + format("<Options>\n");
388  prefix.push(prefix.top() + " ");
389  output += options().render_xml(prefix.top());
390  prefix.pop();
391  output += prefix.top() + format("</Options>\n");
392  prefix.pop();
393  output += prefix.top() + "</ColumnFamily>\n";
394  return output;
395 }
396 
397 namespace {
398  const std::string maybe_quote(const string &name) {
399  auto valid_char = [](char c) { return isalnum(c); };
400  if (!isalpha(name[0]) ||
401  find_if_not(name.begin(), name.end(), valid_char) != name.end())
402  return String("'") + name + "'";
403  return name;
404  }
405 }
406 
407 const std::string ColumnFamilySpec::render_hql() const {
408  string output;
409  // don't display deleted cfs
410  if (get_deleted())
411  return output;
412 
413  output += format(" %s", maybe_quote(get_name()).c_str());
414 
415  output += options().render_hql();
416 
417  if (get_value_index())
418  output += format(", INDEX %s", maybe_quote(get_name()).c_str());
419 
420  if (get_qualifier_index())
421  output += format(", QUALIFIER INDEX %s", maybe_quote(get_name()).c_str());
422 
423  return output;
424 }
bool get_counter() const
Gets the counter option.
void set_id(int32_t id)
Sets column ID.
bool is_set_max_versions() const
Checks if max versions option is set.
bool get_time_order_desc() const
Gets time order desc option.
bool is_set_ttl() const
Checks if ttl option is set.
const std::string render_xml(const std::string &line_prefix, bool with_ids=false) const
Renders spec in XML format.
void parse_xml(const char *base, int len)
Parses XML options document.
std::string m_ag
Access group name.
ColumnFamilyOptions m_options
Options.
void set_option_max_versions(int32_t max_versions)
Sets max versions option.
void set_generation(int64_t generation)
Sets generation.
std::string String
A String is simply a typedef to std::string.
Definition: String.h:44
bool set_max_versions(int32_t max_versions)
Sets max versions option.
bool m_value_index
Value index flag.
void set_deleted(bool value)
Sets deleted flag.
String format(const char *fmt,...)
Returns a String using printf like format facilities Vanilla snprintf is about 1.5x faster than this...
Definition: String.cc:37
const std::string render_hql() const
Renders options in HQL format.
Column family specification.
int32_t m_max_versions
Max version.
void set_qualifier_index(bool value)
Sets qualifier index flag.
void set_name(const std::string &name)
Sets column family name.
const std::string render_hql() const
Renders spec in HQL format.
bool set_ttl(time_t ttl)
Sets ttl option.
Specification for column family options.
STL namespace.
void set_option_time_order_desc(bool value)
Sets time order desc option.
bool m_qualifier_index
Qualifier index flag
bool is_set_counter() const
Checks if counter option is set.
void set_value_index(bool value)
Sets value index flag.
bool operator==(const ColumnFamilySpec &other) const
Equality operator.
void merge_options(const ColumnFamilyOptions &other)
Merges options from another ColumnFamilyOptions object.
Definitions for XmlParser.
void parse_xml(const char *base, int len)
Parses XML options document.
Compatibility Macros for C/C++.
bool set_time_order_desc(bool value)
Sets time order desc option.
std::string m_name
Column family name
int32_t get_max_versions() const
Gets max versions option.
bool set_counter(bool value)
Sets counter option.
void set_option_counter(bool value)
Sets counter option.
bool is_set_time_order_desc() const
Checks if time_order_desc option is set.
void merge(const ColumnFamilyOptions &other)
Merges options from another ColumnFamilyOptions object.
time_t get_ttl() const
Gets ttl option.
void set_option_ttl(time_t ttl)
Sets ttl option.
Hypertable definitions
long long int Lld
Shortcut for printf formats.
Definition: String.h:53
std::bitset< MAX > m_isset
Bit mask describing which options are set.
Base class for XML document parsers.
Definition: XmlParser.h:94
void set_access_group(const std::string &ag)
Sets access group.
#define HT_THROWF(_code_, _fmt_,...)
Definition: Error.h:490
const std::string render_xml(const std::string &line_prefix) const
Renders options in XML format.
int64_t m_generation
Generation.
bool operator==(const ColumnFamilyOptions &other) const
Equality operator.
Error codes, Exception handling, error logging.
#define HT_THROW(_code_, _msg_)
Definition: Error.h:478
Declarations for ColumnFamilySpec.
bool m_time_order_desc
Time order "desc" flag.