Drizzled Public API Documentation

ut0ut.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1994, 2010, Innobase Oy. All Rights Reserved.
00004 Copyright (C) 2009 Sun Microsystems, Inc.
00005 
00006 Portions of this file contain modifications contributed and copyrighted by
00007 Sun Microsystems, Inc. Those modifications are gratefully acknowledged and
00008 are described briefly in the InnoDB documentation. The contributions by
00009 Sun Microsystems are incorporated with their permission, and subject to the
00010 conditions contained in the file COPYING.Sun_Microsystems.
00011 
00012 This program is free software; you can redistribute it and/or modify it under
00013 the terms of the GNU General Public License as published by the Free Software
00014 Foundation; version 2 of the License.
00015 
00016 This program is distributed in the hope that it will be useful, but WITHOUT
00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00018 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License along with
00021 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00022 St, Fifth Floor, Boston, MA 02110-1301 USA
00023 
00024 *****************************************************************************/
00025 
00026 /***************************************************************/
00033 #include "ut0ut.h"
00034 
00035 #ifdef UNIV_NONINL
00036 #include "ut0ut.ic"
00037 #endif
00038 
00039 #include <stdarg.h>
00040 #include <string.h>
00041 #include <ctype.h>
00042 
00043 #ifndef UNIV_HOTBACKUP
00044 # include "trx0trx.h"
00045 # if defined(BUILD_DRIZZLE)
00046 #  include "drizzled/common.h"
00047 #  if TIME_WITH_SYS_TIME
00048 #   include <sys/time.h>
00049 #   include <time.h>
00050 #  else
00051 #   if HAVE_SYS_TIME_H
00052 #    include <sys/time.h>
00053 #   else
00054 #    include <time.h>
00055 #   endif
00056 #  endif
00057 # else
00058 #  include "ha_prototypes.h"
00059 #  include "mysql_com.h" /* NAME_LEN */
00060 # endif /* DRIZZLE */
00061 #endif /* UNIV_HOTBACKUP */
00062 #include <errno.h>
00063 #include <assert.h>
00064 
00066 UNIV_INTERN ibool ut_always_false = FALSE;
00067 
00068 #ifdef __WIN__
00069 /*****************************************************************/
00073 #define WIN_TO_UNIX_DELTA_USEC  ((ib_int64_t) 11644473600000000ULL)
00074 
00075 
00076 /*****************************************************************/
00079 static
00080 int
00081 ut_gettimeofday(
00082 /*============*/
00083   struct timeval* tv, 
00084   void*   tz) 
00085 {
00086   FILETIME  ft;
00087   ib_int64_t  tm;
00088 
00089   if (!tv) {
00090     errno = EINVAL;
00091     return(-1);
00092   }
00093 
00094   GetSystemTimeAsFileTime(&ft);
00095 
00096   tm = (ib_int64_t) ft.dwHighDateTime << 32;
00097   tm |= ft.dwLowDateTime;
00098 
00099   ut_a(tm >= 0);  /* If tm wraps over to negative, the quotient / 10
00100       does not work */
00101 
00102   tm /= 10; /* Convert from 100 nsec periods to usec */
00103 
00104   /* If we don't convert to the Unix epoch the value for
00105   struct timeval::tv_sec will overflow.*/
00106   tm -= WIN_TO_UNIX_DELTA_USEC;
00107 
00108   tv->tv_sec  = (long) (tm / 1000000L);
00109   tv->tv_usec = (long) (tm % 1000000L);
00110 
00111   return(0);
00112 }
00113 #else
00114 
00116 #define ut_gettimeofday   gettimeofday
00117 #endif
00118 
00119 /********************************************************/
00124 UNIV_INTERN
00125 ulint
00126 ut_get_high32(
00127 /*==========*/
00128   ulint a)  
00129 {
00130   ib_int64_t  i;
00131 
00132   i = (ib_int64_t)a;
00133 
00134   i = i >> 32;
00135 
00136   return((ulint)i);
00137 }
00138 
00139 /**********************************************************/
00143 UNIV_INTERN
00144 ib_time_t
00145 ut_time(void)
00146 /*=========*/
00147 {
00148   return(time(NULL));
00149 }
00150 
00151 #ifndef UNIV_HOTBACKUP
00152 /**********************************************************/
00158 UNIV_INTERN
00159 int
00160 ut_usectime(
00161 /*========*/
00162   ulint*  sec,  
00163   ulint*  ms) 
00164 {
00165   struct timeval  tv;
00166   int   ret;
00167   int   errno_gettimeofday;
00168   int   i;
00169 
00170   for (i = 0; i < 10; i++) {
00171 
00172     ret = ut_gettimeofday(&tv, NULL);
00173 
00174     if (ret == -1) {
00175       errno_gettimeofday = errno;
00176       ut_print_timestamp(stderr);
00177       fprintf(stderr, "  InnoDB: gettimeofday(): %s\n",
00178         strerror(errno_gettimeofday));
00179       os_thread_sleep(100000);  /* 0.1 sec */
00180       errno = errno_gettimeofday;
00181     } else {
00182       break;
00183     }
00184   }
00185 
00186   if (ret != -1) {
00187     *sec = (ulint) tv.tv_sec;
00188     *ms  = (ulint) tv.tv_usec;
00189   }
00190 
00191   return(ret);
00192 }
00193 
00194 /**********************************************************/
00199 UNIV_INTERN
00200 ullint
00201 ut_time_us(
00202 /*=======*/
00203   ullint* tloc) 
00204 {
00205   struct timeval  tv;
00206   ullint    us;
00207 
00208   ut_gettimeofday(&tv, NULL);
00209 
00210   us = (ullint) tv.tv_sec * 1000000 + tv.tv_usec;
00211 
00212   if (tloc != NULL) {
00213     *tloc = us;
00214   }
00215 
00216   return(us);
00217 }
00218 
00219 /**********************************************************/
00224 UNIV_INTERN
00225 ulint
00226 ut_time_ms(void)
00227 /*============*/
00228 {
00229   struct timeval  tv;
00230 
00231   ut_gettimeofday(&tv, NULL);
00232 
00233   return((ulint) tv.tv_sec * 1000 + tv.tv_usec / 1000);
00234 }
00235 #endif /* !UNIV_HOTBACKUP */
00236 
00237 /**********************************************************/
00240 UNIV_INTERN
00241 double
00242 ut_difftime(
00243 /*========*/
00244   ib_time_t time2,  
00245   ib_time_t time1)  
00246 {
00247   return(difftime(time2, time1));
00248 }
00249 
00250 /**********************************************************/
00252 UNIV_INTERN
00253 void
00254 ut_print_timestamp(
00255 /*===============*/
00256   FILE*  file) 
00257 {
00258 #ifdef __WIN__
00259   SYSTEMTIME cal_tm;
00260 
00261   GetLocalTime(&cal_tm);
00262 
00263   fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
00264     (int)cal_tm.wYear % 100,
00265     (int)cal_tm.wMonth,
00266     (int)cal_tm.wDay,
00267     (int)cal_tm.wHour,
00268     (int)cal_tm.wMinute,
00269     (int)cal_tm.wSecond);
00270 #else
00271   struct tm  cal_tm;
00272   struct tm* cal_tm_ptr;
00273   time_t     tm;
00274 
00275   time(&tm);
00276 
00277 #ifdef HAVE_LOCALTIME_R
00278   localtime_r(&tm, &cal_tm);
00279   cal_tm_ptr = &cal_tm;
00280 #else
00281   cal_tm_ptr = localtime(&tm);
00282 #endif
00283   fprintf(file,"%02d%02d%02d %2d:%02d:%02d",
00284     cal_tm_ptr->tm_year % 100,
00285     cal_tm_ptr->tm_mon + 1,
00286     cal_tm_ptr->tm_mday,
00287     cal_tm_ptr->tm_hour,
00288     cal_tm_ptr->tm_min,
00289     cal_tm_ptr->tm_sec);
00290 #endif
00291 }
00292 
00293 /**********************************************************/
00295 UNIV_INTERN
00296 void
00297 ut_sprintf_timestamp(
00298 /*=================*/
00299   char* buf) 
00300 {
00301 #ifdef __WIN__
00302   SYSTEMTIME cal_tm;
00303 
00304   GetLocalTime(&cal_tm);
00305 
00306   sprintf(buf, "%02d%02d%02d %2d:%02d:%02d",
00307     (int)cal_tm.wYear % 100,
00308     (int)cal_tm.wMonth,
00309     (int)cal_tm.wDay,
00310     (int)cal_tm.wHour,
00311     (int)cal_tm.wMinute,
00312     (int)cal_tm.wSecond);
00313 #else
00314   struct tm  cal_tm;
00315   struct tm* cal_tm_ptr;
00316   time_t     tm;
00317 
00318   time(&tm);
00319 
00320 #ifdef HAVE_LOCALTIME_R
00321   localtime_r(&tm, &cal_tm);
00322   cal_tm_ptr = &cal_tm;
00323 #else
00324   cal_tm_ptr = localtime(&tm);
00325 #endif
00326   sprintf(buf, "%02d%02d%02d %2d:%02d:%02d",
00327     cal_tm_ptr->tm_year % 100,
00328     cal_tm_ptr->tm_mon + 1,
00329     cal_tm_ptr->tm_mday,
00330     cal_tm_ptr->tm_hour,
00331     cal_tm_ptr->tm_min,
00332     cal_tm_ptr->tm_sec);
00333 #endif
00334 }
00335 
00336 #ifdef UNIV_HOTBACKUP
00337 /**********************************************************/
00340 UNIV_INTERN
00341 void
00342 ut_sprintf_timestamp_without_extra_chars(
00343 /*=====================================*/
00344   char* buf) 
00345 {
00346 #ifdef __WIN__
00347   SYSTEMTIME cal_tm;
00348 
00349   GetLocalTime(&cal_tm);
00350 
00351   sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d",
00352     (int)cal_tm.wYear % 100,
00353     (int)cal_tm.wMonth,
00354     (int)cal_tm.wDay,
00355     (int)cal_tm.wHour,
00356     (int)cal_tm.wMinute,
00357     (int)cal_tm.wSecond);
00358 #else
00359   struct tm  cal_tm;
00360   struct tm* cal_tm_ptr;
00361   time_t     tm;
00362 
00363   time(&tm);
00364 
00365 #ifdef HAVE_LOCALTIME_R
00366   localtime_r(&tm, &cal_tm);
00367   cal_tm_ptr = &cal_tm;
00368 #else
00369   cal_tm_ptr = localtime(&tm);
00370 #endif
00371   sprintf(buf, "%02d%02d%02d_%2d_%02d_%02d",
00372     cal_tm_ptr->tm_year % 100,
00373     cal_tm_ptr->tm_mon + 1,
00374     cal_tm_ptr->tm_mday,
00375     cal_tm_ptr->tm_hour,
00376     cal_tm_ptr->tm_min,
00377     cal_tm_ptr->tm_sec);
00378 #endif
00379 }
00380 
00381 /**********************************************************/
00383 UNIV_INTERN
00384 void
00385 ut_get_year_month_day(
00386 /*==================*/
00387   ulint*  year, 
00388   ulint*  month,  
00389   ulint*  day)  
00390 {
00391 #ifdef __WIN__
00392   SYSTEMTIME cal_tm;
00393 
00394   GetLocalTime(&cal_tm);
00395 
00396   *year = (ulint)cal_tm.wYear;
00397   *month = (ulint)cal_tm.wMonth;
00398   *day = (ulint)cal_tm.wDay;
00399 #else
00400   struct tm  cal_tm;
00401   struct tm* cal_tm_ptr;
00402   time_t     tm;
00403 
00404   time(&tm);
00405 
00406 #ifdef HAVE_LOCALTIME_R
00407   localtime_r(&tm, &cal_tm);
00408   cal_tm_ptr = &cal_tm;
00409 #else
00410   cal_tm_ptr = localtime(&tm);
00411 #endif
00412   *year = (ulint)cal_tm_ptr->tm_year + 1900;
00413   *month = (ulint)cal_tm_ptr->tm_mon + 1;
00414   *day = (ulint)cal_tm_ptr->tm_mday;
00415 #endif
00416 }
00417 #endif /* UNIV_HOTBACKUP */
00418 
00419 #ifndef UNIV_HOTBACKUP
00420 /*************************************************************/
00424 UNIV_INTERN
00425 ulint
00426 ut_delay(
00427 /*=====*/
00428   ulint delay)  
00429 {
00430   ulint i, j;
00431 
00432   j = 0;
00433 
00434   for (i = 0; i < delay * 50; i++) {
00435     j += i;
00436     UT_RELAX_CPU();
00437   }
00438 
00439   if (ut_always_false) {
00440     ut_always_false = (ibool) j;
00441   }
00442 
00443   return(j);
00444 }
00445 #endif /* !UNIV_HOTBACKUP */
00446 
00447 /*************************************************************/
00449 UNIV_INTERN
00450 void
00451 ut_print_buf(
00452 /*=========*/
00453   FILE*   file, 
00454   const void* buf,  
00455   ulint   len)  
00456 {
00457   const byte* data;
00458   ulint   i;
00459 
00460   UNIV_MEM_ASSERT_RW(buf, len);
00461 
00462   fprintf(file, " len %lu; hex ", len);
00463 
00464   for (data = (const byte*)buf, i = 0; i < len; i++) {
00465     fprintf(file, "%02lx", (ulong)*data++);
00466   }
00467 
00468   fputs("; asc ", file);
00469 
00470   data = (const byte*)buf;
00471 
00472   for (i = 0; i < len; i++) {
00473     int c = (int) *data++;
00474     putc(isprint(c) ? c : ' ', file);
00475   }
00476 
00477   putc(';', file);
00478 }
00479 
00480 /*************************************************************/
00483 UNIV_INTERN
00484 ulint
00485 ut_2_power_up(
00486 /*==========*/
00487   ulint n)  
00488 {
00489   ulint res;
00490 
00491   res = 1;
00492 
00493   ut_ad(n > 0);
00494 
00495   while (res < n) {
00496     res = res * 2;
00497   }
00498 
00499   return(res);
00500 }
00501 
00502 /**********************************************************************/
00504 UNIV_INTERN
00505 void
00506 ut_print_filename(
00507 /*==============*/
00508   FILE*   f,  
00509   const char* name) 
00510 {
00511   putc('\'', f);
00512   for (;;) {
00513     int c = *name++;
00514     switch (c) {
00515     case 0:
00516       goto done;
00517     case '\'':
00518       putc(c, f);
00519       /* fall through */
00520     default:
00521       putc(c, f);
00522     }
00523   }
00524 done:
00525   putc('\'', f);
00526 }
00527 #ifndef UNIV_HOTBACKUP
00528 /**********************************************************************/
00533 UNIV_INTERN
00534 void
00535 ut_print_name(
00536 /*==========*/
00537   FILE*   f,  
00538   trx_t*    trx,  
00539   ibool   table_id,
00541   const char* name) 
00542 {
00543   ut_print_namel(f, trx, table_id, name, strlen(name));
00544 }
00545 
00546 /**********************************************************************/
00551 UNIV_INTERN
00552 void
00553 ut_print_namel(
00554 /*===========*/
00555   FILE*   f,  
00556   trx_t*    trx,  
00557   ibool   table_id,
00559   const char* name, 
00560   ulint   namelen)
00561 {
00562   /* 2 * NAME_LEN for database and table name,
00563   and some slack for the #mysql50# prefix and quotes */
00564   char    buf[3 * NAME_LEN];
00565   const char* bufend;
00566 
00567   bufend = innobase_convert_name(buf, sizeof buf,
00568                name, namelen,
00569                trx ? trx->mysql_thd : NULL,
00570                table_id);
00571 
00572   ssize_t ret= fwrite(buf, 1, bufend - buf, f);
00573   assert(ret==bufend-buf);  
00574 }
00575 
00576 /**********************************************************************/
00578 UNIV_INTERN
00579 void
00580 ut_copy_file(
00581 /*=========*/
00582   FILE* dest, 
00583   FILE* src)  
00584 {
00585   long  len = ftell(src);
00586   char  buf[4096];
00587 
00588   rewind(src);
00589   do {
00590     size_t  maxs = len < (long) sizeof buf
00591       ? (size_t) len
00592       : sizeof buf;
00593     size_t  size = fread(buf, 1, maxs, src);
00594     size_t ret= fwrite(buf, 1, size, dest);
00595     assert(ret==size);
00596     len -= (long) size;
00597     if (size < maxs) {
00598       break;
00599     }
00600   } while (len > 0);
00601 }
00602 #endif /* !UNIV_HOTBACKUP */
00603 
00604 #ifdef __WIN__
00605 # include <stdarg.h>
00606 /**********************************************************************/
00611 UNIV_INTERN
00612 int
00613 ut_snprintf(
00614 /*========*/
00615   char*   str,  
00616   size_t    size, 
00617   const char* fmt,  
00618   ...)      
00619 {
00620   int res;
00621   va_list ap1;
00622   va_list ap2;
00623 
00624   va_start(ap1, fmt);
00625   va_start(ap2, fmt);
00626 
00627   res = _vscprintf(fmt, ap1);
00628   ut_a(res != -1);
00629 
00630   if (size > 0) {
00631     _vsnprintf(str, size, fmt, ap2);
00632 
00633     if ((size_t) res >= size) {
00634       str[size - 1] = '\0';
00635     }
00636   }
00637 
00638   va_end(ap1);
00639   va_end(ap2);
00640 
00641   return(res);
00642 }
00643 #endif /* __WIN__ */
00644 
00645 /*************************************************************/
00649 UNIV_INTERN
00650 const char*
00651 ut_strerr(
00652 /*======*/
00653   enum db_err num)  
00654 {
00655   switch (num) {
00656   case DB_SUCCESS:
00657     return("Success");
00658   case DB_SUCCESS_LOCKED_REC:
00659     return("Success, record lock created");
00660   case DB_ERROR:
00661     return("Generic error");
00662   case DB_INTERRUPTED:
00663     return("Operation interrupted");
00664   case DB_OUT_OF_MEMORY:
00665     return("Cannot allocate memory");
00666   case DB_OUT_OF_FILE_SPACE:
00667     return("Out of disk space");
00668   case DB_LOCK_WAIT:
00669     return("Lock wait");
00670   case DB_DEADLOCK:
00671     return("Deadlock");
00672   case DB_ROLLBACK:
00673     return("Rollback");
00674   case DB_DUPLICATE_KEY:
00675     return("Duplicate key");
00676   case DB_QUE_THR_SUSPENDED:
00677     return("The queue thread has been suspended");
00678   case DB_MISSING_HISTORY:
00679     return("Required history data has been deleted");
00680   case DB_CLUSTER_NOT_FOUND:
00681     return("Cluster not found");
00682   case DB_TABLE_NOT_FOUND:
00683     return("Table not found");
00684   case DB_MUST_GET_MORE_FILE_SPACE:
00685     return("More file space needed");
00686   case DB_TABLE_IS_BEING_USED:
00687     return("Table is being used");
00688   case DB_TOO_BIG_RECORD:
00689     return("Record too big");
00690   case DB_LOCK_WAIT_TIMEOUT:
00691     return("Lock wait timeout");
00692   case DB_NO_REFERENCED_ROW:
00693     return("Referenced key value not found");
00694   case DB_ROW_IS_REFERENCED:
00695     return("Row is referenced");
00696   case DB_CANNOT_ADD_CONSTRAINT:
00697     return("Cannot add constraint");
00698   case DB_CORRUPTION:
00699     return("Data structure corruption");
00700   case DB_COL_APPEARS_TWICE_IN_INDEX:
00701     return("Column appears twice in index");
00702   case DB_CANNOT_DROP_CONSTRAINT:
00703     return("Cannot drop constraint");
00704   case DB_NO_SAVEPOINT:
00705     return("No such savepoint");
00706   case DB_TABLESPACE_ALREADY_EXISTS:
00707     return("Tablespace already exists");
00708   case DB_TABLESPACE_DELETED:
00709     return("No such tablespace");
00710   case DB_LOCK_TABLE_FULL:
00711     return("Lock structs have exhausted the buffer pool");
00712   case DB_FOREIGN_DUPLICATE_KEY:
00713     return("Foreign key activated with duplicate keys");
00714   case DB_FOREIGN_EXCEED_MAX_CASCADE:
00715     return("Foreign key cascade delete/update exceeds max depth");
00716   case DB_TOO_MANY_CONCURRENT_TRXS:
00717     return("Too many concurrent transactions");
00718   case DB_UNSUPPORTED:
00719     return("Unsupported");
00720   case DB_PRIMARY_KEY_IS_NULL:
00721     return("Primary key is NULL");
00722   case DB_STATS_DO_NOT_EXIST:
00723     return("Persistent statistics do not exist");
00724   case DB_FAIL:
00725     return("Failed, retry may succeed");
00726   case DB_OVERFLOW:
00727     return("Overflow");
00728   case DB_UNDERFLOW:
00729     return("Underflow");
00730   case DB_STRONG_FAIL:
00731     return("Failed, retry will not succeed");
00732   case DB_ZIP_OVERFLOW:
00733     return("Zip overflow");
00734   case DB_RECORD_NOT_FOUND:
00735     return("Record not found");
00736   case DB_CHILD_NO_INDEX:
00737     return("No index on referencing keys in referencing table");
00738   case DB_PARENT_NO_INDEX:
00739     return("No index on referenced keys in referenced table");
00740   case DB_END_OF_INDEX:
00741     return("End of index");
00742   /* do not add default: in order to produce a warning if new code
00743   is added to the enum but not added here */
00744   }
00745 
00746   /* we abort here because if unknown error code is given, this could
00747   mean that memory corruption has happened and someone's error-code
00748   variable has been overwritten with bogus data */
00749   ut_error;
00750 
00751   /* NOT REACHED */
00752   return("Unknown error");
00753 }