~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to extra/innochecksum.c

  • Committer: Stewart Smith
  • Date: 2009-05-15 06:57:12 UTC
  • mto: (991.1.5 for-brian)
  • mto: This revision was merged to the branch mainline in revision 1022.
  • Revision ID: stewart@flamingspork.com-20090515065712-bmionylacjmexmmm
Make sql_mode=NO_AUTO_VALUE_ON_ZERO default for Drizzle.

Also fix DEFAULT keyword handling for auto-increment so that it defaults to
NULL and not 0 so that the following is valid and generates two auto-inc
values:

create table t1 (a int auto_increment primary key)
insert into t1 (a) values (default);
insert into t1 (a) values (default);

Important to note that 0 is no longer magic. So this gives you duplicate
primary key error:

insert into t1 (a) values(0);
insert into t1 (a) values(0);

as you've inserted the explicit value of 0 twice.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
 
15
 
 
16
/*
 
17
  InnoDB offline file checksum utility.  85% of the code in this file
 
18
  was taken wholesale fron the InnoDB codebase.
 
19
 
 
20
  The final 15% was originally written by Mark Smith of Danga
 
21
  Interactive, Inc. <junior@danga.com>
 
22
 
 
23
  Published with a permission.
 
24
*/
 
25
 
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <time.h>
 
29
#include <sys/types.h>
 
30
#include <sys/stat.h>
 
31
#include <unistd.h>
 
32
#include <stdint.h>
 
33
#include <inttypes.h>
 
34
 
 
35
/* all of these ripped from InnoDB code from MySQL 4.0.22 */
 
36
#define UT_HASH_RANDOM_MASK     1463735687
 
37
#define UT_HASH_RANDOM_MASK2    1653893711
 
38
#define FIL_PAGE_LSN          16
 
39
#define FIL_PAGE_FILE_FLUSH_LSN 26
 
40
#define FIL_PAGE_OFFSET     4
 
41
#define FIL_PAGE_DATA       38
 
42
#define FIL_PAGE_END_LSN_OLD_CHKSUM 8
 
43
#define FIL_PAGE_SPACE_OR_CHKSUM 0
 
44
#define UNIV_PAGE_SIZE          (2 * 8192)
 
45
 
 
46
/* command line argument to do page checks (that's it) */
 
47
/* another argument to specify page ranges... seek to right spot and go from there */
 
48
 
 
49
/* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */
 
50
static uint32_t mach_read_from_4(unsigned char *b)
 
51
{
 
52
  return( ((uint32_t)(b[0]) << 24)
 
53
          + ((uint32_t)(b[1]) << 16)
 
54
          + ((uint32_t)(b[2]) << 8)
 
55
          + (uint32_t)(b[3])
 
56
          );
 
57
}
 
58
 
 
59
static uint32_t
 
60
ut_fold_uint32_t_pair(
 
61
/*===============*/
 
62
            /* out: folded value */
 
63
    uint32_t   n1, /* in: uint32_t */
 
64
    uint32_t   n2) /* in: uint32_t */
 
65
{
 
66
    return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1)
 
67
                        ^ UT_HASH_RANDOM_MASK) + n2);
 
68
}
 
69
 
 
70
static uint32_t
 
71
ut_fold_binary(
 
72
/*===========*/
 
73
            /* out: folded value */
 
74
    unsigned char*   str,    /* in: string of bytes */
 
75
    uint32_t   len)    /* in: length */
 
76
{
 
77
    uint32_t   i;
 
78
    uint32_t   fold= 0;
 
79
 
 
80
    for (i= 0; i < len; i++)
 
81
    {
 
82
      fold= ut_fold_uint32_t_pair(fold, (uint32_t)(*str));
 
83
 
 
84
      str++;
 
85
    }
 
86
 
 
87
    return(fold);
 
88
}
 
89
 
 
90
static uint32_t
 
91
buf_calc_page_new_checksum(
 
92
/*=======================*/
 
93
               /* out: checksum */
 
94
    unsigned char*    page) /* in: buffer page */
 
