1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "storage/browser/fileapi/quota/quota_reservation_buffer.h"
6
7#include "base/bind.h"
8#include "storage/browser/fileapi/quota/open_file_handle.h"
9#include "storage/browser/fileapi/quota/open_file_handle_context.h"
10#include "storage/browser/fileapi/quota/quota_reservation.h"
11
12namespace storage {
13
14QuotaReservationBuffer::QuotaReservationBuffer(
15    base::WeakPtr<QuotaReservationManager> reservation_manager,
16    const GURL& origin,
17    FileSystemType type)
18    : reservation_manager_(reservation_manager),
19      origin_(origin),
20      type_(type),
21      reserved_quota_(0) {
22  DCHECK(origin.is_valid());
23  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
24  reservation_manager_->IncrementDirtyCount(origin, type);
25}
26
27scoped_refptr<QuotaReservation> QuotaReservationBuffer::CreateReservation() {
28  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
29  return make_scoped_refptr(new QuotaReservation(this));
30}
31
32scoped_ptr<OpenFileHandle> QuotaReservationBuffer::GetOpenFileHandle(
33    QuotaReservation* reservation,
34    const base::FilePath& platform_path) {
35  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
36  OpenFileHandleContext** open_file = &open_files_[platform_path];
37  if (!*open_file)
38    *open_file = new OpenFileHandleContext(platform_path, this);
39  return make_scoped_ptr(new OpenFileHandle(reservation, *open_file));
40}
41
42void QuotaReservationBuffer::CommitFileGrowth(int64 reserved_quota_consumption,
43                                              int64 usage_delta) {
44  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
45  if (!reservation_manager_)
46    return;
47  reservation_manager_->CommitQuotaUsage(origin_, type_, usage_delta);
48
49  if (reserved_quota_consumption > 0) {
50    if (reserved_quota_consumption > reserved_quota_) {
51      LOG(ERROR) << "Detected over consumption of the storage quota beyond its"
52                 << " reservation";
53      reserved_quota_consumption = reserved_quota_;
54    }
55
56    reserved_quota_ -= reserved_quota_consumption;
57    reservation_manager_->ReleaseReservedQuota(
58        origin_, type_, reserved_quota_consumption);
59  }
60}
61
62void QuotaReservationBuffer::DetachOpenFileHandleContext(
63    OpenFileHandleContext* open_file) {
64  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
65  DCHECK_EQ(open_file, open_files_[open_file->platform_path()]);
66  open_files_.erase(open_file->platform_path());
67}
68
69void QuotaReservationBuffer::PutReservationToBuffer(int64 reservation) {
70  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
71  DCHECK_LE(0, reservation);
72  reserved_quota_ += reservation;
73}
74
75QuotaReservationBuffer::~QuotaReservationBuffer() {
76  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
77  if (!reservation_manager_)
78    return;
79
80  DCHECK_LE(0, reserved_quota_);
81  if (reserved_quota_ && reservation_manager_) {
82    reservation_manager_->ReserveQuota(
83        origin_, type_, -reserved_quota_,
84        base::Bind(&QuotaReservationBuffer::DecrementDirtyCount,
85                   reservation_manager_, origin_, type_));
86  }
87  reservation_manager_->ReleaseReservationBuffer(this);
88}
89
90// static
91bool QuotaReservationBuffer::DecrementDirtyCount(
92    base::WeakPtr<QuotaReservationManager> reservation_manager,
93    const GURL& origin,
94    FileSystemType type,
95    base::File::Error error,
96    int64 delta_unused) {
97  DCHECK(origin.is_valid());
98  if (error == base::File::FILE_OK && reservation_manager) {
99    reservation_manager->DecrementDirtyCount(origin, type);
100    return true;
101  }
102  return false;
103}
104
105}  // namespace storage
106