leveldb-ruby 0.10 → 0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. data/ext/leveldb/extconf.rb +2 -6
  2. data/ext/leveldb/leveldb.cc +377 -33
  3. data/ext/leveldb/platform.rb +83 -0
  4. data/leveldb/Makefile +29 -28
  5. data/leveldb/build_detect_platform +23 -4
  6. data/leveldb/db/builder.cc +1 -1
  7. data/leveldb/db/builder.h +1 -1
  8. data/leveldb/db/corruption_test.cc +1 -1
  9. data/leveldb/db/db_bench.cc +2 -2
  10. data/leveldb/db/db_impl.cc +8 -16
  11. data/leveldb/db/db_impl.h +1 -1
  12. data/leveldb/db/db_iter.cc +1 -1
  13. data/leveldb/db/db_iter.h +1 -1
  14. data/leveldb/db/db_test.cc +180 -9
  15. data/leveldb/db/dbformat.cc +9 -7
  16. data/leveldb/db/dbformat.h +2 -2
  17. data/leveldb/db/dbformat_test.cc +1 -1
  18. data/leveldb/db/filename.cc +6 -2
  19. data/leveldb/db/filename.h +1 -1
  20. data/leveldb/db/filename_test.cc +1 -1
  21. data/leveldb/db/log_format.h +2 -2
  22. data/leveldb/db/log_reader.cc +2 -2
  23. data/leveldb/db/log_reader.h +2 -2
  24. data/leveldb/db/log_test.cc +2 -2
  25. data/leveldb/db/log_writer.cc +2 -2
  26. data/leveldb/db/log_writer.h +2 -2
  27. data/leveldb/db/memtable.cc +1 -1
  28. data/leveldb/db/memtable.h +1 -1
  29. data/leveldb/db/repair.cc +2 -2
  30. data/leveldb/db/skiplist.h +1 -1
  31. data/leveldb/db/skiplist_test.cc +1 -1
  32. data/leveldb/db/snapshot.h +1 -1
  33. data/leveldb/db/table_cache.cc +1 -1
  34. data/leveldb/db/table_cache.h +1 -1
  35. data/leveldb/db/version_edit.cc +1 -1
  36. data/leveldb/db/version_edit.h +1 -1
  37. data/leveldb/db/version_edit_test.cc +1 -1
  38. data/leveldb/db/version_set.cc +39 -14
  39. data/leveldb/db/version_set.h +1 -1
  40. data/leveldb/db/version_set_test.cc +1 -1
  41. data/leveldb/db/write_batch.cc +2 -2
  42. data/leveldb/db/write_batch_internal.h +1 -1
  43. data/leveldb/db/write_batch_test.cc +1 -1
  44. data/leveldb/helpers/memenv/memenv.cc +374 -0
  45. data/leveldb/helpers/memenv/memenv.h +20 -0
  46. data/leveldb/helpers/memenv/memenv_test.cc +232 -0
  47. data/leveldb/include/leveldb/cache.h +1 -1
  48. data/leveldb/include/leveldb/comparator.h +1 -1
  49. data/leveldb/include/leveldb/db.h +1 -1
  50. data/leveldb/include/leveldb/env.h +1 -1
  51. data/leveldb/include/leveldb/iterator.h +1 -1
  52. data/leveldb/include/leveldb/options.h +1 -1
  53. data/leveldb/include/leveldb/slice.h +1 -1
  54. data/leveldb/include/leveldb/status.h +1 -1
  55. data/leveldb/include/leveldb/table.h +1 -1
  56. data/leveldb/include/leveldb/table_builder.h +1 -1
  57. data/leveldb/include/leveldb/write_batch.h +1 -1
  58. data/leveldb/port/atomic_pointer.h +2 -2
  59. data/leveldb/port/port_android.cc +2 -2
  60. data/leveldb/port/port_android.h +2 -2
  61. data/leveldb/port/port_example.h +2 -2
  62. data/leveldb/port/port_posix.cc +2 -2
  63. data/leveldb/port/port_posix.h +11 -3
  64. data/leveldb/table/block.cc +1 -1
  65. data/leveldb/table/block.h +1 -1
  66. data/leveldb/table/block_builder.cc +1 -1
  67. data/leveldb/table/block_builder.h +1 -1
  68. data/leveldb/table/format.cc +1 -1
  69. data/leveldb/table/format.h +1 -1
  70. data/leveldb/table/iterator.cc +2 -2
  71. data/leveldb/table/merger.cc +2 -2
  72. data/leveldb/table/merger.h +1 -1
  73. data/leveldb/table/table.cc +1 -1
  74. data/leveldb/table/table_builder.cc +1 -1
  75. data/leveldb/table/table_test.cc +3 -3
  76. data/leveldb/table/two_level_iterator.cc +2 -2
  77. data/leveldb/table/two_level_iterator.h +1 -1
  78. data/leveldb/util/arena.cc +1 -1
  79. data/leveldb/util/arena.h +1 -1
  80. data/leveldb/util/arena_test.cc +1 -1
  81. data/leveldb/util/cache.cc +1 -1
  82. data/leveldb/util/cache_test.cc +1 -1
  83. data/leveldb/util/coding.cc +1 -1
  84. data/leveldb/util/coding.h +1 -1
  85. data/leveldb/util/coding_test.cc +1 -1
  86. data/leveldb/util/comparator.cc +7 -4
  87. data/leveldb/util/crc32c.cc +2 -2
  88. data/leveldb/util/crc32c.h +2 -2
  89. data/leveldb/util/crc32c_test.cc +2 -2
  90. data/leveldb/util/env.cc +17 -3
  91. data/leveldb/util/env_posix.cc +2 -2
  92. data/leveldb/util/env_test.cc +13 -11
  93. data/leveldb/util/hash.cc +1 -1
  94. data/leveldb/util/histogram.cc +1 -1
  95. data/leveldb/util/histogram.h +1 -1
  96. data/leveldb/util/logging.cc +1 -1
  97. data/leveldb/util/logging.h +1 -1
  98. data/leveldb/util/mutexlock.h +1 -1
  99. data/leveldb/util/options.cc +1 -1
  100. data/leveldb/util/posix_logger.h +1 -1
  101. data/leveldb/util/random.h +1 -1
  102. data/leveldb/util/status.cc +1 -1
  103. data/leveldb/util/testharness.cc +2 -2
  104. data/leveldb/util/testharness.h +2 -2
  105. data/leveldb/util/testutil.cc +2 -2
  106. data/leveldb/util/testutil.h +2 -2
  107. data/lib/leveldb.rb +34 -2
  108. metadata +7 -13
  109. data/leveldb/port/port_chromium.cc +0 -80
  110. data/leveldb/port/port_chromium.h +0 -97
  111. data/leveldb/port/port_osx.cc +0 -50
  112. data/leveldb/port/port_osx.h +0 -125
  113. data/leveldb/port/sha1_portable.cc +0 -298
  114. data/leveldb/port/sha1_portable.h +0 -25
  115. data/leveldb/port/sha1_test.cc +0 -39
  116. data/leveldb/util/env_chromium.cc +0 -612
