Drizzled Public API Documentation

systab_util_ms.cc
00001 /* Copyright (C) 2009 PrimeBase Technologies GmbH, Germany
00002  *
00003  * PrimeBase Media Stream for MySQL
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation; either version 2 of the License, or
00008  * (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software
00017  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
00018  *
00019  * Barry Leslie
00020  *
00021  * System table utility functions.
00022  *
00023  */
00024 #include "cslib/CSConfig.h"
00025 
00026 #include <sys/types.h>
00027 #include <sys/stat.h>
00028 #include <stdlib.h>
00029 #include <time.h>
00030 #include <inttypes.h>
00031 
00032 #include "cslib/CSGlobal.h"
00033 #include "cslib/CSStrUtil.h"
00034 #include "cslib/CSPath.h"
00035 
00036 #include "systab_util_ms.h"
00037 
00038 //======================
00039 void SysTabRec::logError(const char *text)
00040 {
00041   char msg[80];
00042   enter_();
00043   
00044   snprintf(msg, 80, ", damaged at or near position %"PRIu32" \n", (uint32_t) (ptr - getBuffer(0)));
00045   CSL.log(self, CSLog::Warning, db_name);
00046   CSL.log(self, CSLog::Warning, ".");
00047   CSL.log(self, CSLog::Warning, table_name);
00048   CSL.log(self, CSLog::Warning, " table file ");
00049   CSL.log(self, CSLog::Warning, file_name);
00050   if (text) {
00051     CSL.log(self, CSLog::Warning, " ");
00052     CSL.log(self, CSLog::Warning, text);
00053   }
00054   CSL.log(self, CSLog::Warning, msg);
00055   exit_();
00056 }
00057 
00058 #define HEAD_MARKER ((uint32_t)0XABABABAB)
00059 #define TAIL_MARKER ((uint32_t)0XCDCDCDCD)
00060 //---------------------
00061 bool SysTabRec::findRecord()
00062 {
00063   uint32_t len, marker;
00064   CSDiskData d;
00065 
00066   badRecord = true;
00067   
00068   while (badRecord) {
00069     len = end_of_data - ptr;
00070     if (len < 12)
00071       return false;
00072     
00073     // Look for the record header.
00074     d.rec_chars = ptr;  ptr +=4;  
00075     marker = CS_GET_DISK_4(d.int_val->val_4);
00076     if (marker != HEAD_MARKER) 
00077       continue;
00078       
00079     // Get the record length.
00080     d.rec_chars = ptr;  
00081     recordLength = CS_GET_DISK_4(d.int_val->val_4);
00082     if (len < recordLength)
00083       continue;
00084     
00085     end_of_record = ptr + recordLength;
00086     
00087     // Look for the record trailer.
00088     d.rec_chars = end_of_record;  
00089     marker = CS_GET_DISK_4(d.int_val->val_4);
00090     if (marker != TAIL_MARKER) 
00091       continue;
00092       
00093     ptr +=4; // Skip the record length.
00094     badRecord = false;    
00095   }
00096   
00097   return true;
00098 }
00099 
00100 //---------------------
00101 bool SysTabRec::firstRecord()
00102 {
00103   ptr = getBuffer(0);
00104   end_of_data = ptr + length();
00105   
00106   if (!findRecord()) {
00107     logError("Missing record terminator, file being ignored");
00108     return false;
00109   }
00110   
00111   return true;
00112 }
00113 
00114 //---------------------
00115 bool SysTabRec::nextRecord()
00116 {
00117   if (!ptr)
00118     return firstRecord();
00119     
00120   if (ptr <= end_of_record) 
00121     ptr = end_of_record + 4;
00122   
00123   return findRecord();
00124 }
00125   
00126 //---------------------
00127 void SysTabRec::resetRecord()
00128 {
00129   ptr= 0;
00130 }
00131 
00132 //---------------------
00133 uint8_t SysTabRec::getInt1Field()
00134 {
00135   uint8_t val = 0;
00136   CSDiskData d;
00137   
00138   if (badRecord)
00139     return val;
00140     
00141   if (ptr > (end_of_record -1)) {
00142     logError("Missing 1 byte int field");
00143     ptr = end_of_record;
00144     badRecord = true;
00145     return val;
00146   }
00147   
00148   d.rec_chars = ptr;
00149   val = CS_GET_DISK_1(d.int_val->val_1);
00150   ptr += 1;   
00151   return val;
00152 }
00153 
00154 //---------------------
00155 uint32_t SysTabRec::getInt4Field()
00156 {
00157   uint32_t val = 0;
00158   CSDiskData d;
00159   
00160   if (badRecord)
00161     return val;
00162     
00163   if (ptr > (end_of_record -4)) {
00164     logError("Missing 4 byte int field");
00165     ptr = end_of_record;
00166     badRecord = true;
00167     return val;
00168   }
00169   
00170   d.rec_chars = ptr;
00171   val = CS_GET_DISK_4(d.int_val->val_4);
00172   ptr += 4;   
00173   return val;
00174 }
00175 
00176 //---------------------
00177 const char *SysTabRec::getStringField()
00178 {
00179   const char *val = "";
00180   
00181   if (badRecord)
00182     return val;
00183     
00184   if (ptr > (end_of_record -1)) {
00185     logError("Missing string field");
00186     badRecord = true;
00187     ptr = end_of_record;
00188   } else {
00189     val = ptr;
00190     while (*ptr && ptr < end_of_record) ptr++;
00191     if (ptr == end_of_record) {
00192       logError("Unterminated string field");
00193       badRecord = true;
00194       val = "";
00195     } else
00196       ptr++;
00197   }
00198   
00199   return val;
00200 }
00201 
00202 //---------------------
00203 void SysTabRec::clear()
00204 {
00205   setLength(0);
00206 }
00207 
00208 //---------------------
00209 void SysTabRec::beginRecord()
00210 {
00211   CSDiskData d;
00212   uint32_t len = length();
00213   
00214   setLength(len + 8); // Room for header marker and record length.
00215 
00216   d.rec_chars = getBuffer(len);
00217   CS_SET_DISK_4(d.int_val->val_4, HEAD_MARKER); 
00218 
00219   start_of_record = len + 4;
00220 }
00221 
00222 //---------------------
00223 void SysTabRec::endRecord()
00224 {
00225   CSDiskData d;
00226   uint32_t len = length();
00227   
00228   // Write the record length to the head of the record
00229   d.rec_chars = getBuffer(start_of_record);
00230   CS_SET_DISK_4(d.int_val->val_4, len - start_of_record); 
00231 
00232   // Write the record trailer
00233   setLength(len + 4); 
00234   d.rec_chars = getBuffer(len);
00235   CS_SET_DISK_4(d.int_val->val_4, TAIL_MARKER);   
00236 }
00237 
00238 //---------------------
00239 void SysTabRec::setInt1Field(uint8_t val)
00240 {
00241   CSDiskData d;
00242 
00243   uint32_t len = length();
00244   
00245   setLength(len +1); // Important: set the length before getting the buffer pointer
00246   d.rec_chars = getBuffer(len);
00247   CS_SET_DISK_1(d.int_val->val_1, val); 
00248 }
00249 
00250 //---------------------
00251 void SysTabRec::setInt4Field(uint32_t val)
00252 {
00253   CSDiskData d;
00254 
00255   uint32_t len = length();
00256   
00257   setLength(len +4); // Important: set the length before getting the buffer pointer
00258   d.rec_chars = getBuffer(len);
00259   CS_SET_DISK_4(d.int_val->val_4, val); 
00260 }
00261 
00262 //---------------------
00263 void SysTabRec::setStringField(const char *val)
00264 {
00265   if (!val) val = "";
00266   append(val, strlen(val) +1);
00267 }
00268 
00269 //---------------------
00270 void SysTabRec::setStringField(const char *val, uint32_t len)
00271 {
00272   if (val)
00273     append(val, len);
00274   append("", 1);
00275 }
00276 
00277 
00278 //======================
00279 CSString *getPBMSPath(CSString *db_path)
00280 {
00281   char pbms_path[PATH_MAX];
00282   enter_();
00283   
00284   push_(db_path); 
00285   cs_strcpy(PATH_MAX, pbms_path, db_path->getCString());
00286   release_(db_path);
00287   
00288   cs_remove_last_name_of_path(pbms_path);
00289 
00290   return_(CSString::newString(pbms_path));
00291 }
00292 
00293 
00294 //----------------------------
00295 CSPath *getSysFile(CSString *db_path, const char *name_arg, size_t min_size)
00296 {
00297   CSPath      *path;
00298   CSStringBuffer  *name;
00299   char      *ptr;
00300 
00301   enter_();
00302   
00303   push_(db_path);
00304   new_(name, CSStringBuffer());
00305   push_(name);
00306   name->append(name_arg);
00307   name->append(".dat");
00308   
00309   ptr = name->getBuffer(strlen(name_arg));
00310 
00311 try_again:
00312   path = CSPath::newPath(RETAIN(db_path), name->getCString());
00313   push_(path);
00314   if (!path->exists()) {
00315     CSPath *tmp_path;
00316 
00317     strcpy(ptr, ".tmp");
00318     tmp_path = CSPath::newPath(RETAIN(db_path), name->getCString());
00319     push_(tmp_path);
00320     if (tmp_path->exists()) {
00321       strcpy(ptr, ".dat");
00322       tmp_path->rename(name->getCString());
00323     }
00324     release_(tmp_path);
00325   }
00326   
00327   // If the file if too small assume it is garbage.
00328   if (path->exists() && (path->getSize() < min_size)) {
00329     path->removeFile();
00330     release_(path);
00331     goto try_again;
00332   }
00333   
00334   pop_(path);
00335   release_(name);
00336   release_(db_path);
00337   return_(path);
00338 }
00339