12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/io_buffer.h" 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/disk_cache/flash/format.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/disk_cache/flash/log_store.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/disk_cache/flash/log_store_entry.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace disk_cache { 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::LogStoreEntry(LogStore* store) 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : store_(store), id_(-1), init_(false), closed_(false), deleted_(false) { 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(store); 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::LogStoreEntry(LogStore* store, int32 id) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : store_(store), id_(id), init_(false), closed_(false), deleted_(false) { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(store); 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::~LogStoreEntry() { 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!init_ || closed_); 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogStoreEntry::Init() { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!init_); 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (IsNew()) { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) init_ = true; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 stream_sizes[kFlashLogStoreEntryNumStreams]; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) COMPILE_ASSERT(sizeof(stream_sizes) == kFlashLogStoreEntryHeaderSize, 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) invalid_log_store_entry_header_size); 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!store_->OpenEntry(id_) || 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !store_->ReadData(id_, stream_sizes, kFlashLogStoreEntryHeaderSize, 0)) { 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0, offset = kFlashLogStoreEntryHeaderSize; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i < kFlashLogStoreEntryNumStreams; ++i) { 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) streams_[i].offset = offset; 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) streams_[i].size = stream_sizes[i]; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) offset += stream_sizes[i]; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) init_ = true; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogStoreEntry::Close() { 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(init_ && !closed_); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (IsNew()) { 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closed_ = deleted_ ? true : Save(); 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) store_->CloseEntry(id_); 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (deleted_) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) store_->DeleteEntry(id_, Size()); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closed_ = true; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return closed_; 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 LogStoreEntry::id() const { 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(init_); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id_; 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 LogStoreEntry::GetDataSize(int index) const { 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(init_); 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return InvalidStream(index) ? 0 : streams_[index].size; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int LogStoreEntry::ReadData(int index, int offset, net::IOBuffer* buf, 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int buf_len) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(init_); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (InvalidStream(index)) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return net::ERR_INVALID_ARGUMENT; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int stream_size = streams_[index].size; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (offset >= stream_size || offset < 0 || buf_len == 0) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 0; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (offset + buf_len > stream_size) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buf_len = stream_size - offset; 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!IsNew()) { 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) offset += streams_[index].offset; 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (store_->ReadData(id_, buf->data(), buf_len, offset)) 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return buf_len; 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return net::ERR_FAILED; 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(buf->data(), &streams_[index].write_buffer[offset], buf_len); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return buf_len; 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int LogStoreEntry::WriteData(int index, int offset, net::IOBuffer* buf, 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int buf_len) { 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(init_ && !closed_); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (InvalidStream(index)) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return net::ERR_INVALID_ARGUMENT; 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(offset >= 0 && buf_len >= 0); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Stream& stream = streams_[index]; 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t new_size = static_cast<size_t>(offset + buf_len); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_size) { 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(agayev): Currently, only append and overwrite is supported. Add 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // support for arbitrary writes. 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!offset || offset == stream.size); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (stream.write_buffer.size() < new_size) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream.write_buffer.resize(new_size); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) memcpy(&streams_[index].write_buffer[offset], buf->data(), buf_len); 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream.size = new_size; 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return buf_len; 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void LogStoreEntry::Delete() { 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(init_ && !closed_); 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) deleted_ = true; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool LogStoreEntry::IsNew() const { 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return id_ == -1; 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogStoreEntry::InvalidStream(int stream_index) const { 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return stream_index < 0 || stream_index >= kFlashLogStoreEntryNumStreams; 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int32 LogStoreEntry::Size() const { 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(init_); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 size = kFlashLogStoreEntryHeaderSize; 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kFlashLogStoreEntryNumStreams; ++i) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size += streams_[i].size; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(size > 0 && size <= kFlashSegmentFreeSpace); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return size; 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool LogStoreEntry::Save() { 143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DCHECK(init_ && !closed_ && !deleted_ && IsNew()); 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int32 stream_sizes[kFlashLogStoreEntryNumStreams]; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) COMPILE_ASSERT(sizeof(stream_sizes) == kFlashLogStoreEntryHeaderSize, 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) invalid_log_store_entry_header_size); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kFlashLogStoreEntryNumStreams; ++i) 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) stream_sizes[i] = streams_[i].size; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!store_->CreateEntry(Size(), &id_)) 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!store_->WriteData(stream_sizes, kFlashLogStoreEntryHeaderSize)) 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < kFlashLogStoreEntryNumStreams; ++i) { 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (streams_[i].size > 0 && 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !store_->WriteData(&streams_[i].write_buffer[0], streams_[i].size)) { 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) store_->CloseEntry(id_); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::Stream::Stream() : offset(0), size(0) { 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LogStoreEntry::Stream::~Stream() { 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace disk_cache 172