@@ -1,298 +0,0 @@
1
- // Portions copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
4
- //
5
- // This module provides a slow but portable implementation of
6
- // the SHA1 hash function.
7
- //
8
- // It is adapted from free code written by Paul E. Jones
9
- // <paulej@packetizer.com>. See http://www.packetizer.com/security/sha1/
10
- //
11
- // The license for the original code is:
12
- /*
13
- Copyright (C) 1998, 2009
14
- Paul E. Jones <paulej@packetizer.com>
15
-
16
- Freeware Public License (FPL)
17
-
18
- This software is licensed as "freeware." Permission to distribute
19
- this software in source and binary forms, including incorporation
20
- into other products, is hereby granted without a fee. THIS SOFTWARE
21
- IS PROVIDED 'AS IS' AND WITHOUT ANY EXPRESSED OR IMPLIED WARRANTIES,
22
- INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
- AND FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR SHALL NOT BE HELD
24
- LIABLE FOR ANY DAMAGES RESULTING FROM THE USE OF THIS SOFTWARE, EITHER
25
- DIRECTLY OR INDIRECTLY, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA
26
- OR DATA BEING RENDERED INACCURATE.
27
- */
28
-
29
- #include "port/sha1_portable.h"
30
- #include <stdio.h>
31
- #include <stdlib.h>
32
- #include <stdint.h>
33
-
34
- namespace leveldb {
35
- namespace port {
36
-
37
- /*
38
- * Description:
39
- * This class implements the Secure Hashing Standard as defined
40
- * in FIPS PUB 180-1 published April 17, 1995.
41
- */
42
-
43
- /*
44
- * This structure will hold context information for the hashing
45
- * operation
46
- */
47
- typedef struct SHA1Context {
48
- unsigned Message_Digest[5]; /* Message Digest (output) */
49
-
50
- unsigned Length_Low; /* Message length in bits */
51
- unsigned Length_High; /* Message length in bits */
52
-
53
- unsigned char Message_Block[64]; /* 512-bit message blocks */
54
- int Message_Block_Index; /* Index into message block array */
55
-
56
- bool Computed; /* Is the digest computed? */
57
- bool Corrupted; /* Is the message digest corruped? */
58
- } SHA1Context;
59
-
60
- /*
61
- * Portability Issues:
62
- * SHA-1 is defined in terms of 32-bit "words". This code was
63
- * written with the expectation that the processor has at least
64
- * a 32-bit machine word size. If the machine word size is larger,
65
- * the code should still function properly. One caveat to that
66
- * is that the input functions taking characters and character
67
- * arrays assume that only 8 bits of information are stored in each
68
- * character.
69
- */
70
-
71
- /*
72
- * Define the circular shift macro
73
- */
74
- #define SHA1CircularShift(bits,word) \
75
- ((((word) << (bits)) & 0xFFFFFFFF) | \
76
- ((word) >> (32-(bits))))
77
-
78
- /* Function prototypes */
79
- static void SHA1ProcessMessageBlock(SHA1Context *);
80
- static void SHA1PadMessage(SHA1Context *);
81
-
82
- // Initialize the SHA1Context in preparation for computing a new
83
- // message digest.
84
- static void SHA1Reset(SHA1Context* context) {
85
- context->Length_Low = 0;
86
- context->Length_High = 0;
87
- context->Message_Block_Index = 0;
88
-
89
- context->Message_Digest[0] = 0x67452301;
90
- context->Message_Digest[1] = 0xEFCDAB89;
91
- context->Message_Digest[2] = 0x98BADCFE;
92
- context->Message_Digest[3] = 0x10325476;
93
- context->Message_Digest[4] = 0xC3D2E1F0;
94
-
95
- context->Computed = false;
96
- context->Corrupted = false;
97
- }
98
-
99
- // This function will return the 160-bit message digest into the
100
- // Message_Digest array within the SHA1Context provided
101
- static bool SHA1Result(SHA1Context *context) {
102
- if (context->Corrupted) {
103
- return false;
104
- }
105
-
106
- if (!context->Computed) {
107
- SHA1PadMessage(context);
108
- context->Computed = true;
109
- }
110
- return true;
111
- }
112
-
113
- // This function accepts an array of bytes as the next portion of
114
- // the message.
115
- static void SHA1Input(SHA1Context *context,
116
- const unsigned char *message_array,
117
- unsigned length) {
118
- if (!length) return;
119
-
120
- if (context->Computed || context->Corrupted) {
121
- context->Corrupted = true;
122
- return;
123
- }
124
-
125
- while(length-- && !context->Corrupted) {
126
- context->Message_Block[context->Message_Block_Index++] =
127
- (*message_array & 0xFF);
128
-
129
- context->Length_Low += 8;
130
- /* Force it to 32 bits */
131
- context->Length_Low &= 0xFFFFFFFF;
132
- if (context->Length_Low == 0) {
133
- context->Length_High++;
134
- /* Force it to 32 bits */
135
- context->Length_High &= 0xFFFFFFFF;
136
- if (context->Length_High == 0)
137
- {
138
- /* Message is too long */
139
- context->Corrupted = true;
140
- }
141
- }
142
-
143
- if (context->Message_Block_Index == 64)
144
- {
145
- SHA1ProcessMessageBlock(context);
146
- }
147
-
148
- message_array++;
149
- }
150
- }
151
-
152
- // This function will process the next 512 bits of the message stored
153
- // in the Message_Block array.
154
- static void SHA1ProcessMessageBlock(SHA1Context *context) {
155
- const unsigned K[] = // Constants defined in SHA-1
156
- {
157
- 0x5A827999,
158
- 0x6ED9EBA1,
159
- 0x8F1BBCDC,
160
- 0xCA62C1D6
161
- };
162
- int t; // Loop counter
163
- unsigned temp; // Temporary word value
164
- unsigned W[80]; // Word sequence
165
- unsigned A, B, C, D, E; // Word buffers
166
-
167
- // Initialize the first 16 words in the array W
168
- for(t = 0; t < 16; t++) {
169
- W[t] = ((unsigned) context->Message_Block[t * 4]) << 24;
170
- W[t] |= ((unsigned) context->Message_Block[t * 4 + 1]) << 16;
171
- W[t] |= ((unsigned) context->Message_Block[t * 4 + 2]) << 8;
172
- W[t] |= ((unsigned) context->Message_Block[t * 4 + 3]);
173
- }
174
-
175
- for(t = 16; t < 80; t++) {
176
- W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
177
- }
178
-
179
- A = context->Message_Digest[0];
180
- B = context->Message_Digest[1];
181
- C = context->Message_Digest[2];
182
- D = context->Message_Digest[3];
183
- E = context->Message_Digest[4];
184
-
185
- for(t = 0; t < 20; t++) {
186
- temp = SHA1CircularShift(5,A) +
187
- ((B & C) | ((~B) & D)) + E + W[t] + K[0];
188
- temp &= 0xFFFFFFFF;
189
- E = D;
190
- D = C;
191
- C = SHA1CircularShift(30,B);
192
- B = A;
193
- A = temp;
194
- }
195
-
196
- for(t = 20; t < 40; t++) {
197
- temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
198
- temp &= 0xFFFFFFFF;
199
- E = D;
200
- D = C;
201
- C = SHA1CircularShift(30,B);
202
- B = A;
203
- A = temp;
204
- }
205
-
206
- for(t = 40; t < 60; t++) {
207
- temp = SHA1CircularShift(5,A) +
208
- ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
209
- temp &= 0xFFFFFFFF;
210
- E = D;
211
- D = C;
212
- C = SHA1CircularShift(30,B);
213
- B = A;
214
- A = temp;
215
- }
216
-
217
- for(t = 60; t < 80; t++) {
218
- temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
219
- temp &= 0xFFFFFFFF;
220
- E = D;
221
- D = C;
222
- C = SHA1CircularShift(30,B);
223
- B = A;
224
- A = temp;
225
- }
226
-
227
- context->Message_Digest[0] = (context->Message_Digest[0] + A) & 0xFFFFFFFF;
228
- context->Message_Digest[1] = (context->Message_Digest[1] + B) & 0xFFFFFFFF;
229
- context->Message_Digest[2] = (context->Message_Digest[2] + C) & 0xFFFFFFFF;
230
- context->Message_Digest[3] = (context->Message_Digest[3] + D) & 0xFFFFFFFF;
231
- context->Message_Digest[4] = (context->Message_Digest[4] + E) & 0xFFFFFFFF;
232
-
233
- context->Message_Block_Index = 0;
234
- }
235
-
236
- // According to the standard, the message must be padded to an even
237
- // 512 bits. The first padding bit must be a '1'. The last 64 bits
238
- // represent the length of the original message. All bits in between
239
- // should be 0. This function will pad the message according to those
240
- // rules by filling the Message_Block array accordingly. It will also
241
- // call SHA1ProcessMessageBlock() appropriately. When it returns, it
242
- // can be assumed that the message digest has been computed.
243
- static void SHA1PadMessage(SHA1Context *context) {
244
- // Check to see if the current message block is too small to hold
245
- // the initial padding bits and length. If so, we will pad the
246
- // block, process it, and then continue padding into a second block.
247
- if (context->Message_Block_Index > 55) {
248
- context->Message_Block[context->Message_Block_Index++] = 0x80;
249
- while(context->Message_Block_Index < 64) {
250
- context->Message_Block[context->Message_Block_Index++] = 0;
251
- }
252
-
253
- SHA1ProcessMessageBlock(context);
254
-
255
- while(context->Message_Block_Index < 56) {
256
- context->Message_Block[context->Message_Block_Index++] = 0;
257
- }
258
- } else {
259
- context->Message_Block[context->Message_Block_Index++] = 0x80;
260
- while(context->Message_Block_Index < 56) {
261
- context->Message_Block[context->Message_Block_Index++] = 0;
262
- }
263
- }
264
-
265
- // Store the message length as the last 8 octets
266
- context->Message_Block[56] = (context->Length_High >> 24) & 0xFF;
267
- context->Message_Block[57] = (context->Length_High >> 16) & 0xFF;
268
- context->Message_Block[58] = (context->Length_High >> 8) & 0xFF;
269
- context->Message_Block[59] = (context->Length_High) & 0xFF;
270
- context->Message_Block[60] = (context->Length_Low >> 24) & 0xFF;
271
- context->Message_Block[61] = (context->Length_Low >> 16) & 0xFF;
272
- context->Message_Block[62] = (context->Length_Low >> 8) & 0xFF;
273
- context->Message_Block[63] = (context->Length_Low) & 0xFF;
274
-
275
- SHA1ProcessMessageBlock(context);
276
- }
277
-
278
-
279
- void SHA1_Hash_Portable(const char* data, size_t len, char* hash_array) {
280
- SHA1Context context;
281
- SHA1Reset(&context);
282
- SHA1Input(&context, reinterpret_cast<const unsigned char*>(data), len);
283
- bool ok = SHA1Result(&context);
284
- if (!ok) {
285
- fprintf(stderr, "Unexpected error in SHA1_Hash_Portable code\n");
286
- exit(1);
287
- }
288
- for (int i = 0; i < 5; i++) {
289
- uint32_t value = context.Message_Digest[i];
290
- hash_array[i*4 + 0] = (value >> 24) & 0xff;
291
- hash_array[i*4 + 1] = (value >> 16) & 0xff;
292
- hash_array[i*4 + 2] = (value >> 8) & 0xff;
293
- hash_array[i*4 + 3] = value & 0xff;
294
- }
295
- }
296
-
297
- }
298
- }
@@ -1,25 +0,0 @@
1
- // Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
4
-
5
- #ifndef STORAGE_LEVELDB_PORT_SHA1_PORTABLE_H_
6
- #define STORAGE_LEVELDB_PORT_SHA1_PORTABLE_H_
7
-
8
- #include <stddef.h>
9
-
10
- namespace leveldb {
11
- namespace port {
12
-
13
- // Compute the SHA1 hash value of "data[0..len-1]" and store it in
14
- // "hash_array[0..19]". hash_array must have 20 bytes of space available.
15
- //
16
- // This function is portable but may not be as fast as a version
17
- // optimized for your platform. It is provided as a default method
18
- // that can be used when porting leveldb to a new platform if no
19
- // better SHA1 hash implementation is available.
20
- void SHA1_Hash_Portable(const char* data, size_t len, char* hash_array);
21
-
22
- }
23
- }
24
-
25
- #endif // STORAGE_LEVELDB_PORT_SHA1_PORTABLE_H_
@@ -1,39 +0,0 @@
1
- // Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
4
-
5
- #include "port/port.h"
6
- #include "util/testharness.h"
7
-
8
- namespace leveldb {
9
- namespace port {
10
-
11
- class SHA1 { };
12
-
13
- static std::string TestSHA1(const char* data, size_t len) {
14
- char hash_val[20];
15
- SHA1_Hash(data, len, hash_val);
16
- char buf[41];
17
- for (int i = 0; i < 20; i++) {
18
- snprintf(buf + i * 2, 41 - i * 2,
19
- "%02x",
20
- static_cast<unsigned int>(static_cast<unsigned char>(
21
- hash_val[i])));
22
- }
23
- return std::string(buf, 40);
24
- }
25
-
26
- TEST(SHA1, Simple) {
27
- ASSERT_EQ("da39a3ee5e6b4b0d3255bfef95601890afd80709", TestSHA1("", 0));
28
- ASSERT_EQ("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d", TestSHA1("hello", 5));
29
- std::string x(10000, 'x');
30
- ASSERT_EQ("f8c5cde791c5056cf515881e701c8a9ecb439a75",
31
- TestSHA1(x.data(), x.size()));
32
- }
33
-
34
- }
35
- }
36
-
37
- int main(int argc, char** argv) {
38
- return leveldb::test::RunAllTests();
39
- }
@@ -1,612 +0,0 @@
1
- // Copyright (c) 2011 The LevelDB 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. See the AUTHORS file for names of contributors.
4
-
5
- #include <deque>
6
- #include <errno.h>
7
- #include <stdio.h>
8
- #include "base/at_exit.h"
9
- #include "base/file_path.h"
10
- #include "base/file_util.h"
11
- #include "base/lazy_instance.h"
12
- #include "base/memory/ref_counted.h"
13
- #include "base/message_loop.h"
14
- #include "base/platform_file.h"
15
- #include "base/process_util.h"
16
- #include "base/synchronization/lock.h"
17
- #include "base/sys_info.h"
18
- #include "base/task.h"
19
- #include "base/threading/platform_thread.h"
20
- #include "base/threading/thread.h"
21
- #include "base/utf_string_conversions.h"
22
- #include "leveldb/env.h"
23
- #include "leveldb/slice.h"
24
- #include "port/port.h"
25
- #include "util/logging.h"
26
-
27
- #if defined(OS_WIN)
28
- #include <io.h>
29
- #include "base/win/win_util.h"
30
- #endif
31
-
32
- #if defined(OS_MACOSX) || defined(OS_WIN)
33
- // The following are glibc-specific
34
- namespace {
35
-
36
- size_t fread_unlocked(void *ptr, size_t size, size_t n, FILE *file) {
37
- return fread(ptr, size, n, file);
38
- }
39
-
40
- size_t fwrite_unlocked(const void *ptr, size_t size, size_t n, FILE *file) {
41
- return fwrite(ptr, size, n, file);
42
- }
43
-
44
- int fflush_unlocked(FILE *file) {
45
- return fflush(file);
46
- }
47
-
48
- int fdatasync(int fildes) {
49
- #if defined(OS_WIN)
50
- return _commit(fildes);
51
- #else
52
- return fsync(fildes);
53
- #endif
54
- }
55
-
56
- }
57
- #endif
58
-
59
- namespace leveldb {
60
-
61
- namespace {
62
-
63
- class Thread;
64
-
65
- static const ::FilePath::CharType kLevelDBTestDirectoryPrefix[]
66
- = FILE_PATH_LITERAL("leveldb-test-");
67
-
68
- ::FilePath CreateFilePath(const std::string& file_path) {
69
- #if defined(OS_WIN)
70
- return FilePath(UTF8ToUTF16(file_path));
71
- #else
72
- return FilePath(file_path);
73
- #endif
74
- }
75
-
76
- std::string FilePathToString(const ::FilePath& file_path) {
77
- #if defined(OS_WIN)
78
- return UTF16ToUTF8(file_path.value());
79
- #else
80
- return file_path.value();
81
- #endif
82
- }
83
-
84
- // TODO(jorlow): This should be moved into Chromium's base.
85
- const char* PlatformFileErrorString(const ::base::PlatformFileError& error) {
86
- switch (error) {
87
- case ::base::PLATFORM_FILE_ERROR_FAILED:
88
- return "Opening file failed.";
89
- case ::base::PLATFORM_FILE_ERROR_IN_USE:
90
- return "File currently in use.";
91
- case ::base::PLATFORM_FILE_ERROR_EXISTS:
92
- return "File already exists.";
93
- case ::base::PLATFORM_FILE_ERROR_NOT_FOUND:
94
- return "File not found.";
95
- case ::base::PLATFORM_FILE_ERROR_ACCESS_DENIED:
96
- return "Access denied.";
97
- case ::base::PLATFORM_FILE_ERROR_TOO_MANY_OPENED:
98
- return "Too many files open.";
99
- case ::base::PLATFORM_FILE_ERROR_NO_MEMORY:
100
- return "Out of memory.";
101
- case ::base::PLATFORM_FILE_ERROR_NO_SPACE:
102
- return "No space left on drive.";
103
- case ::base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY:
104
- return "Not a directory.";
105
- case ::base::PLATFORM_FILE_ERROR_INVALID_OPERATION:
106
- return "Invalid operation.";
107
- case ::base::PLATFORM_FILE_ERROR_SECURITY:
108
- return "Security error.";
109
- case ::base::PLATFORM_FILE_ERROR_ABORT:
110
- return "File operation aborted.";
111
- case ::base::PLATFORM_FILE_ERROR_NOT_A_FILE:
112
- return "The supplied path was not a file.";
113
- case ::base::PLATFORM_FILE_ERROR_NOT_EMPTY:
114
- return "The file was not empty.";
115
- }
116
- NOTIMPLEMENTED();
117
- return "Unknown error.";
118
- }
119
-
120
- class ChromiumSequentialFile: public SequentialFile {
121
- private:
122
- std::string filename_;
123
- FILE* file_;
124
-
125
- public:
126
- ChromiumSequentialFile(const std::string& fname, FILE* f)
127
- : filename_(fname), file_(f) { }
128
- virtual ~ChromiumSequentialFile() { fclose(file_); }
129
-
130
- virtual Status Read(size_t n, Slice* result, char* scratch) {
131
- Status s;
132
- size_t r = fread_unlocked(scratch, 1, n, file_);
133
- *result = Slice(scratch, r);
134
- if (r < n) {
135
- if (feof(file_)) {
136
- // We leave status as ok if we hit the end of the file
137
- } else {
138
- // A partial read with an error: return a non-ok status
139
- s = Status::IOError(filename_, strerror(errno));
140
- }
141
- }
142
- return s;
143
- }
144
-
145
- virtual Status Skip(uint64_t n) {
146
- if (fseek(file_, n, SEEK_CUR)) {
147
- return Status::IOError(filename_, strerror(errno));
148
- }
149
- return Status::OK();
150
- }
151
- };
152
-
153
- class ChromiumRandomAccessFile: public RandomAccessFile {
154
- private:
155
- std::string filename_;
156
- ::base::PlatformFile file_;
157
-
158
- public:
159
- ChromiumRandomAccessFile(const std::string& fname, ::base::PlatformFile file)
160
- : filename_(fname), file_(file) { }
161
- virtual ~ChromiumRandomAccessFile() { ::base::ClosePlatformFile(file_); }
162
-
163
- virtual Status Read(uint64_t offset, size_t n, Slice* result,
164
- char* scratch) const {
165
- Status s;
166
- int r = ::base::ReadPlatformFile(file_, offset, scratch, n);
167
- *result = Slice(scratch, (r < 0) ? 0 : r);
168
- if (r < 0) {
169
- // An error: return a non-ok status
170
- s = Status::IOError(filename_, "Could not preform read");
171
- }
172
- return s;
173
- }
174
- };
175
-
176
- class ChromiumWritableFile : public WritableFile {
177
- private:
178
- std::string filename_;
179
- FILE* file_;
180
-
181
- public:
182
- ChromiumWritableFile(const std::string& fname, FILE* f)
183
- : filename_(fname), file_(f) { }
184
-
185
- ~ChromiumWritableFile() {
186
- if (file_ != NULL) {
187
- // Ignoring any potential errors
188
- fclose(file_);
189
- }
190
- }
191
-
192
- virtual Status Append(const Slice& data) {
193
- size_t r = fwrite_unlocked(data.data(), 1, data.size(), file_);
194
- Status result;
195
- if (r != data.size()) {
196
- result = Status::IOError(filename_, strerror(errno));
197
- }
198
- return result;
199
- }
200
-
201
- virtual Status Close() {
202
- Status result;
203
- if (fclose(file_) != 0) {
204
- result = Status::IOError(filename_, strerror(errno));
205
- }
206
- file_ = NULL;
207
- return result;
208
- }
209
-
210
- virtual Status Flush() {
211
- Status result;
212
- if (fflush_unlocked(file_) != 0) {
213
- result = Status::IOError(filename_, strerror(errno));
214
- }
215
- return result;
216
- }
217
-
218
- virtual Status Sync() {
219
- Status result;
220
- if ((fflush_unlocked(file_) != 0) ||
221
- (fdatasync(fileno(file_)) != 0)) {
222
- result = Status::IOError(filename_, strerror(errno));
223
- }
224
- return result;
225
- }
226
- };
227
-
228
- class ChromiumFileLock : public FileLock {
229
- public:
230
- ::base::PlatformFile file_;
231
- };
232
-
233
- class ChromiumEnv : public Env {
234
- public:
235
- ChromiumEnv();
236
- virtual ~ChromiumEnv() {
237
- fprintf(stderr, "Destroying Env::Default()\n");
238
- exit(1);
239
- }
240
-
241
- virtual Status NewSequentialFile(const std::string& fname,
242
- SequentialFile** result) {
243
- FILE* f = fopen(fname.c_str(), "rb");
244
- if (f == NULL) {
245
- *result = NULL;
246
- return Status::IOError(fname, strerror(errno));
247
- } else {
248
- *result = new ChromiumSequentialFile(fname, f);
249
- return Status::OK();
250
- }
251
- }
252
-
253
- virtual Status NewRandomAccessFile(const std::string& fname,
254
- RandomAccessFile** result) {
255
- int flags = ::base::PLATFORM_FILE_READ | ::base::PLATFORM_FILE_OPEN;
256
- bool created;
257
- ::base::PlatformFileError error_code;
258
- ::base::PlatformFile file = ::base::CreatePlatformFile(
259
- CreateFilePath(fname), flags, &created, &error_code);
260
- if (error_code != ::base::PLATFORM_FILE_OK) {
261
- *result = NULL;
262
- return Status::IOError(fname, PlatformFileErrorString(error_code));
263
- }
264
- *result = new ChromiumRandomAccessFile(fname, file);
265
- return Status::OK();
266
- }
267
-
268
- virtual Status NewWritableFile(const std::string& fname,
269
- WritableFile** result) {
270
- *result = NULL;
271
- FILE* f = fopen(fname.c_str(), "wb");
272
- if (f == NULL) {
273
- return Status::IOError(fname, strerror(errno));
274
- } else {
275
- *result = new ChromiumWritableFile(fname, f);
276
- return Status::OK();
277
- }
278
- }
279
-
280
- virtual bool FileExists(const std::string& fname) {
281
- return ::file_util::PathExists(CreateFilePath(fname));
282
- }
283
-
284
- virtual Status GetChildren(const std::string& dir,
285
- std::vector<std::string>* result) {
286
- result->clear();
287
- ::file_util::FileEnumerator iter(
288
- CreateFilePath(dir), false, ::file_util::FileEnumerator::FILES);
289
- ::FilePath current = iter.Next();
290
- while (!current.empty()) {
291
- result->push_back(FilePathToString(current.BaseName()));
292
- current = iter.Next();
293
- }
294
- // TODO(jorlow): Unfortunately, the FileEnumerator swallows errors, so
295
- // we'll always return OK. Maybe manually check for error
296
- // conditions like the file not existing?
297
- return Status::OK();
298
- }
299
-
300
- virtual Status DeleteFile(const std::string& fname) {
301
- Status result;
302
- // TODO(jorlow): Should we assert this is a file?
303
- if (!::file_util::Delete(CreateFilePath(fname), false)) {
304
- result = Status::IOError(fname, "Could not delete file.");
305
- }
306
- return result;
307
- };
308
-
309
- virtual Status CreateDir(const std::string& name) {
310
- Status result;
311
- if (!::file_util::CreateDirectory(CreateFilePath(name))) {
312
- result = Status::IOError(name, "Could not create directory.");
313
- }
314
- return result;
315
- };
316
-
317
- virtual Status DeleteDir(const std::string& name) {
318
- Status result;
319
- // TODO(jorlow): Should we assert this is a directory?
320
- if (!::file_util::Delete(CreateFilePath(name), false)) {
321
- result = Status::IOError(name, "Could not delete directory.");
322
- }
323
- return result;
324
- };
325
-
326
- virtual Status GetFileSize(const std::string& fname, uint64_t* size) {
327
- Status s;
328
- int64_t signed_size;
329
- if (!::file_util::GetFileSize(CreateFilePath(fname), &signed_size)) {
330
- *size = 0;
331
- s = Status::IOError(fname, "Could not determine file size.");
332
- } else {
333
- *size = static_cast<uint64_t>(signed_size);
334
- }
335
- return s;
336
- }
337
-
338
- virtual Status RenameFile(const std::string& src, const std::string& dst) {
339
- Status result;
340
- if (!::file_util::ReplaceFile(CreateFilePath(src), CreateFilePath(dst))) {
341
- result = Status::IOError(src, "Could not rename file.");
342
- }
343
- return result;
344
- }
345
-
346
- virtual Status LockFile(const std::string& fname, FileLock** lock) {
347
- *lock = NULL;
348
- Status result;
349
- int flags = ::base::PLATFORM_FILE_OPEN_ALWAYS |
350
- ::base::PLATFORM_FILE_READ |
351
- ::base::PLATFORM_FILE_WRITE |
352
- ::base::PLATFORM_FILE_EXCLUSIVE_READ |
353
- ::base::PLATFORM_FILE_EXCLUSIVE_WRITE;
354
- bool created;
355
- ::base::PlatformFileError error_code;
356
- ::base::PlatformFile file = ::base::CreatePlatformFile(
357
- CreateFilePath(fname), flags, &created, &error_code);
358
- if (error_code != ::base::PLATFORM_FILE_OK) {
359
- result = Status::IOError(fname, PlatformFileErrorString(error_code));
360
- } else {
361
- ChromiumFileLock* my_lock = new ChromiumFileLock;
362
- my_lock->file_ = file;
363
- *lock = my_lock;
364
- }
365
- return result;
366
- }
367
-
368
- virtual Status UnlockFile(FileLock* lock) {
369
- ChromiumFileLock* my_lock = reinterpret_cast<ChromiumFileLock*>(lock);
370
- Status result;
371
- if (!::base::ClosePlatformFile(my_lock->file_)) {
372
- result = Status::IOError("Could not close lock file.");
373
- }
374
- delete my_lock;
375
- return result;
376
- }
377
-
378
- virtual void Schedule(void (*function)(void*), void* arg);
379
-
380
- virtual void StartThread(void (*function)(void* arg), void* arg);
381
-
382
- virtual std::string UserIdentifier() {
383
- #if defined(OS_WIN)
384
- std::wstring user_sid;
385
- bool ret = ::base::win::GetUserSidString(&user_sid);
386
- DCHECK(ret);
387
- return UTF16ToUTF8(user_sid);
388
- #else
389
- char buf[100];
390
- snprintf(buf, sizeof(buf), "%d", int(geteuid()));
391
- return buf;
392
- #endif
393
- }
394
-
395
- virtual Status GetTestDirectory(std::string* path) {
396
- mu_.Acquire();
397
- if (test_directory_.empty()) {
398
- if (!::file_util::CreateNewTempDirectory(kLevelDBTestDirectoryPrefix,
399
- &test_directory_)) {
400
- mu_.Release();
401
- return Status::IOError("Could not create temp directory.");
402
- }
403
- }
404
- *path = FilePathToString(test_directory_);
405
- mu_.Release();
406
- return Status::OK();
407
- }
408
-
409
- virtual void Logv(WritableFile* info_log, const char* format, va_list ap) {
410
- // TODO(jorlow): We may want to just use Chromium's built in logging.
411
-
412
- uint64_t thread_id = 0;
413
- // Coppied from base/logging.cc.
414
- #if defined(OS_WIN)
415
- thread_id = GetCurrentThreadId();
416
- #elif defined(OS_MACOSX)
417
- thread_id = mach_thread_self();
418
- #elif defined(OS_LINUX)
419
- thread_id = syscall(__NR_gettid);
420
- #elif defined(OS_FREEBSD) || defined(OS_NACL)
421
- // TODO(BSD): find a better thread ID
422
- pthread_t tid = pthread_self();
423
- memcpy(&thread_id, &tid, min(sizeof(r), sizeof(tid)));
424
- #endif
425
-
426
- // We try twice: the first time with a fixed-size stack allocated buffer,
427
- // and the second time with a much larger dynamically allocated buffer.
428
- char buffer[500];
429
- for (int iter = 0; iter < 2; iter++) {
430
- char* base;
431
- int bufsize;
432
- if (iter == 0) {
433
- bufsize = sizeof(buffer);
434
- base = buffer;
435
- } else {
436
- bufsize = 30000;
437
- base = new char[bufsize];
438
- }
439
- char* p = base;
440
- char* limit = base + bufsize;
441
-
442
- ::base::Time::Exploded t;
443
- ::base::Time::Now().LocalExplode(&t);
444
- p += snprintf(p, limit - p,
445
- "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
446
- t.year,
447
- t.month,
448
- t.day_of_month,
449
- t.hour,
450
- t.minute,
451
- t.second,
452
- static_cast<int>(t.millisecond) * 1000,
453
- static_cast<long long unsigned int>(thread_id));
454
-
455
- // Print the message
456
- if (p < limit) {
457
- va_list backup_ap;
458
- va_copy(backup_ap, ap);
459
- p += vsnprintf(p, limit - p, format, backup_ap);
460
- va_end(backup_ap);
461
- }
462
-
463
- // Truncate to available space if necessary
464
- if (p >= limit) {
465
- if (iter == 0) {
466
- continue; // Try again with larger buffer
467
- } else {
468
- p = limit - 1;
469
- }
470
- }
471
-
472
- // Add newline if necessary
473
- if (p == base || p[-1] != '\n') {
474
- *p++ = '\n';
475
- }
476
-
477
- assert(p <= limit);
478
- info_log->Append(Slice(base, p - base));
479
- info_log->Flush();
480
- if (base != buffer) {
481
- delete[] base;
482
- }
483
- break;
484
- }
485
- }
486
-
487
- virtual int AppendLocalTimeToBuffer(char* buffer, size_t size) {
488
- ::base::Time::Exploded t;
489
- ::base::Time::Now().LocalExplode(&t);
490
- return snprintf(buffer, size,
491
- "%04d/%02d/%02d-%02d:%02d:%02d.%06d",
492
- t.year,
493
- t.month,
494
- t.day_of_month,
495
- t.hour,
496
- t.minute,
497
- t.second,
498
- static_cast<int>(t.millisecond) * 1000);
499
- }
500
-
501
- virtual uint64_t NowMicros() {
502
- return ::base::TimeTicks::HighResNow().ToInternalValue();
503
- }
504
-
505
- virtual void SleepForMicroseconds(int micros) {
506
- // Round up to the next millisecond.
507
- ::base::PlatformThread::Sleep((micros + 999) / 1000);
508
- }
509
-
510
- private:
511
- // BGThread() is the body of the background thread
512
- void BGThread();
513
- static void BGThreadWrapper(void* arg) {
514
- reinterpret_cast<ChromiumEnv*>(arg)->BGThread();
515
- }
516
-
517
- FilePath test_directory_;
518
-
519
- size_t page_size_;
520
- ::base::Lock mu_;
521
- ::base::ConditionVariable bgsignal_;
522
- bool started_bgthread_;
523
-
524
- // Entry per Schedule() call
525
- struct BGItem { void* arg; void (*function)(void*); };
526
- typedef std::deque<BGItem> BGQueue;
527
- BGQueue queue_;
528
- };
529
-
530
- ChromiumEnv::ChromiumEnv()
531
- : page_size_(::base::SysInfo::VMAllocationGranularity()),
532
- bgsignal_(&mu_),
533
- started_bgthread_(false) {
534
- #if defined(OS_MACOSX)
535
- ::base::EnableTerminationOnHeapCorruption();
536
- ::base::EnableTerminationOnOutOfMemory();
537
- #endif // OS_MACOSX
538
- }
539
-
540
- class Thread : public ::base::PlatformThread::Delegate {
541
- public:
542
- Thread(void (*function)(void* arg), void* arg)
543
- : function_(function), arg_(arg) {
544
- ::base::PlatformThreadHandle handle;
545
- bool success = ::base::PlatformThread::Create(0, this, &handle);
546
- DCHECK(success);
547
- }
548
- virtual ~Thread() {}
549
- virtual void ThreadMain() {
550
- (*function_)(arg_);
551
- delete this;
552
- }
553
-
554
- private:
555
- void (*function_)(void* arg);
556
- void* arg_;
557
- };
558
-
559
- void ChromiumEnv::Schedule(void (*function)(void*), void* arg) {
560
- mu_.Acquire();
561
-
562
- // Start background thread if necessary
563
- if (!started_bgthread_) {
564
- started_bgthread_ = true;
565
- StartThread(&ChromiumEnv::BGThreadWrapper, this);
566
- }
567
-
568
- // If the queue is currently empty, the background thread may currently be
569
- // waiting.
570
- if (queue_.empty()) {
571
- bgsignal_.Signal();
572
- }
573
-
574
- // Add to priority queue
575
- queue_.push_back(BGItem());
576
- queue_.back().function = function;
577
- queue_.back().arg = arg;
578
-
579
- mu_.Release();
580
- }
581
-
582
- void ChromiumEnv::BGThread() {
583
- while (true) {
584
- // Wait until there is an item that is ready to run
585
- mu_.Acquire();
586
- while (queue_.empty()) {
587
- bgsignal_.Wait();
588
- }
589
-
590
- void (*function)(void*) = queue_.front().function;
591
- void* arg = queue_.front().arg;
592
- queue_.pop_front();
593
-
594
- mu_.Release();
595
- (*function)(arg);
596
- }
597
- }
598
-
599
- void ChromiumEnv::StartThread(void (*function)(void* arg), void* arg) {
600
- new Thread(function, arg); // Will self-delete.
601
- }
602
-
603
- ::base::LazyInstance<ChromiumEnv, ::base::LeakyLazyInstanceTraits<ChromiumEnv> >
604
- default_env(::base::LINKER_INITIALIZED);
605
-
606
- }
607
-
608
- Env* Env::Default() {
609
- return default_env.Pointer();
610
- }
611
-
612
- }