Commit ba11dd69 authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-11127 : Fix innochecksum to work with large files on Windows.

- don't use stat() for file size, it doesn not handle large size
  use GetFileSizeEx() instead

- don't use lseek(), it can't handle large files, use _lseeki64() instead.

- Also, switch off OS file buffering for innochecksum on Windows,
to avoid thrashing file cache.
parent 3321f1ad
...@@ -243,10 +243,9 @@ int main(int argc, char **argv) ...@@ -243,10 +243,9 @@ int main(int argc, char **argv)
time_t lastt; /* last time */ time_t lastt; /* last time */
ulint oldcsum, oldcsumfield, csum, csumfield, crc32, logseq, logseqfield; ulint oldcsum, oldcsumfield, csum, csumfield, crc32, logseq, logseqfield;
/* ulints for checksum storage */ /* ulints for checksum storage */
struct stat st; /* for stat, if you couldn't guess */
unsigned long long int size; /* size of file (has to be 64 bits) */ unsigned long long int size; /* size of file (has to be 64 bits) */
ulint pages; /* number of pages in file */ ulint pages; /* number of pages in file */
off_t offset= 0; unsigned long long offset= 0;
int fd; int fd;
printf("InnoDB offline file checksum utility.\n"); printf("InnoDB offline file checksum utility.\n");
...@@ -269,6 +268,47 @@ int main(int argc, char **argv) ...@@ -269,6 +268,47 @@ int main(int argc, char **argv)
goto error; goto error;
} }
#ifdef _WIN32
/* Switch off OS file buffering for the file. */
HANDLE h = CreateFile(filename, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0,
OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
if (!h)
{
fprintf(stderr, "Error; cant open file\n");
goto error;
}
if (!GetFileSizeEx(h, (LARGE_INTEGER *)&size))
{
fprintf(stderr, "Error; GetFileSize() failed\n");
goto error;
}
fd = _open_osfhandle ((intptr_t) h, _O_RDONLY);
if (fd < 0)
{
fprintf(stderr, "Error; _open_osfhandle() failed\n");
goto error;
}
f = _fdopen(fd, "rb");
if (!f)
{
fprintf(stderr, "Error; fdopen() failed\n");
goto error;
}
/*
Disable stdio buffering (FILE_FLAG_NO_BUFFERING requires properly IO buffers
which stdio does not guarantee.
*/
setvbuf(f, NULL, _IONBF, 0);
#else
struct stat st;
/* stat the file to get size and page count */ /* stat the file to get size and page count */
if (stat(filename, &st)) if (stat(filename, &st))
{ {
...@@ -279,6 +319,8 @@ int main(int argc, char **argv) ...@@ -279,6 +319,8 @@ int main(int argc, char **argv)
/* Open the file for reading */ /* Open the file for reading */
f= fopen(filename, "rb"); f= fopen(filename, "rb");
#endif
if (f == NULL) if (f == NULL)
{ {
fprintf(stderr, "Error; %s cannot be opened", filename); fprintf(stderr, "Error; %s cannot be opened", filename);
...@@ -323,7 +365,7 @@ int main(int argc, char **argv) ...@@ -323,7 +365,7 @@ int main(int argc, char **argv)
} }
else if (verbose) else if (verbose)
{ {
printf("file %s = %llu bytes (%lu pages)...\n", filename, size, pages); printf("file %s = %llu bytes (%lu pages)...\n", filename, size, (ulong)pages);
if (do_one_page) if (do_one_page)
printf("InnoChecksum; checking page %lu\n", do_page); printf("InnoChecksum; checking page %lu\n", do_page);
else else
...@@ -348,9 +390,12 @@ int main(int argc, char **argv) ...@@ -348,9 +390,12 @@ int main(int argc, char **argv)
goto error; goto error;
} }
offset= (off_t)start_page * (off_t)physical_page_size; offset= (ulonglong)start_page * (ulonglong)physical_page_size;
#ifdef _WIN32
if (_lseeki64(fd, offset, SEEK_SET) != offset)
#else
if (lseek(fd, offset, SEEK_SET) != offset) if (lseek(fd, offset, SEEK_SET) != offset)
#endif
{ {
perror("Error; Unable to seek to necessary offset"); perror("Error; Unable to seek to necessary offset");
goto error; goto error;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment