leveldb-ruby 0.10 → 0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
@@ -0,0 +1,83 @@
1
+ ## here lies some platform-specific C++ compile and link environment
2
+ ## variable hacking.
3
+ ##
4
+ ## this code is entirely stolen from eventmachine's extconf.rb. many
5
+ ## thanks to @tmm1 for the pointer.
6
+
7
+ def check_libs libs=[], fatal=false
8
+ libs.all? { |lib| have_library(lib) || (abort("could not find library: #{lib}") if fatal) }
9
+ end
10
+
11
+ def check_heads heads=[], fatal=false
12
+ heads.all? { |head| have_header(head) || (abort("could not find header: #{head}") if fatal)}
13
+ end
14
+
15
+ def add_define name; $defs.push "-D#{name}" end
16
+
17
+ def set_platform_specific_variables!
18
+ puts "setting build environment for #{RUBY_PLATFORM}..."
19
+ case RUBY_PLATFORM
20
+ when /mswin32/, /mingw32/, /bccwin32/
21
+ check_heads(%w[windows.h winsock.h], true)
22
+ check_libs(%w[kernel32 rpcrt4 gdi32], true)
23
+
24
+ if GNU_CHAIN
25
+ CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++"
26
+ else
27
+ $defs.push "-EHs"
28
+ $defs.push "-GR"
29
+ end
30
+
31
+ when /solaris/
32
+ add_define 'OS_SOLARIS8'
33
+ check_libs(%w[nsl socket], true)
34
+
35
+ if CONFIG['CC'] == 'cc' and `cc -flags 2>&1` =~ /Sun/ # detect SUNWspro compiler
36
+ # SUN CHAIN
37
+ add_define 'CC_SUNWspro'
38
+ $preload = ["\nCXX = CC"] # hack a CXX= line into the makefile
39
+ $CFLAGS = CONFIG['CFLAGS'] = "-KPIC"
40
+ CONFIG['CCDLFLAGS'] = "-KPIC"
41
+ CONFIG['LDSHARED'] = "$(CXX) -G -KPIC -lCstd"
42
+ else
43
+ # GNU CHAIN
44
+ # on Unix we need a g++ link, not gcc.
45
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
46
+ end
47
+
48
+ when /openbsd/
49
+ # OpenBSD branch contributed by Guillaume Sellier.
50
+
51
+ # on Unix we need a g++ link, not gcc. On OpenBSD, linking against libstdc++ have to be explicitly done for shared libs
52
+ CONFIG['LDSHARED'] = "$(CXX) -shared -lstdc++ -fPIC"
53
+ CONFIG['LDSHAREDXX'] = "$(CXX) -shared -lstdc++ -fPIC"
54
+
55
+ when /darwin/
56
+ # on Unix we need a g++ link, not gcc.
57
+ # Ff line contributed by Daniel Harple.
58
+ CONFIG['LDSHARED'] = "$(CXX) " + CONFIG['LDSHARED'].split[1..-1].join(' ')
59
+
60
+ when /linux/
61
+ add_define 'HAVE_EPOLL' if have_func('epoll_create', 'sys/epoll.h')
62
+
63
+ # on Unix we need a g++ link, not gcc.
64
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
65
+
66
+ when /aix/
67
+ CONFIG['LDSHARED'] = "$(CXX) -shared -Wl,-G -Wl,-brtl"
68
+
69
+ when /cygwin/
70
+ # For rubies built with Cygwin, CXX may be set to CC, which is just
71
+ # a wrapper for gcc.
72
+ # This will compile, but it will not link to the C++ std library.
73
+ # Explicitly set CXX to use g++.
74
+ CONFIG['CXX'] = "g++"
75
+ # on Unix we need a g++ link, not gcc.
76
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
77
+
78
+ else
79
+ # on Unix we need a g++ link, not gcc.
80
+ CONFIG['LDSHARED'] = "$(CXX) -shared"
81
+ end
82
+ end
83
+
@@ -2,15 +2,16 @@
2
2
  # Use of this source code is governed by a BSD-style license that can be
3
3
  # found in the LICENSE file. See the AUTHORS file for names of contributors.
4
4
 
