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

Side by Side Diff: content/browser/indexed_db/indexed_db_leveldb_coding.cc

Issue 1682253004: Indexed DB: Pull leveldb coding scheme docs into a markdown file (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add compile asserts, reformat docs Created 4 years, 10 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
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h" 5 #include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
6 6
7 #include <iterator> 7 #include <iterator>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/strings/string16.h" 11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h"
13 #include "base/sys_byteorder.h" 13 #include "base/sys_byteorder.h"
14 #include "content/common/indexed_db/indexed_db_key.h" 14 #include "content/common/indexed_db/indexed_db_key.h"
15 #include "content/common/indexed_db/indexed_db_key_path.h" 15 #include "content/common/indexed_db/indexed_db_key_path.h"
16 16
17 // LevelDB Coding Scheme 17 // See leveldb_coding_scheme.md for detailed documentation of the coding
18 // ===================== 18 // scheme implemented here.
19 //
20 // LevelDB stores key/value pairs. Keys and values are strings of bytes,
21 // normally of type std::string.
22 //
23 // The keys in the backing store are variable-length tuples with different
24 // types of fields. Each key in the backing store starts with a ternary
25 // prefix: (database id, object store id, index id). For each, 0 is reserved
26 // for metadata. See KeyPrefix::Decode() for details of the prefix coding.
27 //
28 // The prefix makes sure that data for a specific database, object store, and
29 // index are grouped together. The locality is important for performance:
30 // common operations should only need a minimal number of seek operations. For
31 // example, all the metadata for a database is grouped together so that
32 // reading that metadata only requires one seek.
33 //
34 // Each key type has a class (in square brackets below) which knows how to
35 // encode, decode, and compare that key type.
36 //
37 // Strings (origins, names, etc) are encoded as UTF-16BE.
38 //
39 //
40 // Global metadata
41 // ---------------
42 // The prefix is <0, 0, 0>, followed by a metadata type byte:
43 //
44 // <0, 0, 0, 0> => backing store schema version [SchemaVersionKey]
45 // <0, 0, 0, 1> => maximum allocated database [MaxDatabaseIdKey]
46 // <0, 0, 0, 2> => SerializedScriptValue version [DataVersionKey]
47 // <0, 0, 0, 3>
48 // => Blob journal
49 // The format of the journal is:
50 // {database_id (var int), blobKey (var int)}*.
51 // If the blobKey is kAllBlobsKey, the whole database should be deleted.
52 // [BlobJournalKey]
53 // <0, 0, 0, 4> => Live blob journal; same format. [LiveBlobJournalKey]
54 // <0, 0, 0, 100, database id>
55 // => Existence implies the database id is in the free list
56 // [DatabaseFreeListKey]
57 // <0, 0, 0, 201, origin, database name> => Database id (int) [DatabaseNameKey]
58 //
59 //
60 // Database metadata: [DatabaseMetaDataKey]
61 // ----------------------------------------
62 // The prefix is <database id, 0, 0> followed by a metadata type byte:
63 //
64 // <database id, 0, 0, 0> => origin name
65 // <database id, 0, 0, 1> => database name
66 // <database id, 0, 0, 2> => IDB string version data (obsolete)
67 // <database id, 0, 0, 3> => maximum allocated object store id
68 // <database id, 0, 0, 4> => IDB integer version (var int)
69 // <database id, 0, 0, 5> => blob key generator current number
70 //
71 //
72 // Object store metadata: [ObjectStoreMetaDataKey]
73 // -----------------------------------------------
74 // The prefix is <database id, 0, 0>, followed by a type byte (50), then the
75 // object store id (var int), then a metadata type byte.
76 //
77 // <database id, 0, 0, 50, object store id, 0> => object store name
78 // <database id, 0, 0, 50, object store id, 1> => key path
79 // <database id, 0, 0, 50, object store id, 2> => auto increment flag
80 // <database id, 0, 0, 50, object store id, 3> => is evictable
81 // <database id, 0, 0, 50, object store id, 4> => last "version" number
82 // <database id, 0, 0, 50, object store id, 5> => maximum allocated index id
83 // <database id, 0, 0, 50, object store id, 6> => has key path flag (obsolete)
84 // <database id, 0, 0, 50, object store id, 7> => key generator current number
85 //
86 // The key path was originally just a string (#1) or null (identified by flag,
87 // #6). To support null, string, or array the coding is now identified by the
88 // leading bytes in #1 - see EncodeIDBKeyPath.
89 //
90 // The "version" field is used to weed out stale index data. Whenever new
91 // object store data is inserted, it gets a new "version" number, and new
92 // index data is written with this number. When the index is used for
93 // look-ups, entries are validated against the "exists" entries, and records
94 // with old "version" numbers are deleted when they are encountered in
95 // GetPrimaryKeyViaIndex, IndexCursorImpl::LoadCurrentRow and
96 // IndexKeyCursorImpl::LoadCurrentRow.
97 //
98 //
99 // Index metadata: [IndexMetaDataKey]
100 // ----------------------------------
101 // The prefix is <database id, 0, 0>, followed by a type byte (100), then the
102 // object store id (var int), then the index id (var int), then a metadata
103 // type byte.
104 //
105 // <database id, 0, 0, 100, object store id, index id, 0> => index name
106 // <database id, 0, 0, 100, object store id, index id, 1> => unique flag
107 // <database id, 0, 0, 100, object store id, index id, 2> => key path
108 // <database id, 0, 0, 100, object store id, index id, 3> => multi-entry flag
109 //
110 //
111 // Other object store and index metadata
112 // -------------------------------------
113 // The prefix is <database id, 0, 0> followed by a type byte. The object
114 // store and index id are variable length integers, the names are variable
115 // length strings.
116 //
117 // <database id, 0, 0, 150, object store id>
118 // => existence implies the object store id is in the free list
119 // [ObjectStoreFreeListKey]
120 // <database id, 0, 0, 151, object store id, index id>
121 // => existence implies the index id is in the free list [IndexFreeListKey]
122 // <database id, 0, 0, 200, object store name>
123 // => object store id [ObjectStoreNamesKey]
124 // <database id, 0, 0, 201, object store id, index name>
125 // => index id [IndexNamesKey]
126 //
127 //
128 // Object store data: [ObjectStoreDataKey]
129 // ---------------------------------------
130 // The prefix is followed by a type byte and the encoded IDB primary key. The
131 // data has a "version" prefix followed by the serialized script value.
132 //
133 // <database id, object store id, 1, user key>
134 // => "version", serialized script value
135 //
136 //
137 // "Exists" entry: [ExistsEntryKey]
138 // --------------------------------
139 // The prefix is followed by a type byte and the encoded IDB primary key.
140 //
141 // <database id, object store id, 2, user key> => "version"
142 //
143 //
144 // Blob entry table: [BlobEntryKey]
145 // --------------------------------
146 //
147 // The prefix is followed by a type byte and the encoded IDB primary key.
148 //
149 // <database id, object store id, 3, user key> => array of IndexedDBBlobInfo
150 //
151 //
152 // Index data
153 // ----------
154 // The prefix is followed by a type byte, the encoded IDB index key, a
155 // "sequence" number (obsolete; var int), and the encoded IDB primary key.
156 //
157 // <database id, object store id, index id, index key, sequence number,
158 // primary key> => "version", primary key [IndexDataKey]
159 //
160 // The sequence number is obsolete; it was used to allow two entries with the
161 // same user (index) key in non-unique indexes prior to the inclusion of the
162 // primary key in the data.
163 //
164 // Note: In order to be compatible with LevelDB's Bloom filter each bit of the
cmumford 2016/02/11 00:48:31 This last sentence is omitted from the *.md file.
jsbell 2016/02/11 23:26:55 It was moved earlier.
165 // encoded key needs to used and "not ignored" by the comparator.
166 19
167 using base::StringPiece; 20 using base::StringPiece;
168 using blink::WebIDBKeyType; 21 using blink::WebIDBKeyType;
169 using blink::WebIDBKeyTypeArray; 22 using blink::WebIDBKeyTypeArray;
170 using blink::WebIDBKeyTypeBinary; 23 using blink::WebIDBKeyTypeBinary;
171 using blink::WebIDBKeyTypeDate; 24 using blink::WebIDBKeyTypeDate;
172 using blink::WebIDBKeyTypeInvalid; 25 using blink::WebIDBKeyTypeInvalid;
173 using blink::WebIDBKeyTypeMin; 26 using blink::WebIDBKeyTypeMin;
174 using blink::WebIDBKeyTypeNull; 27 using blink::WebIDBKeyTypeNull;
175 using blink::WebIDBKeyTypeNumber; 28 using blink::WebIDBKeyTypeNumber;
(...skipping 14 matching lines...) Expand all
190 static const unsigned char kIndexedDBKeyStringTypeByte = 1; 43 static const unsigned char kIndexedDBKeyStringTypeByte = 1;
191 static const unsigned char kIndexedDBKeyDateTypeByte = 2; 44 static const unsigned char kIndexedDBKeyDateTypeByte = 2;
192 static const unsigned char kIndexedDBKeyNumberTypeByte = 3; 45 static const unsigned char kIndexedDBKeyNumberTypeByte = 3;
193 static const unsigned char kIndexedDBKeyArrayTypeByte = 4; 46 static const unsigned char kIndexedDBKeyArrayTypeByte = 4;
194 static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5; 47 static const unsigned char kIndexedDBKeyMinKeyTypeByte = 5;
195 static const unsigned char kIndexedDBKeyBinaryTypeByte = 6; 48 static const unsigned char kIndexedDBKeyBinaryTypeByte = 6;
196 49
197 static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0; 50 static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
198 static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0; 51 static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
199 52
53 static const unsigned char kIndexedDBKeyPathNullTypeByte = 0;
54 static const unsigned char kIndexedDBKeyPathStringTypeByte = 1;
55 static const unsigned char kIndexedDBKeyPathArrayTypeByte = 2;
56
200 static const unsigned char kObjectStoreDataIndexId = 1; 57 static const unsigned char kObjectStoreDataIndexId = 1;
201 static const unsigned char kExistsEntryIndexId = 2; 58 static const unsigned char kExistsEntryIndexId = 2;
202 static const unsigned char kBlobEntryIndexId = 3; 59 static const unsigned char kBlobEntryIndexId = 3;
203 60
204 static const unsigned char kSchemaVersionTypeByte = 0; 61 static const unsigned char kSchemaVersionTypeByte = 0;
205 static const unsigned char kMaxDatabaseIdTypeByte = 1; 62 static const unsigned char kMaxDatabaseIdTypeByte = 1;
206 static const unsigned char kDataVersionTypeByte = 2; 63 static const unsigned char kDataVersionTypeByte = 2;
207 static const unsigned char kBlobJournalTypeByte = 3; 64 static const unsigned char kBlobJournalTypeByte = 3;
208 static const unsigned char kLiveBlobJournalTypeByte = 4; 65 static const unsigned char kLiveBlobJournalTypeByte = 4;
209 static const unsigned char kMaxSimpleGlobalMetaDataTypeByte = 66 static const unsigned char kMaxSimpleGlobalMetaDataTypeByte =
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 case WebIDBKeyTypeNull: 203 case WebIDBKeyTypeNull:
347 case WebIDBKeyTypeInvalid: 204 case WebIDBKeyTypeInvalid:
348 case WebIDBKeyTypeMin: 205 case WebIDBKeyTypeMin:
349 default: 206 default:
350 NOTREACHED(); 207 NOTREACHED();
351 EncodeByte(kIndexedDBKeyNullTypeByte, into); 208 EncodeByte(kIndexedDBKeyNullTypeByte, into);
352 return; 209 return;
353 } 210 }
354 } 211 }
355 212
213 #define COMPILE_ASSERT_MATCHING_VALUES(a, b) \
214 static_assert( \
215 static_cast<unsigned char>(a) == static_cast<unsigned char>(b), \
216 "Blink enum and coding byte must match.")
217
218 COMPILE_ASSERT_MATCHING_VALUES(WebIDBKeyPathTypeNull,
219 kIndexedDBKeyPathNullTypeByte);
220 COMPILE_ASSERT_MATCHING_VALUES(WebIDBKeyPathTypeString,
221 kIndexedDBKeyPathStringTypeByte);
222 COMPILE_ASSERT_MATCHING_VALUES(WebIDBKeyPathTypeArray,
223 kIndexedDBKeyPathArrayTypeByte);
224
356 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) { 225 void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
357 // May be typed, or may be a raw string. An invalid leading 226 // May be typed, or may be a raw string. An invalid leading
358 // byte is used to identify typed coding. New records are 227 // byte is used to identify typed coding. New records are
359 // always written as typed. 228 // always written as typed.
360 EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into); 229 EncodeByte(kIndexedDBKeyPathTypeCodedByte1, into);
361 EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into); 230 EncodeByte(kIndexedDBKeyPathTypeCodedByte2, into);
362 EncodeByte(static_cast<char>(value.type()), into); 231 EncodeByte(static_cast<char>(value.type()), into);
363 switch (value.type()) { 232 switch (value.type()) {
364 case WebIDBKeyPathTypeNull: 233 case WebIDBKeyPathTypeNull:
365 break; 234 break;
(...skipping 1661 matching lines...) Expand 10 before | Expand all | Expand 10 after
2027 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const { 1896 scoped_ptr<IndexedDBKey> IndexDataKey::primary_key() const {
2028 scoped_ptr<IndexedDBKey> key; 1897 scoped_ptr<IndexedDBKey> key;
2029 StringPiece slice(encoded_primary_key_); 1898 StringPiece slice(encoded_primary_key_);
2030 if (!DecodeIDBKey(&slice, &key)) { 1899 if (!DecodeIDBKey(&slice, &key)) {
2031 // TODO(jsbell): Return error. 1900 // TODO(jsbell): Return error.
2032 } 1901 }
2033 return key; 1902 return key;
2034 } 1903 }
2035 1904
2036 } // namespace content 1905 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698