0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
MetaLogReader.cc
Go to the documentation of this file.
1 /* -*- c++ -*-
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 
28 #include "Common/Compat.h"
29 #include "Common/Checksum.h"
30 #include "Common/Config.h"
31 #include "Common/Error.h"
32 #include "Common/FailureInducer.h"
33 #include "Common/ScopeGuard.h"
34 #include "Common/Serialization.h"
35 #include "Common/FileUtils.h"
36 #include "Common/Path.h"
37 
38 #include "Common/StringExt.h"
39 
40 #include <algorithm>
41 #include <cstdio>
42 
43 #include <boost/algorithm/string.hpp>
44 #include <boost/shared_ptr.hpp>
45 
46 #include "MetaLog.h"
47 #include "MetaLogReader.h"
48 
49 using namespace Hypertable;
50 using namespace Hypertable::MetaLog;
51 
52 Reader::Reader(FilesystemPtr &fs, DefinitionPtr &definition, int flags) :
53  m_fs(fs), m_definition(definition), m_flags(flags), m_version(0) {
54 }
55 
56 
58  const string &path, int flags) :
59  m_fs(fs), m_definition(definition), m_flags(flags), m_version(0) {
60 
61  // Setup FS path name
62  m_path = path;
63  boost::trim_right_if(m_path, boost::is_any_of("/"));
64 
65  // Setup local backup path name
66  Path data_dir = Config::properties->get_str("Hypertable.DataDirectory");
67  m_backup_path = (data_dir /= String("/run/log_backup/") + String(m_definition->name()) + "/" +
68  String(m_definition->backup_label())).string();
69 
70  reload();
71 }
72 
73 void Reader::get_entities(std::vector<EntityPtr> &entities) {
74  std::map<EntityHeader, EntityPtr>::iterator iter;
75  for (iter = m_entity_map.begin(); iter != m_entity_map.end(); ++iter)
76  entities.push_back(iter->second);
77 }
78 
79 void Reader::get_all_entities(std::vector<EntityPtr> &entities) {
80  entities = m_entities;
81 }
82 
83 
85  try {
87  if (!m_file_nums.empty()) {
88  verify_backup(m_file_nums.front());
89  load_file(m_path + "/" + m_file_nums.front());
90  }
91  }
92  catch (Exception &e) {
93  if (e.code() & Error::METALOG_ERROR)
94  throw;
96  }
97 }
98 
99 
100 namespace {
101  const uint32_t READAHEAD_BUFSZ = 1024 * 1024;
102  const uint32_t OUTSTANDING_READS = 1;
103  void close_descriptor(FilesystemPtr fs, int *fdp) {
104  try {
105  fs->close(*fdp);
106  }
107  catch (Exception &e) {
108  HT_ERRORF("Problem closing MetaLog: %s - %s",
109  Error::get_text(e.code()), e.what());
110  }
111  }
112 }
113 
114 void Reader::verify_backup(int32_t file_num) {
115 
116  string fname = m_path + "/" + file_num;
117  string backup_filename = m_backup_path + "/" + file_num;
118 
119  if (!FileUtils::exists(backup_filename))
120  return;
121 
122  size_t file_length = m_fs->length(fname);
123  size_t backup_file_length = FileUtils::size(backup_filename);
124 
125  if (backup_file_length < file_length)
127  "MetaLog file '%s' has length %lld backup file '%s' length is %lld",
128  fname.c_str(), (Lld)file_length, backup_filename.c_str(),
129  (Lld)backup_file_length);
130 }
131 
132 
133 void Reader::load_file(const string &fname) {
134  int64_t file_length = m_fs->length(fname);
135  int fd = m_fs->open_buffered(fname, 0, READAHEAD_BUFSZ, OUTSTANDING_READS);
136  bool found_recover_entry = false;
137  int64_t cur_offset = 0;
138 
139  HT_MAYBE_FAIL("bad-rsml");
140 
141  m_entity_map.clear();
142 
143  HT_ON_SCOPE_EXIT(&close_descriptor, m_fs, &fd);
144 
145  read_header(fd, &cur_offset);
146 
147  try {
148  size_t remaining;
149  EntityHeader header;
150  DynamicBuffer buf;
151 
153 
154  while (cur_offset < file_length) {
155 
156  buf.clear();
157 
158  size_t nread = m_fs->read(fd, buf.base, EntityHeader::LENGTH);
159 
160  if (nread != EntityHeader::LENGTH)
161  HT_THROW(Error::METALOG_ENTRY_TRUNCATED, "reading entity header");
162 
163  remaining = EntityHeader::LENGTH;
164  const uint8_t *ptr = buf.base;
165  header.decode(&ptr, &remaining);
166 
167  cur_offset += nread;
168 
169  if (header.type == EntityType::RECOVER) {
170  found_recover_entry = true;
171  continue;
172  }
173  else if (header.flags & EntityHeader::FLAG_REMOVE) {
174  std::map<EntityHeader, EntityPtr>::iterator iter = m_entity_map.find(header);
175  if (iter != m_entity_map.end())
176  m_entity_map.erase(iter);
177  continue;
178  }
179 
180  EntityPtr entity(m_definition->create(header));
181 
182  buf.clear();
183  buf.ensure(header.length);
184 
185  nread = m_fs->read(fd, buf.base, header.length);
186 
187  if (nread != (size_t)header.length)
188  HT_THROW(Error::METALOG_ENTRY_TRUNCATED, "reading entity payload");
189 
190  cur_offset += nread;
191 
192  if (entity) {
193  remaining = header.length;
194  ptr = buf.base;
195  entity->decode(&ptr, &remaining, m_version);
196 
197  // verify checksum
198  int32_t computed_checksum = fletcher32(buf.base, header.length);
199  if (header.checksum != computed_checksum)
201  "MetaLog entry checksum mismatch header=%d, computed=%d",
202  header.checksum, computed_checksum);
203 
204  m_entity_map[header] = entity;
206  m_entities.push_back(entity);
207  }
208 
209  }
210 
211  }
212  catch (Exception &e) {
213  HT_THROW2F(e.code(), e, "Error reading metalog file: %s: read %llu/%llu",
214  fname.c_str(), (Llu)cur_offset, (Llu)file_length);
215  }
216 
217  if (!found_recover_entry)
219 
220 }
221 
222 
223 void Reader::read_header(int fd, int64_t *offsetp) {
224  MetaLog::Header header;
225  uint8_t buf[Header::LENGTH];
226  const uint8_t *ptr = buf;
227  size_t remaining = Header::LENGTH;
228 
229  size_t nread = m_fs->read(fd, buf, Header::LENGTH);
230 
231  if (nread != Header::LENGTH)
233  "Short read of %s header (expected %d, got %d)",
234  m_definition->name(), (int)Header::LENGTH, (int)nread);
235 
236  *offsetp += nread;
237 
238  header.decode(&ptr, &remaining);
239 
240  if (strcmp(header.name, m_definition->name()))
241  HT_THROWF(Error::METALOG_BAD_HEADER, "Wrong name in %s header ('%s' != '%s')",
242  m_definition->name(), header.name, m_definition->name());
243 
244  m_version = header.version;
245 
246  if (m_definition->version() < m_version)
248  "Unsuported %s version %d (definition version is %d)",
249  m_definition->name(), m_version, m_definition->version());
250 }
#define HT_THROW2F(_code_, _ex_, _fmt_,...)
Definition: Error.h:494
int32_t flags
Flags (either FLAG_REMOVE or 0)
void read_header(int fd, int64_t *offsetp)
Reads the log file header.
int32_t length
Length of entity header plus serialized state.
Declarations for MetaLog::Reader.
char name[14]
MetaLog definition name (e.g. "mml" or "rsml")
Definition: MetaLog.h:88
The FailureInducer simulates errors.
int m_flags
Flags that control read behavior.
PropertiesPtr properties
This singleton map stores all options.
Definition: Config.cc:47
std::string String
A String is simply a typedef to std::string.
Definition: String.h:44
Compatibility class for boost::filesystem::path.
std::shared_ptr< Entity > EntityPtr
Smart pointer to Entity.
void reload()
Loads MetaLog.
void get_all_entities(std::vector< EntityPtr > &entities)
Returns all versions of all entities.
long long unsigned int Llu
Shortcut for printf formats.
Definition: String.h:50
static bool exists(const String &fname)
Checks if a file or directory exists.
Definition: FileUtils.cc:420
std::string m_backup_path
Local backup path initialized in primary_metalog_reader_constructor.
#define HT_ON_SCOPE_EXIT(...)
Definition: ScopeGuard.h:301
MetaLog::DefinitionPtr m_definition
Smart pointer to MetaLog Definition.
A dynamic, resizable and reference counted memory buffer.
Definition: DynamicBuffer.h:42
static uint64_t size(const String &fname)
Returns the size of a file (0 on error)
Definition: FileUtils.cc:450
uint32_t fletcher32(const void *data8, size_t len8)
Compute fletcher32 checksum for arbitary data.
Definition: Checksum.cc:42
Compatibility class for boost::filesystem::path.
Definition: Path.h:45
File system utility functions.
void decode(const uint8_t **bufp, size_t *remainp)
Decodes serialized header.
Definition: MetaLog.cc:46
Static length of entity header.
const char * get_text(int error)
Returns a descriptive error message.
Definition: Error.cc:330
int32_t type
Entity type defined within the context of a Definition
Compatibility Macros for C/C++.
std::map< EntityHeader, EntityPtr > m_entity_map
Map containing latest version of each Entity read from MetaLog.
Functions to serialize/deserialize primitives to/from a memory buffer.
Static header length.
Definition: MetaLog.h:81
void scan_log_directory(FilesystemPtr &fs, const std::string &path, std::deque< int32_t > &file_ids)
Scans MetaLog directory for numeric file names.
Definition: MetaLog.cc:54
void get_entities(std::vector< EntityPtr > &entities)
Returns latest version of all entities.
FilesystemPtr m_fs
Smart pointer to Filesystem object.
Hypertable definitions
long long int Lld
Shortcut for printf formats.
Definition: String.h:53
Implementation of checksum routines.
uint16_t version
MetaLog definition version number
Definition: MetaLog.h:85
void clear()
Clears the buffer.
std::vector< EntityPtr > m_entities
Vector containing all versions of each Entity read from MetaLog.
#define HT_THROW2_(_code_, _ex_)
Definition: Error.h:487
uint16_t m_version
MetaLog Definition version read from log file header.
std::shared_ptr< Filesystem > FilesystemPtr
Smart pointer to Filesystem.
Definition: Filesystem.h:572
#define HT_THROWF(_code_, _fmt_,...)
Definition: Error.h:490
uint8_t * base
Pointer to the allocated memory buffer.
This is a generic exception class for Hypertable.
Definition: Error.h:314
Declarations for MetaLog.
int32_t checksum
Checksum of serialized entity state
#define HT_ERRORF(msg,...)
Definition: Logger.h:300
Configuration settings.
#define HT_MAYBE_FAIL(_label_)
String extensions and helpers: sets, maps, append operators etc.
Metalog file header.
Definition: MetaLog.h:57
Error codes, Exception handling, error logging.
#define HT_THROW(_code_, _msg_)
Definition: Error.h:478
void decode(const uint8_t **bufp, size_t *remainp)
Decodes serialzed header from buffer.
Reader(FilesystemPtr &fs, DefinitionPtr &definition, int flags=0)
Constructor.
void load_file(const std::string &fname)
Loads MetaLog file.
void ensure(size_t len)
Ensure space for additional data Will grow the space to 1.5 of the needed space with existing data un...
Definition: DynamicBuffer.h:82
std::deque< int32_t > m_file_nums
Vector of numeric file names found in log directory.
std::shared_ptr< Definition > DefinitionPtr
Smart pointer to Definition.
MetaLog framework.
Definition: MetaLog.h:44
std::string m_path
Path name of MetaLog directory.
int code() const
Returns the error code.
Definition: Error.h:391
void reserve(size_t len, bool nocopy=false)
Reserve space for additional data Will grow the space to exactly what's needed.
Definition: DynamicBuffer.h:95
Executes user-defined functions when leaving the current scope.
void verify_backup(int32_t file_num)
Sanity check local backup file.