5
- CC = g++
5
+ CXX ?= g++
6
+ CC ?= gcc
6
7
 
7
8
  #-----------------------------------------------
8
9
  # Uncomment exactly one of the lines labelled (A), (B), and (C) below
9
10
  # to switch between compilation modes.
10
11
 
11
- OPT = -O2 -DNDEBUG -fPIC # (A) Production use (optimized mode)
12
- # OPT = -g2 # (B) Debug mode, w/ full line-level debugging symbols
13
- # OPT = -O2 -g2 -DNDEBUG # (C) Profiling mode: opt, but w/debugging symbols
12
+ OPT ?= -O2 -DNDEBUG -fPIC # (A) Production use (optimized mode)
13
+ # OPT ?= -g2 # (B) Debug mode, w/ full line-level debugging symbols
14
+ # OPT ?= -O2 -g2 -DNDEBUG # (C) Profiling mode: opt, but w/debugging symbols
14
15
  #-----------------------------------------------
15
16
 
16
17
  # detect what platform we're building on
@@ -38,7 +39,7 @@ endif
38
39
 
39
40
  CFLAGS = -c -I. -I./include $(PORT_CFLAGS) $(PLATFORM_CFLAGS) $(OPT) $(SNAPPY_CFLAGS)
40
41
 
41
- LDFLAGS=$(PLATFORM_LDFLAGS) $(SNAPPY_LDFLAGS) $(GOOGLE_PERFTOOLS_LDFLAGS)
42
+ LDFLAGS += $(PLATFORM_LDFLAGS) $(SNAPPY_LDFLAGS) $(GOOGLE_PERFTOOLS_LDFLAGS)
42
43
 
43
44
  LIBOBJECTS = \
44
45
  ./db/builder.o \
@@ -120,68 +121,68 @@ $(LIBRARY): $(LIBOBJECTS)
120
121
  $(AR) -rs $@ $(LIBOBJECTS)
121
122
 
122
123
  db_bench: db/db_bench.o $(LIBOBJECTS) $(TESTUTIL)
123
- $(CC) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@
124
+ $(CXX) $(LDFLAGS) db/db_bench.o $(LIBOBJECTS) $(TESTUTIL) -o $@
124
125
 
125
126
  db_bench_sqlite3: doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL)
126
- $(CC) $(LDFLAGS) -lsqlite3 doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) -o $@
127
+ $(CXX) $(LDFLAGS) -lsqlite3 doc/bench/db_bench_sqlite3.o $(LIBOBJECTS) $(TESTUTIL) -o $@
127
128
 
128
129
  db_bench_tree_db: doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL)
129
- $(CC) $(LDFLAGS) -lkyotocabinet doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) -o $@
130
+ $(CXX) $(LDFLAGS) -lkyotocabinet doc/bench/db_bench_tree_db.o $(LIBOBJECTS) $(TESTUTIL) -o $@
130
131
 
131
132
  arena_test: util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS)
132
- $(CC) $(LDFLAGS) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
133
+ $(CXX) $(LDFLAGS) util/arena_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
133
134
 
134
135
  c_test: db/c_test.o $(LIBOBJECTS) $(TESTHARNESS)
135
- $(CC) $(LDFLAGS) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
136
+ $(CXX) $(LDFLAGS) db/c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
136
137
 
137
138
  cache_test: util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS)
138
- $(CC) $(LDFLAGS) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
139
+ $(CXX) $(LDFLAGS) util/cache_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
139
140
 
140
141
  coding_test: util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS)
141
- $(CC) $(LDFLAGS) util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
142
+ $(CXX) $(LDFLAGS) util/coding_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
142
143
 
143
144
  corruption_test: db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS)
144
- $(CC) $(LDFLAGS) db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
145
+ $(CXX) $(LDFLAGS) db/corruption_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
145
146
 
146
147
  crc32c_test: util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS)
147
- $(CC) $(LDFLAGS) util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
148
+ $(CXX) $(LDFLAGS) util/crc32c_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
148
149
 
149
150
  db_test: db/db_test.o $(LIBOBJECTS) $(TESTHARNESS)
150
- $(CC) $(LDFLAGS) db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
151
+ $(CXX) $(LDFLAGS) db/db_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
151
152
 
152
153
  dbformat_test: db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS)
153
- $(CC) $(LDFLAGS) db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
154
+ $(CXX) $(LDFLAGS) db/dbformat_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
154
155
 
155
156
  env_test: util/env_test.o $(LIBOBJECTS) $(TESTHARNESS)
156
- $(CC) $(LDFLAGS) util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
157
+ $(CXX) $(LDFLAGS) util/env_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
157
158
 
158
159
  filename_test: db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS)
159
- $(CC) $(LDFLAGS) db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
160
+ $(CXX) $(LDFLAGS) db/filename_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
160
161
 
161
162
  log_test: db/log_test.o $(LIBOBJECTS) $(TESTHARNESS)
162
- $(CC) $(LDFLAGS) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
163
+ $(CXX) $(LDFLAGS) db/log_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
163
164
 
164
165
  table_test: table/table_test.o $(LIBOBJECTS) $(TESTHARNESS)
165
- $(CC) $(LDFLAGS) table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
166
+ $(CXX) $(LDFLAGS) table/table_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
166
167
 
167
168
  skiplist_test: db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS)
168
- $(CC) $(LDFLAGS) db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
169
+ $(CXX) $(LDFLAGS) db/skiplist_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
169
170
 
170
171
  version_edit_test: db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS)
171
- $(CC) $(LDFLAGS) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
172
+ $(CXX) $(LDFLAGS) db/version_edit_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
172
173
 
173
174
  version_set_test: db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS)
174
- $(CC) $(LDFLAGS) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
175
+ $(CXX) $(LDFLAGS) db/version_set_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
175
176
 
176
177
  write_batch_test: db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS)
177
- $(CC) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
178
+ $(CXX) $(LDFLAGS) db/write_batch_test.o $(LIBOBJECTS) $(TESTHARNESS) -o $@
178
179
 
179
180
  $(MEMENVLIBRARY) : helpers/memenv/memenv.o
180
181
  rm -f $@
181
182
  $(AR) -rs $@ helpers/memenv/memenv.o
182
183
 
183
184
  memenv_test : helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS)
184
- $(CC) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@
185
+ $(CXX) $(LDFLAGS) helpers/memenv/memenv_test.o $(MEMENVLIBRARY) $(LIBRARY) $(TESTHARNESS) -o $@
185
186
 
186
187
  ifeq ($(PLATFORM), IOS)
187
188
  # For iOS, create universal object files to be used on both the simulator and
@@ -192,9 +193,9 @@ IOSVERSION=$(shell defaults read /Developer/Platforms/iPhoneOS.platform/version
192
193
 
193
194
  .cc.o:
194
195
  mkdir -p ios-x86/$(dir $@)
195
- $(SIMULATORROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 $< -o ios-x86/$@
196
+ $(SIMULATORROOT)/usr/bin/$(CXX) $(CFLAGS) -isysroot $(SIMULATORROOT)/SDKs/iPhoneSimulator$(IOSVERSION).sdk -arch i686 $< -o ios-x86/$@
196
197
  mkdir -p ios-arm/$(dir $@)
197
- $(DEVICEROOT)/usr/bin/$(CC) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 $< -o ios-arm/$@
198
+ $(DEVICEROOT)/usr/bin/$(CXX) $(CFLAGS) -isysroot $(DEVICEROOT)/SDKs/iPhoneOS$(IOSVERSION).sdk -arch armv6 -arch armv7 $< -o ios-arm/$@
198
199
  lipo ios-x86/$@ ios-arm/$@ -create -output $@
199
200
 
200
201
  .c.o:
@@ -206,7 +207,7 @@ IOSVERSION=$(shell defaults read /Developer/Platforms/iPhoneOS.platform/version
206
207
 
207
208
  else
208
209
  .cc.o:
209
- $(CC) $(CFLAGS) $< -o $@
210
+ $(CXX) $(CFLAGS) $< -o $@
210
211
 
211
212
  .c.o:
212
213
  $(CC) $(CFLAGS) $< -o $@
@@ -13,6 +13,10 @@
13
13
  # Delete existing build_config.mk
14
14
  rm -f build_config.mk
15
15
 
16
+ if test -z "$CXX"; then
17
+ CXX=g++
18
+ fi
19
+
16
20
  # Detect OS
17
21
  case `uname -s` in
18
22
  Darwin)
@@ -23,7 +27,7 @@ case `uname -s` in
23
27
  Linux)
24
28
  PLATFORM=OS_LINUX
25
29
  echo "PLATFORM_CFLAGS=-pthread -DOS_LINUX" >> build_config.mk
26
- echo "PLATFORM_LDFLAGS=-lpthread" >> build_config.mk
30
+ echo "PLATFORM_LDFLAGS=-pthread" >> build_config.mk
27
31
  ;;
28
32
  SunOS)
