0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
OperationCreateTable.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 "OperationCreateTable.h"
29 
33 
34 #include <Hypertable/Lib/Key.h>
37 
38 #include <Hyperspace/Session.h>
39 
40 #include <Common/Error.h>
41 #include <Common/FailureInducer.h>
42 #include <Common/ScopeGuard.h>
43 #include <Common/Serialization.h>
44 #include <Common/Time.h>
45 
46 #include <boost/algorithm/string.hpp>
47 
48 #include <chrono>
49 #include <thread>
50 #include <vector>
51 
52 using namespace Hypertable;
53 using namespace Hyperspace;
54 using namespace std;
55 
57  const String &name,
58  const String &schema,
59  TableParts parts)
60  : Operation(context, MetaLog::EntityType::OPERATION_CREATE_TABLE),
61  m_params(name, schema), m_parts(parts) {
62 }
63 
65  : Operation(context, event, MetaLog::EntityType::OPERATION_CREATE_TABLE) {
66  const uint8_t *ptr = event->payload;
67  size_t remaining = event->payload_len;
68  m_params.decode(&ptr, &remaining);
69  m_exclusivities.insert(m_params.name());
70  if (!boost::algorithm::starts_with(m_params.name(), "/sys/"))
74 }
75 
200  RangeSpec range, index_range, qualifier_index_range;
201  std::string range_name;
202  int32_t state = get_state();
203  bool is_namespace;
204 
205  HT_INFOF("Entering CreateTable-%lld(%s, location=%s, parts=%s) state=%s",
206  (Lld)header.id, m_params.name().c_str(), m_location.c_str(),
207  m_parts.to_string().c_str(), OperationState::get_text(state));
208 
209  // If skipping primary table creation, jumpt to create index
210  if (state == OperationState::INITIAL && !m_parts.primary())
212 
213  switch (state) {
214 
216  // Check to see if namespace exists
217  if (m_context->namemap->exists_mapping(m_params.name(), &is_namespace))
219 
220  // Update table/schema generation number
221  {
223  int64_t generation = get_ts64();
224  schema->update_generation(generation);
225  m_schema = schema->render_xml(true);
226  m_table.generation = schema->get_generation();
227  }
228 
230  m_context->mml_writer->record_state(shared_from_this());
231  HT_MAYBE_FAIL("create-table-INITIAL");
232  break;
233 
235  try {
237  &m_table);
238  }
239  catch (Exception &e) {
240  if (e.code() == Error::INDUCED_FAILURE)
241  throw;
243  HT_ERROR_OUT << e << HT_END;
244  complete_error(e);
245  break;
246  }
247 
248  // Update m_parts to reflect indices actually found in the schema
249  {
250  uint8_t parts {};
252  if (m_parts.primary())
253  parts |= TableParts::PRIMARY;
254  if (m_parts.value_index() && schema_parts.value_index())
255  parts |= TableParts::VALUE_INDEX;
256  if (m_parts.qualifier_index() && schema_parts.qualifier_index())
258  m_parts = TableParts(parts);
259  }
260 
261  HT_MAYBE_FAIL("create-table-ASSIGN_ID");
263  // fall through
264 
266 
267  if (m_parts.value_index()) {
268  try {
269  String index_name;
270  String index_schema;
271 
272  HT_INFOF(" creating index for table %s", m_params.name().c_str());
274  false, index_name, index_schema);
275  stage_subop(make_shared<OperationCreateTable>(m_context, index_name, index_schema,
277  }
278  catch (Exception &e) {
279  if (e.code() == Error::INDUCED_FAILURE)
280  throw;
282  HT_ERROR_OUT << e << HT_END;
283  complete_error(e);
284  break;
285  }
286 
287  HT_MAYBE_FAIL("create-table-CREATE_INDEX-1");
289  record_state();
290  HT_MAYBE_FAIL("create-table-CREATE_INDEX-2");
291  break;
292  }
293 
295 
296  // fall through
297 
299 
300  if (!validate_subops())
301  break;
302 
303  if (m_parts.qualifier_index()) {
304  try {
305  String index_name;
306  String index_schema;
307 
308  HT_INFOF(" creating qualifier index for table %s", m_params.name().c_str());
310  true, index_name, index_schema);
311  stage_subop(make_shared<OperationCreateTable>(m_context, index_name, index_schema,
313  }
314  catch (Exception &e) {
315  if (e.code() == Error::INDUCED_FAILURE)
316  throw;
318  HT_ERROR_OUT << e << HT_END;
319  complete_error(e);
320  break;
321  }
322 
323  HT_MAYBE_FAIL("create-table-CREATE_QUALIFIER_INDEX-1");
325  record_state();
326  HT_MAYBE_FAIL("create-table-CREATE_QUALIFIER_INDEX-2");
327  break;
328  }
330  record_state();
331 
332  // fall through
333 
335 
336  if (!validate_subops())
337  break;
338 
339  // If skipping primary table creation, finish here
340  if (!m_parts.primary()) {
341  complete_ok();
342  break;
343  }
344 
346  HT_MAYBE_FAIL("create-table-WRITE_METADATA-a");
347 
348  range_name = format("%s[..%s]", m_table.id, Key::END_ROW_MARKER);
349  {
350  lock_guard<mutex> lock(m_mutex);
354  m_obstructions.insert(String("OperationMove ") + range_name);
356  }
357  record_state();
358  HT_MAYBE_FAIL("create-table-WRITE_METADATA-b");
359  break;
360 
362 
363  if (range_name.empty())
364  range_name = format("%s[..%s]", m_table.id, Key::END_ROW_MARKER);
365 
366  range.start_row = 0;
368  m_context->get_balance_plan_authority()->get_balance_destination(m_table, range, m_location);
369  {
370  lock_guard<mutex> lock(m_mutex);
372  m_state = OperationState::LOAD_RANGE;
373  }
374  m_context->mml_writer->record_state(shared_from_this());
375  HT_MAYBE_FAIL("create-table-ASSIGN_LOCATION");
376  break;
377 
379  try {
380  range.start_row = 0;
383  range, false);
384  }
385  catch (Exception &e) {
386  HT_INFOF("%s - %s", Error::get_text(e.code()), e.what());
387  this_thread::sleep_for(chrono::milliseconds(5000));
389  break;
390  }
391  HT_MAYBE_FAIL("create-table-LOAD_RANGE-a");
393  m_context->mml_writer->record_state(shared_from_this());
394  HT_MAYBE_FAIL("create-table-LOAD_RANGE-b");
395 
397 
398  try {
399  range.start_row = 0;
402  m_table, range);
403  }
404  catch (Exception &e) {
405  if (range_name.empty())
406  range_name = format("%s[..%s]", m_table.id, Key::END_ROW_MARKER);
407  // Destination might be down - go back to the initial state
408  HT_INFOF("Problem acknowledging load range %s: %s - %s (dest %s)",
409  range_name.c_str(), Error::get_text(e.code()),
410  e.what(), m_location.c_str());
411  this_thread::sleep_for(chrono::milliseconds(5000));
412  // Fetch new destination, if changed, and then try again
413  range.start_row = 0;
415  m_context->get_balance_plan_authority()->get_balance_destination(m_table, range, m_location);
416  break;
417  }
418  HT_MAYBE_FAIL("create-table-ACKNOWLEDGE");
420 
422  range.start_row = 0;
424  m_context->get_balance_plan_authority()->balance_move_complete(m_table, range);
425  {
426  String tablefile = m_context->toplevel_dir + "/tables/" + m_table.id;
427  m_context->hyperspace->attr_set(tablefile, "x", "", 0);
428  HT_MAYBE_FAIL("create-table-FINALIZE");
429  MetaLog::EntityPtr bpa_entity;
430  m_context->get_balance_plan_authority(bpa_entity);
431  complete_ok(bpa_entity);
432  }
433  break;
434 
435  default:
436  HT_FATALF("Unrecognized state %d", state);
437  }
438 
439  HT_INFOF("Leaving CreateTable-%lld(%s, id=%s, generation=%u) state=%s",
440  (Lld)header.id, m_params.name().c_str(), m_table.id ? m_table.id : "",
441  (unsigned)m_table.generation,
443 
444 }
445 
446 
447 void OperationCreateTable::display_state(std::ostream &os) {
448  os << " name=" << m_params.name() << " ";
449  if (m_table.id)
450  os << m_table << " ";
451  os << " location=" << m_location << " ";
452 }
453 
455  return 1;
456 }
457 
463 }
464 
465 void OperationCreateTable::encode_state(uint8_t **bufp) const {
466  m_params.encode(bufp);
467  m_table.encode(bufp);
470  m_parts.encode(bufp);
471 }
472 
473 void OperationCreateTable::decode_state(uint8_t version, const uint8_t **bufp, size_t *remainp) {
474  m_params.decode(bufp, remainp);
475  m_table.decode(bufp, remainp);
476  m_schema = Serialization::decode_vstr(bufp, remainp);
477  m_location = Serialization::decode_vstr(bufp, remainp);
478  m_parts.decode(bufp, remainp);
479 }
480 
481 void OperationCreateTable::decode_state_old(uint8_t version, const uint8_t **bufp, size_t *remainp) {
482  {
483  string name = Serialization::decode_vstr(bufp, remainp);
484  m_schema = Serialization::decode_vstr(bufp, remainp);
486  }
487  legacy_decode(bufp, remainp, &m_table);
488  m_location = Serialization::decode_vstr(bufp, remainp);
489  if (version >= 2) {
490  int8_t parts = (int8_t)Serialization::decode_byte(bufp, remainp);
491  m_parts = TableParts(parts);
492  }
493 }
494 
496  return "OperationCreateTable";
497 }
498 
500  return String("CreateTable ") + m_params.name();
501 }
char * decode_vstr(const uint8_t **bufp, size_t *remainp)
Decode a vstr (vint64, data, null).
size_t encoded_length_state() const override
Returns serialized state length.
void decode_state(uint8_t version, const uint8_t **bufp, size_t *remainp) override
Reads serialized encoding of object state.
void prepare_index(ContextPtr &context, const String &name, const String &schema_str, bool qualifier, String &index_name, String &index_schema_str)
Prepares index schema and table name.
Definition: Utility.cc:229
The FailureInducer simulates errors.
void display_state(std::ostream &os) override
Writes human readable representation of object to output stream.
Lib::Master::Request::Parameters::CreateTable m_params
Request parmaeters.
ContextPtr m_context
Pointer to Master context.
Definition: Operation.h:553
Range specification.
Definition: RangeSpec.h:40
const string & name() const
Gets name of table to create.
Definition: CreateTable.h:62
std::string String
A String is simply a typedef to std::string.
Definition: String.h:44
std::shared_ptr< Entity > EntityPtr
Smart pointer to Entity.
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
Request parameters for create table operation.
Definition: CreateTable.h:46
const char * SERVERS
Definition: Operation.cc:46
bool validate_subops()
Handles the results of sub operations.
Definition: Operation.cc:512
virtual size_t encoded_length() const
Returns serialized object length.
Definition: Serializable.cc:37
int64_t id
Unique ID of entity.
Declarations for TableIdentifier and TableIdentifierManaged.
Declarations for OperationCreateTable.
void decode_state_old(uint8_t version, const uint8_t **bufp, size_t *remainp) override
OperationCreateTable(ContextPtr &context, const String &name, const String &schema, TableParts parts)
Constructor.
std::mutex m_mutex
Mutex for serializing access to members
void create_table_load_range(ContextPtr &context, const String &location, TableIdentifier &table, RangeSpec &range, bool needs_compaction)
Loads a table's initial range.
Definition: Utility.cc:313
void create_table_acknowledge_range(ContextPtr &context, const String &location, TableIdentifier &table, RangeSpec &range)
Calls RangeServer::acknowledge_load for a range.
Definition: Utility.cc:350
std::shared_ptr< Event > EventPtr
Smart pointer to Event.
Definition: Event.h:228
STL namespace.
const String label() override
Returns label for operation Returns string "CreateTable " Label for operation.
EntityHeader header
Entity header
size_t encoded_length_vstr(size_t len)
Computes the encoded length of vstr (vint64, data, null)
TableParts m_parts
Which parts of table to create.
const char * get_text(int32_t state)
Definition: Operation.cc:609
const string & schema() const
Gets table schema.
Definition: CreateTable.h:66
Represents a set of table parts (sub-tables).
Definition: TableParts.h:47
String m_schema
Schema for the table
Declarations for ReferenceManager.
std::shared_ptr< Context > ContextPtr
Smart pointer to Context.
Definition: Context.h:265
Hyperspace definitions
const char * end_row
Definition: RangeSpec.h:60
virtual void encode(uint8_t **bufp) const
Writes serialized representation of object to a buffer.
Definition: Serializable.cc:64
void set_state(int32_t state)
Definition: Operation.h:473
const char * get_text(int error)
Returns a descriptive error message.
Definition: Error.cc:330
const char * INIT
Definition: Operation.cc:45
Compatibility Macros for C/C++.
void stage_subop(std::shared_ptr< Operation > operation)
Stages a sub operation for execution.
Definition: Operation.cc:536
const String name() override
Returns name of operation Returns name of operation (OperationCreateTable)
#define HT_END
Definition: Logger.h:220
Functions to serialize/deserialize primitives to/from a memory buffer.
void record_state()
Records operation state to the MML.
Definition: Operation.h:401
#define HT_ERROR_OUT
Definition: Logger.h:301
const char * METADATA
Definition: Operation.cc:48
Time related declarations.
virtual void decode(const uint8_t **bufp, size_t *remainp)
Reads serialized representation of object from a buffer.
Definition: Serializable.cc:70
bool primary() const
Test if primary table is included in set.
Definition: TableParts.h:70
String m_location
Proxy name of server to hold initial range
void lock()
Locks the entity's mutex.
Definition: MetaLogEntity.h:97
void encode_vstr(uint8_t **bufp, const void *buf, size_t len)
Encode a buffer as variable length string (vint64, data, null)
Hypertable definitions
static Schema * new_instance(const std::string &buf)
Creates schema object from XML schema string.
Definition: Schema.cc:202
TableIdentifierManaged m_table
Table identifier
#define HT_FATALF(msg,...)
Definition: Logger.h:343
long long int Lld
Shortcut for printf formats.
Definition: String.h:53
DependencySet m_obstructions
Set of obstructions.
Definition: Operation.h:598
uint8_t encoding_version_state() const override
Returns encoding version of serialization format.
Declarations for general-purpose utility functions.
void legacy_decode(const uint8_t **bufp, size_t *remainp, BalancePlan *plan)
void execute() override
Carries out the create table operation.
const char * start_row
Definition: RangeSpec.h:59
void create_table_in_hyperspace(ContextPtr &context, const String &name, const String &schema_str, TableIdentifierManaged *table)
Creates a table in Hyperspace.
Definition: Utility.cc:182
DependencySet m_dependencies
Set of dependencies.
Definition: Operation.h:595
#define HT_INFOF(msg,...)
Definition: Logger.h:272
void create_table_write_metadata(ContextPtr &context, TableIdentifier *table)
Creates initial METADATA table entry for table.
Definition: Utility.cc:275
bool value_index() const
Test if value index is included in set.
Definition: TableParts.h:75
const char * SYSTEM
Definition: Operation.cc:49
Abstract base class for master operations.
Definition: Operation.h:124
void encode_state(uint8_t **bufp) const override
Writes serialized encoding of object state.
This is a generic exception class for Hypertable.
Definition: Error.h:314
const std::string to_string() const
Returns human readable string describing table parts.
Definition: TableParts.cc:63
DependencySet m_exclusivities
Set of exclusivities.
Definition: Operation.h:592
std::shared_ptr< Schema > SchemaPtr
Smart pointer to Schema.
Definition: Schema.h:465
TableParts get_index_parts(const std::string &schema)
Gets index parts specified in schema.
Definition: Utility.cc:124
#define HT_MAYBE_FAIL(_label_)
void complete_ok(std::vector< MetaLog::EntityPtr > &additional)
Definition: Operation.cc:436
Declarations for BalancePlanAuthority.
uint8_t decode_byte(const uint8_t **bufp, size_t *remainp)
Decodes a single byte from the given buffer.
Definition: Serialization.h:73
Error codes, Exception handling, error logging.
static const char * END_ROW_MARKER
Definition: Key.h:49
void complete_error(int error, const String &msg, std::vector< MetaLog::EntityPtr > &additional)
Completes operation with error.
Definition: Operation.cc:400
int64_t get_ts64()
Returns the current time in nanoseconds as a 64bit number.
Definition: Time.cc:40
int code() const
Returns the error code.
Definition: Error.h:391
Executes user-defined functions when leaving the current scope.
bool qualifier_index() const
Test if qualifier index is included in set.
Definition: TableParts.h:80