0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
TableInfo.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 "TableInfo.h"
29 
30 #include <Common/Logger.h>
31 
32 using namespace std;
33 using namespace Hypertable;
34 
35 TableInfo::TableInfo(const TableIdentifier *identifier, SchemaPtr &schema,
36  bool maintenance_disabled)
37  : m_identifier(*identifier), m_schema(schema),
38  m_maintenance_disabled(maintenance_disabled) {
39 }
40 
41 
42 bool TableInfo::remove(const String &start_row, const String &end_row) {
43  lock_guard<mutex> lock(m_mutex);
44  RangeInfo range_info(start_row, end_row);
45  auto iter = m_active_set.find(range_info);
46 
47  if (iter == m_active_set.end() || !iter->range) {
48  HT_INFOF("Unable to remove %s[%s..%s] from TableInfo because non-existant",
49  m_identifier.id, start_row.c_str(), end_row.c_str());
50  return false;
51  }
52 
53  HT_ASSERT(iter->start_row.compare(start_row) == 0);
54 
55  HT_INFOF("Removing %s[%s..%s] from TableInfo",
56  m_identifier.id, start_row.c_str(), end_row.c_str());
57 
58  m_active_set.erase(iter);
59 
60  return true;
61 }
62 
63 
64 void
65 TableInfo::change_end_row(const String &start_row, const String &old_end_row,
66  const String &new_end_row) {
67  lock_guard<mutex> lock(m_mutex);
68  RangeInfo range_info(start_row, old_end_row);
69  auto iter = m_active_set.find(range_info);
70 
71  if (iter == m_active_set.end() || !iter->range)
72  HT_FATALF("Problem changing old end row '%s' to '%s' (start row '%s')",
73  old_end_row.c_str(), new_end_row.c_str(), start_row.c_str());
74 
75  range_info.range = iter->range;
76  range_info.end_row = new_end_row;
77 
78  HT_INFOF("Changing end row %s removing old row '%s' (start row '%s')",
79  m_identifier.id, old_end_row.c_str(), start_row.c_str());
80 
81  m_active_set.erase(iter);
82 
83  HT_ASSERT(m_active_set.insert(range_info).second);
84 
85  HT_INFOF("Changing end row %s adding new row '%s' (start row '%s')",
86  m_identifier.id, new_end_row.c_str(), start_row.c_str());
87 }
88 
89 void
90 TableInfo::change_start_row(const String &old_start_row, const String &new_start_row,
91  const String &end_row) {
92  lock_guard<mutex> lock(m_mutex);
93  RangeInfo range_info(old_start_row, end_row);
94  auto iter = m_active_set.find(range_info);
95 
96  if (iter == m_active_set.end()|| !iter->range)
97  HT_FATALF("Problem changing old start row '%s' to '%s' (end row '%s')",
98  old_start_row.c_str(), new_start_row.c_str(), end_row.c_str());
99 
100  range_info.range = iter->range;
101  range_info.start_row = new_start_row;
102 
103  HT_INFOF("Changing start row %s removing old row '%s' (end row '%s')",
104  m_identifier.id, old_start_row.c_str(), end_row.c_str());
105 
106  m_active_set.erase(iter);
107 
108  HT_ASSERT(m_active_set.insert(range_info).second);
109 
110  HT_INFOF("Changing start row %s adding new start row '%s' (end row '%s')",
111  m_identifier.id, new_start_row.c_str(), end_row.c_str());
112 
113 }
114 
115 
116 bool TableInfo::get_range(const RangeSpec &range_spec, RangePtr &range) {
117  lock_guard<mutex> lock(m_mutex);
118  RangeInfo range_info(range_spec.start_row, range_spec.end_row);
119 
120  auto iter = m_active_set.find(range_info);
121 
122  if (iter == m_active_set.end() || !iter->range) {
123  HT_DEBUG_OUT << "TableInfo couldn't find range (" << range_spec.start_row
124  << ", " << range_spec.end_row << ")" << HT_END;
125  return false;
126  }
127 
128  range = iter->range;
129  return true;
130 }
131 
132 bool TableInfo::has_range(const RangeSpec &range_spec) {
133  lock_guard<mutex> lock(m_mutex);
134  RangeInfo range_info(range_spec.start_row, range_spec.end_row);
135  if (m_active_set.find(range_info) == m_active_set.end())
136  return false;
137  return true;
138 }
139 
140 
141 bool TableInfo::remove_range(const RangeSpec &range_spec, RangePtr &range) {
142  lock_guard<mutex> lock(m_mutex);
143  RangeInfo range_info(range_spec.start_row, range_spec.end_row);
144  auto iter = m_active_set.find(range_info);
145 
146  if (iter == m_active_set.end() || !iter->range) {
147  HT_INFOF("Problem removing range %s[%s..%s] from TableInfo, range not found",
148  m_identifier.id, range_spec.start_row, range_spec.end_row);
149  return false;
150  }
151 
152  range = iter->range;
153 
154  HT_INFOF("Removing range %s[%s..%s] from TableInfo",
155  m_identifier.id, range_spec.start_row, range_spec.end_row);
156 
157  m_active_set.erase(iter);
158 
159  return true;
160 }
161 
162 
163 void TableInfo::stage_range(const RangeSpec &range_spec,
164  ClockT::time_point deadline) {
165  unique_lock<mutex> lock(m_mutex);
166  RangeInfo range_info(range_spec.start_row, range_spec.end_row);
167 
169  while (m_staged_set.find(range_info) != m_staged_set.end()) {
170  if (m_cond.wait_until(lock, deadline) == std::cv_status::timeout)
171  HT_THROWF(Error::REQUEST_TIMEOUT, "Waiting for staging of %s[%s..%s]",
172  m_identifier.id, range_spec.start_row, range_spec.end_row);
173  }
174 
176  auto iter = m_active_set.find(range_info);
177 
178  if (iter != m_active_set.end()) {
179  String name = format("%s[%s..%s]", m_identifier.id, range_spec.start_row,
180  range_spec.end_row);
181  int state = iter->range->get_state();
182  if (state != RangeState::STEADY)
184  "Unable to stage range %s because is in state %s",
185  name.c_str(), RangeState::get_text(state).c_str());
187  }
188 
189  HT_ASSERT(m_staged_set.insert(range_info).second);
190 
191  // Notify of change to m_staged_set
192  m_cond.notify_all();
193 }
194 
195 void TableInfo::unstage_range(const RangeSpec &range_spec) {
196  lock_guard<mutex> lock(m_mutex);
197  RangeInfo range_info(range_spec.start_row, range_spec.end_row);
198  auto iter = m_staged_set.find(range_info);
199  HT_ASSERT(iter != m_staged_set.end());
200  m_staged_set.erase(iter);
201  m_cond.notify_all();
202 }
203 
205  lock_guard<mutex> lock(m_mutex);
206  String start_row, end_row;
207  range->get_boundary_rows(start_row, end_row);
208  RangeInfo range_info(start_row, end_row);
209  auto iter = m_staged_set.find(range_info);
210  HT_ASSERT(iter != m_staged_set.end());
211  range_info.range = range;
212  m_staged_set.erase(iter);
213  HT_ASSERT(m_active_set.insert(range_info).second);
214  m_cond.notify_all();
215 }
216 
217 void TableInfo::add_range(RangePtr &range, bool remove_if_exists) {
218  lock_guard<mutex> lock(m_mutex);
219  String start_row, end_row;
220  range->get_boundary_rows(start_row, end_row);
221  RangeInfo range_info(start_row, end_row);
222  range_info.range = range;
223  auto iter = m_active_set.find(range_info);
224  if (iter != m_active_set.end() && remove_if_exists) {
225  m_active_set.erase(iter);
226  iter = m_active_set.end();
227  }
228  HT_ASSERT(iter == m_active_set.end());
229  HT_INFOF("Adding range %s to TableInfo", range->get_name().c_str());
230  HT_ASSERT(m_active_set.insert(range_info).second);
231 }
232 
233 bool
235  String &start_row, String &end_row) {
236  lock_guard<mutex> lock(m_mutex);
237  RangeInfo range_info("", row);
238  auto iter = m_active_set.lower_bound(range_info);
239 
240  if (iter == m_active_set.end() || iter->start_row.compare(row) >= 0)
241  return false;
242 
243  start_row = iter->start_row;
244  end_row = iter->end_row;
245  range = iter->range;
246 
247  return true;
248 }
249 
250 
251 bool TableInfo::includes_row(const String &row) const {
252  RangeInfo range_info("", row);
253  auto iter = m_active_set.lower_bound(range_info);
254  if (iter == m_active_set.end() || iter->start_row.compare(row) >= 0)
255  return false;
256  return true;
257 }
258 
260  lock_guard<mutex> lock(m_mutex);
261  for (auto &range_info : m_active_set)
262  ranges.array.push_back(RangeData(range_info.range));
263 }
264 
265 
267  lock_guard<mutex> lock(m_mutex);
268  return m_active_set.size();
269 }
270 
271 
273  lock_guard<mutex> lock(m_mutex);
274  HT_INFOF("Clearing set for table %s", m_identifier.id);
275  m_active_set.clear();
276 }
277 
279  lock_guard<mutex> lock(m_mutex);
280 
281  if (schema->get_generation() < m_schema->get_generation())
283  "Updated schema generation %lld < current schema generation %lld",
284  (Lld)schema->get_generation(), (Lld)m_schema->get_generation());
285 
286  for (auto &range_info : m_active_set)
287  range_info.range->update_schema(schema);
288 
289  m_schema = schema;
290 }
bool remove_range(const RangeSpec &range_spec, RangePtr &range)
Removes the range specified by the given RangeSpec from the active set.
Definition: TableInfo.cc:141
RangePtr range
Smart pointer to Range object.
Definition: TableInfo.h:106
void stage_range(const RangeSpec &range_spec, std::chrono::fast_clock::time_point deadline)
Stages a range to being added.
Definition: TableInfo.cc:163
void clear()
Clears the active range set.
Definition: TableInfo.cc:272
bool has_range(const RangeSpec &range_spec)
Checks if range corresponding to the given RangeSpec exists in the active set.
Definition: TableInfo.cc:132
virtual void change_end_row(const String &start_row, const String &old_end_row, const String &new_end_row)
Changes the end row of a range in the active set.
Definition: TableInfo.cc:65
Range specification.
Definition: RangeSpec.h:40
std::string String
A String is simply a typedef to std::string.
Definition: String.h:44
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
chrono::time_point< fast_clock > time_point
Definition: fast_clock.h:42
std::condition_variable m_cond
Condition variable signalled on m_staged_set change.
Definition: TableInfo.h:293
void update_schema(SchemaPtr &schema)
Updates schema, propagating change to all ranges in active set.
Definition: TableInfo.cc:278
STL namespace.
String end_row
Cached end row of range.
Definition: TableInfo.h:104
#define HT_ASSERT(_e_)
Definition: Logger.h:396
std::set< RangeInfo > m_active_set
Set of active ranges.
Definition: TableInfo.h:302
bool find_containing_range(const String &row, RangePtr &range, String &start_row, String &end_row)
Finds the range to which the given row belongs.
Definition: TableInfo.cc:234
void get_ranges(Ranges &ranges)
Fills Ranges vector with ranges from the active set.
Definition: TableInfo.cc:259
const char * end_row
Definition: RangeSpec.h:60
std::set< RangeInfo > m_staged_set
Set of staged ranges (soon to become active)
Definition: TableInfo.h:305
std::vector< RangeData > array
Vector of RangeData objects.
Definition: TableInfo.h:85
Logging routines and macros.
Compatibility Macros for C/C++.
#define HT_END
Definition: Logger.h:220
bool get_range(const RangeSpec &range_spec, RangePtr &range)
Returns range object corresponding to the given RangeSpec.
Definition: TableInfo.cc:116
void add_range(RangePtr &range, bool remove_if_exists=false)
Adds a range to the active set.
Definition: TableInfo.cc:217
static std::string get_text(uint8_t state)
Returns string representation of range state value.
Definition: RangeState.cc:48
void promote_staged_range(RangePtr &range)
Promotes a range from the staged set to the active set.
Definition: TableInfo.cc:204
Holds pointer to range and cached start and end rows.
Definition: TableInfo.h:94
Hypertable definitions
size_t get_range_count()
Returns the number of ranges in the active set.
Definition: TableInfo.cc:266
virtual bool remove(const String &start_row, const String &end_row)
Remove range with the given start and end row from the active set.
Definition: TableInfo.cc:42
#define HT_FATALF(msg,...)
Definition: Logger.h:343
long long int Lld
Shortcut for printf formats.
Definition: String.h:53
Declarations for TableInfo.
const char * start_row
Definition: RangeSpec.h:59
void unstage_range(const RangeSpec &range_spec)
Unstages a previously staged range.
Definition: TableInfo.cc:195
bool includes_row(const String &row) const
Checks to see if a given row belongs to any of the ranges in the active set.
Definition: TableInfo.cc:251
#define HT_INFOF(msg,...)
Definition: Logger.h:272
#define HT_THROWF(_code_, _fmt_,...)
Definition: Error.h:490
std::shared_ptr< Range > RangePtr
Smart pointer to Range.
Definition: Range.h:404
String start_row
Cached start row of range.
Definition: TableInfo.h:102
std::shared_ptr< Schema > SchemaPtr
Smart pointer to Schema.
Definition: Schema.h:465
virtual void change_start_row(const String &old_start_row, const String &new_start_row, const String &end_row)
Changes the start row of a range in the active set.
Definition: TableInfo.cc:90
TableIdentifierManaged m_identifier
Table identifier
Definition: TableInfo.h:296
std::mutex m_mutex
Mutex for serializing member access
Definition: TableInfo.h:290
Holds pointers to a Range and associated Range::MaintenanceData.
Definition: TableInfo.h:55
SchemaPtr m_schema
Table schema object
Definition: TableInfo.h:299
Holds vector of RangeData objects and memory arena.
Definition: TableInfo.h:72
#define HT_DEBUG_OUT
Definition: Logger.h:261