29
33
  PLATFORM=OS_SOLARIS
@@ -35,6 +39,21 @@ case `uname -s` in
35
39
  echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_FREEBSD" >> build_config.mk
36
40
  echo "PLATFORM_LDFLAGS=-lpthread" >> build_config.mk
37
41
  ;;
42
+ NetBSD)
43
+ PLATFORM=OS_NETBSD
44
+ echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_NETBSD" >> build_config.mk
45
+ echo "PLATFORM_LDFLAGS=-lpthread -lgcc_s" >> build_config.mk
46
+ ;;
47
+ OpenBSD)
48
+ PLATFORM=OS_OPENBSD
49
+ echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_OPENBSD" >> build_config.mk
50
+ echo "PLATFORM_LDFLAGS=-pthread" >> build_config.mk
51
+ ;;
52
+ DragonFly)
53
+ PLATFORM=OS_DRAGONFLYBSD
54
+ echo "PLATFORM_CFLAGS=-D_REENTRANT -DOS_DRAGONFLYBSD" >> build_config.mk
55
+ echo "PLATFORM_LDFLAGS=-lpthread" >> build_config.mk
56
+ ;;
38
57
  *)
39
58
  echo "Unknown platform!"
40
59
  exit 1
@@ -48,8 +67,8 @@ PORT_CFLAGS="-fno-builtin-memcmp"
48
67
  # Detect C++0x -- this determines whether we'll use port_noatomic.h
49
68
  # or port_posix.h by:
50
69
  # 1. Rrying to compile with -std=c++0x and including <cstdatomic>.
51
- # 2. If g++ returns error code, we know to use port_posix.h
52
- g++ $CFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null <<EOF
70
+ # 2. If $CXX returns error code, we know to use port_posix.h
71
+ $CXX $CFLAGS -std=c++0x -x c++ - -o /dev/null 2>/dev/null <<EOF
53
72
  #include <cstdatomic>
54
73
  int main() {}
55
74
  EOF
@@ -61,7 +80,7 @@ fi
61
80
 
62
81
  # Test whether Snappy library is installed
63
82
  # http://code.google.com/p/snappy/
64
- g++ $CFLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
83
+ $CXX $CFLAGS -x c++ - -o /dev/null 2>/dev/null <<EOF
65
84
  #include <snappy.h>
66
85
  int main() {}
67
86
  EOF
@@ -85,4 +85,4 @@ Status BuildTable(const std::string& dbname,
85
85
  return s;
86
86
  }
87
87
 
88
- }
88
+ } // namespace leveldb
@@ -29,6 +29,6 @@ extern Status BuildTable(const std::string& dbname,
29
29
  Iterator* iter,
30
30
  FileMetaData* meta);
31
31
 
32
- }
32
+ } // namespace leveldb
33
33
 
34
34
  #endif // STORAGE_LEVELDB_DB_BUILDER_H_
@@ -352,7 +352,7 @@ TEST(CorruptionTest, UnrelatedKeys) {
352
352
  ASSERT_EQ(Value(1000, &tmp2).ToString(), v);
353
353
  }
354
354
 
355
- }
355
+ } // namespace leveldb
356
356
 
357
357
  int main(int argc, char** argv) {
358
358
  return leveldb::test::RunAllTests();
@@ -288,7 +288,7 @@ struct ThreadState {
288
288
  }
289
289
  };
