File: blob_builder_from_stream.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (170 lines) | stat: -rw-r--r-- 6,674 bytes parent folder | download | duplicates (11)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef STORAGE_BROWSER_BLOB_BLOB_BUILDER_FROM_STREAM_H_
#define STORAGE_BROWSER_BLOB_BLOB_BUILDER_FROM_STREAM_H_

#include "base/component_export.h"
#include "base/containers/queue.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/shareable_blob_data_item.h"
#include "third_party/blink/public/mojom/blob/blob_registry.mojom.h"

namespace storage {

// This class can be used to create a blob from a stream source, when it is not
// known in advance how large the blob is going to be. The actual blob won't be
// created until all the data is received. This class deals with memory
// management and quota allocation for the new blob, and makes sure we have
// enough available blob quota for the blob being constructed.
//
// This class will allocate space from the BlobMemoryController as data is
// received. If more data is received than we can allocate space for we abort
// the creation of the blob, free up all space already allocated and return an
// error.
//
// The high-level strategy for how this class allocated space is that it stores
// the first several KB of a blob in memory, and switches to files on disk if
// the blob grows bigger than a certain size (assuming paging to disk is
// enabled, otherwise the entire blob of course has to be stored in memory).
// Space is allocated in chunks, before data is received for that chunk. If the
// end of the stream is reached before a chunk is filled up, the chunk (and its
// space allocation) is shrunk to match the actual size of the data in it.
//
// Generally this class tries avoid evicting other blobs that are already in
// memory to disk. So if there is no more room in-memory so store the blob being
// built we might switch to disk before the normal trigger size is reached.
//
// Finally you can pass an |length_hint| to the constructor. If this is done,
// the size is used for an initial space allocation, and if the size is too
// large to fit in memory anyway, the entire blob will be stored on disk.
//
// If this needs to be destroyed before building has finished, you should make
// sure to call Abort() before destroying the instance. No blob will be created
// in that case.
class COMPONENT_EXPORT(STORAGE_BROWSER) BlobBuilderFromStream {
 public:
  using ResultCallback =
      base::OnceCallback<void(BlobBuilderFromStream*,
                              std::unique_ptr<BlobDataHandle>)>;

  BlobBuilderFromStream(
      base::WeakPtr<BlobStorageContext> context,
      std::string content_type,
      std::string content_disposition,
      ResultCallback callback);
  ~BlobBuilderFromStream();

  // This may call |callback| synchronously when |length_hint| is larger than
  // the disk space.
  void Start(uint64_t length_hint,
             mojo::ScopedDataPipeConsumerHandle data,
             mojo::PendingAssociatedRemote<blink::mojom::ProgressClient>
                 progress_client);

  void Abort();

 private:
  class WritePipeToFileHelper;
  class WritePipeToFutureDataHelper;

  void AllocateMoreMemorySpace(
      uint64_t length_hint,
      mojo::PendingAssociatedRemote<blink::mojom::ProgressClient>
          progress_client,
      mojo::ScopedDataPipeConsumerHandle pipe);
  void MemoryQuotaAllocated(
      mojo::ScopedDataPipeConsumerHandle pipe,
      mojo::PendingAssociatedRemote<blink::mojom::ProgressClient>
          progress_client,
      std::vector<scoped_refptr<ShareableBlobDataItem>> chunk_items,
      size_t item_to_populate,
      bool success);
  void DidWriteToMemory(
      std::vector<scoped_refptr<ShareableBlobDataItem>> chunk_items,
      size_t populated_item_index,
      uint64_t bytes_written,
      mojo::ScopedDataPipeConsumerHandle pipe,
      mojo::PendingAssociatedRemote<blink::mojom::ProgressClient>
          progress_client);

  void AllocateMoreFileSpace(
      uint64_t length_hint,
      mojo::PendingAssociatedRemote<blink::mojom::ProgressClient>
          progress_client,
      mojo::ScopedDataPipeConsumerHandle pipe);
  void FileQuotaAllocated(
      mojo::ScopedDataPipeConsumerHandle pipe,
      mojo::PendingAssociatedRemote<blink::mojom::ProgressClient>
          progress_client,
      std::vector<scoped_refptr<ShareableBlobDataItem>> chunk_items,
      size_t item_to_populate,
      std::vector<BlobMemoryController::FileCreationInfo> info,
      bool success);
  void DidWriteToFile(
      std::vector<scoped_refptr<ShareableBlobDataItem>> chunk_items,
      std::vector<BlobMemoryController::FileCreationInfo> info,
      size_t populated_item_index,
      bool success,
      uint64_t bytes_written,
      mojo::ScopedDataPipeConsumerHandle pipe,
      mojo::PendingAssociatedRemote<blink::mojom::ProgressClient>
          progress_client,
      const base::Time& modification_time);
  void DidWriteToExtendedFile(
      scoped_refptr<ShareableFileReference> file_reference,
      uint64_t old_file_size,
      bool success,
      uint64_t bytes_written,
      mojo::ScopedDataPipeConsumerHandle pipe,
      mojo::PendingAssociatedRemote<blink::mojom::ProgressClient>
          progress_client,
      const base::Time& modification_time);

  // These values are persisted to logs. Entries should not be renumbered and
  // numeric values should never be reused.
  enum class Result {
    kSuccess = 0,
    kAborted = 1,
    kMemoryAllocationFailed = 2,
    kFileAllocationFailed = 3,
    kFileWriteFailed = 4,
    kMaxValue = kFileWriteFailed
  };

  void OnError(Result result);
  void OnSuccess();

  bool ShouldStoreNextBlockOnDisk(uint64_t length_hint);

  // Amount of memory space we allocate at a time.
  const size_t kMemoryBlockSize;

  // Maximum total amount of space this blob will take up in memory. If the
  // blob becomes bigger than this we switch to files.
  const size_t kMaxBytesInMemory;

  // Amount of file space we allocate at a time.
  const uint64_t kFileBlockSize;

  // Maximum size of individual files.
  const uint64_t kMaxFileSize;

  base::WeakPtr<BlobStorageContext> context_;
  ResultCallback callback_;

  std::string content_type_;
  std::string content_disposition_;

  std::vector<scoped_refptr<ShareableBlobDataItem>> items_;
  uint64_t current_total_size_ = 0;
  base::WeakPtr<BlobMemoryController::QuotaAllocationTask> pending_quota_task_;
  base::WeakPtrFactory<BlobBuilderFromStream> weak_factory_{this};
};

}  // namespace storage

#endif  // STORAGE_BROWSER_BLOB_BLOB_BUILDER_FROM_STREAM_H_