Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: third_party/WebKit/Source/modules/indexeddb/IDBValueWrapping.h

Issue 2822453003: Wrap large IndexedDB values into Blobs before writing to LevelDB. (Closed)
Patch Set: WIP: Getting IDBRequestTest.EventsAfterStopping to pass. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 #ifndef IDBValueWrapping_h
6 #define IDBValueWrapping_h
7
8 #include "bindings/core/v8/ExceptionState.h"
9 #include "platform/SharedBuffer.h"
10 #include "platform/wtf/RefPtr.h"
11 #include "platform/wtf/Vector.h"
12 #include "public/platform/WebBlobInfo.h"
13 #include "v8/include/v8.h"
14
15 namespace WTF {
16 class String;
17 }
18
19 namespace blink {
20
21 class Blob;
22 class BlobDataHandle;
23 class ExceptionState;
24 class IDBValue;
25 class ScriptState;
26 class ScriptValue;
27 class SerializedScriptValue;
28 class SharedBuffer;
29
30 // Logic for serializing V8 values for storage in IndexedDB.
31 //
32 // "Normal" V8 values are stored on disk using the format implemented in
jsbell 2017/05/15 23:37:39 nit: this first sentence is true whether we wrap o
pwnall 2017/05/19 18:27:35 Done.
33 // SerializedScriptValue. In order to avoid operating IndexedDB's backing store
34 // in a sub-optimal region, "large" V8 values are wrapped in Blobs. In this
35 // case, the SSV output is stored using the Blob storage system, and IndexedDB's
36 // backing store only holds references to the Blobs.
37 //
38 // In summary:
39 // "normal" v8::Value -> SSV -> IDBValue (stores SSV output) -> LevelDB
40 // "large" v8::Value -> SSV -> IDBValue (stores SSV output) ->
41 // Blob (stores SSV output) + IDBValue (stores Blob reference) -> LevelDB
42 class IDBValueWrapper {
43 public:
44 // Wrapper for an IndexedDB value.
45 //
46 // The serialization process can throw an exception. The caller is responsible
47 // for checking exception_state.
48 IDBValueWrapper(v8::Isolate*,
49 v8::Local<v8::Value>,
50 bool write_wasm_to_stream,
51 ExceptionState&);
52
53 // Creates a clone of the serialized value.
54 //
55 // This method is necessary because the IndexedDB specification demands that a
56 // value's key and index keys are extracted from a structured clone of the
57 // value.
jsbell 2017/05/15 23:37:39 Add "... to avoid side effects." (We didn't spec
pwnall 2017/05/19 18:27:35 Done. Yikes, I didn't mean to criticize the spec,
58 //
59 // This method cannot be called after WrapIfBiggerThan().
60 void Clone(ScriptState*, ScriptValue* clone);
61
62 // Wraps the serialized value into a Blob if it exceeds the given size.
63 //
64 // In production, the threshold is currently always kWrapThreshold.
65 //
66 // This method must be called before ExtractWireBytes() and cannot be called
67 // after ExtractWireBytes().
68 bool WrapIfBiggerThan(unsigned max_bytes);
69
70 void ExtractBlobDataHandles(
71 Vector<RefPtr<BlobDataHandle>>* blob_data_handles);
72
73 RefPtr<SharedBuffer> ExtractWireBytes();
74
75 inline Vector<WebBlobInfo>& WrappedBlobInfo() {
76 #if DCHECK_IS_ON()
77 DCHECK(!had_exception_)
78 << "WrapBlobInfo() called on wrapper with serialization exception";
79 #endif // DCHECK_IS_ON()
80 return blob_info_;
81 }
82
83 // Default threshold for WrapIfBiggerThan().
84 //
85 // This should be tuned to achieve a compromise between short-term IndexedDB
86 // throughput and long-term I/O load and memory usage. LevelDB, the underlying
87 // storage for IndexedDB, was not designed with large values in mind. At the
88 // very least, large values will slow down compaction, causing occasional I/O
89 // spikes.
90 static constexpr unsigned kWrapThreshold = 64 * 1024;
91
92 // MIME type used for Blobs that wrap IDBValues.
93 static constexpr const char* kWrapMimeType =
94 "application/x-blink-idb-value-wrapper";
95
96 private:
97 // Used to serialize the wrapped value.
98 static void WriteVarint(unsigned value, Vector<char>& output);
99 static void WriteAsciiString(const String& value, Vector<char>& output);
100
101 RefPtr<SerializedScriptValue> serialized_value_;
102 RefPtr<BlobDataHandle> wrapper_handle_;
103 Vector<WebBlobInfo> blob_info_;
104 Vector<BlobDataHandle> blob_handles_;
105 Vector<char> wire_bytes_;
106 #if DCHECK_IS_ON()
107 bool had_exception_ = false;
108 bool wrap_called_ = false;
109 #endif // DCHECK_IS_ON()
110 };
111
112 // State and logic for unwrapping large IndexedDB values from Blobs.
113 //
114 // See IDBValueWrapper for an explanation of the wrapping concept.
115 //
116 // Once created, an IDBValueUnwrapper instance can be used to unwrap multiple
117 // Blobs. For each Blob to be unwrapped, the caller should first call Parse().
118 // If the method succeeds, the IDBValueUnwrapper will store the parse state,
119 // which can be obtained using WrapperBlobSize() and WrapperBlobHandle().
120 class IDBValueUnwrapper {
121 public:
122 IDBValueUnwrapper();
123
124 // Checks whether a IDBValue's data was wrapped in a Blob.
125 static bool IsWrapped(IDBValue*);
126
127 // Pieces together an unwrapped IDBValue from a wrapped value and Blob data.
128 static RefPtr<IDBValue> CreateUnwrapped(
129 IDBValue* wrapped_value,
130 RefPtr<SharedBuffer>&& wrapper_blob_content);
131
132 // Parses the wrapper Blob information from a wrapped IDBValue.
133 //
134 // Returns true for success, and false for failure. Failure can mean that the
135 // given value was not a wrapped IDBValue, or that the value bytes were
136 // corrupted.
137 bool Parse(IDBValue*);
138
139 // Returns the size of the Blob obtained by the last Unwrap() call.
140 //
141 // Should only be called after a successful result from Unwrap().
142 inline unsigned WrapperBlobSize() const {
143 DCHECK(end_);
144 return blob_size_;
145 }
146
147 // Returns a handle to the Blob obtained by the last Unwrap() call.
148 //
149 // Should only be called exactly once after a successful result from Unwrap().
150 RefPtr<BlobDataHandle> WrapperBlobHandle();
151
152 private:
153 // Used to deserialize the wrapped value.
154 bool ReadVarint(unsigned& value);
155 bool ReadAsciiString(String& value);
156
157 // Resets the parsing state.
158 inline bool Reset() {
159 #if DCHECK_IS_ON()
160 blob_handle_.Clear();
161 current_ = nullptr;
162 end_ = nullptr;
163 #endif // DCHECK_IS_ON()
164 return false;
165 }
166
167 // Deserialization cursor in the SharedBuffer of the IDBValue being unwrapped.
168 const uint8_t* current_;
169
170 // Smallest invalid position_ value.
171 const uint8_t* end_;
172
173 // The size of the Blob holding the data for the last unwrapped IDBValue.
174 unsigned blob_size_;
175
176 // Handle to the Blob holding the data for the last unwrapped IDBValue.
177 RefPtr<BlobDataHandle> blob_handle_;
178 };
179
180 } // namespace blink
181
182 #endif // IDBValueWrapping_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698