MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
printSchemaFile.cpp
1 /*
2  Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of 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 St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 
19 #include <ndb_global.h>
20 #include <util/version.h>
21 #include <my_global.h>
22 #include <my_sys.h>
23 #include <my_dir.h>
24 
25 #include <NdbMain.h>
26 #include <NdbOut.hpp>
27 #include "SchemaFile.hpp"
28 #include <kernel_types.h>
29 
30 static const char* progname = 0;
31 static bool allflag = false;
32 static bool checkonly = false;
33 static bool equalcontents = false;
34 static bool okquiet = false;
35 static bool transok = false;
36 
37 static void
38 usage()
39 {
40  ndbout
41  << "Usage: " << progname << " [-aceq]" << " file ..." << endl
42  << "-a print also unused slots" << endl
43  << "-c check only (return status 1 on error)" << endl
44  << "-e check also that the files have identical contents" << endl
45  << "-q no output if file is ok" << endl
46  << "-t non-zero trans key is not error (has active trans)" << endl
47  << "Example: " << progname << " -ceq ndb_*_fs/D[12]/DBDICT/P0.SchemaLog" << endl;
48 }
49 
50 #ifdef NOT_USED
51 
52 static void
53 fill(const char * buf, int mod)
54 {
55  int len = strlen(buf)+1;
56  ndbout << buf << " ";
57  while((len % mod) != 0){
58  ndbout << " ";
59  len++;
60  }
61 }
62 #endif
63 
64 static const char*
65 version(Uint32 v)
66 {
67  static char buf[40];
68  sprintf(buf, "%d.%d.%d", v >> 16, (v >> 8) & 0xFF, v & 0xFF);
69  return buf;
70 }
71 
72 static int
73 print_head(const char * filename, const SchemaFile * sf)
74 {
75  int retcode = 0;
76 
77  if (! checkonly) {
78  ndbout << "----- Schemafile: " << filename << " -----" << endl;
79  ndbout_c("Magic: %.*s ByteOrder: %.8x NdbVersion: %s FileSize: %d",
80  (int) sizeof(sf->Magic),
81  sf->Magic,
82  sf->ByteOrder,
83  version(sf->NdbVersion),
84  sf->FileSize);
85  }
86 
87  if (memcmp(sf->Magic, "NDBSCHMA", sizeof(sf->Magic) != 0)) {
88  ndbout << filename << ": invalid header magic" << endl;
89  retcode = 1;
90  }
91 
92  if ((sf->NdbVersion >> 16) < 4 || (sf->NdbVersion >> 16) > 9) {
93  ndbout << filename << ": impossible version " << hex << sf->NdbVersion << endl;
94  retcode = 1;
95  }
96 
97  return retcode;
98 }
99 
100 inline
101 Uint32
102 table_version_minor(Uint32 ver)
103 {
104  return ver >> 24;
105 }
106 
107 static int
108 print_old(const char * filename, const SchemaFile * sf, Uint32 sz)
109 {
110  int retcode = 0;
111 
112  if (print_head(filename, sf) != 0)
113  retcode = 1;
114 
115  for (Uint32 i = 0; i < sf->NoOfTableEntries; i++) {
116  SchemaFile::TableEntry_old te = sf->TableEntries_old[i];
117  if (allflag ||
118  (te.m_tableState != SchemaFile::SF_UNUSED))
119  {
120  if (! checkonly)
121  ndbout << "Table " << i << ":"
122  << " State = " << te.m_tableState
123  << " version = " << table_version_major(te.m_tableVersion)
124  << "(" << table_version_minor(te.m_tableVersion) << ")"
125  << " type = " << te.m_tableType
126  << " noOfPages = " << te.m_noOfPages
127  << " gcp: " << te.m_gcp << endl;
128  }
129  }
130  return retcode;
131 }
132 
133 static int
134 print(const char * filename, const SchemaFile * xsf, Uint32 sz)
135 {
136  int retcode = 0;
137 
138  if (print_head(filename, xsf) != 0)
139  retcode = 1;
140 
141  assert(sizeof(SchemaFile) == NDB_SF_PAGE_SIZE);
142  if (xsf->FileSize != sz || xsf->FileSize % NDB_SF_PAGE_SIZE != 0) {
143  ndbout << filename << ": invalid FileSize " << xsf->FileSize << endl;
144  retcode = 1;
145  }
146  Uint32 noOfPages = xsf->FileSize / NDB_SF_PAGE_SIZE;
147  for (Uint32 n = 0; n < noOfPages; n++) {
148  if (! checkonly) {
149  ndbout << "----- Page: " << n << " (" << noOfPages << ") -----" << endl;
150  }
151  const SchemaFile * sf = &xsf[n];
152  if (memcmp(sf->Magic, xsf->Magic, sizeof(sf->Magic)) != 0) {
153  ndbout << filename << ": page " << n << " invalid magic" << endl;
154  retcode = 1;
155  }
156  if (sf->FileSize != xsf->FileSize) {
157  ndbout << filename << ": page " << n << " FileSize changed to " << sf->FileSize << "!=" << xsf->FileSize << endl;
158  retcode = 1;
159  }
160  Uint32 cs = 0;
161  for (Uint32 j = 0; j < NDB_SF_PAGE_SIZE_IN_WORDS; j++)
162  cs ^= ((const Uint32*)sf)[j];
163  if (cs != 0) {
164  ndbout << filename << ": page " << n << " invalid CheckSum" << endl;
165  retcode = 1;
166  }
167  if (sf->NoOfTableEntries != NDB_SF_PAGE_ENTRIES) {
168  ndbout << filename << ": page " << n << " invalid NoOfTableEntries " << sf->NoOfTableEntries << endl;
169  retcode = 1;
170  }
171  for (Uint32 i = 0; i < NDB_SF_PAGE_ENTRIES; i++) {
172  SchemaFile::TableEntry te = sf->TableEntries[i];
173  Uint32 j = n * NDB_SF_PAGE_ENTRIES + i;
174  bool entryerr = false;
175  if (! transok && te.m_transId != 0) {
176  ndbout << filename << ": entry " << j << ": active transaction, transId: " << hex << te.m_transId << endl;
177  entryerr = true;
178  retcode = 1;
179  }
180  const Uint32 num_unused = sizeof(te.m_unused) / sizeof(te.m_unused[0]);
181  for (Uint32 k = 0; k < num_unused; k++) {
182  if (te.m_unused[k] != 0) {
183  ndbout << filename << ": entry " << j << ": garbage in unused word " << k << ": " << te.m_unused[k] << endl;
184  entryerr = true;
185  retcode = 1;
186  }
187  }
188  if (allflag ||
189  (te.m_tableState != SchemaFile::SF_UNUSED) ||
190  entryerr) {
191  if (! checkonly || entryerr)
192  ndbout << "Table " << j << ":"
193  << " State = " << te.m_tableState
194  << " version = " << table_version_major(te.m_tableVersion)
195  << "(" << table_version_minor(te.m_tableVersion) << ")"
196  << " type = " << te.m_tableType
197  << " noOfWords = " << te.m_info_words
198  << " gcp: " << te.m_gcp
199  << " transId: " << hex << te.m_transId << endl;
200  }
201  }
202  }
203 
204  return retcode;
205 }
206 
207 NDB_COMMAND(printSchemafile,
208  "printSchemafile", "printSchemafile", "Prints a schemafile", 16384)
209 {
210  ndb_init();
211  progname = argv[0];
212  int exitcode = 0;
213 
214  while (argc > 1 && argv[1][0] == '-') {
215  if (strchr(argv[1], 'a') != 0)
216  allflag = true;
217  if (strchr(argv[1], 'c') != 0)
218  checkonly = true;
219  if (strchr(argv[1], 'e') != 0)
220  equalcontents = true;
221  if (strchr(argv[1], 'q') != 0)
222  okquiet = true;
223  if (strchr(argv[1], 't') != 0)
224  transok = true;
225  if (strchr(argv[1], 'h') != 0 || strchr(argv[1], '?') != 0) {
226  usage();
227  return 0;
228  }
229  argc--, argv++;
230  }
231 
232  const char * prevfilename = 0;
233  Uint32 * prevbuf = 0;
234  Uint32 prevbytes = 0;
235 
236  while (argc > 1) {
237  const char * filename = argv[1];
238  argc--, argv++;
239 
240  MY_STAT sbuf,*st;
241  if(!(st=my_stat(filename, &sbuf,0)))
242  {
243  ndbout << filename << ": not found my_errno=" << my_errno << endl;
244  exitcode = 1;
245  continue;
246  }
247  const Uint32 bytes = sbuf.st_size;
248 
249  Uint32 * buf = new Uint32[bytes/4+1];
250 
251  FILE * f = fopen(filename, "rb");
252  if (f == 0) {
253  ndbout << filename << ": open failed errno=" << errno << endl;
254  delete [] buf;
255  exitcode = 1;
256  continue;
257  }
258  Uint32 sz = (Uint32)fread(buf, 1, bytes, f);
259  fclose(f);
260  if (sz != bytes) {
261  ndbout << filename << ": read failed errno=" << errno << endl;
262  delete [] buf;
263  exitcode = 1;
264  continue;
265  }
266 
267  if (sz < 32) {
268  ndbout << filename << ": too short (no header)" << endl;
269  delete [] buf;
270  exitcode = 1;
271  continue;
272  }
273 
274  SchemaFile* sf = (SchemaFile *)&buf[0];
275  int ret;
276  if (sf->NdbVersion < NDB_SF_VERSION_5_0_6)
277  ret = print_old(filename, sf, sz);
278  else
279  ret = print(filename, sf, sz);
280 
281  if (ret != 0) {
282  ndbout << filename << ": check failed"
283  << " version=" << version(sf->NdbVersion) << endl;
284  exitcode = 1;
285  } else if (! okquiet) {
286  ndbout << filename << ": ok"
287  << " version=" << version(sf->NdbVersion) << endl;
288  }
289 
290  if (equalcontents && prevfilename != 0) {
291  if (prevbytes != bytes || memcmp(prevbuf, buf, bytes) != 0) {
292  ndbout << filename << ": differs from " << prevfilename << endl;
293  exitcode = 1;
294  }
295  }
296 
297  prevfilename = filename;
298  delete [] prevbuf;
299  prevbuf = buf;
300  prevbytes = bytes;
301  }
302 
303  delete [] prevbuf;
304  return exitcode;
305 }