1 /* Copyright (C) 2014 InfiniDB, Inc.
2
3 This program is free software; you can redistribute it and/or
4 modify it under the terms of the GNU General Public License
5 as published by the Free Software Foundation; version 2 of
6 the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
16 MA 02110-1301, USA. */
17
18 #include "we_bulkrollbackfilecompressedhdfs.h"
19
20 #include <sstream>
21 #include <boost/scoped_array.hpp>
22 #include <boost/filesystem/path.hpp>
23 #include <boost/filesystem/convenience.hpp>
24
25 #include "we_define.h"
26 #include "we_fileop.h"
27 #include "we_bulkrollbackmgr.h"
28 #include "we_confirmhdfsdbfile.h"
29 #include "we_convertor.h"
30 #include "messageids.h"
31 #include "IDBDataFile.h"
32 #include "IDBPolicy.h"
33 using namespace idbdatafile;
34 using namespace compress;
35 using namespace execplan;
36
37 namespace
38 {
39 const char* DATA_DIR_SUFFIX = "_data";
40 const char* OLD_FILE_SUFFIX = ".old_bulk";
41 }
42
43 namespace WriteEngine
44 {
45
46 //------------------------------------------------------------------------------
47 // BulkRollbackFileCompressedHdfs constructor
48 //------------------------------------------------------------------------------
BulkRollbackFileCompressedHdfs(BulkRollbackMgr * mgr)49 BulkRollbackFileCompressedHdfs::BulkRollbackFileCompressedHdfs(
50 BulkRollbackMgr* mgr) :
51 BulkRollbackFile(mgr)
52 {
53 }
54
55 //------------------------------------------------------------------------------
56 // BulkRollbackFileCompressedHdfs destructor
57 //------------------------------------------------------------------------------
~BulkRollbackFileCompressedHdfs()58 BulkRollbackFileCompressedHdfs::~BulkRollbackFileCompressedHdfs()
59 {
60 }
61
62 //------------------------------------------------------------------------------
63 // Truncate the specified database segment file to the extent specified by
64 // the given file offset. Also updates the header(s) as well.
65 //
66 // columnOID - OID of segment file to be truncated
67 // dbRoot - DBRoot of segment file to be truncated
68 // partNum - Partition number of segment file to be truncated
69 // segNum - Segment number of segment file to be truncated
70 // fileSizeBlocks - Number of raw data blocks to be left in the file.
71 // Remainder of file is to be truncated.
72 //------------------------------------------------------------------------------
truncateSegmentFile(OID columnOID,uint32_t dbRoot,uint32_t partNum,uint32_t segNum,long long fileSizeBlocks)73 void BulkRollbackFileCompressedHdfs::truncateSegmentFile(
74 OID columnOID,
75 uint32_t dbRoot,
76 uint32_t partNum,
77 uint32_t segNum,
78 long long fileSizeBlocks )
79 {
80 std::ostringstream msgText;
81 msgText << "Truncating compressed HDFS column file"
82 ": dbRoot-" << dbRoot <<
83 "; part#-" << partNum <<
84 "; seg#-" << segNum <<
85 "; rawTotBlks-" << fileSizeBlocks;
86 fMgr->logAMessage( logging::LOG_TYPE_INFO,
87 logging::M0075, columnOID, msgText.str() );
88
89 restoreFromBackup( "column", columnOID, dbRoot, partNum, segNum );
90 }
91
92 //------------------------------------------------------------------------------
93 // Reinitialize a column segment extent (in the db file) to empty values,
94 // following the HWM. Remaining extents in the file are truncated.
95 // Also updates the header(s) as well.
96 //
97 // columnOID - OID of segment file to be reinitialized
98 // dbRoot - DBRoot of segment file to be reinitialized
99 // partNum - Partition number of segment file to be reinitialized
100 // segNum - Segment number of segment file to be reinitialized
101 // startOffsetBlk - File offset (after the HWM block), at which the file is
102 // to be reinitialized. Value is in raw data blocks.
103 // nBlocks - Number of blocks to be reinitialized
104 // colType - Data type of the applicable column
105 // colWidth - Width in bytes, of the applicable column
106 // restoreHwmChk - Specifies whether HWM chunk is to be restored.
107 //------------------------------------------------------------------------------
reInitTruncColumnExtent(OID columnOID,uint32_t dbRoot,uint32_t partNum,uint32_t segNum,long long startOffsetBlk,int nBlocks,CalpontSystemCatalog::ColDataType colType,uint32_t colWidth,bool restoreHwmChk)108 void BulkRollbackFileCompressedHdfs::reInitTruncColumnExtent(
109 OID columnOID,
110 uint32_t dbRoot,
111 uint32_t partNum,
112 uint32_t segNum,
113 long long startOffsetBlk,
114 int nBlocks,
115 CalpontSystemCatalog::ColDataType colType,
116 uint32_t colWidth,
117 bool restoreHwmChk )
118 {
119 long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
120
121 std::ostringstream msgText;
122 msgText << "Reinit HWM compressed column extent in HDFS db file" <<
123 ": dbRoot-" << dbRoot <<
124 "; part#-" << partNum <<
125 "; seg#-" << segNum <<
126 "; rawOffset(bytes)-" << startOffset <<
127 "; rawFreeBlks-" << nBlocks;
128 fMgr->logAMessage( logging::LOG_TYPE_INFO,
129 logging::M0075, columnOID, msgText.str() );
130
131 restoreFromBackup( "column", columnOID, dbRoot, partNum, segNum );
132 }
133
134 //------------------------------------------------------------------------------
135 // Reinitialize a dictionary segment extent (in the db file) to empty blocks,
136 // following the HWM. Remaining extents in the file are truncated.
137 // Also updates the header(s) as well.
138 //
139 // dStoreOID - OID of segment store file to be reinitialized
140 // dbRoot - DBRoot of segment file to be reinitialized
141 // partNum - Partition number of segment file to be reinitialized
142 // segNum - Segment number of segment file to be reinitialized
143 // startOffsetBlk - Starting block (after the HWM block), at which the file is
144 // to be reinitialized. Value is in raw data blocks.
145 // nBlocks - Number of blocks to be reinitialized
146 //------------------------------------------------------------------------------
reInitTruncDctnryExtent(OID dStoreOID,uint32_t dbRoot,uint32_t partNum,uint32_t segNum,long long startOffsetBlk,int nBlocks)147 void BulkRollbackFileCompressedHdfs::reInitTruncDctnryExtent(
148 OID dStoreOID,
149 uint32_t dbRoot,
150 uint32_t partNum,
151 uint32_t segNum,
152 long long startOffsetBlk,
153 int nBlocks )
154 {
155 long long startOffset = startOffsetBlk * BYTE_PER_BLOCK;
156
157 std::ostringstream msgText;
158 msgText << "Reinit HWM compressed dictionary store extent in HDFS db file"
159 ": dbRoot-" << dbRoot <<
160 "; part#-" << partNum <<
161 "; seg#-" << segNum <<
162 "; rawOffset(bytes)-" << startOffset <<
163 "; rawFreeBlks-" << nBlocks;
164 fMgr->logAMessage( logging::LOG_TYPE_INFO,
165 logging::M0075, dStoreOID, msgText.str() );
166
167 restoreFromBackup( "dictionary store", dStoreOID, dbRoot, partNum, segNum );
168 }
169
170 //------------------------------------------------------------------------------
171 // For HDFS system, just always return true.
172 // Let ConfirmHdfsDbFile later determine when/if/how to restore from any
173 // existing backup file.
174 //------------------------------------------------------------------------------
doWeReInitExtent(OID columnOID,uint32_t dbRoot,uint32_t partNum,uint32_t segNum) const175 bool BulkRollbackFileCompressedHdfs::doWeReInitExtent( OID columnOID,
176 uint32_t dbRoot,
177 uint32_t partNum,
178 uint32_t segNum) const
179 {
180 return true;
181 }
182
183 //------------------------------------------------------------------------------
184 // Replace the currently specified db file with it's corresponding backup file.
185 // The backup file is a complete backup, not just a backup of a single chunk.
186 //
187 // The initial implementation for this function restored from a NNN.pNNN.sNNN
188 // file stored under the meta file directory.
189 // The latest implementation for this function restores from a FILENNN.cdf.tmp
190 // or FILENNN.cdf.orig file stored in the same OID directory as the FILENNN.cdf
191 // file.
192 // However, this function still looks for the first backup file (NNN.pNNN.sNNN)
193 // in case the user did not upgrade cleanly, and we have to restore using an
194 // old leftover backup file.
195 //------------------------------------------------------------------------------
restoreFromBackup(const char * colType,OID columnOID,uint32_t dbRoot,uint32_t partNum,uint32_t segNum)196 void BulkRollbackFileCompressedHdfs::restoreFromBackup(const char* colType,
197 OID columnOID,
198 uint32_t dbRoot,
199 uint32_t partNum,
200 uint32_t segNum)
201 {
202 // Construct file name for db file to be restored
203 char dbFileName[FILE_NAME_SIZE];
204 int rc = fDbFile.getFileName( columnOID, dbFileName,
205 dbRoot, partNum, segNum );
206
207 if (rc != NO_ERROR)
208 {
209 std::ostringstream oss;
210 oss << "Error restoring " << colType <<
211 " HDFS file for OID " << columnOID <<
212 "; Can't construct file name for DBRoot" << dbRoot <<
213 "; partition-" << partNum <<
214 "; segment-" << segNum;
215 throw WeException( oss.str(), rc );
216 }
217
218 // Construct file name for backup copy of db file
219 std::ostringstream ossFile;
220 ossFile << "/" << columnOID << ".p" << partNum << ".s" << segNum;
221 std::string backupFileName( fMgr->getMetaFileName() );
222 backupFileName += DATA_DIR_SUFFIX;
223 backupFileName += ossFile.str();
224
225 std::string dbFileNameTmp = dbFileName;
226 dbFileNameTmp += OLD_FILE_SUFFIX;
227
228 // For backwards compatibility...
229 // Restore from backup file used in initial HDFS release, in case the user
230 // upgraded without going down cleanly. In that case we might need to
231 // rollback using an old backup file left from previous release.
232 if ( IDBPolicy::exists(backupFileName.c_str()) )
233 {
234 // Rename current db file to make room for restored file
235 rc = IDBPolicy::rename( dbFileName, dbFileNameTmp.c_str() );
236
237 if (rc != 0)
238 {
239 std::ostringstream oss;
240 oss << "Error restoring " << colType <<
241 " HDFS file for OID " << columnOID <<
242 "; Can't move old file for DBRoot" << dbRoot <<
243 "; partition-" << partNum <<
244 "; segment-" << segNum;
245 throw WeException( oss.str(), ERR_COMP_RENAME_FILE );
246 }
247
248 // Rename backup file to replace current db file
249 rc = IDBPolicy::rename( backupFileName.c_str(), dbFileName );
250
251 if (rc != 0)
252 {
253 std::ostringstream oss;
254 oss << "Error restoring " << colType <<
255 " HDFS file for OID " << columnOID <<
256 "; Can't rename backup file for DBRoot" << dbRoot <<
257 "; partition-" << partNum <<
258 "; segment-" << segNum;
259 throw WeException( oss.str(), ERR_METADATABKUP_COMP_RENAME );
260 }
261
262 // Delete db file we just replaced with backup
263 IDBPolicy::remove( dbFileNameTmp.c_str() );
264 }
265 else // Restore from HDFS temp swap backup file; This is the normal case
266 {
267 std::string errMsg;
268 ConfirmHdfsDbFile confirmHdfs;
269 rc = confirmHdfs.endDbFileChange( std::string("tmp"),
270 dbFileName,
271 false,
272 errMsg);
273
274 if (rc != 0)
275 {
276 std::ostringstream oss;
277 oss << "Error restoring " << colType <<
278 " HDFS file for OID " << columnOID <<
279 "; DBRoot" << dbRoot <<
280 "; partition-" << partNum <<
281 "; segment-" << segNum <<
282 "; " << errMsg;
283 throw WeException( oss.str(), rc );
284 }
285 }
286 }
287
288 } //end of namespace
289