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 /*****************************************************************************
19  * $Id: we_colbufmgrdctnry.cpp 4726 2013-08-07 03:38:36Z bwilkinson $
20  *
21  ****************************************************************************/
22 
23 #include "we_colbufmgr.h"
24 #include "we_columninfo.h"
25 #include "we_log.h"
26 #include <iostream>
27 #include <sstream>
28 
29 namespace WriteEngine
30 {
31 
32 //------------------------------------------------------------------------------
33 // ColumnBufferManagerDctnry constructor that takes a ColumnInfo, colWidth, and
34 // FILE*.
35 //------------------------------------------------------------------------------
ColumnBufferManagerDctnry(ColumnInfo * pColInfo,int colWidth,Log * logger,int compressionType)36 ColumnBufferManagerDctnry::ColumnBufferManagerDctnry(
37     ColumnInfo* pColInfo,  int colWidth, Log* logger, int compressionType) :
38     ColumnBufferManager(pColInfo, colWidth, logger, compressionType)
39 {
40 }
41 
42 //------------------------------------------------------------------------------
43 // ColumnBufferManagerDctnry destructor.
44 //------------------------------------------------------------------------------
~ColumnBufferManagerDctnry()45 ColumnBufferManagerDctnry::~ColumnBufferManagerDctnry()
46 {
47 }
48 
49 //------------------------------------------------------------------------------
50 // If we wanted to intercept the row data being written out by
51 // ColumnBufferManagerDctnry in order to break up any buffer crossing an
52 // extent boundary, this is where that logic would reside.  However, for
53 // dictionary columns we perform this extent division up front.  So for a
54 // dictionary column, this function is a simple pass-thru to the ColumnBuffer's
55 // writeToFile() function.
56 // The data to be written, starts at "startOffset" in the internal buffer and
57 // is "writeSize" bytes long.
58 //------------------------------------------------------------------------------
writeToFileExtentCheck(uint32_t startOffset,uint32_t writeSize)59 int ColumnBufferManagerDctnry::writeToFileExtentCheck(
60     uint32_t startOffset, uint32_t writeSize)
61 {
62     if (fLog->isDebug( DEBUG_3 ))
63     {
64         std::ostringstream oss;
65         oss << "Dctnry writeToFileExtentCheck"
66             ": OID-"    << fColInfo->curCol.dataFile.fid        <<
67             "; DBRoot-" << fColInfo->curCol.dataFile.fDbRoot    <<
68             "; part-"   << fColInfo->curCol.dataFile.fPartition <<
69             "; seg-"    << fColInfo->curCol.dataFile.fSegment   <<
70             "; writeSize-"        << writeSize                  <<
71             "; oldAvailFileSize-" << fColInfo->availFileSize    <<
72             "; newAvailFileSize-" << (fColInfo->availFileSize - writeSize);
73         fLog->logMsg( oss.str(), MSGLVL_INFO2 );
74     }
75 
76     int rc = fCBuf->writeToFile(startOffset, writeSize);
77 
78     if (rc != NO_ERROR)
79     {
80         WErrorCodes ec;
81         std::ostringstream oss;
82         oss << "writeToFileExtentCheck: write token extent failed: " <<
83             ec.errorString(rc);
84         fLog->logMsg( oss.str(), rc, MSGLVL_ERROR );
85         return rc;
86     }
87 
88     fColInfo->updateBytesWrittenCounts( writeSize );
89 
90     return NO_ERROR;
91 }
92 
93 //------------------------------------------------------------------------------
94 // Before a section is reserved to contain "nRows" of incoming data, this
95 // function can be called to determine whether this group of rows will cause
96 // the buffer to cross an extent boundary.  If there is not room for "nRows",
97 // the number of rows that will fit in the current extent are returned.
98 // This function also catches and handles the case where an abbreviated
99 // extent needs to be expanded to a full extent on disk.
100 //
101 // WARNING: If the extent is expanded, then this function will change the
102 //          information in the ColumnInfo struct that owns this
103 //          ColumnBufferManagerDctnry.
104 //------------------------------------------------------------------------------
rowsExtentCheck(int nRows,int & nRows2)105 int ColumnBufferManagerDctnry::rowsExtentCheck( int nRows, int& nRows2 )
106 {
107     nRows2 = nRows;
108 
109     int bufferSize    = fCBuf->getSize();
110     long long spaceRequired = nRows * fColWidth;
111     long dataInBuffer  = 0;
112 
113     if (bufferSize > 0)
114         dataInBuffer = (fBufFreeOffset - fBufWriteOffset + bufferSize) % bufferSize;
115 
116     // if extent is out of space, see if this is an abbrev extent we can expand
117     if (((dataInBuffer + spaceRequired) > fColInfo->availFileSize) &&
118             (fColInfo->isAbbrevExtent()))
119     {
120         RETURN_ON_ERROR( fColInfo->expandAbbrevExtent(true) )
121     }
122 
123     if ((dataInBuffer + spaceRequired) > fColInfo->availFileSize)
124     {
125         spaceRequired = fColInfo->availFileSize - dataInBuffer;
126         nRows2        = (int)(spaceRequired / fColWidth);
127 
128         if (fLog->isDebug( DEBUG_1 ))
129         {
130             std::ostringstream oss1;
131             oss1 << "Dctnry rowsExtentCheck (filling extent): OID-"    <<
132                  fColInfo->curCol.dataFile.fid <<
133                  "; DBRoot-" << fColInfo->curCol.dataFile.fDbRoot    <<
134                  "; part-"   << fColInfo->curCol.dataFile.fPartition <<
135                  "; seg-"    << fColInfo->curCol.dataFile.fSegment   <<
136                  "; spaceRequired-" << spaceRequired <<
137                  "; dataInBuffer-"  << dataInBuffer <<
138                  "; availSpace-"    << fColInfo->availFileSize;
139             fLog->logMsg( oss1.str(), MSGLVL_INFO2 );
140 
141             std::ostringstream oss2;
142             oss2 << "Dctnry rowsExtentCheck: OID-" <<
143                  fColInfo->curCol.dataFile.fid <<
144                  "; DBRoot-" << fColInfo->curCol.dataFile.fDbRoot    <<
145                  "; part-"   << fColInfo->curCol.dataFile.fPartition <<
146                  "; seg-"    << fColInfo->curCol.dataFile.fSegment   <<
147                  "; Changing nRows from " << nRows << " to " << nRows2;
148             fLog->logMsg( oss2.str(), MSGLVL_INFO2 );
149         }
150     }
151     else
152     {
153         if (fLog->isDebug( DEBUG_2 ))
154         {
155             std::ostringstream oss;
156             oss << "Dctnry rowsExtentCheck: OID-" <<
157                 fColInfo->curCol.dataFile.fid <<
158                 "; DBRoot-" << fColInfo->curCol.dataFile.fDbRoot    <<
159                 "; part-"   << fColInfo->curCol.dataFile.fPartition <<
160                 "; seg-"    << fColInfo->curCol.dataFile.fSegment   <<
161                 "; spaceRequired-" << spaceRequired <<
162                 "; dataInBuffer-"  << dataInBuffer <<
163                 "; availSpace-"    << fColInfo->availFileSize;
164             fLog->logMsg( oss.str(), MSGLVL_INFO2 );
165         }
166     }
167 
168     return NO_ERROR;
169 }
170 
171 }
172