📄 file.cxx
字号:
{
error_code = GetLastError();
TRACE_MSG(("file::open: failed to read file in memory: "
"%s\n", get_error_text(buf, sizeof buf)));
CloseHandle(fd);
VirtualFree(vmem, 0, MEM_RELEASE);
return false;
}
}
size_t page_map_size = ((mapped_size / page_size) + 31) >> 5;
dirty_page_map = new int[page_map_size];
memset(dirty_page_map, 0, sizeof(int)*page_map_size);
}
n_locked_pages = 0;
if (max_locked_pages != 0) {
// check if we can use VirtualLock()
if (VirtualLock(base, page_size)) {
VirtualUnlock(base, page_size);
} else {
error_code = GetLastError();
TRACE_MSG(("file::open: VirtualLock test failed: %s\n",
get_error_text(buf, sizeof buf)));
max_locked_pages = 0;
}
}
int log_flags = FILE_FLAG_SEQUENTIAL_SCAN;
if (max_locked_pages == 0 && platform == VER_PLATFORM_WIN32_NT) {
log_flags |= FILE_FLAG_WRITE_THROUGH;
}
log = CreateFile(log_name, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, log_flags, NULL);
if (log == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
log = CreateFile(log_name, GENERIC_READ|GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, log_flags, NULL);
}
if (log == INVALID_HANDLE_VALUE) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to create log file '%': %s\n",
log_name, get_error_text(buf, sizeof buf)));
return_error:
if (md != NULL) {
UnmapViewOfFile(base);
CloseHandle(md);
} else {
VirtualFree(base, 0, MEM_RELEASE);
}
CloseHandle(fd);
CloseHandle(log);
delete[] dirty_page_map;
return false;
}
if (size != 0
&& platform == VER_PLATFORM_WIN32_NT
&& !VirtualProtect(base, size, PAGE_READONLY, &old_prot))
{
error_code = GetLastError();
TRACE_MSG(("file::open: VirtualProtect failed for base=%p, "
"size=%ld: %s\n",
base, size, get_error_text(buf, sizeof buf)));
goto return_error;
}
next = chain;
chain = this;
} else {
next = chain;
chain = this;
recover_file();
if (!commit()) {
chain = next;
goto return_error;
}
}
} else { // non-shadow_pages_transaction mode
int access_flags = (mode == map_file)
? GENERIC_READ|GENERIC_WRITE : GENERIC_READ;
int create_flags = (mode == map_file)
? OPEN_ALWAYS : OPEN_EXISTING;
int hint_flags = (mode == load_in_memory)
? FILE_FLAG_SEQUENTIAL_SCAN : FILE_FLAG_RANDOM_ACCESS;
int share_mode = (prot == read_only) ? FILE_SHARE_READ|FILE_SHARE_WRITE : FILE_SHARE_READ;
fd = CreateFile(name, access_flags, share_mode, NULL,
create_flags, hint_flags, NULL);
size = 0;
base = NULL;
if (fd != INVALID_HANDLE_VALUE) {
DWORD read_bytes;
if (!ReadFile(fd, &base, sizeof base, &read_bytes, NULL)
|| (read_bytes != 0 && read_bytes != sizeof base))
{
error_code = GetLastError();
TRACE_MSG(("file::open: failed to read file '%s': %s\n",
name, get_error_text(buf, sizeof buf)));
CloseHandle(fd);
return false;
}
size = GetFileSize(fd, NULL);
if ((size & (allocation_granularity-1)) != 0
&& prot != read_only
&& mode == copy_on_write_map
&& size < max_file_size)
{
error_code = file_size_not_aligned;
TRACE_MSG(("file::open: size of file '%s' is not aligned "
"on %ld\n", name, allocation_granularity));
return false;
}
if (mode == copy_on_write_map) {
mapped_size = size;
md = CreateFileMapping(fd, NULL, PAGE_WRITECOPY, 0, size,NULL);
if (md == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to create file mapping: "
"%s\n", get_error_text(buf, sizeof buf)));
CloseHandle(fd);
return false;
}
TRACE_MSG(("file::open: create file mapping: size=%ld\n",
size));
void* p = MapViewOfFileEx(md, prot == read_only
&& platform == VER_PLATFORM_WIN32_NT
? FILE_MAP_READ : FILE_MAP_COPY,
0, 0, size, base);
if (p == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to map view of file on "
"address %p: %s\n",
base, get_error_text(buf, sizeof buf)));
p = MapViewOfFileEx(md, prot == read_only
&& platform == VER_PLATFORM_WIN32_NT
? FILE_MAP_READ : FILE_MAP_COPY,
0, 0, size, NULL);
}
if (p == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to map view of file: %s\n",
get_error_text(buf, sizeof buf)));
CloseHandle(md);
CloseHandle(fd);
return false;
}
base = (char*)p;
TRACE_MSG(("file::open: map view of file on %p\n", base));
if (prot != read_only && size < max_file_size) {
mapped_size = max_file_size;
vmem = (char*)VirtualAlloc(base + size, mapped_size - size,
MEM_RESERVE, PAGE_READWRITE);
if (vmem == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to allocate end of "
"region: base=%p, size=%ld: %s\n",
base+size, mapped_size-size,
get_error_text(buf, sizeof(buf))));
UnmapViewOfFile(p);
CloseHandle(md);
CloseHandle(fd);
return false;
}
TRACE_MSG(("file::open: virtual alloc: address=%p, "
"size=%ld\n", vmem, mapped_size));
assert(vmem == base + size);
}
} else if (mode == map_file) {
mapped_size = (prot == read_only || size > max_file_size)
? size : max_file_size;
md = CreateFileMapping(fd, NULL, PAGE_READWRITE, 0,
mapped_size, NULL);
if (md == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to create file mapping: "
"%s\n", get_error_text(buf, sizeof buf)));
CloseHandle(fd);
return false;
}
TRACE_MSG(("file::open: create file mapping: size=%ld\n",
size));
void* p = MapViewOfFileEx(md, prot == read_only
?FILE_MAP_READ :FILE_MAP_ALL_ACCESS,
0, 0, mapped_size, base);
if (p == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to map view of file on "
"address %p: %s\n",
base, get_error_text(buf, sizeof buf)));
p = MapViewOfFileEx(md, prot == read_only
? FILE_MAP_READ : FILE_MAP_ALL_ACCESS,
0, 0, mapped_size, NULL);
}
if (p == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to map view of file: %s\n",
get_error_text(buf, sizeof buf)));
CloseHandle(md);
CloseHandle(fd);
return false;
}
base = (char*)p;
TRACE_MSG(("file::open: map view of file on %p\n", base));
} else { // read file to memory
mapped_size = (prot == read_only || size > max_file_size)
? size : max_file_size;
if (!read_file_in_memory()) {
return false;
}
CloseHandle(fd);
fd = INVALID_HANDLE_VALUE;
}
} else {
error_code = GetLastError();
if (error_code != ERROR_FILE_NOT_FOUND) {
TRACE_MSG(("file::open: failed to open file '%s': %s\n",
name, get_error_text(buf, sizeof buf)));
return false;
}
TRACE_MSG(("file::open: file '%s' not found\n", name));
if (prot == read_only) {
TRACE_MSG(("file::open: failed to open in read only mode "
"unexisted file '%s'\n", name));
return false;
}
mapped_size = max_file_size;
base = vmem = (char*)VirtualAlloc(NULL, mapped_size,
MEM_RESERVE, PAGE_READWRITE);
if (base == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::open: failed to virtual alloc: %s\n",
get_error_text(buf, sizeof buf)));
return false;
}
}
}
error_code = ok;
return true;
}
bool file::set_size(size_t new_size)
{
if (new_size > mapped_size) {
error_code = file_mapping_size_exceeded;
return false;
}
if (mode == shadow_pages_transaction) {
new_size = ALIGN(new_size, page_size);
if (platform != VER_PLATFORM_WIN32_NT) { // Windows 95, uhh...
if (new_size > allocated_size) {
allocated_size = ALIGN(new_size, allocation_granularity);
if (!VirtualAlloc(base+size, allocated_size-size, MEM_COMMIT,
PAGE_READWRITE))
{
error_code = GetLastError();
return false;
}
unsigned page_no = size / page_size;
size_t offs = size;
while (offs < allocated_size) {
dirty_page_map[page_no >> 5] |= 1 << (page_no & 0x1F);
offs += page_size;
page_no += 1;
}
}
}
} else {
if (mode != map_file) {
new_size = ALIGN(new_size, allocation_granularity);
if (new_size > size) {
if (!VirtualAlloc(base+size, new_size-size, MEM_COMMIT,
PAGE_READWRITE))
{
error_code = GetLastError();
return false;
}
}
}
}
size = new_size;
error_code = ok;
return true;
}
bool file::set_protection(access_prot prot)
{
DWORD old_prot;
if (platform == VER_PLATFORM_WIN32_NT || mode == map_file) {
if (!VirtualProtect(base, mapped_size,
prot == file::read_only
? PAGE_READONLY
: mode == copy_on_write_map
? PAGE_WRITECOPY : PAGE_READWRITE,
&old_prot))
{
error_code = GetLastError();
return false;
}
}
this->prot = prot;
error_code = ok;
return true;
}
bool file::commit()
{
DWORD old_prot;
if (mode != shadow_pages_transaction) {
error_code = not_in_transaction;
return false;
}
if (n_locked_pages != 0 || platform != VER_PLATFORM_WIN32_NT) {
if (!flush_log_buffer()) {
return false;
}
}
if (platform == VER_PLATFORM_WIN32_NT) {
if (size > 0 && !FlushViewOfFile(base, size)) {
error_code = GetLastError();
TRACE_MSG(("file::commit: FlushViewOfFile(%p, %ld) failed: %d\n",
base, size, error_code));
return false;
}
} else {
if (!write_dirty_pages_in_file()) {
return false;
}
}
if (SetFilePointer(log, 0, NULL, FILE_BEGIN) != 0 || !SetEndOfFile(log)) {
error_code = GetLastError();
TRACE_MSG(("file::commit: failed to truncate lof file: %d\n",
error_code));
return false;
}
if (size > 0 && platform == VER_PLATFORM_WIN32_NT && !VirtualProtect(base, size, PAGE_READONLY, &old_prot)){
error_code = GetLastError();
TRACE_MSG(("file::commit: VirtualProtect(%p, %ld) failed: %d\n",
base, size, error_code));
return false;
}
error_code = ok;
return true;
}
bool file::rollback()
{
if (mode != shadow_pages_transaction) {
error_code = not_in_transaction;
return false;
}
SetFilePointer(log, 0, NULL, FILE_BEGIN);
return recover_file();
}
bool file::flush()
{
if (prot == read_only) {
return true;
}
if (mode == shadow_pages_transaction) {
return commit();
} else if (mode == map_file) {
if (!FlushViewOfFile(base, size)) {
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to flush file mapping: %d\n",
error_code));
return false;
}
error_code = ok;
return true;
} else { // non-shadow_pages_transaction mode
HANDLE tmp_fd = CreateFile(tmp_name, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
if (tmp_fd == INVALID_HANDLE_VALUE) {
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to create temporary file '%s': "
"%d\n", tmp_name, error_code));
return false;
}
DWORD written_bytes;
if (!WriteFile(tmp_fd, base, size, &written_bytes, NULL)
|| written_bytes != size)
{
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to write %ld bytes to file '%s': "
"%d\n", size, tmp_name, error_code));
CloseHandle(tmp_fd);
return false;
}
CloseHandle(tmp_fd);
if (platform == VER_PLATFORM_WIN32_NT) {
if (fd != INVALID_HANDLE_VALUE) {
assert(md != NULL);
if (!UnmapViewOfFile(base)) {
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to unmap %p: %d\n",
base, error_code));
return false;
}
if (!CloseHandle(md)) {
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to close file mapping: "
"%d\n", error_code));
return false;
}
if (!CloseHandle(fd)) {
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to close file: %d\n",
error_code));
return false;
}
if (!MoveFileEx(tmp_name, name, MOVEFILE_REPLACE_EXISTING|
MOVEFILE_WRITE_THROUGH) != 0)
{
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to reanme fileL %d\n",
error_code));
return false;
}
fd = CreateFile(name, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fd == INVALID_HANDLE_VALUE) {
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to open file: %d\n",
error_code));
return false;
}
assert(vmem != NULL);
md = CreateFileMapping(fd, NULL, PAGE_WRITECOPY, 0,
vmem - base, NULL);
if (md == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to create file mapping: "
"base=%p, size=%ld: %d\n",
base, vmem - base, error_code));
CloseHandle(fd);
return false;
}
void* p = MapViewOfFileEx(md, FILE_MAP_COPY,
0, 0, vmem - base, base);
if (p == NULL) {
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to map view of file on "
"address %p size %d: %d\n",
base, vmem-base, error_code));
CloseHandle(fd);
CloseHandle(md);
return false;
}
assert(p == base);
} else { // just rename
if (!MoveFileEx(tmp_name, name, MOVEFILE_REPLACE_EXISTING|
MOVEFILE_WRITE_THROUGH) != 0)
{
error_code = GetLastError();
TRACE_MSG(("file::flush: failed to reanme fileL %d\n",
error_code));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -