|  | // 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 "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 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 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 sparse_offset, | 
|  | int length, | 
|  | int64* 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 sparse_offset = 0; | 
|  | const int length = 0; | 
|  | int64* 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 end = sparse_offset_ + length_; | 
|  | int64 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 sparse_offset, | 
|  | int length, | 
|  | int64* 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 |