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