95
{
 
96
    uint32_t checksum;
 
97
 
 
98
    /* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO
 
99
    are written outside the buffer pool to the first pages of data
 
100
    files, we have to skip them in the page checksum calculation.
 
101
    We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
 
102
    checksum is stored, and also the last 8 bytes of page because
 
103
    there we store the old formula checksum. */
 
104
 
 
105
    checksum= ut_fold_binary(page + FIL_PAGE_OFFSET,
 
106
                             FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
 
107
            + ut_fold_binary(page + FIL_PAGE_DATA,
 
108
                             UNIV_PAGE_SIZE - FIL_PAGE_DATA
 
109
                             - FIL_PAGE_END_LSN_OLD_CHKSUM);
 
110
    checksum= checksum & 0xFFFFFFFF;
 
111
 
 
112
    return(checksum);
 
113
}
 
114
 
 
115
static uint32_t
 
116
buf_calc_page_old_checksum(
 
117
/*=======================*/
 
118
               /* out: checksum */
 
119
    unsigned char*    page) /* in: buffer page */
 
120
{
 
121
    uint32_t checksum;
 
122
 
 
123
    checksum= ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
 
124
 
 
125
    checksum= checksum & 0xFFFFFFFF;
 
126
 
 
127
    return(checksum);
 
128
}
 
129
 
 
130
 
 
131
int main(int argc, char **argv)
 
132
{
 
133
  FILE *f;                     /* our input file */
 
134
  unsigned char *p;                     /* storage of pages read */
 
135
  int bytes;                   /* bytes read count */
 
136
  uint32_t ct;                    /* current page number (0 based) */
 
137
  int now;                     /* current time */
 
138
  int lastt;                   /* last time */
 
139
  uint32_t oldcsum, oldcsumfield, csum, csumfield, logseq, logseqfield; /* uint32_ts for checksum storage */
 
140
  struct stat st;              /* for stat, if you couldn't guess */
 
141
  uint64_t size; /* size of file (has to be 64 bits) */
 
142
  uint32_t pages;                 /* number of pages in file */
 
143
  uint32_t start_page= 0, end_page= 0, use_end_page= 0; /* for starting and ending at certain pages */
 
144
  off_t offset= 0;
 
145
  int just_count= 0;          /* if true, just print page count */
 
146
  int verbose= 0;
 
147
  int debug= 0;
 
148
  int c;
 
149
  int fd;
 
150
 
 
151
  /* remove arguments */
 
152
  while ((c= getopt(argc, argv, "cvds:e:p:")) != -1)
 
153
  {
 
154
    switch (c)
 
155
    {
 
156
    case 'v':
 
157
      verbose= 1;
 
158
      break;
 
159
    case 'c':
 
160
      just_count= 1;
 
161
      break;
 
162
    case 's':
 
163
      start_page= atoi(optarg);
 
164
      break;
 
165
    case 'e':
 
166
      end_page= atoi(optarg);
 
167
      use_end_page= 1;
 
168
      break;
 
169
    case 'p':
 
170
      start_page= atoi(optarg);
 
171
      end_page= atoi(optarg);
 
172
      use_end_page= 1;
 
173
      break;
 
174
    case 'd':
 
175
      debug= 1;
 
176
      break;
 
177
    case ':':
 
178
      fprintf(stderr, "option -%c requires an argument\n", optopt);
 
179
      return 1;
 
180
    case '?':
 
181
      fprintf(stderr, "unrecognized option: -%c\n", optopt);
 
182
      return 1;
 
183
    }
 
184
  }
 
185
 
 
186
  /* debug implies verbose... */
 
187
  if (debug) verbose= 1;
 
188
 
 
189
  /* make sure we have the right arguments */
 
190
  if (optind >= argc)
 
191
  {
 
192
    printf("InnoDB offline file checksum utility.\n");
 
193
    printf("usage: %s [-c] [-s <start page>] [-e <end page>] [-p <page>] [-v] [-d] <filename>\n", argv[0]);
 
194
    printf("\t-c\tprint the count of pages in the file\n");
 
195
    printf("\t-s n\tstart on this page number (0 based)\n");
 
196
    printf("\t-e n\tend at this page number (0 based)\n");
 
197
    printf("\t-p n\tcheck only this page (0 based)\n");
 
198
    printf("\t-v\tverbose (prints progress every 5 seconds)\n");
 
199
    printf("\t-d\tdebug mode (prints checksums for each page)\n");
 
200
    return 1;
 
201
  }
 
202
 
 
203
  /* stat the file to get size and page count */
 
204
  if (stat(argv[optind], &st))
 
205
  {
 
206
    perror("error statting file");
 
207
    return 1;
 
208
  }
 
209
  size= st.st_size;
 
210
  pages= size / UNIV_PAGE_SIZE;
 
211
  if (just_count)
 
212
  {
 
213
    printf("%u\n", pages);
 
214
    return 0;
 
215
  }
 
216
  else if (verbose)
 
217
  {
 
218
    printf("file %s= %"PRIu64" bytes (%u pages)...\n", argv[1], size, pages);
 
219
    printf("checking pages in range %u to %u\n", start_page, use_end_page ? end_page : (pages - 1));
 
220
  }
 
221
 
 
222
  /* open the file for reading */
 
223
  f= fopen(argv[optind], "r");
 
224
  if (!f)
 
225
  {
 
226
    perror("error opening file");
 
227
    return 1;
 
228
  }
 
229
 
 
230
  /* seek to the necessary position */
 
231
  if (start_page)
 
232
  {
 
233
    fd= fileno(f);
 
234
    if (!fd)
 
235
    {
 
236
      perror("unable to obtain file descriptor number");
 
237
      return 1;
 
238
    }
 
239
 
 
240
    offset= (off_t)start_page * (off_t)UNIV_PAGE_SIZE;
 
241
 
 
242
    if (lseek(fd, offset, SEEK_SET) != offset)
 
243
    {
 
244
      perror("unable to seek to necessary offset");
 
245
      return 1;
 
246
    }
 
247
  }
 
248
 
 
249
  /* allocate buffer for reading (so we don't realloc every time) */
 
250
  p= (unsigned char *)malloc(UNIV_PAGE_SIZE);
 
251
 
 
252
  /* main checksumming loop */
 
253
  ct= start_page;
 
254
  lastt= 0;
 
255
  while (!feof(f))
 
256
  {
 
257
    bytes= fread(p, 1, UNIV_PAGE_SIZE, f);
 
258
    if (!bytes && feof(f)) return 0;
 
259
    if (bytes != UNIV_PAGE_SIZE)
 
260
    {
 
261
      fprintf(stderr, "bytes read (%d) doesn't match universal page size (%d)\n", bytes, UNIV_PAGE_SIZE);
 
262
      return 1;
 
263
    }
 
264
 
 
265
    /* check the "stored log sequence numbers" */
 
266
    logseq= mach_read_from_4(p + FIL_PAGE_LSN + 4);
 
267
    logseqfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM + 4);
 
268
    if (debug)
 
269
      printf("page %u: log sequence number: first = %u; second = %u\n", ct, logseq, logseqfield);
 
270
    if (logseq != logseqfield)
 
271
    {
 
272
      fprintf(stderr, "page %u invalid (fails log sequence number check)\n", ct);
 
273
      return 1;
 
274
    }
 
275
 
 
276
    /* check old method of checksumming */
 
277
    oldcsum= buf_calc_page_old_checksum(p);
 
278
    oldcsumfield= mach_read_from_4(p + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
 
279
    if (debug)
 
280
      printf("page %u: old style: calculated = %u; recorded = %u\n", ct, oldcsum, oldcsumfield);
 
281
    if (oldcsumfield != mach_read_from_4(p + FIL_PAGE_LSN) && oldcsumfield != oldcsum)
 
282
    {
 
283
      fprintf(stderr, "page %u invalid (fails old style checksum)\n", ct);
 
284
      return 1;
 
285
    }
 
286
 
 
287
    /* now check the new method */
 
288
    csum= buf_calc_page_new_checksum(p);
 
289
    csumfield= mach_read_from_4(p + FIL_PAGE_SPACE_OR_CHKSUM);
 
290
    if (debug)
 
291
      printf("page %u: new style: calculated = %u; recorded = %u\n", ct, csum, csumfield);
 
292
    if (csumfield != 0 && csum != csumfield)
 
293
    {
 
294
      fprintf(stderr, "page %u invalid (fails new style checksum)\n", ct);
 
295
      return 1;
 
296
    }
 
297
 
 
298
    /* end if this was the last page we were supposed to check */
 
299
    if (use_end_page && (ct >= end_page))
 
300
      return 0;
 
301
 
 
302
    /* do counter increase and progress printing */
 
303
    ct++;
 
304
    if (verbose)
 
305
    {
 
306
      if (ct % 64 == 0)
 
307
      {
 
308
        now= time(0);
 
309
        if (!lastt) lastt= now;
 
310
        if (now - lastt >= 1)
 
311
        {
 
312
          printf("page %u okay: %.3f%% done\n", (ct - 1), (float) ct / pages * 100);
 
313
          lastt= now;
 
314
        }
 
315
      }
 
316
    }
 
317
  }
 
318
  return 0;
 
319
}
 
320