0.9.8.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
CellStoreFactory.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 
26 
27 #include <Common/Compat.h>
28 #include "CellStoreFactory.h"
29 
47 
48 #include <Common/Filesystem.h>
49 #include <Common/Serialization.h>
50 
51 #include <boost/shared_array.hpp>
52 
53 using namespace Hypertable;
54 using namespace std;
55 
57  const char *start_row, const char *end_row) {
58  String start = (start_row) ? start_row : "";
59  String end = (end_row) ? end_row : Key::END_ROW_MARKER;
60  int64_t file_length;
61  int32_t fd;
62  size_t nread, amount;
63  uint64_t offset;
64  uint16_t version;
65  uint32_t oflags = 0;
66  CellStorePtr cellstore;
67 
69  file_length = Global::dfs->length(name, false);
70 
71  bool second_try = false;
72 
73  if (HT_IO_ALIGNED(file_length))
75 
77  fd = Global::dfs->open(name, oflags);
78 
79  try_again:
80 
81  amount = (file_length < HT_DIRECT_IO_ALIGNMENT) ? file_length : HT_DIRECT_IO_ALIGNMENT;
82  offset = file_length - amount;
83 
84  boost::shared_array<uint8_t> trailer_buf( new uint8_t [amount] );
85 
86  nread = Global::dfs->pread(fd, trailer_buf.get(), amount, offset, second_try);
87 
88  if (nread != amount)
90  "Problem reading trailer for CellStore file '%s'"
91  " - only read %d of %lu bytes", name.c_str(),
92  (int)nread, (Lu)amount);
93 
94  const uint8_t *ptr = trailer_buf.get() + (amount-2);
95  size_t remaining = 2;
96 
97  version = Serialization::decode_i16(&ptr, &remaining);
98 
99  // If file format is < 4 and happens to be aligned, reopen non-directio
100  if (version < 4 && oflags) {
101  Global::dfs->close(fd);
102  fd = Global::dfs->open(name, 0);
103  }
104 
105  if (version == 7) {
106  CellStoreTrailerV7 trailer_v7;
107 
108  if (amount < trailer_v7.size())
110  "Bad length of CellStoreV7 file '%s' - %llu",
111  name.c_str(), (Llu)file_length);
112 
113  try {
114  trailer_v7.deserialize(trailer_buf.get() + (amount - trailer_v7.size()));
115  }
116  catch (Exception &e) {
117  Global::dfs->close(fd);
118  if (!second_try && e.code() == Error::CHECKSUM_MISMATCH) {
119  fd = Global::dfs->open(name, oflags|Filesystem::OPEN_FLAG_VERIFY_CHECKSUM);
120  second_try = true;
121  goto try_again;
122  }
123  HT_ERRORF("Problem deserializing trailer of %s", name.c_str());
124  throw;
125  }
126 
127  cellstore = make_shared<CellStoreV7>(Global::dfs.get());
128  cellstore->open(name, start, end, fd, file_length, &trailer_v7);
129  if (!cellstore)
130  HT_ERRORF("Failed to open CellStore %s [%s..%s], length=%llu",
131  name.c_str(), start.c_str(), end.c_str(), (Llu)file_length);
132  return cellstore;
133  }
134  else if (version == 6) {
135  CellStoreTrailerV6 trailer_v6;
136 
137  if (amount < trailer_v6.size())
139  "Bad length of CellStoreV6 file '%s' - %llu",
140  name.c_str(), (Llu)file_length);
141 
142  try {
143  trailer_v6.deserialize(trailer_buf.get() + (amount - trailer_v6.size()));
144  }
145  catch (Exception &e) {
146  Global::dfs->close(fd);
147  if (!second_try && e.code() == Error::CHECKSUM_MISMATCH) {
148  fd = Global::dfs->open(name, oflags|Filesystem::OPEN_FLAG_VERIFY_CHECKSUM);
149  second_try = true;
150  goto try_again;
151  }
152  HT_ERRORF("Problem deserializing trailer of %s", name.c_str());
153  throw;
154  }
155 
156  cellstore = make_shared<CellStoreV6>(Global::dfs.get());
157  cellstore->open(name, start, end, fd, file_length, &trailer_v6);
158  if (!cellstore)
159  HT_ERRORF("Failed to open CellStore %s [%s..%s], length=%llu",
160  name.c_str(), start.c_str(), end.c_str(), (Llu)file_length);
161  return cellstore;
162  }
163  else if (version == 5) {
164  CellStoreTrailerV5 trailer_v5;
165 
166  if (amount < trailer_v5.size())
168  "Bad length of CellStoreV5 file '%s' - %llu",
169  name.c_str(), (Llu)file_length);
170 
171  trailer_v5.deserialize(trailer_buf.get() + (amount - trailer_v5.size()));
172 
173  cellstore = make_shared<CellStoreV5>(Global::dfs.get());
174  cellstore->open(name, start, end, fd, file_length, &trailer_v5);
175  if (!cellstore)
176  HT_ERRORF("Failed to open CellStore %s [%s..%s], length=%llu",
177  name.c_str(), start.c_str(), end.c_str(), (Llu)file_length);
178  return cellstore;
179  }
180  else if (version == 4) {
181  CellStoreTrailerV4 trailer_v4;
182 
183  if (amount < trailer_v4.size())
185  "Bad length of CellStoreV4 file '%s' - %llu",
186  name.c_str(), (Llu)file_length);
187 
188  trailer_v4.deserialize(trailer_buf.get() + (amount - trailer_v4.size()));
189 
190  cellstore = make_shared<CellStoreV4>(Global::dfs.get());
191  cellstore->open(name, start, end, fd, file_length, &trailer_v4);
192  if (!cellstore)
193  HT_ERRORF("Failed to open CellStore %s [%s..%s], length=%llu",
194  name.c_str(), start.c_str(), end.c_str(), (Llu)file_length);
195  return cellstore;
196  }
197  else if (version == 3) {
198  CellStoreTrailerV3 trailer_v3;
199 
200  if (amount < trailer_v3.size())
202  "Bad length of CellStoreV3 file '%s' - %llu",
203  name.c_str(), (Llu)file_length);
204 
205  trailer_v3.deserialize(trailer_buf.get() + (amount - trailer_v3.size()));
206 
207  cellstore = make_shared<CellStoreV3>(Global::dfs.get());
208  cellstore->open(name, start, end, fd, file_length, &trailer_v3);
209  if (!cellstore)
210  HT_ERRORF("Failed to open CellStore %s [%s..%s], length=%llu",
211  name.c_str(), start.c_str(), end.c_str(), (Llu)file_length);
212  return cellstore;
213  }
214  else if (version == 2) {
215  CellStoreTrailerV2 trailer_v2;
216 
217  if (amount < trailer_v2.size())
219  "Bad length of CellStoreV2 file '%s' - %llu",
220  name.c_str(), (Llu)file_length);
221 
222  trailer_v2.deserialize(trailer_buf.get() + (amount - trailer_v2.size()));
223 
224  cellstore = make_shared<CellStoreV2>(Global::dfs.get());
225  cellstore->open(name, start, end, fd, file_length, &trailer_v2);
226  if (!cellstore)
227  HT_ERRORF("Failed to open CellStore %s [%s..%s], length=%llu",
228  name.c_str(), start.c_str(), end.c_str(), (Llu)file_length);
229  return cellstore;
230  }
231  else if (version == 1) {
232  CellStoreTrailerV1 trailer_v1;
233 
234  if (amount < trailer_v1.size())
236  "Bad length of CellStoreV1 file '%s' - %llu",
237  name.c_str(), (Llu)file_length);
238 
239  trailer_v1.deserialize(trailer_buf.get() + (amount - trailer_v1.size()));
240 
241  cellstore = make_shared<CellStoreV1>(Global::dfs.get());
242  cellstore->open(name, start, end, fd, file_length, &trailer_v1);
243  if (!cellstore)
244  HT_ERRORF("Failed to open CellStore %s [%s..%s], length=%llu",
245  name.c_str(), start.c_str(), end.c_str(), (Llu)file_length);
246  return cellstore;
247  }
248  else if (version == 0) {
249  CellStoreTrailerV0 trailer_v0;
250 
251  if (amount < trailer_v0.size())
253  "Bad length of CellStoreV0 file '%s' - %llu",
254  name.c_str(), (Llu)file_length);
255 
256  trailer_v0.deserialize(trailer_buf.get() + (amount - trailer_v0.size()));
257 
258  cellstore = make_shared<CellStoreV0>(Global::dfs.get());
259  cellstore->open(name, start, end, fd, file_length, &trailer_v0);
260  if (!cellstore)
261  HT_ERRORF("Failed to open CellStore %s [%s..%s], length=%llu",
262  name.c_str(), start.c_str(), end.c_str(), (Llu)file_length);
263  return cellstore;
264  }
265  else {
266  Global::dfs->close(fd);
267  if (!second_try) {
268  fd = Global::dfs->open(name, oflags|Filesystem::OPEN_FLAG_VERIFY_CHECKSUM);
269  second_try = true;
270  goto try_again;
271  }
273  "Unrecognized cell store version %d", (int)version);
274  }
275  return CellStorePtr();
276 }
virtual size_t size()
Returns the serialized size of the trailer.
Declarations for CellStoreFactory.
Abstract base class for a filesystem.
Declarations for CellStoreV7.
std::string String
A String is simply a typedef to std::string.
Definition: String.h:44
#define HT_IO_ALIGNED(size)
Definition: Filesystem.h:51
virtual void deserialize(const uint8_t *buf)
Deserializes the trailer from the given buffer.
virtual void deserialize(const uint8_t *buf)
Deserializes the trailer from the given buffer.
virtual size_t size()
Returns the serialized size of the trailer.
long long unsigned int Llu
Shortcut for printf formats.
Definition: String.h:50
STL namespace.
virtual size_t size()
Returns the serialized size of the trailer.
virtual size_t size()
Returns the serialized size of the trailer.
virtual void deserialize(const uint8_t *buf)
Deserializes the trailer from the given buffer.
virtual size_t size()
Returns the serialized size of the trailer.
uint16_t decode_i16(const uint8_t **bufp, size_t *remainp)
Decode a 16-bit integer in little-endian order.
virtual size_t size()
Returns the serialized size of the trailer.
Compatibility Macros for C/C++.
Functions to serialize/deserialize primitives to/from a memory buffer.
static Hypertable::FilesystemPtr dfs
Definition: Global.h:64
virtual void deserialize(const uint8_t *buf)
Deserializes the trailer from the given buffer.
std::shared_ptr< CellStore > CellStorePtr
Smart pointer to CellStore.
Definition: CellStore.h:340
Hypertable definitions
virtual void deserialize(const uint8_t *buf)
Deserializes the trailer from the given buffer.
Represents the trailer for CellStore version 7.
#define HT_THROWF(_code_, _fmt_,...)
Definition: Error.h:490
virtual size_t size()
Returns the serialized size of the trailer.
This is a generic exception class for Hypertable.
Definition: Error.h:314
virtual void deserialize(const uint8_t *buf)
Deserializes the trailer from the given buffer.
Declarations for CellStoreTrailerV7.
long unsigned int Lu
Shortcut for printf formats.
Definition: String.h:47
#define HT_ERRORF(msg,...)
Definition: Logger.h:300
virtual size_t size()
Returns the serialized size of the trailer.
static CellStorePtr open(const String &name, const char *start_row, const char *end_row)
Creates a CellStore object from a given cell store file.
Declarations for CellStoreV6.
virtual void deserialize(const uint8_t *buf)
Deserializes the trailer from the given buffer.
static const char * END_ROW_MARKER
Definition: Key.h:49
virtual void deserialize(const uint8_t *buf)
Deserializes the trailer from the given buffer.
#define HT_DIRECT_IO_ALIGNMENT
Definition: Filesystem.h:49
int code() const
Returns the error code.
Definition: Error.h:391