// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "net/disk_cache/mapped_file.h" #include #include "base/file_path.h" #include "base/logging.h" namespace disk_cache { void* MappedFile::Init(const FilePath& name, size_t size) { DCHECK(!init_); if (init_ || !File::Init(name)) return NULL; if (!size) size = GetLength(); buffer_ = malloc(size); snapshot_ = malloc(size); if (buffer_ && snapshot_ && Read(buffer_, size, 0)) { memcpy(snapshot_, buffer_, size); } else { free(buffer_); free(snapshot_); buffer_ = snapshot_ = 0; } init_ = true; view_size_ = size; return buffer_; } bool MappedFile::Load(const FileBlock* block) { size_t offset = block->offset() + view_size_; return Read(block->buffer(), block->size(), offset); } bool MappedFile::Store(const FileBlock* block) { size_t offset = block->offset() + view_size_; return Write(block->buffer(), block->size(), offset); } void MappedFile::Flush() { DCHECK(buffer_); DCHECK(snapshot_); if (0 == memcmp(buffer_, snapshot_, view_size_)) { // Nothing changed, no need to flush. return; } const char* buffer_ptr = static_cast(buffer_); char* snapshot_ptr = static_cast(snapshot_); size_t i = 0; while (i < view_size_) { size_t run_start = i; // Look for a run of changed bytes (possibly zero-sized). Write them out. while(i < view_size_ && snapshot_ptr[i] != buffer_ptr[i]) { snapshot_ptr[i] = buffer_ptr[i]; i++; } if (i > run_start) { Write(snapshot_ptr + run_start, i - run_start, run_start); } // Look for a run of unchanged bytes (possibly zero-sized). Skip them. while (i < view_size_ && snapshot_ptr[i] == buffer_ptr[i]) { i++; } } DCHECK(0 == memcmp(buffer_, snapshot_, view_size_)); } MappedFile::~MappedFile() { if (!init_) return; if (buffer_ && snapshot_) { Flush(); } free(buffer_); free(snapshot_); } } // namespace disk_cache