290
290
 
291
- }
291
+ } // namespace
292
292
 
293
293
  class Benchmark {
294
294
  private:
@@ -829,7 +829,7 @@ class Benchmark {
829
829
  }
830
830
  };
831
831
 
832
- }
832
+ } // namespace leveldb
833
833
 
834
834
  int main(int argc, char** argv) {
835
835
  FLAGS_write_buffer_size = leveldb::Options().write_buffer_size;
@@ -655,6 +655,8 @@ void DBImpl::BackgroundCompaction() {
655
655
  CompactionState* compact = new CompactionState(c);
656
656
  status = DoCompactionWork(compact);
657
657
  CleanupCompaction(compact);
658
+ c->ReleaseInputs();
659
+ DeleteObsoleteFiles();
658
660
  }
659
661
  delete c;
660
662
 
@@ -672,6 +674,9 @@ void DBImpl::BackgroundCompaction() {
672
674
 
673
675
  if (is_manual) {
674
676
  ManualCompaction* m = manual_compaction_;
677
+ if (!status.ok()) {
678
+ m->done = true;
679
+ }
675
680
  if (!m->done) {
676
681
  // We only compacted part of the requested range. Update *m
677
682
  // to the range that is left to be compacted.
@@ -793,21 +798,8 @@ Status DBImpl::InstallCompactionResults(CompactionState* compact) {
793
798
  compact->compaction->edit()->AddFile(
794
799
  level + 1,
795
800
  out.number, out.file_size, out.smallest, out.largest);
796
- pending_outputs_.erase(out.number);
797
801
  }
798
- compact->outputs.clear();
799
-
800
- Status s = versions_->LogAndApply(compact->compaction->edit(), &mutex_);
801
- if (s.ok()) {
802
- compact->compaction->ReleaseInputs();
803
- DeleteObsoleteFiles();
804
- } else {
805
- // Discard any files we may have created during this failed compaction
806
- for (size_t i = 0; i < compact->outputs.size(); i++) {
807
- env_->DeleteFile(TableFileName(dbname_, compact->outputs[i].number));
808
- }
809
- }
810
- return s;
802
+ return versions_->LogAndApply(compact->compaction->edit(), &mutex_);
811
803
  }
812
804
 
813
805
  Status DBImpl::DoCompactionWork(CompactionState* compact) {
@@ -985,7 +977,7 @@ static void CleanupIteratorState(void* arg1, void* arg2) {
985
977
  state->mu->Unlock();
986
978
  delete state;
987
979
  }
988
- }
980
+ } // namespace
989
981
 
990
982
  Iterator* DBImpl::NewInternalIterator(const ReadOptions& options,
991
983
  SequenceNumber* latest_snapshot) {
@@ -1378,4 +1370,4 @@ Status DestroyDB(const std::string& dbname, const Options& options) {
1378
1370
  return result;
1379
1371
  }
1380
1372
 
1381
- }
1373
+ } // namespace leveldb
@@ -187,6 +187,6 @@ extern Options SanitizeOptions(const std::string& db,
187
187
  const InternalKeyComparator* icmp,
188
188
  const Options& src);
189
189
 
190
- }
190
+ } // namespace leveldb
191
191
 
192
192
  #endif // STORAGE_LEVELDB_DB_DB_IMPL_H_
@@ -296,4 +296,4 @@ Iterator* NewDBIterator(
296
296
  return new DBIter(dbname, env, user_key_comparator, internal_iter, sequence);
297
297
  }
298
298
 
299
- }
299
+ } // namespace leveldb
@@ -21,6 +21,6 @@ extern Iterator* NewDBIterator(
21
21
  Iterator* internal_iter,
22
22
  const SequenceNumber& sequence);
23
23
 
24
- }
24
+ } // namespace leveldb
25
25
 
26
26
  #endif // STORAGE_LEVELDB_DB_DB_ITER_H_
