Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: base/test_file_util_win.cc

Issue 12833: Making sure that the buffer we use with ReadFile/WriteFile is page... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/test_file_util.h" 5 #include "base/test_file_util.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/scoped_handle.h" 12 #include "base/scoped_handle.h"
13 13
14 namespace file_util { 14 namespace file_util {
15 15
16 // We could use GetSystemInfo to get the page size, but this serves
17 // our purpose fine since 4K is the page size on x86 as well as x64.
18 static const ptrdiff_t kPageSize = 4096;
19
16 bool EvictFileFromSystemCache(const wchar_t* file) { 20 bool EvictFileFromSystemCache(const wchar_t* file) {
17 // Request exclusive access to the file and overwrite it with no buffering. 21 // Request exclusive access to the file and overwrite it with no buffering.
18 ScopedHandle hfile( 22 ScopedHandle file_handle(
19 CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, NULL, 23 CreateFile(file, GENERIC_READ | GENERIC_WRITE, 0, NULL,
20 OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 24 OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL));
21 NULL)); 25 if (!file_handle)
22 if (!hfile)
23 return false; 26 return false;
24 27
28 // Get some attributes to restore later.
29 BY_HANDLE_FILE_INFORMATION bhi = {0};
30 CHECK(::GetFileInformationByHandle(file_handle, &bhi));
31
25 // Execute in chunks. It could be optimized. We want to do few of these since 32 // Execute in chunks. It could be optimized. We want to do few of these since
26 // these opterations will be slow without the cache. 33 // these operations will be slow without the cache.
27 char buffer[4096]; 34
35 // Non-buffered reads and writes need to be sector aligned and since sector
36 // sizes typically range from 512-4096 bytes, we just use the page size.
37 // The buffer size is twice the size of a page (minus one) since we need to
38 // get an aligned pointer into the buffer that we can use.
39 char buffer[2 * kPageSize - 1];
40 // Get an aligned pointer into buffer.
41 char* read_write = reinterpret_cast<char*>(
42 reinterpret_cast<ptrdiff_t>(buffer + kPageSize - 1) & ~(kPageSize - 1));
43 DCHECK((reinterpret_cast<int>(read_write) % kPageSize) == 0);
44
45 // If the file size isn't a multiple of kPageSize, we'll need special
46 // processing.
47 bool file_is_page_aligned = true;
28 int total_bytes = 0; 48 int total_bytes = 0;
29 DWORD bytes_read; 49 DWORD bytes_read, bytes_written;
30 for (;;) { 50 for (;;) {
31 bytes_read = 0; 51 bytes_read = 0;
32 ReadFile(hfile, buffer, sizeof(buffer), &bytes_read, NULL); 52 ReadFile(file_handle, read_write, kPageSize, &bytes_read, NULL);
33 if (bytes_read == 0) 53 if (bytes_read == 0)
34 break; 54 break;
35 55
36 SetFilePointer(hfile, total_bytes, 0, FILE_BEGIN); 56 if (bytes_read < kPageSize) {
37 if (!WriteFile(hfile, buffer, bytes_read, &bytes_read, NULL)) 57 // Zero out the remaining part of the buffer.
58 // WriteFile will fail if we provide a buffer size that isn't a
59 // sector multiple, so we'll have to write the entire buffer with
60 // padded zeros and then use SetEndOfFile to truncate the file.
61 ZeroMemory(read_write + bytes_read, kPageSize - bytes_read);
62 file_is_page_aligned = false;
63 }
64
65 // Move back to the position we just read from.
66 // Note that SetFilePointer will also fail if total_bytes isn't sector
67 // aligned, but that shouldn't happen here.
68 DCHECK((total_bytes % kPageSize) == 0);
69 SetFilePointer(file_handle, total_bytes, NULL, FILE_BEGIN);
70 if (!WriteFile(file_handle, read_write, kPageSize, &bytes_written, NULL) ||
71 bytes_written != kPageSize) {
72 DCHECK(false);
38 return false; 73 return false;
74 }
75
39 total_bytes += bytes_read; 76 total_bytes += bytes_read;
77
78 // If this is false, then we just processed the last portion of the file.
79 if (!file_is_page_aligned)
80 break;
40 } 81 }
82
83 if (!file_is_page_aligned) {
84 // The size of the file isn't a multiple of the page size, so we'll have
85 // to open the file again, this time without the FILE_FLAG_NO_BUFFERING
86 // flag and use SetEndOfFile to mark EOF.
87 file_handle.Set(CreateFile(file, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
88 0, NULL));
89 CHECK(SetFilePointer(file_handle, total_bytes, NULL, FILE_BEGIN) !=
90 INVALID_SET_FILE_POINTER);
91 CHECK(::SetEndOfFile(file_handle));
92 }
93
94 // Restore the file attributes.
95 CHECK(::SetFileTime(file_handle, &bhi.ftCreationTime, &bhi.ftLastAccessTime,
96 &bhi.ftLastWriteTime));
97
41 return true; 98 return true;
42 } 99 }
43 100
44 // Like CopyFileNoCache but recursively copies all files and subdirectories 101 // Like CopyFileNoCache but recursively copies all files and subdirectories
45 // in the given input directory to the output directory. 102 // in the given input directory to the output directory.
46 bool CopyRecursiveDirNoCache(const std::wstring& source_dir, 103 bool CopyRecursiveDirNoCache(const std::wstring& source_dir,
47 const std::wstring& dest_dir) { 104 const std::wstring& dest_dir) {
48 // Try to create the directory if it doesn't already exist. 105 // Try to create the directory if it doesn't already exist.
49 if (!CreateDirectory(dest_dir)) { 106 if (!CreateDirectory(dest_dir)) {
50 if (GetLastError() != ERROR_ALREADY_EXISTS) 107 if (GetLastError() != ERROR_ALREADY_EXISTS)
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
92 EvictFileFromSystemCache(cur_dest_path.c_str()); 149 EvictFileFromSystemCache(cur_dest_path.c_str());
93 } 150 }
94 } while (FindNextFile(fh, &fd)); 151 } while (FindNextFile(fh, &fd));
95 152
96 FindClose(fh); 153 FindClose(fh);
97 return true; 154 return true;
98 } 155 }
99 156
100 } // namespace file_util 157 } // namespace file_util
101 158
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698