Drizzled Public API Documentation

mtr0log.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved.
00004 
00005 This program is free software; you can redistribute it and/or modify it under
00006 the terms of the GNU General Public License as published by the Free Software
00007 Foundation; version 2 of the License.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT
00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with
00014 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00015 St, Fifth Floor, Boston, MA 02110-1301 USA
00016 
00017 *****************************************************************************/
00018 
00019 /**************************************************/
00026 #include "mtr0log.h"
00027 
00028 #ifdef UNIV_NONINL
00029 #include "mtr0log.ic"
00030 #endif
00031 
00032 #include "buf0buf.h"
00033 #include "dict0dict.h"
00034 #include "log0recv.h"
00035 #include "page0page.h"
00036 
00037 #ifndef UNIV_HOTBACKUP
00038 # include "dict0boot.h"
00039 
00040 /********************************************************/
00042 UNIV_INTERN
00043 void
00044 mlog_catenate_string(
00045 /*=================*/
00046   mtr_t*    mtr,  
00047   const byte* str,  
00048   ulint   len)  
00049 {
00050   dyn_array_t*  mlog;
00051 
00052   if (mtr_get_log_mode(mtr) == MTR_LOG_NONE) {
00053 
00054     return;
00055   }
00056 
00057   mlog = &(mtr->log);
00058 
00059   dyn_push_string(mlog, str, len);
00060 }
00061 
00062 /********************************************************/
00066 UNIV_INTERN
00067 void
00068 mlog_write_initial_log_record(
00069 /*==========================*/
00070   const byte* ptr,  
00073   byte    type, 
00074   mtr_t*    mtr)  
00075 {
00076   byte* log_ptr;
00077 
00078   ut_ad(type <= MLOG_BIGGEST_TYPE);
00079   ut_ad(type > MLOG_8BYTES);
00080 
00081   log_ptr = mlog_open(mtr, 11);
00082 
00083   /* If no logging is requested, we may return now */
00084   if (log_ptr == NULL) {
00085 
00086     return;
00087   }
00088 
00089   log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
00090 
00091   mlog_close(mtr, log_ptr);
00092 }
00093 #endif /* !UNIV_HOTBACKUP */
00094 
00095 /********************************************************/
00098 UNIV_INTERN
00099 byte*
00100 mlog_parse_initial_log_record(
00101 /*==========================*/
00102   byte* ptr,  
00103   byte* end_ptr,
00104   byte* type, 
00105   ulint*  space,  
00106   ulint*  page_no)
00107 {
00108   if (end_ptr < ptr + 1) {
00109 
00110     return(NULL);
00111   }
00112 
00113   *type = (byte)((ulint)*ptr & ~MLOG_SINGLE_REC_FLAG);
00114   ut_ad(*type <= MLOG_BIGGEST_TYPE);
00115 
00116   ptr++;
00117 
00118   if (end_ptr < ptr + 2) {
00119 
00120     return(NULL);
00121   }
00122 
00123   ptr = mach_parse_compressed(ptr, end_ptr, space);
00124 
00125   if (ptr == NULL) {
00126 
00127     return(NULL);
00128   }
00129 
00130   ptr = mach_parse_compressed(ptr, end_ptr, page_no);
00131 
00132   return(ptr);
00133 }
00134 
00135 /********************************************************/
00138 UNIV_INTERN
00139 byte*
00140 mlog_parse_nbytes(
00141 /*==============*/
00142   ulint type, 
00143   byte* ptr,  
00144   byte* end_ptr,
00145   byte* page, 
00146   void* page_zip)
00147 {
00148   ulint   offset;
00149   ulint   val;
00150   ib_uint64_t dval;
00151 
00152   ut_a(type <= MLOG_8BYTES);
00153   ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
00154 
00155   if (end_ptr < ptr + 2) {
00156 
00157     return(NULL);
00158   }
00159 
00160   offset = mach_read_from_2(ptr);
00161   ptr += 2;
00162 
00163   if (offset >= UNIV_PAGE_SIZE) {
00164     recv_sys->found_corrupt_log = TRUE;
00165 
00166     return(NULL);
00167   }
00168 
00169   if (type == MLOG_8BYTES) {
00170     ptr = mach_ull_parse_compressed(ptr, end_ptr, &dval);
00171 
00172     if (ptr == NULL) {
00173 
00174       return(NULL);
00175     }
00176 
00177     if (page) {
00178       if (UNIV_LIKELY_NULL(page_zip)) {
00179         mach_write_to_8
00180           (((page_zip_des_t*) page_zip)->data
00181            + offset, dval);
00182       }
00183       mach_write_to_8(page + offset, dval);
00184     }
00185 
00186     return(ptr);
00187   }
00188 
00189   ptr = mach_parse_compressed(ptr, end_ptr, &val);
00190 
00191   if (ptr == NULL) {
00192 
00193     return(NULL);
00194   }
00195 
00196   switch (type) {
00197   case MLOG_1BYTE:
00198     if (UNIV_UNLIKELY(val > 0xFFUL)) {
00199       goto corrupt;
00200     }
00201     if (page) {
00202       if (UNIV_LIKELY_NULL(page_zip)) {
00203         mach_write_to_1
00204           (((page_zip_des_t*) page_zip)->data
00205            + offset, val);
00206       }
00207       mach_write_to_1(page + offset, val);
00208     }
00209     break;
00210   case MLOG_2BYTES:
00211     if (UNIV_UNLIKELY(val > 0xFFFFUL)) {
00212       goto corrupt;
00213     }
00214     if (page) {
00215       if (UNIV_LIKELY_NULL(page_zip)) {
00216         mach_write_to_2
00217           (((page_zip_des_t*) page_zip)->data
00218            + offset, val);
00219       }
00220       mach_write_to_2(page + offset, val);
00221     }
00222     break;
00223   case MLOG_4BYTES:
00224     if (page) {
00225       if (UNIV_LIKELY_NULL(page_zip)) {
00226         mach_write_to_4
00227           (((page_zip_des_t*) page_zip)->data
00228            + offset, val);
00229       }
00230       mach_write_to_4(page + offset, val);
00231     }
00232     break;
00233   default:
00234   corrupt:
00235     recv_sys->found_corrupt_log = TRUE;
00236     ptr = NULL;
00237   }
00238 
00239   return(ptr);
00240 }
00241 
00242 /********************************************************/
00245 UNIV_INTERN
00246 void
00247 mlog_write_ulint(
00248 /*=============*/
00249   byte* ptr,  
00250   ulint val,  
00251   byte  type, 
00252   mtr_t*  mtr)  
00253 {
00254   byte* log_ptr;
00255 
00256   switch (type) {
00257   case MLOG_1BYTE:
00258     mach_write_to_1(ptr, val);
00259     break;
00260   case MLOG_2BYTES:
00261     mach_write_to_2(ptr, val);
00262     break;
00263   case MLOG_4BYTES:
00264     mach_write_to_4(ptr, val);
00265     break;
00266   default:
00267     ut_error;
00268   }
00269 
00270   log_ptr = mlog_open(mtr, 11 + 2 + 5);
00271 
00272   /* If no logging is requested, we may return now */
00273   if (log_ptr == NULL) {
00274 
00275     return;
00276   }
00277 
00278   log_ptr = mlog_write_initial_log_record_fast(ptr, type, log_ptr, mtr);
00279 
00280   mach_write_to_2(log_ptr, page_offset(ptr));
00281   log_ptr += 2;
00282 
00283   log_ptr += mach_write_compressed(log_ptr, val);
00284 
00285   mlog_close(mtr, log_ptr);
00286 }
00287 
00288 /********************************************************/
00291 UNIV_INTERN
00292 void
00293 mlog_write_ull(
00294 /*===========*/
00295   byte*   ptr,  
00296   ib_uint64_t val,  
00297   mtr_t*    mtr)  
00298 {
00299   byte* log_ptr;
00300 
00301   ut_ad(ptr && mtr);
00302 
00303   mach_write_to_8(ptr, val);
00304 
00305   log_ptr = mlog_open(mtr, 11 + 2 + 9);
00306 
00307   /* If no logging is requested, we may return now */
00308   if (log_ptr == NULL) {
00309 
00310     return;
00311   }
00312 
00313   log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_8BYTES,
00314                  log_ptr, mtr);
00315 
00316   mach_write_to_2(log_ptr, page_offset(ptr));
00317   log_ptr += 2;
00318 
00319   log_ptr += mach_ull_write_compressed(log_ptr, val);
00320 
00321   mlog_close(mtr, log_ptr);
00322 }
00323 
00324 #ifndef UNIV_HOTBACKUP
00325 /********************************************************/
00328 UNIV_INTERN
00329 void
00330 mlog_write_string(
00331 /*==============*/
00332   byte*   ptr,  
00333   const byte* str,  
00334   ulint   len,  
00335   mtr_t*    mtr)  
00336 {
00337   ut_ad(ptr && mtr);
00338   ut_a(len < UNIV_PAGE_SIZE);
00339 
00340   memcpy(ptr, str, len);
00341 
00342   mlog_log_string(ptr, len, mtr);
00343 }
00344 
00345 /********************************************************/
00348 UNIV_INTERN
00349 void
00350 mlog_log_string(
00351 /*============*/
00352   byte* ptr,  
00353   ulint len,  
00354   mtr_t*  mtr)  
00355 {
00356   byte* log_ptr;
00357 
00358   ut_ad(ptr && mtr);
00359   ut_ad(len <= UNIV_PAGE_SIZE);
00360 
00361   log_ptr = mlog_open(mtr, 30);
00362 
00363   /* If no logging is requested, we may return now */
00364   if (log_ptr == NULL) {
00365 
00366     return;
00367   }
00368 
00369   log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_WRITE_STRING,
00370                  log_ptr, mtr);
00371   mach_write_to_2(log_ptr, page_offset(ptr));
00372   log_ptr += 2;
00373 
00374   mach_write_to_2(log_ptr, len);
00375   log_ptr += 2;
00376 
00377   mlog_close(mtr, log_ptr);
00378 
00379   mlog_catenate_string(mtr, ptr, len);
00380 }
00381 #endif /* !UNIV_HOTBACKUP */
00382 
00383 /********************************************************/
00386 UNIV_INTERN
00387 byte*
00388 mlog_parse_string(
00389 /*==============*/
00390   byte* ptr,  
00391   byte* end_ptr,
00392   byte* page, 
00393   void* page_zip)
00394 {
00395   ulint offset;
00396   ulint len;
00397 
00398   ut_a(!page || !page_zip || fil_page_get_type(page) != FIL_PAGE_INDEX);
00399 
00400   if (end_ptr < ptr + 4) {
00401 
00402     return(NULL);
00403   }
00404 
00405   offset = mach_read_from_2(ptr);
00406   ptr += 2;
00407   len = mach_read_from_2(ptr);
00408   ptr += 2;
00409 
00410   if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
00411       || UNIV_UNLIKELY(len + offset) > UNIV_PAGE_SIZE) {
00412     recv_sys->found_corrupt_log = TRUE;
00413 
00414     return(NULL);
00415   }
00416 
00417   if (end_ptr < ptr + len) {
00418 
00419     return(NULL);
00420   }
00421 
00422   if (page) {
00423     if (UNIV_LIKELY_NULL(page_zip)) {
00424       memcpy(((page_zip_des_t*) page_zip)->data
00425         + offset, ptr, len);
00426     }
00427     memcpy(page + offset, ptr, len);
00428   }
00429 
00430   return(ptr + len);
00431 }
00432 
00433 #ifndef UNIV_HOTBACKUP
00434 /********************************************************/
00438 UNIV_INTERN
00439 byte*
00440 mlog_open_and_write_index(
00441 /*======================*/
00442   mtr_t*    mtr,  
00443   const byte* rec,  
00444   dict_index_t* index,  
00445   byte    type, 
00446   ulint   size) 
00448 {
00449   byte*   log_ptr;
00450   const byte* log_start;
00451   const byte* log_end;
00452 
00453   ut_ad(!!page_rec_is_comp(rec) == dict_table_is_comp(index->table));
00454 
00455   if (!page_rec_is_comp(rec)) {
00456     log_start = log_ptr = mlog_open(mtr, 11 + size);
00457     if (!log_ptr) {
00458       return(NULL); /* logging is disabled */
00459     }
00460     log_ptr = mlog_write_initial_log_record_fast(rec, type,
00461                    log_ptr, mtr);
00462     log_end = log_ptr + 11 + size;
00463   } else {
00464     ulint i;
00465     ulint n = dict_index_get_n_fields(index);
00466     /* total size needed */
00467     ulint total = 11 + size + (n + 2) * 2;
00468     ulint alloc = total;
00469     /* allocate at most DYN_ARRAY_DATA_SIZE at a time */
00470     if (alloc > DYN_ARRAY_DATA_SIZE) {
00471       alloc = DYN_ARRAY_DATA_SIZE;
00472     }
00473     log_start = log_ptr = mlog_open(mtr, alloc);
00474     if (!log_ptr) {
00475       return(NULL); /* logging is disabled */
00476     }
00477     log_end = log_ptr + alloc;
00478     log_ptr = mlog_write_initial_log_record_fast(rec, type,
00479                    log_ptr, mtr);
00480     mach_write_to_2(log_ptr, n);
00481     log_ptr += 2;
00482     mach_write_to_2(log_ptr,
00483         dict_index_get_n_unique_in_tree(index));
00484     log_ptr += 2;
00485     for (i = 0; i < n; i++) {
00486       dict_field_t*   field;
00487       const dict_col_t* col;
00488       ulint     len;
00489 
00490       field = dict_index_get_nth_field(index, i);
00491       col = dict_field_get_col(field);
00492       len = field->fixed_len;
00493       ut_ad(len < 0x7fff);
00494       if (len == 0
00495           && (col->len > 255 || col->mtype == DATA_BLOB)) {
00496         /* variable-length field
00497         with maximum length > 255 */
00498         len = 0x7fff;
00499       }
00500       if (col->prtype & DATA_NOT_NULL) {
00501         len |= 0x8000;
00502       }
00503       if (log_ptr + 2 > log_end) {
00504         mlog_close(mtr, log_ptr);
00505         ut_a(total > (ulint) (log_ptr - log_start));
00506         total -= log_ptr - log_start;
00507         alloc = total;
00508         if (alloc > DYN_ARRAY_DATA_SIZE) {
00509           alloc = DYN_ARRAY_DATA_SIZE;
00510         }
00511         log_start = log_ptr = mlog_open(mtr, alloc);
00512         if (!log_ptr) {
00513           return(NULL); /* logging is disabled */
00514         }
00515         log_end = log_ptr + alloc;
00516       }
00517       mach_write_to_2(log_ptr, len);
00518       log_ptr += 2;
00519     }
00520   }
00521   if (size == 0) {
00522     mlog_close(mtr, log_ptr);
00523     log_ptr = NULL;
00524   } else if (log_ptr + size > log_end) {
00525     mlog_close(mtr, log_ptr);
00526     log_ptr = mlog_open(mtr, size);
00527   }
00528   return(log_ptr);
00529 }
00530 #endif /* !UNIV_HOTBACKUP */
00531 
00532 /********************************************************/
00535 UNIV_INTERN
00536 byte*
00537 mlog_parse_index(
00538 /*=============*/
00539   byte*   ptr,  
00540   const byte* end_ptr,
00541   ibool   comp, 
00542   dict_index_t**  index)  
00543 {
00544   ulint   i, n, n_uniq;
00545   dict_table_t* table;
00546   dict_index_t* ind;
00547 
00548   ut_ad(comp == FALSE || comp == TRUE);
00549 
00550   if (comp) {
00551     if (end_ptr < ptr + 4) {
00552       return(NULL);
00553     }
00554     n = mach_read_from_2(ptr);
00555     ptr += 2;
00556     n_uniq = mach_read_from_2(ptr);
00557     ptr += 2;
00558     ut_ad(n_uniq <= n);
00559     if (end_ptr < ptr + n * 2) {
00560       return(NULL);
00561     }
00562   } else {
00563     n = n_uniq = 1;
00564   }
00565   table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n,
00566               comp ? DICT_TF_COMPACT : 0);
00567   ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY",
00568             DICT_HDR_SPACE, 0, n);
00569   ind->table = table;
00570   ind->n_uniq = (unsigned int) n_uniq;
00571   if (n_uniq != n) {
00572     ut_a(n_uniq + DATA_ROLL_PTR <= n);
00573     ind->type = DICT_CLUSTERED;
00574   }
00575   if (comp) {
00576     for (i = 0; i < n; i++) {
00577       ulint len = mach_read_from_2(ptr);
00578       ptr += 2;
00579       /* The high-order bit of len is the NOT NULL flag;
00580       the rest is 0 or 0x7fff for variable-length fields,
00581       and 1..0x7ffe for fixed-length fields. */
00582       dict_mem_table_add_col(
00583         table, NULL, NULL,
00584         ((len + 1) & 0x7fff) <= 1
00585         ? DATA_BINARY : DATA_FIXBINARY,
00586         len & 0x8000 ? DATA_NOT_NULL : 0,
00587         len & 0x7fff);
00588 
00589       dict_index_add_col(ind, table,
00590              dict_table_get_nth_col(table, i),
00591              0);
00592     }
00593     dict_table_add_system_columns(table, table->heap);
00594     if (n_uniq != n) {
00595       /* Identify DB_TRX_ID and DB_ROLL_PTR in the index. */
00596       ut_a(DATA_TRX_ID_LEN
00597            == dict_index_get_nth_col(ind, DATA_TRX_ID - 1
00598                    + n_uniq)->len);
00599       ut_a(DATA_ROLL_PTR_LEN
00600            == dict_index_get_nth_col(ind, DATA_ROLL_PTR - 1
00601                    + n_uniq)->len);
00602       ind->fields[DATA_TRX_ID - 1 + n_uniq].col
00603         = &table->cols[n + DATA_TRX_ID];
00604       ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col
00605         = &table->cols[n + DATA_ROLL_PTR];
00606     }
00607   }
00608   /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
00609   ind->cached = TRUE;
00610   *index = ind;
00611   return(ptr);
00612 }