@@ -28,8 +28,12 @@ class SpecialEnv : public EnvWrapper {
28
28
  // sstable Sync() calls are blocked while this pointer is non-NULL.
29
29
  port::AtomicPointer delay_sstable_sync_;
30
30
 
31
+ // Simulate no-space errors while this pointer is non-NULL.
32
+ port::AtomicPointer no_space_;
33
+
31
34
  explicit SpecialEnv(Env* base) : EnvWrapper(base) {
32
35
  delay_sstable_sync_.Release_Store(NULL);
36
+ no_space_.Release_Store(NULL);
33
37
  }
34
38
 
35
39
  Status NewWritableFile(const std::string& f, WritableFile** r) {
@@ -44,7 +48,14 @@ class SpecialEnv : public EnvWrapper {
44
48
  base_(base) {
45
49
  }
46
50
  ~SSTableFile() { delete base_; }
47
- Status Append(const Slice& data) { return base_->Append(data); }
51
+ Status Append(const Slice& data) {
52
+ if (env_->no_space_.Acquire_Load() != NULL) {
53
+ // Drop writes on the floor
54
+ return Status::OK();
55
+ } else {
56
+ return base_->Append(data);
57
+ }
58
+ }
48
59
  Status Close() { return base_->Close(); }
49
60
  Status Flush() { return base_->Flush(); }
50
61
  Status Sync() {
@@ -136,6 +147,33 @@ class DBTest {
136
147
  return result;
137
148
  }
138
149
 
150
+ // Return a string that contains all key,value pairs in order,
151
+ // formatted like "(k1->v1)(k2->v2)".
152
+ std::string Contents() {
153
+ std::vector<std::string> forward;
154
+ std::string result;
155
+ Iterator* iter = db_->NewIterator(ReadOptions());
156
+ for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
157
+ std::string s = IterStatus(iter);
158
+ result.push_back('(');
159
+ result.append(s);
160
+ result.push_back(')');
161
+ forward.push_back(s);
162
+ }
163
+
164
+ // Check reverse iteration results are the reverse of forward results
165
+ int matched = 0;
166
+ for (iter->SeekToLast(); iter->Valid(); iter->Prev()) {
167
+ ASSERT_LT(matched, forward.size());
168
+ ASSERT_EQ(IterStatus(iter), forward[forward.size() - matched - 1]);
169
+ matched++;
170
+ }
171
+ ASSERT_EQ(matched, forward.size());
172
+
173
+ delete iter;
174
+ return result;
175
+ }
176
+
139
177
  std::string AllEntriesFor(const Slice& user_key) {
140
178
  Iterator* iter = dbfull()->TEST_NewInternalIterator();
141
179
  InternalKey target(user_key, kMaxSequenceNumber, kTypeValue);
@@ -212,6 +250,12 @@ class DBTest {
212
250
  return result;
213
251
  }
214
252
 
253
+ int CountFiles() {
254
+ std::vector<std::string> files;
255
+ env_->GetChildren(dbname_, &files);
256
+ return static_cast<int>(files.size());
257
+ }
258
+
215
259
  uint64_t Size(const Slice& start, const Slice& limit) {
216
260
  Range r(start, limit);
217
261
  uint64_t size;
@@ -1048,6 +1092,49 @@ TEST(DBTest, OverlapInLevel0) {
1048
1092
  ASSERT_EQ("NOT_FOUND", Get("600"));
1049
1093
  }
1050
1094
 
1095
+ TEST(DBTest, L0_CompactionBug_Issue44_a) {
1096
+ Reopen();
1097
+ ASSERT_OK(Put("b", "v"));
1098
+ Reopen();
1099
+ ASSERT_OK(Delete("b"));
1100
+ ASSERT_OK(Delete("a"));
1101
+ Reopen();
1102
+ ASSERT_OK(Delete("a"));
1103
+ Reopen();
1104
+ ASSERT_OK(Put("a", "v"));
1105
+ Reopen();
1106
+ Reopen();
1107
+ ASSERT_EQ("(a->v)", Contents());
1108
+ env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
1109
+ ASSERT_EQ("(a->v)", Contents());
1110
+ }
1111
+
1112
+ TEST(DBTest, L0_CompactionBug_Issue44_b) {
1113
+ Reopen();
1114
+ Put("","");
1115
+ Reopen();
1116
+ Delete("e");
1117
+ Put("","");
1118
+ Reopen();
1119
+ Put("c", "cv");
1120
+ Reopen();
1121
+ Put("","");
1122
+ Reopen();
1123
+ Put("","");
1124
+ env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
1125
+ Reopen();
1126
+ Put("d","dv");
1127
+ Reopen();
1128
+ Put("","");
1129
+ Reopen();
1130
+ Delete("d");
1131
+ Delete("b");
1132
+ Reopen();
1133
+ ASSERT_EQ("(->)(c->cv)", Contents());
1134
+ env_->SleepForMicroseconds(1000000); // Wait for compaction to finish
1135
+ ASSERT_EQ("(->)(c->cv)", Contents());
1136
+ }
1137
+
1051
1138
  TEST(DBTest, ComparatorCheck) {
1052
1139
  class NewComparator : public Comparator {
1053
1140
  public:
@@ -1071,6 +1158,58 @@ TEST(DBTest, ComparatorCheck) {
1071
1158
  << s.ToString();
1072
1159
  }
1073
1160
 
1161
+ TEST(DBTest, CustomComparator) {
1162
+ class NumberComparator : public Comparator {
1163
+ public:
1164
+ virtual const char* Name() const { return "test.NumberComparator"; }
1165
+ virtual int Compare(const Slice& a, const Slice& b) const {
1166
+ return ToNumber(a) - ToNumber(b);
1167
+ }
1168
+ virtual void FindShortestSeparator(std::string* s, const Slice& l) const {
1169
+ ToNumber(*s); // Check format
1170
+ ToNumber(l); // Check format
1171
+ }
1172
+ virtual void FindShortSuccessor(std::string* key) const {
1173
+ ToNumber(*key); // Check format
1174
+ }
1175
+ private:
1176
+ static int ToNumber(const Slice& x) {
1177
+ // Check that there are no extra characters.
1178
+ ASSERT_TRUE(x.size() >= 2 && x[0] == '[' && x[x.size()-1] == ']')
1179
+ << EscapeString(x);
1180
+ int val;
1181
+ char ignored;
1182
+ ASSERT_TRUE(sscanf(x.ToString().c_str(), "[%i]%c", &val, &ignored) == 1)
1183
+ << EscapeString(x);
1184
+ return val;
1185
+ }
1186
+ };
1187
+ NumberComparator cmp;
1188
+ Options new_options;
1189
+ new_options.create_if_missing = true;
1190
+ new_options.comparator = &cmp;
1191
+ new_options.write_buffer_size = 1000; // Compact more often
1192
+ DestroyAndReopen(&new_options);
1193
+ ASSERT_OK(Put("[10]", "ten"));
1194
+ ASSERT_OK(Put("[0x14]", "twenty"));
1195
+ for (int i = 0; i < 2; i++) {
1196
+ ASSERT_EQ("ten", Get("[10]"));
1197
+ ASSERT_EQ("ten", Get("[0xa]"));
1198
+ ASSERT_EQ("twenty", Get("[20]"));
1199
+ ASSERT_EQ("twenty", Get("[0x14]"));
1200
+ Compact("[0]", "[9999]");
1201
+ }
1202
+
1203
+ for (int run = 0; run < 2; run++) {
1204
+ for (int i = 0; i < 1000; i++) {
1205
+ char buf[100];
1206
+ snprintf(buf, sizeof(buf), "[%d]", i*10);
1207
+ ASSERT_OK(Put(buf, buf));
1208
+ }
1209
+ Compact("[0]", "[1000000]");
1210
+ }
1211
+ }
1212
+
1074
1213
  TEST(DBTest, ManualCompaction) {
1075
1214
  ASSERT_EQ(config::kMaxMemCompactLevel, 2)
1076
1215
  << "Need to update this test to match kMaxMemCompactLevel";
@@ -1144,6 +1283,37 @@ TEST(DBTest, DBOpen_Options) {
1144
1283
  db = NULL;
1145
1284
  }
1146
1285
 
1286
+ // Check that number of files does not grow when we are out of space
1287
+ TEST(DBTest, NoSpace) {
1288
+ Options options;
1289
+ options.env = env_;
1290
+ Reopen(&options);
1291
+
1292
+ ASSERT_OK(Put("foo", "v1"));
1293
+ ASSERT_EQ("v1", Get("foo"));
1294
+ Compact("a", "z");
1295
+ const int num_files = CountFiles();
1296
+ env_->no_space_.Release_Store(env_); // Force out-of-space errors
1297
+ for (int i = 0; i < 10; i++) {
1298
+ for (int level = 0; level < config::kNumLevels-1; level++) {
1299
+ dbfull()->TEST_CompactRange(level, NULL, NULL);
1300
+ }
1301
+ }
1302
+ env_->no_space_.Release_Store(NULL);
1303
+ ASSERT_LT(CountFiles(), num_files + 5);
1304
+ }
1305
+
1306
+ TEST(DBTest, FilesDeletedAfterCompaction) {
1307
+ ASSERT_OK(Put("foo", "v2"));
1308
+ Compact("a", "z");
1309
+ const int num_files = CountFiles();
1310
+ for (int i = 0; i < 10; i++) {
1311
+ ASSERT_OK(Put("foo", "v2"));
1312
+ Compact("a", "z");
1313
+ }
1314
+ ASSERT_EQ(CountFiles(), num_files);
1315
+ }
1316
+
1147
1317
  // Multi-threaded test:
1148
1318
  namespace {
1149
1319
 
@@ -1165,14 +1335,15 @@ struct MTThread {
1165
1335
 
1166
1336
  static void MTThreadBody(void* arg) {
1167
1337
  MTThread* t = reinterpret_cast<MTThread*>(arg);
1338
+ int id = t->id;
1168
1339
  DB* db = t->state->test->db_;
1169
1340
  uintptr_t counter = 0;
1170
- fprintf(stderr, "... starting thread %d\n", t->id);
1171
- Random rnd(1000 + t->id);
1341
+ fprintf(stderr, "... starting thread %d\n", id);
1342
+ Random rnd(1000 + id);
1172
1343
  std::string value;
1173
1344
  char valbuf[1500];
1174
1345
  while (t->state->stop.Acquire_Load() == NULL) {
1175
- t->state->counter[t->id].Release_Store(reinterpret_cast<void*>(counter));
1346
+ t->state->counter[id].Release_Store(reinterpret_cast<void*>(counter));
1176
1347
 
1177
1348
  int key = rnd.Uniform(kNumKeys);
1178
1349
  char keybuf[20];
@@ -1182,7 +1353,7 @@ static void MTThreadBody(void* arg) {
1182
1353
  // Write values of the form <key, my id, counter>.
1183
1354
  // We add some padding for force compactions.
1184
1355
  snprintf(valbuf, sizeof(valbuf), "%d.%d.%-1000d",
1185
- key, t->id, static_cast<int>(counter));
1356
+ key, id, static_cast<int>(counter));
1186
1357
  ASSERT_OK(db->Put(WriteOptions(), Slice(keybuf), Slice(valbuf)));
1187
1358
  } else {
1188
1359
  // Read a value and verify that it matches the pattern written above.
@@ -1203,11 +1374,11 @@ static void MTThreadBody(void* arg) {
1203
1374
  }
1204
1375
  counter++;
1205
1376
  }
1206
- t->state->thread_done[t->id].Release_Store(t);
1207
- fprintf(stderr, "... stopping thread %d after %d ops\n", t->id, int(counter));
1377
+ t->state->thread_done[id].Release_Store(t);
1378
+ fprintf(stderr, "... stopping thread %d after %d ops\n", id, int(counter));
1208
1379
  }
1209
1380
 
1210
- }
1381
+ } // namespace
1211
1382
 
1212
1383
  TEST(DBTest, MultiThreaded) {
1213
1384
  // Initialize state
@@ -1525,7 +1696,7 @@ void BM_LogAndApply(int iters, int num_base_files) {
1525
1696
  buf, iters, us, ((float)us) / iters);
1526
1697
  }
1527
1698
 
1528
- }
1699
+ } // namespace leveldb
1529
1700
 
1530
1701
  int main(int argc, char** argv) {
1531
1702
  if (argc > 1 && std::string(argv[1]) == "--benchmark") {