| // Copyright 2013 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/simple/simple_entry_operation.h" |
| |
| #include <limits.h> |
| |
| #include "base/logging.h" |
| #include "net/base/io_buffer.h" |
| #include "net/disk_cache/disk_cache.h" |
| #include "net/disk_cache/simple/simple_entry_impl.h" |
| |
| namespace disk_cache { |
| |
| namespace { |
| |
| bool IsReadWriteType(unsigned int type) { |
| return type == SimpleEntryOperation::TYPE_READ || |
| type == SimpleEntryOperation::TYPE_WRITE || |
| type == SimpleEntryOperation::TYPE_READ_SPARSE || |
| type == SimpleEntryOperation::TYPE_WRITE_SPARSE; |
| } |
| |
| bool IsReadType(unsigned type) { |
| return type == SimpleEntryOperation::TYPE_READ || |
| type == SimpleEntryOperation::TYPE_READ_SPARSE; |
| } |
| |
| bool IsSparseType(unsigned type) { |
| return type == SimpleEntryOperation::TYPE_READ_SPARSE || |
| type == SimpleEntryOperation::TYPE_WRITE_SPARSE; |
| } |
| |
| } |
| |
| SimpleEntryOperation::SimpleEntryOperation(const SimpleEntryOperation& other) |
| : entry_(other.entry_.get()), |
| buf_(other.buf_), |
| callback_(other.callback_), |
| out_entry_(other.out_entry_), |
| offset_(other.offset_), |
| sparse_offset_(other.sparse_offset_), |
| length_(other.length_), |
| out_start_(other.out_start_), |
| type_(other.type_), |
| have_index_(other.have_index_), |
| index_(other.index_), |
| truncate_(other.truncate_), |
| optimistic_(other.optimistic_), |
| alone_in_queue_(other.alone_in_queue_) { |
| } |
| |
| SimpleEntryOperation::~SimpleEntryOperation() {} |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::OpenOperation( |
| SimpleEntryImpl* entry, |
| bool have_index, |
| const CompletionCallback& callback, |
| Entry** out_entry) { |
| return SimpleEntryOperation(entry, |
| NULL, |
| callback, |
| out_entry, |
| 0, |
| 0, |
| 0, |
| NULL, |
| TYPE_OPEN, |
| have_index, |
| 0, |
| false, |
| false, |
| false); |
| } |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::CreateOperation( |
| SimpleEntryImpl* entry, |
| bool have_index, |
| const CompletionCallback& callback, |
| Entry** out_entry) { |
| return SimpleEntryOperation(entry, |
| NULL, |
| callback, |
| out_entry, |
| 0, |
| 0, |
| 0, |
| NULL, |
| TYPE_CREATE, |
| have_index, |
| 0, |
| false, |
| false, |
| false); |
| } |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::CloseOperation( |
| SimpleEntryImpl* entry) { |
| return SimpleEntryOperation(entry, |
| NULL, |
| CompletionCallback(), |
| NULL, |
| 0, |
| 0, |
| 0, |
| NULL, |
| TYPE_CLOSE, |
| false, |
| 0, |
| false, |
| false, |
| false); |
| } |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::ReadOperation( |
| SimpleEntryImpl* entry, |
| int index, |
| int offset, |
| int length, |
| net::IOBuffer* buf, |
| const CompletionCallback& callback, |
| bool alone_in_queue) { |
| return SimpleEntryOperation(entry, |
| buf, |
| callback, |
| NULL, |
| offset, |
| 0, |
| length, |
| NULL, |
| TYPE_READ, |
| false, |
| index, |
| false, |
| false, |
| alone_in_queue); |
| } |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::WriteOperation( |
| SimpleEntryImpl* entry, |
| int index, |
| int offset, |
| int length, |
| net::IOBuffer* buf, |
| bool truncate, |
| bool optimistic, |
| const CompletionCallback& callback) { |
| return SimpleEntryOperation(entry, |
| buf, |
| callback, |
| NULL, |
| offset, |
| 0, |
| length, |
| NULL, |
| TYPE_WRITE, |
| false, |
| index, |
| truncate, |
| optimistic, |
| false); |
| } |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::ReadSparseOperation( |
| SimpleEntryImpl* entry, |
| int64_t sparse_offset, |
| int length, |
| net::IOBuffer* buf, |
| const CompletionCallback& callback) { |
| return SimpleEntryOperation(entry, |
| buf, |
| callback, |
| NULL, |
| 0, |
| sparse_offset, |
| length, |
| NULL, |
| TYPE_READ_SPARSE, |
| false, |
| 0, |
| false, |
| false, |
| false); |
| } |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::WriteSparseOperation( |
| SimpleEntryImpl* entry, |
| int64_t sparse_offset, |
| int length, |
| net::IOBuffer* buf, |
| const CompletionCallback& callback) { |
| return SimpleEntryOperation(entry, |
| buf, |
| callback, |
| NULL, |
| 0, |
| sparse_offset, |
| length, |
| NULL, |
| TYPE_WRITE_SPARSE, |
| false, |
| 0, |
| false, |
| false, |
| false); |
| } |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::GetAvailableRangeOperation( |
| SimpleEntryImpl* entry, |
| int64_t sparse_offset, |
| int length, |
| int64_t* out_start, |
| const CompletionCallback& callback) { |
| return SimpleEntryOperation(entry, |
| NULL, |
| callback, |
| NULL, |
| 0, |
| sparse_offset, |
| length, |
| out_start, |
| TYPE_GET_AVAILABLE_RANGE, |
| false, |
| 0, |
| false, |
| false, |
| false); |
| } |
| |
| // static |
| SimpleEntryOperation SimpleEntryOperation::DoomOperation( |
| SimpleEntryImpl* entry, |
| const CompletionCallback& callback) { |
| net::IOBuffer* const buf = NULL; |
| Entry** const out_entry = NULL; |
| const int offset = 0; |
| const int64_t sparse_offset = 0; |
| const int length = 0; |
| int64_t* const out_start = NULL; |
| const bool have_index = false; |
| const int index = 0; |
| const bool truncate = false; |
| const bool optimistic = false; |
| const bool alone_in_queue = false; |
| return SimpleEntryOperation(entry, |
| buf, |
| callback, |
| out_entry, |
| offset, |
| sparse_offset, |
| length, |
| out_start, |
| TYPE_DOOM, |
| have_index, |
| index, |
| truncate, |
| optimistic, |
| alone_in_queue); |
| } |
| |
| bool SimpleEntryOperation::ConflictsWith( |
| const SimpleEntryOperation& other_op) const { |
| EntryOperationType other_type = other_op.type(); |
| |
| // Non-read/write operations conflict with everything. |
| if (!IsReadWriteType(type_) || !IsReadWriteType(other_type)) |
| return true; |
| |
| // Reads (sparse or otherwise) conflict with nothing. |
| if (IsReadType(type_) && IsReadType(other_type)) |
| return false; |
| |
| // Sparse and non-sparse operations do not conflict with each other. |
| if (IsSparseType(type_) != IsSparseType(other_type)) { |
| return false; |
| } |
| |
| // There must be two read/write operations, at least one must be a write, and |
| // they must be either both non-sparse or both sparse. Compare the streams |
| // and offsets to see whether they overlap. |
| |
| if (IsSparseType(type_)) { |
| int64_t end = sparse_offset_ + length_; |
| int64_t other_op_end = other_op.sparse_offset() + other_op.length(); |
| return sparse_offset_ < other_op_end && other_op.sparse_offset() < end; |
| } |
| |
| if (index_ != other_op.index_) |
| return false; |
| int end = (type_ == TYPE_WRITE && truncate_) ? INT_MAX : offset_ + length_; |
| int other_op_end = (other_op.type() == TYPE_WRITE && other_op.truncate()) |
| ? INT_MAX |
| : other_op.offset() + other_op.length(); |
| return offset_ < other_op_end && other_op.offset() < end; |
| } |
| |
| void SimpleEntryOperation::ReleaseReferences() { |
| callback_ = CompletionCallback(); |
| buf_ = NULL; |
| entry_ = NULL; |
| } |
| |
| SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry, |
| net::IOBuffer* buf, |
| const CompletionCallback& callback, |
| Entry** out_entry, |
| int offset, |
| int64_t sparse_offset, |
| int length, |
| int64_t* out_start, |
| EntryOperationType type, |
| bool have_index, |
| int index, |
| bool truncate, |
| bool optimistic, |
| bool alone_in_queue) |
| : entry_(entry), |
| buf_(buf), |
| callback_(callback), |
| out_entry_(out_entry), |
| offset_(offset), |
| sparse_offset_(sparse_offset), |
| length_(length), |
| out_start_(out_start), |
| type_(type), |
| have_index_(have_index), |
| index_(index), |
| truncate_(truncate), |
| optimistic_(optimistic), |
| alone_in_queue_(alone_in_queue) {} |
| |
| } // namespace disk_cache |