├── webbench
├── debian
│ ├── dirs
│ ├── copyright
│ ├── control
│ ├── rules
│ └── changelog
├── COPYRIGHT
├── ChangeLog
├── Makefile
├── socket.c
└── webbench.1
├── leveldb
├── desktop.ini
├── .gitignore
├── AUTHORS
├── util
│ ├── filter_policy.cc
│ ├── hash.h
│ ├── options.cc
│ ├── histogram.h
│ ├── mutexlock.h
│ ├── hash.cc
│ ├── logging.h
│ ├── crc32c.h
│ ├── testutil.cc
│ ├── hash_test.cc
│ ├── arena_test.cc
│ ├── testharness.cc
│ ├── logging.cc
│ ├── crc32c_test.cc
│ ├── status.cc
│ ├── testutil.h
│ ├── arena.h
│ ├── random.h
│ ├── arena.cc
│ ├── comparator.cc
│ ├── env.cc
│ ├── env_test.cc
│ ├── posix_logger.h
│ └── bloom.cc
├── port
│ ├── README
│ ├── port.h
│ ├── win
│ │ └── stdint.h
│ ├── thread_annotations.h
│ └── port_posix.cc
├── NEWS
├── TODO
├── helpers
│ └── memenv
│ │ └── memenv.h
├── db
│ ├── db_iter.h
│ ├── log_format.h
│ ├── builder.h
│ ├── version_edit_test.cc
│ ├── write_batch_internal.h
│ ├── leveldb_main.cc
│ ├── log_writer.h
│ ├── snapshot.h
│ ├── table_cache.h
│ ├── builder.cc
│ ├── memtable.h
│ ├── filename.h
│ ├── log_writer.cc
│ ├── autocompact_test.cc
│ ├── filename_test.cc
│ ├── write_batch_test.cc
│ ├── version_edit.h
│ ├── dbformat_test.cc
│ └── log_reader.h
├── table
│ ├── merger.h
│ ├── two_level_iterator.h
│ ├── block.h
│ ├── iterator.cc
│ ├── block_builder.h
│ ├── iterator_wrapper.h
│ ├── filter_block.h
│ ├── format.h
│ ├── filter_block.cc
│ └── filter_block_test.cc
├── include
│ └── leveldb
│ │ ├── dumpfile.h
│ │ ├── write_batch.h
│ │ ├── comparator.h
│ │ ├── filter_policy.h
│ │ ├── table.h
│ │ ├── slice.h
│ │ ├── iterator.h
│ │ ├── table_builder.h
│ │ └── status.h
├── doc
│ ├── doc.css
│ ├── log_format.txt
│ └── table_format.txt
├── LICENSE
├── CONTRIBUTING.md
└── issues
│ ├── issue200_test.cc
│ └── issue178_test.cc
├── attachment
├── leveldb实现解析.pdf
└── mm_facetoface_collect_qrcode_1454761904254.png
├── tinyhttpd
├── Makefile
├── htdocs
│ ├── index.html
│ ├── README
│ ├── color.cgi
│ └── check.cgi
├── simpleclient.c
└── README
├── threadpool
├── package.json
├── README.md
├── Makefile
├── tests
│ ├── shutdown.c
│ ├── thrdtest.c
│ └── heavy.c
├── LICENSE
└── src
│ └── threadpool.h
├── README.md
└── memorypool
├── StackAlloc.h
├── C-11
└── MemoryPool.h
└── C-98
└── MemoryPool.h
/webbench/debian/dirs:
--------------------------------------------------------------------------------
1 | usr/bin
--------------------------------------------------------------------------------
/webbench/COPYRIGHT:
--------------------------------------------------------------------------------
1 | debian/copyright
--------------------------------------------------------------------------------
/webbench/ChangeLog:
--------------------------------------------------------------------------------
1 | debian/changelog
--------------------------------------------------------------------------------
/leveldb/desktop.ini:
--------------------------------------------------------------------------------
1 | [.ShellClassInfo]
2 | IconResource=C:\Program Files (x86)\iDisk\iDisk.exe,0
3 |
--------------------------------------------------------------------------------
/attachment/leveldb实现解析.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AngryHacker/code-with-comments/HEAD/attachment/leveldb实现解析.pdf
--------------------------------------------------------------------------------
/leveldb/.gitignore:
--------------------------------------------------------------------------------
1 | build_config.mk
2 | *.a
3 | *.o
4 | *.dylib*
5 | *.so
6 | *.so.*
7 | *_test
8 | db_bench
9 | leveldbutil
10 |
--------------------------------------------------------------------------------
/tinyhttpd/Makefile:
--------------------------------------------------------------------------------
1 | all: httpd
2 |
3 | httpd: httpd.c
4 | gcc -W -Wall -lsocket -lpthread -o httpd httpd.c
5 |
6 | clean:
7 | rm httpd
8 |
--------------------------------------------------------------------------------
/attachment/mm_facetoface_collect_qrcode_1454761904254.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AngryHacker/code-with-comments/HEAD/attachment/mm_facetoface_collect_qrcode_1454761904254.png
--------------------------------------------------------------------------------
/webbench/debian/copyright:
--------------------------------------------------------------------------------
1 | Webbench was written by Radim Kolar 1997-2004 (hsn@netmag.cz).
2 |
3 | UNIX sockets code (socket.c) taken from popclient 1.5 4/1/94
4 | public domain code, created by Virginia Tech Computing Center.
5 |
6 | Copyright: GPL (see /usr/share/common-licenses/GPL)
7 |
--------------------------------------------------------------------------------
/tinyhttpd/htdocs/index.html:
--------------------------------------------------------------------------------
1 |
2 |
Index
3 |
4 | Welcome to J. David's webserver.
5 |
CGI demo
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/threadpool/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "threadpool",
3 | "version": "0.1.0",
4 | "repo": "mbrossard/threadpool",
5 | "description": "Simple C Thread pool implementation.",
6 | "keywords": ["thread", "posix"],
7 | "license": "MIT",
8 | "src": ["src/threadpool.c", "src/threadpool.h"]
9 | }
10 |
--------------------------------------------------------------------------------
/tinyhttpd/htdocs/README:
--------------------------------------------------------------------------------
1 | These are sample CGI scripts and webpages for tinyhttpd. They can
2 | be redistributed under the terms of the GPL.
3 |
4 | The most impressive demonstration I gave of tinyhttpd to my
5 | professor and my classmates was to load color.cgi with a value of
6 | "chartreuse." :) It's actually a very simple script, guys.
7 |
8 | jdb
9 |
--------------------------------------------------------------------------------
/leveldb/AUTHORS:
--------------------------------------------------------------------------------
1 | # Names should be added to this file like so:
2 | # Name or Organization
3 |
4 | Google Inc.
5 |
6 | # Initial version authors:
7 | Jeffrey Dean
8 | Sanjay Ghemawat
9 |
10 | # Partial list of contributors:
11 | Kevin Regan
12 | Johan Bilien
13 |
--------------------------------------------------------------------------------
/leveldb/util/filter_policy.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 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 "leveldb/filter_policy.h"
6 |
7 | namespace leveldb {
8 |
9 | FilterPolicy::~FilterPolicy() { }
10 |
11 | } // namespace leveldb
12 |
--------------------------------------------------------------------------------
/tinyhttpd/htdocs/color.cgi:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/perl -Tw
2 |
3 | use strict;
4 | use CGI;
5 |
6 | my($cgi) = new CGI;
7 |
8 | print $cgi->header;
9 | my($color) = "blue";
10 | $color = $cgi->param('color') if defined $cgi->param('color');
11 |
12 | print $cgi->start_html(-title => uc($color),
13 | -BGCOLOR => $color);
14 | print $cgi->h1("This is $color");
15 | print $cgi->end_html;
16 |
--------------------------------------------------------------------------------
/leveldb/port/README:
--------------------------------------------------------------------------------
1 | This directory contains interfaces and implementations that isolate the
2 | rest of the package from platform details.
3 |
4 | Code in the rest of the package includes "port.h" from this directory.
5 | "port.h" in turn includes a platform specific "port_.h" file
6 | that provides the platform specific implementation.
7 |
8 | See port_posix.h for an example of what must be provided in a platform
9 | specific header file.
10 |
11 |
--------------------------------------------------------------------------------
/webbench/debian/control:
--------------------------------------------------------------------------------
1 | Source: webbench
2 | Section: web
3 | Priority: extra
4 | Maintainer: Radim Kolar
5 | Build-Depends: debhelper (>> 3.0.0)
6 | Standards-Version: 3.5.2
7 |
8 | Package: webbench
9 | Architecture: any
10 | Depends: ${shlibs:Depends}
11 | Description: Simple forking Web benchmark
12 | webbench is very simple program for benchmarking WWW or Proxy servers.
13 | Uses fork() for simulating multiple clients load. Can use HTTP 0.9 - 1.1
14 | requests, but Keep-Alive connections are not supported.
15 |
--------------------------------------------------------------------------------
/leveldb/NEWS:
--------------------------------------------------------------------------------
1 | Release 1.2 2011-05-16
2 | ----------------------
3 |
4 | Fixes for larger databases (tested up to one billion 100-byte entries,
5 | i.e., ~100GB).
6 |
7 | (1) Place hard limit on number of level-0 files. This fixes errors
8 | of the form "too many open files".
9 |
10 | (2) Fixed memtable management. Before the fix, a heavy write burst
11 | could cause unbounded memory usage.
12 |
13 | A fix for a logging bug where the reader would incorrectly complain
14 | about corruption.
15 |
16 | Allow public access to WriteBatch contents so that users can easily
17 | wrap a DB.
18 |
--------------------------------------------------------------------------------
/tinyhttpd/htdocs/check.cgi:
--------------------------------------------------------------------------------
1 | #!/usr/local/bin/perl -Tw
2 |
3 | use strict;
4 | use CGI;
5 |
6 | my($cgi) = new CGI;
7 |
8 | print $cgi->header('text/html');
9 | print $cgi->start_html(-title => "Example CGI script",
10 | -BGCOLOR => 'red');
11 | print $cgi->h1("CGI Example");
12 | print $cgi->p, "This is an example of CGI\n";
13 | print $cgi->p, "Parameters given to this script:\n";
14 | print "\n";
15 | foreach my $param ($cgi->param)
16 | {
17 | print "- ", "$param ", $cgi->param($param), "\n";
18 | }
19 | print "
";
20 | print $cgi->end_html, "\n";
21 |
--------------------------------------------------------------------------------
/leveldb/TODO:
--------------------------------------------------------------------------------
1 | ss
2 | - Stats
3 |
4 | db
5 | - Maybe implement DB::BulkDeleteForRange(start_key, end_key)
6 | that would blow away files whose ranges are entirely contained
7 | within [start_key..end_key]? For Chrome, deletion of obsolete
8 | object stores, etc. can be done in the background anyway, so
9 | probably not that important.
10 | - There have been requests for MultiGet.
11 |
12 | After a range is completely deleted, what gets rid of the
13 | corresponding files if we do no future changes to that range. Make
14 | the conditions for triggering compactions fire in more situations?
15 |
--------------------------------------------------------------------------------
/leveldb/util/hash.h:
--------------------------------------------------------------------------------
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 | // Simple hash function used for internal data structures
6 |
7 | #ifndef STORAGE_LEVELDB_UTIL_HASH_H_
8 | #define STORAGE_LEVELDB_UTIL_HASH_H_
9 |
10 | #include
11 | #include
12 |
13 | namespace leveldb {
14 |
15 | extern uint32_t Hash(const char* data, size_t n, uint32_t seed);
16 |
17 | }
18 |
19 | #endif // STORAGE_LEVELDB_UTIL_HASH_H_
20 |
--------------------------------------------------------------------------------
/leveldb/port/port.h:
--------------------------------------------------------------------------------
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_PORT_H_
6 | #define STORAGE_LEVELDB_PORT_PORT_H_
7 |
8 | #include
9 |
10 | // Include the appropriate platform specific file below. If you are
11 | // porting to a new platform, see "port_example.h" for documentation
12 | // of what the new port_.h file must provide.
13 | #if defined(LEVELDB_PLATFORM_POSIX)
14 | # include "port/port_posix.h"
15 | #elif defined(LEVELDB_PLATFORM_CHROMIUM)
16 | # include "port/port_chromium.h"
17 | #endif
18 |
19 | #endif // STORAGE_LEVELDB_PORT_PORT_H_
20 |
--------------------------------------------------------------------------------
/leveldb/helpers/memenv/memenv.h:
--------------------------------------------------------------------------------
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_HELPERS_MEMENV_MEMENV_H_
6 | #define STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_
7 |
8 | namespace leveldb {
9 |
10 | class Env;
11 |
12 | // Returns a new environment that stores its data in memory and delegates
13 | // all non-file-storage tasks to base_env. The caller must delete the result
14 | // when it is no longer needed.
15 | // *base_env must remain live while the result is in use.
16 | Env* NewMemEnv(Env* base_env);
17 |
18 | } // namespace leveldb
19 |
20 | #endif // STORAGE_LEVELDB_HELPERS_MEMENV_MEMENV_H_
21 |
--------------------------------------------------------------------------------
/tinyhttpd/simpleclient.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | int main(int argc, char *argv[])
9 | {
10 | int sockfd;
11 | int len;
12 | struct sockaddr_in address;
13 | int result;
14 | char ch = 'A';
15 |
16 | sockfd = socket(AF_INET, SOCK_STREAM, 0);
17 | address.sin_family = AF_INET;
18 | address.sin_addr.s_addr = inet_addr("127.0.0.1");
19 | address.sin_port = htons(9734);
20 | len = sizeof(address);
21 | result = connect(sockfd, (struct sockaddr *)&address, len);
22 |
23 | if (result == -1)
24 | {
25 | perror("oops: client1");
26 | exit(1);
27 | }
28 | write(sockfd, &ch, 1);
29 | read(sockfd, &ch, 1);
30 | printf("char from server = %c\n", ch);
31 | close(sockfd);
32 | exit(0);
33 | }
34 |
--------------------------------------------------------------------------------
/leveldb/util/options.cc:
--------------------------------------------------------------------------------
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 "leveldb/options.h"
6 |
7 | #include "leveldb/comparator.h"
8 | #include "leveldb/env.h"
9 |
10 | namespace leveldb {
11 |
12 | Options::Options()
13 | : comparator(BytewiseComparator()),
14 | create_if_missing(false),
15 | error_if_exists(false),
16 | paranoid_checks(false),
17 | env(Env::Default()),
18 | info_log(NULL),
19 | write_buffer_size(4<<20),
20 | max_open_files(1000),
21 | block_cache(NULL),
22 | block_size(4096),
23 | block_restart_interval(16),
24 | compression(kSnappyCompression),
25 | reuse_logs(false),
26 | filter_policy(NULL) {
27 | }
28 |
29 | } // namespace leveldb
30 |
--------------------------------------------------------------------------------
/leveldb/db/db_iter.h:
--------------------------------------------------------------------------------
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_DB_DB_ITER_H_
6 | #define STORAGE_LEVELDB_DB_DB_ITER_H_
7 |
8 | #include
9 | #include "leveldb/db.h"
10 | #include "db/dbformat.h"
11 |
12 | namespace leveldb {
13 |
14 | class DBImpl;
15 |
16 | // Return a new iterator that converts internal keys (yielded by
17 | // "*internal_iter") that were live at the specified "sequence" number
18 | // into appropriate user keys.
19 | extern Iterator* NewDBIterator(
20 | DBImpl* db,
21 | const Comparator* user_key_comparator,
22 | Iterator* internal_iter,
23 | SequenceNumber sequence,
24 | uint32_t seed);
25 |
26 | } // namespace leveldb
27 |
28 | #endif // STORAGE_LEVELDB_DB_DB_ITER_H_
29 |
--------------------------------------------------------------------------------
/leveldb/port/win/stdint.h:
--------------------------------------------------------------------------------
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 | // MSVC didn't ship with this file until the 2010 version.
6 |
7 | #ifndef STORAGE_LEVELDB_PORT_WIN_STDINT_H_
8 | #define STORAGE_LEVELDB_PORT_WIN_STDINT_H_
9 |
10 | #if !defined(_MSC_VER)
11 | #error This file should only be included when compiling with MSVC.
12 | #endif
13 |
14 | // Define C99 equivalent types.
15 | typedef signed char int8_t;
16 | typedef signed short int16_t;
17 | typedef signed int int32_t;
18 | typedef signed long long int64_t;
19 | typedef unsigned char uint8_t;
20 | typedef unsigned short uint16_t;
21 | typedef unsigned int uint32_t;
22 | typedef unsigned long long uint64_t;
23 |
24 | #endif // STORAGE_LEVELDB_PORT_WIN_STDINT_H_
25 |
--------------------------------------------------------------------------------
/leveldb/table/merger.h:
--------------------------------------------------------------------------------
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_TABLE_MERGER_H_
6 | #define STORAGE_LEVELDB_TABLE_MERGER_H_
7 |
8 | namespace leveldb {
9 |
10 | class Comparator;
11 | class Iterator;
12 |
13 | // Return an iterator that provided the union of the data in
14 | // children[0,n-1]. Takes ownership of the child iterators and
15 | // will delete them when the result iterator is deleted.
16 | //
17 | // The result does no duplicate suppression. I.e., if a particular
18 | // key is present in K child iterators, it will be yielded K times.
19 | //
20 | // REQUIRES: n >= 0
21 | extern Iterator* NewMergingIterator(
22 | const Comparator* comparator, Iterator** children, int n);
23 |
24 | } // namespace leveldb
25 |
26 | #endif // STORAGE_LEVELDB_TABLE_MERGER_H_
27 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/dumpfile.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2014 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_INCLUDE_DUMPFILE_H_
6 | #define STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_
7 |
8 | #include
9 | #include "leveldb/env.h"
10 | #include "leveldb/status.h"
11 |
12 | namespace leveldb {
13 |
14 | // Dump the contents of the file named by fname in text format to
15 | // *dst. Makes a sequence of dst->Append() calls; each call is passed
16 | // the newline-terminated text corresponding to a single item found
17 | // in the file.
18 | //
19 | // Returns a non-OK result if fname does not name a leveldb storage
20 | // file, or if the file cannot be read.
21 | Status DumpFile(Env* env, const std::string& fname, WritableFile* dst);
22 |
23 | } // namespace leveldb
24 |
25 | #endif // STORAGE_LEVELDB_INCLUDE_DUMPFILE_H_
26 |
--------------------------------------------------------------------------------
/threadpool/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/mbrossard/threadpool)
2 |
3 | A simple C thread pool implementation
4 | =====================================
5 |
6 | Currently, the implementation:
7 | * Works with pthreads only, but API is intentionally opaque to allow
8 | other implementations (Windows for instance).
9 | * Starts all threads on creation of the thread pool.
10 | * Reserves one task for signaling the queue is full.
11 | * Stops and joins all worker threads on destroy.
12 |
13 | Possible enhancements
14 | =====================
15 |
16 | The API contains addtional unused 'flags' parameters that would allow
17 | some additional options:
18 |
19 | * Lazy creation of threads (easy)
20 | * Reduce number of threads automatically (hard)
21 | * Unlimited queue size (medium)
22 | * Kill worker threads on destroy (hard, dangerous)
23 | * Support Windows API (medium)
24 | * Reduce locking contention (medium/hard)
25 |
--------------------------------------------------------------------------------
/leveldb/db/log_format.h:
--------------------------------------------------------------------------------
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 | // Log format information shared by reader and writer.
6 | // See ../doc/log_format.txt for more detail.
7 |
8 | #ifndef STORAGE_LEVELDB_DB_LOG_FORMAT_H_
9 | #define STORAGE_LEVELDB_DB_LOG_FORMAT_H_
10 |
11 | namespace leveldb {
12 | namespace log {
13 |
14 | enum RecordType {
15 | // Zero is reserved for preallocated files
16 | kZeroType = 0,
17 |
18 | kFullType = 1,
19 |
20 | // For fragments
21 | // 一条 record 可能被分片
22 | kFirstType = 2,
23 | kMiddleType = 3,
24 | kLastType = 4
25 | };
26 | static const int kMaxRecordType = kLastType;
27 |
28 | static const int kBlockSize = 32768; // 一个 block 大小,32 kb
29 |
30 | // Header is checksum (4 bytes), length (2 bytes), type (1 byte).
31 | static const int kHeaderSize = 4 + 2 + 1;
32 |
33 | } // namespace log
34 | } // namespace leveldb
35 |
36 | #endif // STORAGE_LEVELDB_DB_LOG_FORMAT_H_
37 |
--------------------------------------------------------------------------------
/threadpool/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS = -D_REENTRANT -Wall -pedantic -Isrc
2 | LDLIBS = -lpthread
3 |
4 | ifdef DEBUG
5 | CFLAGS += -g
6 | LDFLAGS += -g
7 | endif
8 |
9 | TARGETS = tests/thrdtest tests/heavy tests/shutdown \
10 | libthreadpool.so libthreadpool.a
11 |
12 | all: $(TARGETS)
13 |
14 | tests/shutdown: tests/shutdown.o src/threadpool.o
15 | tests/thrdtest: tests/thrdtest.o src/threadpool.o
16 | tests/heavy: tests/heavy.o src/threadpool.o
17 | src/threadpool.o: src/threadpool.c src/threadpool.h
18 | tests/thrdtest.o: tests/thrdtest.c src/threadpool.h
19 | tests/heavy.o: tests/heavy.c src/threadpool.h
20 |
21 | # Short-hand aliases
22 | shared: libthreadpool.so
23 | static: libthreadpool.a
24 |
25 | libthreadpool.so: src/threadpool.c src/threadpool.h
26 | $(CC) -shared -fPIC ${CFLAGS} -o $@ $< ${LDLIBS}
27 |
28 | src/libthreadpool.o: src/threadpool.c src/threadpool.h
29 | $(CC) -c -fPIC ${CFLAGS} -o $@ $<
30 |
31 | libthreadpool.a: src/libthreadpool.o
32 | ar rcs $@ $^
33 |
34 | clean:
35 | rm -f $(TARGETS) *~ */*~ */*.o
36 |
37 | test:
38 | ./tests/shutdown
39 | ./tests/thrdtest
40 | ./tests/heavy
41 |
42 |
--------------------------------------------------------------------------------
/leveldb/util/histogram.h:
--------------------------------------------------------------------------------
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_UTIL_HISTOGRAM_H_
6 | #define STORAGE_LEVELDB_UTIL_HISTOGRAM_H_
7 |
8 | #include
9 |
10 | namespace leveldb {
11 |
12 | class Histogram {
13 | public:
14 | Histogram() { }
15 | ~Histogram() { }
16 |
17 | void Clear();
18 | void Add(double value);
19 | void Merge(const Histogram& other);
20 |
21 | std::string ToString() const;
22 |
23 | private:
24 | double min_;
25 | double max_;
26 | double num_;
27 | double sum_;
28 | double sum_squares_;
29 |
30 | enum { kNumBuckets = 154 };
31 | static const double kBucketLimit[kNumBuckets];
32 | double buckets_[kNumBuckets];
33 |
34 | double Median() const;
35 | double Percentile(double p) const;
36 | double Average() const;
37 | double StandardDeviation() const;
38 | };
39 |
40 | } // namespace leveldb
41 |
42 | #endif // STORAGE_LEVELDB_UTIL_HISTOGRAM_H_
43 |
--------------------------------------------------------------------------------
/webbench/Makefile:
--------------------------------------------------------------------------------
1 | CFLAGS?= -Wall -ggdb -W -O
2 | CC?= gcc
3 | LIBS?=
4 | LDFLAGS?=
5 | PREFIX?= /usr/local
6 | VERSION=1.5
7 | TMPDIR=/tmp/webbench-$(VERSION)
8 |
9 | all: webbench tags
10 |
11 | tags: *.c
12 | -ctags *.c
13 |
14 | install: webbench
15 | install -s webbench $(DESTDIR)$(PREFIX)/bin
16 | install -m 644 webbench.1 $(DESTDIR)$(PREFIX)/man/man1
17 | install -d $(DESTDIR)$(PREFIX)/share/doc/webbench
18 | install -m 644 debian/copyright $(DESTDIR)$(PREFIX)/share/doc/webbench
19 | install -m 644 debian/changelog $(DESTDIR)$(PREFIX)/share/doc/webbench
20 |
21 | webbench: webbench.o Makefile
22 | $(CC) $(CFLAGS) $(LDFLAGS) -o webbench webbench.o $(LIBS)
23 |
24 | clean:
25 | -rm -f *.o webbench *~ core *.core tags
26 |
27 | tar: clean
28 | -debian/rules clean
29 | rm -rf $(TMPDIR)
30 | install -d $(TMPDIR)
31 | cp -p Makefile webbench.c socket.c webbench.1 $(TMPDIR)
32 | install -d $(TMPDIR)/debian
33 | -cp -p debian/* $(TMPDIR)/debian
34 | ln -sf debian/copyright $(TMPDIR)/COPYRIGHT
35 | ln -sf debian/changelog $(TMPDIR)/ChangeLog
36 | -cd $(TMPDIR) && cd .. && tar cozf webbench-$(VERSION).tar.gz webbench-$(VERSION)
37 |
38 | webbench.o: webbench.c socket.c Makefile
39 |
40 | .PHONY: clean install all tar
41 |
--------------------------------------------------------------------------------
/threadpool/tests/shutdown.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "threadpool.h"
7 |
8 | #define THREAD 4
9 | #define SIZE 8192
10 |
11 | threadpool_t *pool;
12 | int left;
13 | pthread_mutex_t lock;
14 |
15 | int error;
16 |
17 | void dummy_task(void *arg) {
18 | usleep(100);
19 | pthread_mutex_lock(&lock);
20 | left--;
21 | pthread_mutex_unlock(&lock);
22 | }
23 |
24 | int main(int argc, char **argv)
25 | {
26 | int i;
27 |
28 | pthread_mutex_init(&lock, NULL);
29 |
30 | /* Testing immediate shutdown */
31 | left = SIZE;
32 | pool = threadpool_create(THREAD, SIZE, 0);
33 | for(i = 0; i < SIZE; i++) {
34 | assert(threadpool_add(pool, &dummy_task, NULL, 0) == 0);
35 | }
36 | assert(threadpool_destroy(pool, 0) == 0);
37 | assert(left > 0);
38 |
39 | /* Testing graceful shutdown */
40 | left = SIZE;
41 | pool = threadpool_create(THREAD, SIZE, 0);
42 | for(i = 0; i < SIZE; i++) {
43 | assert(threadpool_add(pool, &dummy_task, NULL, 0) == 0);
44 | }
45 | assert(threadpool_destroy(pool, threadpool_graceful) == 0);
46 | assert(left == 0);
47 |
48 | pthread_mutex_destroy(&lock);
49 |
50 | return 0;
51 | }
52 |
--------------------------------------------------------------------------------
/leveldb/util/mutexlock.h:
--------------------------------------------------------------------------------
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_UTIL_MUTEXLOCK_H_
6 | #define STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_
7 |
8 | #include "port/port.h"
9 | #include "port/thread_annotations.h"
10 |
11 | namespace leveldb {
12 |
13 | // Helper class that locks a mutex on construction and unlocks the mutex when
14 | // the destructor of the MutexLock object is invoked.
15 | //
16 | // Typical usage:
17 | //
18 | // void MyClass::MyMethod() {
19 | // MutexLock l(&mu_); // mu_ is an instance variable
20 | // ... some complex code, possibly with multiple return paths ...
21 | // }
22 |
23 | class SCOPED_LOCKABLE MutexLock {
24 | public:
25 | explicit MutexLock(port::Mutex *mu) EXCLUSIVE_LOCK_FUNCTION(mu)
26 | : mu_(mu) {
27 | this->mu_->Lock();
28 | }
29 | ~MutexLock() UNLOCK_FUNCTION() { this->mu_->Unlock(); }
30 |
31 | private:
32 | port::Mutex *const mu_;
33 | // No copying allowed
34 | MutexLock(const MutexLock&);
35 | void operator=(const MutexLock&);
36 | };
37 |
38 | } // namespace leveldb
39 |
40 |
41 | #endif // STORAGE_LEVELDB_UTIL_MUTEXLOCK_H_
42 |
--------------------------------------------------------------------------------
/threadpool/tests/thrdtest.c:
--------------------------------------------------------------------------------
1 | #define THREAD 32
2 | #define QUEUE 256
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "threadpool.h"
10 |
11 | int tasks = 0, done = 0;
12 | pthread_mutex_t lock;
13 |
14 | void dummy_task(void *arg) {
15 | usleep(10000);
16 | pthread_mutex_lock(&lock);
17 | /* 记录成功完成的任务数 */
18 | done++;
19 | pthread_mutex_unlock(&lock);
20 | }
21 |
22 | int main(int argc, char **argv)
23 | {
24 | threadpool_t *pool;
25 |
26 | /* 初始化互斥锁 */
27 | pthread_mutex_init(&lock, NULL);
28 |
29 | /* 断言线程池创建成功 */
30 | assert((pool = threadpool_create(THREAD, QUEUE, 0)) != NULL);
31 | fprintf(stderr, "Pool started with %d threads and "
32 | "queue size of %d\n", THREAD, QUEUE);
33 |
34 | /* 只要任务队列还没满,就一直添加 */
35 | while(threadpool_add(pool, &dummy_task, NULL, 0) == 0) {
36 | pthread_mutex_lock(&lock);
37 | tasks++;
38 | pthread_mutex_unlock(&lock);
39 | }
40 |
41 | fprintf(stderr, "Added %d tasks\n", tasks);
42 |
43 | /* 不断检查任务数是否完成一半以上,没有则继续休眠 */
44 | while((tasks / 2) > done) {
45 | usleep(10000);
46 | }
47 | /* 这时候销毁线程池,0 代表 immediate_shutdown */
48 | assert(threadpool_destroy(pool, 0) == 0);
49 | fprintf(stderr, "Did %d tasks\n", done);
50 |
51 | return 0;
52 | }
53 |
--------------------------------------------------------------------------------
/leveldb/table/two_level_iterator.h:
--------------------------------------------------------------------------------
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_TABLE_TWO_LEVEL_ITERATOR_H_
6 | #define STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_
7 |
8 | #include "leveldb/iterator.h"
9 |
10 | namespace leveldb {
11 |
12 | struct ReadOptions;
13 |
14 | // Return a new two level iterator. A two-level iterator contains an
15 | // index iterator whose values point to a sequence of blocks where
16 | // each block is itself a sequence of key,value pairs. The returned
17 | // two-level iterator yields the concatenation of all key/value pairs
18 | // in the sequence of blocks. Takes ownership of "index_iter" and
19 | // will delete it when no longer needed.
20 | //
21 | // Uses a supplied function to convert an index_iter value into
22 | // an iterator over the contents of the corresponding block.
23 | extern Iterator* NewTwoLevelIterator(
24 | Iterator* index_iter,
25 | Iterator* (*block_function)(
26 | void* arg,
27 | const ReadOptions& options,
28 | const Slice& index_value),
29 | void* arg,
30 | const ReadOptions& options);
31 |
32 | } // namespace leveldb
33 |
34 | #endif // STORAGE_LEVELDB_TABLE_TWO_LEVEL_ITERATOR_H_
35 |
--------------------------------------------------------------------------------
/leveldb/db/builder.h:
--------------------------------------------------------------------------------
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_DB_BUILDER_H_
6 | #define STORAGE_LEVELDB_DB_BUILDER_H_
7 |
8 | #include "leveldb/status.h"
9 |
10 | namespace leveldb {
11 |
12 | struct Options;
13 | struct FileMetaData;
14 |
15 | class Env;
16 | class Iterator;
17 | class TableCache;
18 | class VersionEdit;
19 |
20 | // Build a Table file from the contents of *iter. The generated file
21 | // will be named according to meta->number. On success, the rest of
22 | // *meta will be filled with metadata about the generated table.
23 | // If no data is present in *iter, meta->file_size will be set to
24 | // zero, and no Table file will be produced.
25 | // 以 iter 中的数据生成一个 sstable, 函数名以 meta->number 为基准
26 | // 成功会把 sstable 的元信息填入 meta
27 | // iter 中无数据时,meta->file_size 会置为 0,不会有 sstable 文件产生
28 | extern Status BuildTable(const std::string& dbname,
29 | Env* env,
30 | const Options& options,
31 | TableCache* table_cache,
32 | Iterator* iter,
33 | FileMetaData* meta);
34 |
35 | } // namespace leveldb
36 |
37 | #endif // STORAGE_LEVELDB_DB_BUILDER_H_
38 |
--------------------------------------------------------------------------------
/leveldb/table/block.h:
--------------------------------------------------------------------------------
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_TABLE_BLOCK_H_
6 | #define STORAGE_LEVELDB_TABLE_BLOCK_H_
7 |
8 | #include
9 | #include
10 | #include "leveldb/iterator.h"
11 |
12 | namespace leveldb {
13 |
14 | struct BlockContents;
15 | class Comparator;
16 |
17 | // sstable 的数据由一个个的 block 组成。
18 | // 当持久化数据时,多份 KV 聚合成 block 一次写入;当读取时,也是以 block 单位做 IO。
19 | // sstable 的索引信息中会保存符合 key-range 的 block 在文件中的 offset/size(BlockHandle)。
20 | class Block {
21 | public:
22 | // Initialize the block with the specified contents.
23 | explicit Block(const BlockContents& contents);
24 |
25 | ~Block();
26 |
27 | size_t size() const { return size_; }
28 | Iterator* NewIterator(const Comparator* comparator);
29 |
30 | private:
31 | uint32_t NumRestarts() const;
32 |
33 | const char* data_;
34 | size_t size_;
35 | uint32_t restart_offset_; // Offset in data_ of restart array
36 | bool owned_; // Block owns data_[]
37 |
38 | // No copying allowed
39 | Block(const Block&);
40 | void operator=(const Block&);
41 |
42 | class Iter;
43 | };
44 |
45 | } // namespace leveldb
46 |
47 | #endif // STORAGE_LEVELDB_TABLE_BLOCK_H_
48 |
--------------------------------------------------------------------------------
/threadpool/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013, Mathias Brossard. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | 1. Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 |
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 |
14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
18 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/leveldb/doc/doc.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin-left: 0.5in;
3 | margin-right: 0.5in;
4 | background: white;
5 | color: black;
6 | }
7 |
8 | h1 {
9 | margin-left: -0.2in;
10 | font-size: 14pt;
11 | }
12 | h2 {
13 | margin-left: -0in;
14 | font-size: 12pt;
15 | }
16 | h3 {
17 | margin-left: -0in;
18 | }
19 | h4 {
20 | margin-left: -0in;
21 | }
22 | hr {
23 | margin-left: -0in;
24 | }
25 |
26 | /* Definition lists: definition term bold */
27 | dt {
28 | font-weight: bold;
29 | }
30 |
31 | address {
32 | text-align: center;
33 | }
34 | code,samp,var {
35 | color: blue;
36 | }
37 | kbd {
38 | color: #600000;
39 | }
40 | div.note p {
41 | float: right;
42 | width: 3in;
43 | margin-right: 0%;
44 | padding: 1px;
45 | border: 2px solid #6060a0;
46 | background-color: #fffff0;
47 | }
48 |
49 | ul {
50 | margin-top: -0em;
51 | margin-bottom: -0em;
52 | }
53 |
54 | ol {
55 | margin-top: -0em;
56 | margin-bottom: -0em;
57 | }
58 |
59 | UL.nobullets {
60 | list-style-type: none;
61 | list-style-image: none;
62 | margin-left: -1em;
63 | }
64 |
65 | p {
66 | margin: 1em 0 1em 0;
67 | padding: 0 0 0 0;
68 | }
69 |
70 | pre {
71 | line-height: 1.3em;
72 | padding: 0.4em 0 0.8em 0;
73 | margin: 0 0 0 0;
74 | border: 0 0 0 0;
75 | color: blue;
76 | }
77 |
78 | .datatable {
79 | margin-left: auto;
80 | margin-right: auto;
81 | margin-top: 2em;
82 | margin-bottom: 2em;
83 | border: 1px solid;
84 | }
85 |
86 | .datatable td,th {
87 | padding: 0 0.5em 0 0.5em;
88 | text-align: right;
89 | }
90 |
--------------------------------------------------------------------------------
/webbench/debian/rules:
--------------------------------------------------------------------------------
1 | #!/usr/bin/make -f
2 | # Sample debian/rules that uses debhelper.
3 | # GNU copyright 1997 to 1999 by Joey Hess.
4 |
5 | # Uncomment this to turn on verbose mode.
6 | #export DH_VERBOSE=1
7 |
8 | # This is the debhelper compatability version to use.
9 | export DH_COMPAT=3
10 |
11 | configure: configure-stamp
12 | configure-stamp:
13 | dh_testdir
14 | touch configure-stamp
15 |
16 | build: configure-stamp build-stamp
17 | build-stamp:
18 | dh_testdir
19 | $(MAKE)
20 | touch build-stamp
21 |
22 | clean:
23 | dh_testdir
24 | rm -f build-stamp configure-stamp
25 |
26 | # Add here commands to clean up after the build process.
27 | -$(MAKE) clean
28 |
29 | dh_clean
30 |
31 | install: build
32 | dh_testdir
33 | dh_testroot
34 | dh_clean -k
35 | dh_installdirs
36 |
37 | # Add here commands to install the package into debian/webbench.
38 | $(MAKE) install DESTDIR=$(CURDIR)/debian/webbench
39 |
40 |
41 | # Build architecture-independent files here.
42 | binary-indep: build install
43 | # We have nothing to do by default.
44 |
45 | # Build architecture-dependent files here.
46 | binary-arch: build install
47 | dh_testdir
48 | dh_testroot
49 | dh_installdocs
50 | dh_installman webbench.1
51 | dh_installchangelogs
52 | dh_link
53 | dh_strip
54 | dh_compress
55 | dh_fixperms
56 | # dh_makeshlibs
57 | dh_installdeb
58 | dh_shlibdeps
59 | dh_gencontrol
60 | dh_md5sums
61 | dh_builddeb
62 |
63 | binary: binary-indep binary-arch
64 | .PHONY: build clean binary-indep binary-arch binary install configure
65 |
--------------------------------------------------------------------------------
/leveldb/db/version_edit_test.cc:
--------------------------------------------------------------------------------
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 "db/version_edit.h"
6 | #include "util/testharness.h"
7 |
8 | namespace leveldb {
9 |
10 | static void TestEncodeDecode(const VersionEdit& edit) {
11 | std::string encoded, encoded2;
12 | edit.EncodeTo(&encoded);
13 | VersionEdit parsed;
14 | Status s = parsed.DecodeFrom(encoded);
15 | ASSERT_TRUE(s.ok()) << s.ToString();
16 | parsed.EncodeTo(&encoded2);
17 | ASSERT_EQ(encoded, encoded2);
18 | }
19 |
20 | class VersionEditTest { };
21 |
22 | TEST(VersionEditTest, EncodeDecode) {
23 | static const uint64_t kBig = 1ull << 50;
24 |
25 | VersionEdit edit;
26 | for (int i = 0; i < 4; i++) {
27 | TestEncodeDecode(edit);
28 | edit.AddFile(3, kBig + 300 + i, kBig + 400 + i,
29 | InternalKey("foo", kBig + 500 + i, kTypeValue),
30 | InternalKey("zoo", kBig + 600 + i, kTypeDeletion));
31 | edit.DeleteFile(4, kBig + 700 + i);
32 | edit.SetCompactPointer(i, InternalKey("x", kBig + 900 + i, kTypeValue));
33 | }
34 |
35 | edit.SetComparatorName("foo");
36 | edit.SetLogNumber(kBig + 100);
37 | edit.SetNextFile(kBig + 200);
38 | edit.SetLastSequence(kBig + 1000);
39 | TestEncodeDecode(edit);
40 | }
41 |
42 | } // namespace leveldb
43 |
44 | int main(int argc, char** argv) {
45 | return leveldb::test::RunAllTests();
46 | }
47 |
--------------------------------------------------------------------------------
/leveldb/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011 The LevelDB Authors. All rights reserved.
2 |
3 | Redistribution and use in source and binary forms, with or without
4 | modification, are permitted provided that the following conditions are
5 | met:
6 |
7 | * Redistributions of source code must retain the above copyright
8 | notice, this list of conditions and the following disclaimer.
9 | * Redistributions in binary form must reproduce the above
10 | copyright notice, this list of conditions and the following disclaimer
11 | in the documentation and/or other materials provided with the
12 | distribution.
13 | * Neither the name of Google Inc. nor the names of its
14 | contributors may be used to endorse or promote products derived from
15 | this software without specific prior written permission.
16 |
17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/leveldb/util/hash.cc:
--------------------------------------------------------------------------------
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
6 | #include "util/coding.h"
7 | #include "util/hash.h"
8 |
9 | // The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
10 | // between switch labels. The real definition should be provided externally.
11 | // This one is a fallback version for unsupported compilers.
12 | #ifndef FALLTHROUGH_INTENDED
13 | #define FALLTHROUGH_INTENDED do { } while (0)
14 | #endif
15 |
16 | namespace leveldb {
17 |
18 | uint32_t Hash(const char* data, size_t n, uint32_t seed) {
19 | // Similar to murmur hash
20 | const uint32_t m = 0xc6a4a793;
21 | const uint32_t r = 24;
22 | const char* limit = data + n;
23 | uint32_t h = seed ^ (n * m);
24 |
25 | // Pick up four bytes at a time
26 | while (data + 4 <= limit) {
27 | uint32_t w = DecodeFixed32(data);
28 | data += 4;
29 | h += w;
30 | h *= m;
31 | h ^= (h >> 16);
32 | }
33 |
34 | // Pick up remaining bytes
35 | switch (limit - data) {
36 | case 3:
37 | h += static_cast(data[2]) << 16;
38 | FALLTHROUGH_INTENDED;
39 | case 2:
40 | h += static_cast(data[1]) << 8;
41 | FALLTHROUGH_INTENDED;
42 | case 1:
43 | h += static_cast(data[0]);
44 | h *= m;
45 | h ^= (h >> r);
46 | break;
47 | }
48 | return h;
49 | }
50 |
51 |
52 | } // namespace leveldb
53 |
--------------------------------------------------------------------------------
/leveldb/util/logging.h:
--------------------------------------------------------------------------------
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 | // Must not be included from any .h files to avoid polluting the namespace
6 | // with macros.
7 |
8 | #ifndef STORAGE_LEVELDB_UTIL_LOGGING_H_
9 | #define STORAGE_LEVELDB_UTIL_LOGGING_H_
10 |
11 | #include
12 | #include
13 | #include
14 | #include "port/port.h"
15 |
16 | namespace leveldb {
17 |
18 | class Slice;
19 | class WritableFile;
20 |
21 | // Append a human-readable printout of "num" to *str
22 | extern void AppendNumberTo(std::string* str, uint64_t num);
23 |
24 | // Append a human-readable printout of "value" to *str.
25 | // Escapes any non-printable characters found in "value".
26 | extern void AppendEscapedStringTo(std::string* str, const Slice& value);
27 |
28 | // Return a human-readable printout of "num"
29 | extern std::string NumberToString(uint64_t num);
30 |
31 | // Return a human-readable version of "value".
32 | // Escapes any non-printable characters found in "value".
33 | extern std::string EscapeString(const Slice& value);
34 |
35 | // Parse a human-readable number from "*in" into *value. On success,
36 | // advances "*in" past the consumed number and sets "*val" to the
37 | // numeric value. Otherwise, returns false and leaves *in in an
38 | // unspecified state.
39 | extern bool ConsumeDecimalNumber(Slice* in, uint64_t* val);
40 |
41 | } // namespace leveldb
42 |
43 | #endif // STORAGE_LEVELDB_UTIL_LOGGING_H_
44 |
--------------------------------------------------------------------------------
/leveldb/port/thread_annotations.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 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_THREAD_ANNOTATIONS_H_
6 | #define STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_
7 |
8 | // Some environments provide custom macros to aid in static thread-safety
9 | // analysis. Provide empty definitions of such macros unless they are already
10 | // defined.
11 |
12 | #ifndef EXCLUSIVE_LOCKS_REQUIRED
13 | #define EXCLUSIVE_LOCKS_REQUIRED(...)
14 | #endif
15 |
16 | #ifndef SHARED_LOCKS_REQUIRED
17 | #define SHARED_LOCKS_REQUIRED(...)
18 | #endif
19 |
20 | #ifndef LOCKS_EXCLUDED
21 | #define LOCKS_EXCLUDED(...)
22 | #endif
23 |
24 | #ifndef LOCK_RETURNED
25 | #define LOCK_RETURNED(x)
26 | #endif
27 |
28 | #ifndef LOCKABLE
29 | #define LOCKABLE
30 | #endif
31 |
32 | #ifndef SCOPED_LOCKABLE
33 | #define SCOPED_LOCKABLE
34 | #endif
35 |
36 | #ifndef EXCLUSIVE_LOCK_FUNCTION
37 | #define EXCLUSIVE_LOCK_FUNCTION(...)
38 | #endif
39 |
40 | #ifndef SHARED_LOCK_FUNCTION
41 | #define SHARED_LOCK_FUNCTION(...)
42 | #endif
43 |
44 | #ifndef EXCLUSIVE_TRYLOCK_FUNCTION
45 | #define EXCLUSIVE_TRYLOCK_FUNCTION(...)
46 | #endif
47 |
48 | #ifndef SHARED_TRYLOCK_FUNCTION
49 | #define SHARED_TRYLOCK_FUNCTION(...)
50 | #endif
51 |
52 | #ifndef UNLOCK_FUNCTION
53 | #define UNLOCK_FUNCTION(...)
54 | #endif
55 |
56 | #ifndef NO_THREAD_SAFETY_ANALYSIS
57 | #define NO_THREAD_SAFETY_ANALYSIS
58 | #endif
59 |
60 | #endif // STORAGE_LEVELDB_PORT_THREAD_ANNOTATIONS_H_
61 |
--------------------------------------------------------------------------------
/leveldb/port/port_posix.cc:
--------------------------------------------------------------------------------
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_posix.h"
6 |
7 | #include
8 | #include
9 | #include
10 |
11 | namespace leveldb {
12 | namespace port {
13 |
14 | static void PthreadCall(const char* label, int result) {
15 | if (result != 0) {
16 | fprintf(stderr, "pthread %s: %s\n", label, strerror(result));
17 | abort();
18 | }
19 | }
20 |
21 | Mutex::Mutex() { PthreadCall("init mutex", pthread_mutex_init(&mu_, NULL)); }
22 |
23 | Mutex::~Mutex() { PthreadCall("destroy mutex", pthread_mutex_destroy(&mu_)); }
24 |
25 | void Mutex::Lock() { PthreadCall("lock", pthread_mutex_lock(&mu_)); }
26 |
27 | void Mutex::Unlock() { PthreadCall("unlock", pthread_mutex_unlock(&mu_)); }
28 |
29 | CondVar::CondVar(Mutex* mu)
30 | : mu_(mu) {
31 | PthreadCall("init cv", pthread_cond_init(&cv_, NULL));
32 | }
33 |
34 | CondVar::~CondVar() { PthreadCall("destroy cv", pthread_cond_destroy(&cv_)); }
35 |
36 | void CondVar::Wait() {
37 | PthreadCall("wait", pthread_cond_wait(&cv_, &mu_->mu_));
38 | }
39 |
40 | void CondVar::Signal() {
41 | PthreadCall("signal", pthread_cond_signal(&cv_));
42 | }
43 |
44 | void CondVar::SignalAll() {
45 | PthreadCall("broadcast", pthread_cond_broadcast(&cv_));
46 | }
47 |
48 | void InitOnce(OnceType* once, void (*initializer)()) {
49 | PthreadCall("once", pthread_once(once, initializer));
50 | }
51 |
52 | } // namespace port
53 | } // namespace leveldb
54 |
--------------------------------------------------------------------------------
/leveldb/util/crc32c.h:
--------------------------------------------------------------------------------
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_UTIL_CRC32C_H_
6 | #define STORAGE_LEVELDB_UTIL_CRC32C_H_
7 |
8 | #include
9 | #include
10 |
11 | namespace leveldb {
12 | namespace crc32c {
13 |
14 | // Return the crc32c of concat(A, data[0,n-1]) where init_crc is the
15 | // crc32c of some string A. Extend() is often used to maintain the
16 | // crc32c of a stream of data.
17 | extern uint32_t Extend(uint32_t init_crc, const char* data, size_t n);
18 |
19 | // Return the crc32c of data[0,n-1]
20 | inline uint32_t Value(const char* data, size_t n) {
21 | return Extend(0, data, n);
22 | }
23 |
24 | static const uint32_t kMaskDelta = 0xa282ead8ul;
25 |
26 | // Return a masked representation of crc.
27 | //
28 | // Motivation: it is problematic to compute the CRC of a string that
29 | // contains embedded CRCs. Therefore we recommend that CRCs stored
30 | // somewhere (e.g., in files) should be masked before being stored.
31 | inline uint32_t Mask(uint32_t crc) {
32 | // Rotate right by 15 bits and add a constant.
33 | return ((crc >> 15) | (crc << 17)) + kMaskDelta;
34 | }
35 |
36 | // Return the crc whose masked representation is masked_crc.
37 | inline uint32_t Unmask(uint32_t masked_crc) {
38 | uint32_t rot = masked_crc - kMaskDelta;
39 | return ((rot >> 17) | (rot << 15));
40 | }
41 |
42 | } // namespace crc32c
43 | } // namespace leveldb
44 |
45 | #endif // STORAGE_LEVELDB_UTIL_CRC32C_H_
46 |
--------------------------------------------------------------------------------
/leveldb/util/testutil.cc:
--------------------------------------------------------------------------------
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 "util/testutil.h"
6 |
7 | #include "util/random.h"
8 |
9 | namespace leveldb {
10 | namespace test {
11 |
12 | Slice RandomString(Random* rnd, int len, std::string* dst) {
13 | dst->resize(len);
14 | for (int i = 0; i < len; i++) {
15 | (*dst)[i] = static_cast(' ' + rnd->Uniform(95)); // ' ' .. '~'
16 | }
17 | return Slice(*dst);
18 | }
19 |
20 | std::string RandomKey(Random* rnd, int len) {
21 | // Make sure to generate a wide variety of characters so we
22 | // test the boundary conditions for short-key optimizations.
23 | static const char kTestChars[] = {
24 | '\0', '\1', 'a', 'b', 'c', 'd', 'e', '\xfd', '\xfe', '\xff'
25 | };
26 | std::string result;
27 | for (int i = 0; i < len; i++) {
28 | result += kTestChars[rnd->Uniform(sizeof(kTestChars))];
29 | }
30 | return result;
31 | }
32 |
33 |
34 | extern Slice CompressibleString(Random* rnd, double compressed_fraction,
35 | size_t len, std::string* dst) {
36 | int raw = static_cast(len * compressed_fraction);
37 | if (raw < 1) raw = 1;
38 | std::string raw_data;
39 | RandomString(rnd, raw, &raw_data);
40 |
41 | // Duplicate the random data until we have filled "len" bytes
42 | dst->clear();
43 | while (dst->size() < len) {
44 | dst->append(raw_data);
45 | }
46 | dst->resize(len);
47 | return Slice(*dst);
48 | }
49 |
50 | } // namespace test
51 | } // namespace leveldb
52 |
--------------------------------------------------------------------------------
/leveldb/db/write_batch_internal.h:
--------------------------------------------------------------------------------
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_DB_WRITE_BATCH_INTERNAL_H_
6 | #define STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_
7 |
8 | #include "db/dbformat.h"
9 | #include "leveldb/write_batch.h"
10 |
11 | namespace leveldb {
12 |
13 | class MemTable;
14 |
15 | // WriteBatchInternal provides static methods for manipulating a
16 | // WriteBatch that we don't want in the public WriteBatch interface.
17 | class WriteBatchInternal {
18 | public:
19 | // Return the number of entries in the batch.
20 | static int Count(const WriteBatch* batch);
21 |
22 | // Set the count for the number of entries in the batch.
23 | static void SetCount(WriteBatch* batch, int n);
24 |
25 | // Return the sequence number for the start of this batch.
26 | static SequenceNumber Sequence(const WriteBatch* batch);
27 |
28 | // Store the specified number as the sequence number for the start of
29 | // this batch.
30 | static void SetSequence(WriteBatch* batch, SequenceNumber seq);
31 |
32 | static Slice Contents(const WriteBatch* batch) {
33 | return Slice(batch->rep_);
34 | }
35 |
36 | static size_t ByteSize(const WriteBatch* batch) {
37 | return batch->rep_.size();
38 | }
39 |
40 | static void SetContents(WriteBatch* batch, const Slice& contents);
41 |
42 | static Status InsertInto(const WriteBatch* batch, MemTable* memtable);
43 |
44 | static void Append(WriteBatch* dst, const WriteBatch* src);
45 | };
46 |
47 | } // namespace leveldb
48 |
49 |
50 | #endif // STORAGE_LEVELDB_DB_WRITE_BATCH_INTERNAL_H_
51 |
--------------------------------------------------------------------------------
/threadpool/tests/heavy.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #include "threadpool.h"
7 |
8 | #define THREAD 4
9 | #define SIZE 8192
10 | #define QUEUES 64
11 |
12 | /*
13 | * Warning do not increase THREAD and QUEUES too much on 32-bit
14 | * platforms: because of each thread (and there will be THREAD *
15 | * QUEUES of them) will allocate its own stack (8 MB is the default on
16 | * Linux), you'll quickly run out of virtual space.
17 | */
18 |
19 | threadpool_t *pool[QUEUES];
20 | int tasks[SIZE], left;
21 | pthread_mutex_t lock;
22 |
23 | int error;
24 |
25 | void dummy_task(void *arg) {
26 | int *pi = (int *)arg;
27 | *pi += 1;
28 |
29 | if(*pi < QUEUES) {
30 | assert(threadpool_add(pool[*pi], &dummy_task, arg, 0) == 0);
31 | } else {
32 | pthread_mutex_lock(&lock);
33 | left--;
34 | pthread_mutex_unlock(&lock);
35 | }
36 | }
37 |
38 | int main(int argc, char **argv)
39 | {
40 | int i, copy = 1;
41 |
42 | left = SIZE;
43 | pthread_mutex_init(&lock, NULL);
44 |
45 | for(i = 0; i < QUEUES; i++) {
46 | pool[i] = threadpool_create(THREAD, SIZE, 0);
47 | assert(pool[i] != NULL);
48 | }
49 |
50 | usleep(10);
51 |
52 | for(i = 0; i < SIZE; i++) {
53 | tasks[i] = 0;
54 | assert(threadpool_add(pool[0], &dummy_task, &(tasks[i]), 0) == 0);
55 | }
56 |
57 | while(copy > 0) {
58 | usleep(10);
59 | pthread_mutex_lock(&lock);
60 | copy = left;
61 | pthread_mutex_unlock(&lock);
62 | }
63 |
64 | for(i = 0; i < QUEUES; i++) {
65 | assert(threadpool_destroy(pool[i], 0) == 0);
66 | }
67 |
68 | pthread_mutex_destroy(&lock);
69 |
70 | return 0;
71 | }
72 |
--------------------------------------------------------------------------------
/leveldb/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | We'd love to accept your code patches! However, before we can take them, we
4 | have to jump a couple of legal hurdles.
5 |
6 | ## Contributor License Agreements
7 |
8 | Please fill out either the individual or corporate Contributor License
9 | Agreement as appropriate.
10 |
11 | * If you are an individual writing original source code and you're sure you
12 | own the intellectual property, then sign an [individual CLA](https://developers.google.com/open-source/cla/individual).
13 | * If you work for a company that wants to allow you to contribute your work,
14 | then sign a [corporate CLA](https://developers.google.com/open-source/cla/corporate).
15 |
16 | Follow either of the two links above to access the appropriate CLA and
17 | instructions for how to sign and return it.
18 |
19 | ## Submitting a Patch
20 |
21 | 1. Sign the contributors license agreement above.
22 | 2. Decide which code you want to submit. A submission should be a set of changes
23 | that addresses one issue in the [issue tracker](https://github.com/google/leveldb/issues).
24 | Please don't mix more than one logical change per submission, because it makes
25 | the history hard to follow. If you want to make a change
26 | (e.g. add a sample or feature) that doesn't have a corresponding issue in the
27 | issue tracker, please create one.
28 | 3. **Submitting**: When you are ready to submit, send us a Pull Request. Be
29 | sure to include the issue number you fixed and the name you used to sign
30 | the CLA.
31 |
32 | ## Writing Code ##
33 |
34 | If your contribution contains code, please make sure that it follows
35 | [the style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml).
36 | Otherwise we will have to ask you to make changes, and that's no fun for anyone.
37 |
--------------------------------------------------------------------------------
/leveldb/db/leveldb_main.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 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
6 | #include "leveldb/dumpfile.h"
7 | #include "leveldb/env.h"
8 | #include "leveldb/status.h"
9 |
10 | namespace leveldb {
11 | namespace {
12 |
13 | class StdoutPrinter : public WritableFile {
14 | public:
15 | virtual Status Append(const Slice& data) {
16 | fwrite(data.data(), 1, data.size(), stdout);
17 | return Status::OK();
18 | }
19 | virtual Status Close() { return Status::OK(); }
20 | virtual Status Flush() { return Status::OK(); }
21 | virtual Status Sync() { return Status::OK(); }
22 | };
23 |
24 | bool HandleDumpCommand(Env* env, char** files, int num) {
25 | StdoutPrinter printer;
26 | bool ok = true;
27 | for (int i = 0; i < num; i++) {
28 | Status s = DumpFile(env, files[i], &printer);
29 | if (!s.ok()) {
30 | fprintf(stderr, "%s\n", s.ToString().c_str());
31 | ok = false;
32 | }
33 | }
34 | return ok;
35 | }
36 |
37 | } // namespace
38 | } // namespace leveldb
39 |
40 | static void Usage() {
41 | fprintf(
42 | stderr,
43 | "Usage: leveldbutil command...\n"
44 | " dump files... -- dump contents of specified files\n"
45 | );
46 | }
47 |
48 | int main(int argc, char** argv) {
49 | leveldb::Env* env = leveldb::Env::Default();
50 | bool ok = true;
51 | if (argc < 2) {
52 | Usage();
53 | ok = false;
54 | } else {
55 | std::string command = argv[1];
56 | if (command == "dump") {
57 | ok = leveldb::HandleDumpCommand(env, argv+2, argc-2);
58 | } else {
59 | Usage();
60 | ok = false;
61 | }
62 | }
63 | return (ok ? 0 : 1);
64 | }
65 |
--------------------------------------------------------------------------------
/webbench/socket.c:
--------------------------------------------------------------------------------
1 | /* $Id: socket.c 1.1 1995/01/01 07:11:14 cthuang Exp $
2 | *
3 | * This module has been modified by Radim Kolar for OS/2 emx
4 | */
5 |
6 | /***********************************************************************
7 | module: socket.c
8 | program: popclient
9 | SCCS ID: @(#)socket.c 1.5 4/1/94
10 | programmer: Virginia Tech Computing Center
11 | compiler: DEC RISC C compiler (Ultrix 4.1)
12 | environment: DEC Ultrix 4.3
13 | description: UNIX sockets code.
14 | ***********************************************************************/
15 |
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | int Socket(const char *host, int clientPort)
30 | {
31 | int sock;
32 | unsigned long inaddr;
33 | struct sockaddr_in ad;
34 | struct hostent *hp;
35 |
36 | /* 初始化地址 */
37 | memset(&ad, 0, sizeof(ad));
38 | ad.sin_family = AF_INET;
39 |
40 | /* 尝试把主机名转化为数字 */
41 | inaddr = inet_addr(host);
42 | if (inaddr != INADDR_NONE)
43 | memcpy(&ad.sin_addr, &inaddr, sizeof(inaddr));
44 | else
45 | {
46 | /* 取得 ip 地址 */
47 | hp = gethostbyname(host);
48 | if (hp == NULL)
49 | return -1;
50 | memcpy(&ad.sin_addr, hp->h_addr, hp->h_length);
51 | }
52 | ad.sin_port = htons(clientPort);
53 |
54 | /* 建立 socket */
55 | sock = socket(AF_INET, SOCK_STREAM, 0);
56 | if (sock < 0)
57 | return sock;
58 | /* 建立链接 */
59 | if (connect(sock, (struct sockaddr *)&ad, sizeof(ad)) < 0)
60 | return -1;
61 | return sock;
62 | }
63 |
64 |
--------------------------------------------------------------------------------
/leveldb/db/log_writer.h:
--------------------------------------------------------------------------------
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_DB_LOG_WRITER_H_
6 | #define STORAGE_LEVELDB_DB_LOG_WRITER_H_
7 |
8 | #include
9 | #include "db/log_format.h"
10 | #include "leveldb/slice.h"
11 | #include "leveldb/status.h"
12 |
13 | namespace leveldb {
14 |
15 | class WritableFile;
16 |
17 | namespace log {
18 |
19 | // 每条 record 都会立刻往文件写,顺序写
20 | class Writer {
21 | public:
22 | // Create a writer that will append data to "*dest".
23 | // "*dest" must be initially empty.
24 | // "*dest" must remain live while this Writer is in use.
25 | explicit Writer(WritableFile* dest);
26 |
27 | // Create a writer that will append data to "*dest".
28 | // "*dest" must have initial length "dest_length".
29 | // "*dest" must remain live while this Writer is in use.
30 | // 文件必须有 dest_length 的初始长度
31 | Writer(WritableFile* dest, uint64_t dest_length);
32 |
33 | ~Writer();
34 |
35 | Status AddRecord(const Slice& slice);
36 |
37 | private:
38 | // 可写文件
39 | WritableFile* dest_;
40 | // 当前 block 偏移量
41 | int block_offset_; // Current offset in block
42 |
43 | // crc32c values for all supported record types. These are
44 | // pre-computed to reduce the overhead of computing the crc of the
45 | // record type stored in the header.
46 | //
47 | uint32_t type_crc_[kMaxRecordType + 1];
48 |
49 | Status EmitPhysicalRecord(RecordType type, const char* ptr, size_t length);
50 |
51 | // No copying allowed
52 | Writer(const Writer&);
53 | void operator=(const Writer&);
54 | };
55 |
56 | } // namespace log
57 | } // namespace leveldb
58 |
59 | #endif // STORAGE_LEVELDB_DB_LOG_WRITER_H_
60 |
--------------------------------------------------------------------------------
/leveldb/util/hash_test.cc:
--------------------------------------------------------------------------------
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 "util/hash.h"
6 | #include "util/testharness.h"
7 |
8 | namespace leveldb {
9 |
10 | class HASH { };
11 |
12 | TEST(HASH, SignedUnsignedIssue) {
13 | const unsigned char data1[1] = {0x62};
14 | const unsigned char data2[2] = {0xc3, 0x97};
15 | const unsigned char data3[3] = {0xe2, 0x99, 0xa5};
16 | const unsigned char data4[4] = {0xe1, 0x80, 0xb9, 0x32};
17 | const unsigned char data5[48] = {
18 | 0x01, 0xc0, 0x00, 0x00,
19 | 0x00, 0x00, 0x00, 0x00,
20 | 0x00, 0x00, 0x00, 0x00,
21 | 0x00, 0x00, 0x00, 0x00,
22 | 0x14, 0x00, 0x00, 0x00,
23 | 0x00, 0x00, 0x04, 0x00,
24 | 0x00, 0x00, 0x00, 0x14,
25 | 0x00, 0x00, 0x00, 0x18,
26 | 0x28, 0x00, 0x00, 0x00,
27 | 0x00, 0x00, 0x00, 0x00,
28 | 0x02, 0x00, 0x00, 0x00,
29 | 0x00, 0x00, 0x00, 0x00,
30 | };
31 |
32 | ASSERT_EQ(Hash(0, 0, 0xbc9f1d34), 0xbc9f1d34);
33 | ASSERT_EQ(
34 | Hash(reinterpret_cast(data1), sizeof(data1), 0xbc9f1d34),
35 | 0xef1345c4);
36 | ASSERT_EQ(
37 | Hash(reinterpret_cast(data2), sizeof(data2), 0xbc9f1d34),
38 | 0x5b663814);
39 | ASSERT_EQ(
40 | Hash(reinterpret_cast(data3), sizeof(data3), 0xbc9f1d34),
41 | 0x323c078f);
42 | ASSERT_EQ(
43 | Hash(reinterpret_cast(data4), sizeof(data4), 0xbc9f1d34),
44 | 0xed21633a);
45 | ASSERT_EQ(
46 | Hash(reinterpret_cast(data5), sizeof(data5), 0x12345678),
47 | 0xf333dabb);
48 | }
49 |
50 | } // namespace leveldb
51 |
52 | int main(int argc, char** argv) {
53 | return leveldb::test::RunAllTests();
54 | }
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Code With Comments
2 | =========
3 |
4 | ### Tinyhttpd
5 | 介绍:tinyhttpd 是一个不到 500 行的超轻量型 Http Server,非常适合学习服务器工作原理
6 |
7 | 源码分析:[在此](https://github.com/AngryHacker/articles/blob/master/src/code_reading/tinyhttpd.md)
8 |
9 | 链接:[tinyhttpd](https://github.com/AngryHacker/code-with-comments/tree/master/tinyhttpd)
10 |
11 | ### MemoryPool
12 | 介绍:一个用 C++ 实现的简单内存池
13 |
14 | 源码分析:[在此](http://blog.csdn.net/jcjc918/article/details/44997089)
15 |
16 | 链接:[MemoryPool(98 版本)](https://github.com/AngryHacker/code-with-comments/tree/master/memorypool/C-98)
17 |
18 | ### Webbench
19 | 介绍:Webbench是一个在linux下使用的非常简单的网站压测工具。它使用fork()模拟多个客户端同时访问我们设定的URL,
20 | 测试网站在压力下工作的性能,最多可以模拟3万个并发连接去测试网站的负载能力。
21 |
22 | 源码分析:[在此](http://blog.csdn.net/jcjc918/article/details/44965951)
23 |
24 | 链接:[webbench](https://github.com/AngryHacker/code-with-comments/tree/master/webbench)
25 |
26 | ### Threadpool
27 | 介绍:基于 pthread 实现的简单线程池
28 |
29 | 源码分析:[在此](https://github.com/AngryHacker/articles/blob/master/src/code_reading/threadpool.md)
30 |
31 | 链接:[Threadpool](https://github.com/AngryHacker/code-with-comments/tree/master/threadpool)
32 |
33 | ### Leveldb
34 | 介绍:Jeff Dean 和 Sanjay Ghemawat 两位超级大神实现的高效 kv 数据库。
35 |
36 | 源码分析:
37 |
38 | * [LevelDb 日知录](http://www.cnblogs.com/haippy/archive/2011/12/04/2276064.html)
39 | * [leveldb 实现解析 - 那岩](https://github.com/AngryHacker/code-with-comments/blob/master/attachment/leveldb%E5%AE%9E%E7%8E%B0%E8%A7%A3%E6%9E%90.pdf)
40 |
41 | 以上是我觉得分析得最好的两篇。不过随着 leveldb 项目的推进,有些代码也发生了变动。我进行注释的源码是最新的 1.18 版本,结合两篇解析写自己的理解,目前已阅读的是主要流程,水平有限,有些地方也不甚清楚,欢迎交流。
42 |
43 | 链接:[Leveldb](https://github.com/AngryHacker/code-with-comments/tree/master/leveldb)
44 |
45 |
46 |
47 |
48 | 有帮助?给我个小红包吧
49 |
--------------------------------------------------------------------------------
/webbench/debian/changelog:
--------------------------------------------------------------------------------
1 | webbench (1.5) unstable; urgency=low
2 |
3 | * allow building with both Gnu and BSD make
4 |
5 | -- Radim Kolar Fri, Jun 25 12:00:20 CEST 2004
6 |
7 | webbench (1.4) unstable; urgency=low
8 |
9 | * check if url is not too long
10 | * report correct program version number
11 | * use yield() when waiting for test start
12 | * corrected error codes
13 | * check availability of test server first
14 | * do not abort test if first request failed
15 | * report when some childrens are dead.
16 | * use alarm, not time() for lower syscal use by bench
17 | * use mode 644 for installed doc
18 | * makefile cleaned for better freebsd ports integration
19 |
20 | -- Radim Kolar Thu, 15 Jan 2004 11:15:52 +0100
21 |
22 | webbench (1.3) unstable; urgency=low
23 |
24 | * Build fixes for freeBSD
25 | * Default benchmark time 60 -> 30
26 | * generate tar with subdirectory
27 | * added to freeBSD ports collection
28 |
29 | -- Radim Kolar Mon, 12 Jan 2004 17:00:24 +0100
30 |
31 | webbench (1.2) unstable; urgency=low
32 |
33 | * Only debian-related bugfixes
34 | * Updated Debian/rules
35 | * Adapted to fit new directory system
36 | * moved from debstd to dh_*
37 |
38 | -- Radim Kolar Fri, 18 Jan 2002 12:33:04 +0100
39 |
40 | webbench (1.1) unstable; urgency=medium
41 |
42 | * Program debianized
43 | * added support for multiple methods (GET, HEAD, OPTIONS, TRACE)
44 | * added support for multiple HTTP versions (0.9 -- 1.1)
45 | * added long options
46 | * added multiple clients
47 | * wait for start of second before test
48 | * test time can be specified
49 | * better error checking when reading reply from server
50 | * FIX: tests was one second longer than expected
51 |
52 | -- Radim Kolar Thu, 16 Sep 1999 18:48:00 +0200
53 |
54 | Local variables:
55 | mode: debian-changelog
56 | End:
57 |
--------------------------------------------------------------------------------
/leveldb/issues/issue200_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 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 | // Test for issue 200: when iterator switches direction from backward
6 | // to forward, the current key can be yielded unexpectedly if a new
7 | // mutation has been added just before the current key.
8 |
9 | #include "leveldb/db.h"
10 | #include "util/testharness.h"
11 |
12 | namespace leveldb {
13 |
14 | class Issue200 { };
15 |
16 | TEST(Issue200, Test) {
17 | // Get rid of any state from an old run.
18 | std::string dbpath = test::TmpDir() + "/leveldb_issue200_test";
19 | DestroyDB(dbpath, Options());
20 |
21 | DB *db;
22 | Options options;
23 | options.create_if_missing = true;
24 | ASSERT_OK(DB::Open(options, dbpath, &db));
25 |
26 | WriteOptions write_options;
27 | ASSERT_OK(db->Put(write_options, "1", "b"));
28 | ASSERT_OK(db->Put(write_options, "2", "c"));
29 | ASSERT_OK(db->Put(write_options, "3", "d"));
30 | ASSERT_OK(db->Put(write_options, "4", "e"));
31 | ASSERT_OK(db->Put(write_options, "5", "f"));
32 |
33 | ReadOptions read_options;
34 | Iterator *iter = db->NewIterator(read_options);
35 |
36 | // Add an element that should not be reflected in the iterator.
37 | ASSERT_OK(db->Put(write_options, "25", "cd"));
38 |
39 | iter->Seek("5");
40 | ASSERT_EQ(iter->key().ToString(), "5");
41 | iter->Prev();
42 | ASSERT_EQ(iter->key().ToString(), "4");
43 | iter->Prev();
44 | ASSERT_EQ(iter->key().ToString(), "3");
45 | iter->Next();
46 | ASSERT_EQ(iter->key().ToString(), "4");
47 | iter->Next();
48 | ASSERT_EQ(iter->key().ToString(), "5");
49 |
50 | delete iter;
51 | delete db;
52 | DestroyDB(dbpath, options);
53 | }
54 |
55 | } // namespace leveldb
56 |
57 | int main(int argc, char** argv) {
58 | return leveldb::test::RunAllTests();
59 | }
60 |
--------------------------------------------------------------------------------
/leveldb/util/arena_test.cc:
--------------------------------------------------------------------------------
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 "util/arena.h"
6 |
7 | #include "util/random.h"
8 | #include "util/testharness.h"
9 |
10 | namespace leveldb {
11 |
12 | class ArenaTest { };
13 |
14 | TEST(ArenaTest, Empty) {
15 | Arena arena;
16 | }
17 |
18 | TEST(ArenaTest, Simple) {
19 | std::vector > allocated;
20 | Arena arena;
21 | const int N = 100000;
22 | size_t bytes = 0;
23 | Random rnd(301);
24 | for (int i = 0; i < N; i++) {
25 | size_t s;
26 | if (i % (N / 10) == 0) {
27 | s = i;
28 | } else {
29 | s = rnd.OneIn(4000) ? rnd.Uniform(6000) :
30 | (rnd.OneIn(10) ? rnd.Uniform(100) : rnd.Uniform(20));
31 | }
32 | if (s == 0) {
33 | // Our arena disallows size 0 allocations.
34 | s = 1;
35 | }
36 | char* r;
37 | if (rnd.OneIn(10)) {
38 | r = arena.AllocateAligned(s);
39 | } else {
40 | r = arena.Allocate(s);
41 | }
42 |
43 | for (size_t b = 0; b < s; b++) {
44 | // Fill the "i"th allocation with a known bit pattern
45 | r[b] = i % 256;
46 | }
47 | bytes += s;
48 | allocated.push_back(std::make_pair(s, r));
49 | ASSERT_GE(arena.MemoryUsage(), bytes);
50 | if (i > N/10) {
51 | ASSERT_LE(arena.MemoryUsage(), bytes * 1.10);
52 | }
53 | }
54 | for (size_t i = 0; i < allocated.size(); i++) {
55 | size_t num_bytes = allocated[i].first;
56 | const char* p = allocated[i].second;
57 | for (size_t b = 0; b < num_bytes; b++) {
58 | // Check the "i"th allocation for the known bit pattern
59 | ASSERT_EQ(int(p[b]) & 0xff, i % 256);
60 | }
61 | }
62 | }
63 |
64 | } // namespace leveldb
65 |
66 | int main(int argc, char** argv) {
67 | return leveldb::test::RunAllTests();
68 | }
69 |
--------------------------------------------------------------------------------
/leveldb/table/iterator.cc:
--------------------------------------------------------------------------------
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 "leveldb/iterator.h"
6 |
7 | namespace leveldb {
8 |
9 | Iterator::Iterator() {
10 | cleanup_.function = NULL;
11 | cleanup_.next = NULL;
12 | }
13 |
14 | Iterator::~Iterator() {
15 | if (cleanup_.function != NULL) {
16 | (*cleanup_.function)(cleanup_.arg1, cleanup_.arg2);
17 | for (Cleanup* c = cleanup_.next; c != NULL; ) {
18 | (*c->function)(c->arg1, c->arg2);
19 | Cleanup* next = c->next;
20 | delete c;
21 | c = next;
22 | }
23 | }
24 | }
25 |
26 | void Iterator::RegisterCleanup(CleanupFunction func, void* arg1, void* arg2) {
27 | assert(func != NULL);
28 | Cleanup* c;
29 | if (cleanup_.function == NULL) {
30 | c = &cleanup_;
31 | } else {
32 | c = new Cleanup;
33 | c->next = cleanup_.next;
34 | cleanup_.next = c;
35 | }
36 | c->function = func;
37 | c->arg1 = arg1;
38 | c->arg2 = arg2;
39 | }
40 |
41 | namespace {
42 | class EmptyIterator : public Iterator {
43 | public:
44 | EmptyIterator(const Status& s) : status_(s) { }
45 | virtual bool Valid() const { return false; }
46 | virtual void Seek(const Slice& target) { }
47 | virtual void SeekToFirst() { }
48 | virtual void SeekToLast() { }
49 | virtual void Next() { assert(false); }
50 | virtual void Prev() { assert(false); }
51 | Slice key() const { assert(false); return Slice(); }
52 | Slice value() const { assert(false); return Slice(); }
53 | virtual Status status() const { return status_; }
54 | private:
55 | Status status_;
56 | };
57 | } // namespace
58 |
59 | Iterator* NewEmptyIterator() {
60 | return new EmptyIterator(Status::OK());
61 | }
62 |
63 | Iterator* NewErrorIterator(const Status& status) {
64 | return new EmptyIterator(status);
65 | }
66 |
67 | } // namespace leveldb
68 |
--------------------------------------------------------------------------------
/leveldb/db/snapshot.h:
--------------------------------------------------------------------------------
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_DB_SNAPSHOT_H_
6 | #define STORAGE_LEVELDB_DB_SNAPSHOT_H_
7 |
8 | #include "db/dbformat.h"
9 | #include "leveldb/db.h"
10 |
11 | namespace leveldb {
12 |
13 | class SnapshotList;
14 |
15 | // Snapshots are kept in a doubly-linked list in the DB.
16 | // Each SnapshotImpl corresponds to a particular sequence number.
17 | class SnapshotImpl : public Snapshot {
18 | public:
19 | SequenceNumber number_; // const after creation
20 |
21 | private:
22 | friend class SnapshotList;
23 |
24 | // SnapshotImpl is kept in a doubly-linked circular list
25 | SnapshotImpl* prev_;
26 | SnapshotImpl* next_;
27 |
28 | SnapshotList* list_; // just for sanity checks
29 | };
30 |
31 | class SnapshotList {
32 | public:
33 | SnapshotList() {
34 | list_.prev_ = &list_;
35 | list_.next_ = &list_;
36 | }
37 |
38 | bool empty() const { return list_.next_ == &list_; }
39 | SnapshotImpl* oldest() const { assert(!empty()); return list_.next_; }
40 | SnapshotImpl* newest() const { assert(!empty()); return list_.prev_; }
41 |
42 | // 新节点插入到链表尾
43 | const SnapshotImpl* New(SequenceNumber seq) {
44 | SnapshotImpl* s = new SnapshotImpl;
45 | s->number_ = seq;
46 | s->list_ = this;
47 | s->next_ = &list_;
48 | s->prev_ = list_.prev_;
49 | s->prev_->next_ = s;
50 | s->next_->prev_ = s;
51 | return s;
52 | }
53 |
54 | // 删除节点
55 | void Delete(const SnapshotImpl* s) {
56 | assert(s->list_ == this);
57 | s->prev_->next_ = s->next_;
58 | s->next_->prev_ = s->prev_;
59 | delete s;
60 | }
61 |
62 | private:
63 | // Dummy head of doubly-linked list of snapshots
64 | SnapshotImpl list_;
65 | };
66 |
67 | } // namespace leveldb
68 |
69 | #endif // STORAGE_LEVELDB_DB_SNAPSHOT_H_
70 |
--------------------------------------------------------------------------------
/leveldb/util/testharness.cc:
--------------------------------------------------------------------------------
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 "util/testharness.h"
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | namespace leveldb {
13 | namespace test {
14 |
15 | namespace {
16 | struct Test {
17 | const char* base;
18 | const char* name;
19 | void (*func)();
20 | };
21 | std::vector* tests;
22 | }
23 |
24 | bool RegisterTest(const char* base, const char* name, void (*func)()) {
25 | if (tests == NULL) {
26 | tests = new std::vector;
27 | }
28 | Test t;
29 | t.base = base;
30 | t.name = name;
31 | t.func = func;
32 | tests->push_back(t);
33 | return true;
34 | }
35 |
36 | int RunAllTests() {
37 | const char* matcher = getenv("LEVELDB_TESTS");
38 |
39 | int num = 0;
40 | if (tests != NULL) {
41 | for (size_t i = 0; i < tests->size(); i++) {
42 | const Test& t = (*tests)[i];
43 | if (matcher != NULL) {
44 | std::string name = t.base;
45 | name.push_back('.');
46 | name.append(t.name);
47 | if (strstr(name.c_str(), matcher) == NULL) {
48 | continue;
49 | }
50 | }
51 | fprintf(stderr, "==== Test %s.%s\n", t.base, t.name);
52 | (*t.func)();
53 | ++num;
54 | }
55 | }
56 | fprintf(stderr, "==== PASSED %d tests\n", num);
57 | return 0;
58 | }
59 |
60 | std::string TmpDir() {
61 | std::string dir;
62 | Status s = Env::Default()->GetTestDirectory(&dir);
63 | ASSERT_TRUE(s.ok()) << s.ToString();
64 | return dir;
65 | }
66 |
67 | int RandomSeed() {
68 | const char* env = getenv("TEST_RANDOM_SEED");
69 | int result = (env != NULL ? atoi(env) : 301);
70 | if (result <= 0) {
71 | result = 301;
72 | }
73 | return result;
74 | }
75 |
76 | } // namespace test
77 | } // namespace leveldb
78 |
--------------------------------------------------------------------------------
/leveldb/util/logging.cc:
--------------------------------------------------------------------------------
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 "util/logging.h"
6 |
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include "leveldb/env.h"
12 | #include "leveldb/slice.h"
13 |
14 | namespace leveldb {
15 |
16 | void AppendNumberTo(std::string* str, uint64_t num) {
17 | char buf[30];
18 | snprintf(buf, sizeof(buf), "%llu", (unsigned long long) num);
19 | str->append(buf);
20 | }
21 |
22 | void AppendEscapedStringTo(std::string* str, const Slice& value) {
23 | for (size_t i = 0; i < value.size(); i++) {
24 | char c = value[i];
25 | if (c >= ' ' && c <= '~') {
26 | str->push_back(c);
27 | } else {
28 | char buf[10];
29 | snprintf(buf, sizeof(buf), "\\x%02x",
30 | static_cast(c) & 0xff);
31 | str->append(buf);
32 | }
33 | }
34 | }
35 |
36 | std::string NumberToString(uint64_t num) {
37 | std::string r;
38 | AppendNumberTo(&r, num);
39 | return r;
40 | }
41 |
42 | std::string EscapeString(const Slice& value) {
43 | std::string r;
44 | AppendEscapedStringTo(&r, value);
45 | return r;
46 | }
47 |
48 | bool ConsumeDecimalNumber(Slice* in, uint64_t* val) {
49 | uint64_t v = 0;
50 | int digits = 0;
51 | while (!in->empty()) {
52 | char c = (*in)[0];
53 | if (c >= '0' && c <= '9') {
54 | ++digits;
55 | const int delta = (c - '0');
56 | static const uint64_t kMaxUint64 = ~static_cast(0);
57 | if (v > kMaxUint64/10 ||
58 | (v == kMaxUint64/10 && delta > kMaxUint64%10)) {
59 | // Overflow
60 | return false;
61 | }
62 | v = (v * 10) + delta;
63 | in->remove_prefix(1);
64 | } else {
65 | break;
66 | }
67 | }
68 | *val = v;
69 | return (digits > 0);
70 | }
71 |
72 | } // namespace leveldb
73 |
--------------------------------------------------------------------------------
/tinyhttpd/README:
--------------------------------------------------------------------------------
1 | This software is copyright 1999 by J. David Blackstone. Permission
2 | is granted to redistribute and modify this software under the terms of
3 | the GNU General Public License, available at http://www.gnu.org/ .
4 |
5 | If you use this software or examine the code, I would appreciate
6 | knowing and would be overjoyed to hear about it at
7 | jdavidb@sourceforge.net .
8 |
9 | This software is not production quality. It comes with no warranty
10 | of any kind, not even an implied warranty of fitness for a particular
11 | purpose. I am not responsible for the damage that will likely result
12 | if you use this software on your computer system.
13 |
14 | I wrote this webserver for an assignment in my networking class in
15 | 1999. We were told that at a bare minimum the server had to serve
16 | pages, and told that we would get extra credit for doing "extras."
17 | Perl had introduced me to a whole lot of UNIX functionality (I learned
18 | sockets and fork from Perl!), and O'Reilly's lion book on UNIX system
19 | calls plus O'Reilly's books on CGI and writing web clients in Perl got
20 | me thinking and I realized I could make my webserver support CGI with
21 | little trouble.
22 |
23 | Now, if you're a member of the Apache core group, you might not be
24 | impressed. But my professor was blown over. Try the color.cgi sample
25 | script and type in "chartreuse." Made me seem smarter than I am, at
26 | any rate. :)
27 |
28 | Apache it's not. But I do hope that this program is a good
29 | educational tool for those interested in http/socket programming, as
30 | well as UNIX system calls. (There's some textbook uses of pipes,
31 | environment variables, forks, and so on.)
32 |
33 | One last thing: if you look at my webserver or (are you out of
34 | mind?!?) use it, I would just be overjoyed to hear about it. Please
35 | email me. I probably won't really be releasing major updates, but if
36 | I help you learn something, I'd love to know!
37 |
38 | Happy hacking!
39 |
40 | J. David Blackstone
41 |
--------------------------------------------------------------------------------
/leveldb/util/crc32c_test.cc:
--------------------------------------------------------------------------------
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 "util/crc32c.h"
6 | #include "util/testharness.h"
7 |
8 | namespace leveldb {
9 | namespace crc32c {
10 |
11 | class CRC { };
12 |
13 | TEST(CRC, StandardResults) {
14 | // From rfc3720 section B.4.
15 | char buf[32];
16 |
17 | memset(buf, 0, sizeof(buf));
18 | ASSERT_EQ(0x8a9136aa, Value(buf, sizeof(buf)));
19 |
20 | memset(buf, 0xff, sizeof(buf));
21 | ASSERT_EQ(0x62a8ab43, Value(buf, sizeof(buf)));
22 |
23 | for (int i = 0; i < 32; i++) {
24 | buf[i] = i;
25 | }
26 | ASSERT_EQ(0x46dd794e, Value(buf, sizeof(buf)));
27 |
28 | for (int i = 0; i < 32; i++) {
29 | buf[i] = 31 - i;
30 | }
31 | ASSERT_EQ(0x113fdb5c, Value(buf, sizeof(buf)));
32 |
33 | unsigned char data[48] = {
34 | 0x01, 0xc0, 0x00, 0x00,
35 | 0x00, 0x00, 0x00, 0x00,
36 | 0x00, 0x00, 0x00, 0x00,
37 | 0x00, 0x00, 0x00, 0x00,
38 | 0x14, 0x00, 0x00, 0x00,
39 | 0x00, 0x00, 0x04, 0x00,
40 | 0x00, 0x00, 0x00, 0x14,
41 | 0x00, 0x00, 0x00, 0x18,
42 | 0x28, 0x00, 0x00, 0x00,
43 | 0x00, 0x00, 0x00, 0x00,
44 | 0x02, 0x00, 0x00, 0x00,
45 | 0x00, 0x00, 0x00, 0x00,
46 | };
47 | ASSERT_EQ(0xd9963a56, Value(reinterpret_cast(data), sizeof(data)));
48 | }
49 |
50 | TEST(CRC, Values) {
51 | ASSERT_NE(Value("a", 1), Value("foo", 3));
52 | }
53 |
54 | TEST(CRC, Extend) {
55 | ASSERT_EQ(Value("hello world", 11),
56 | Extend(Value("hello ", 6), "world", 5));
57 | }
58 |
59 | TEST(CRC, Mask) {
60 | uint32_t crc = Value("foo", 3);
61 | ASSERT_NE(crc, Mask(crc));
62 | ASSERT_NE(crc, Mask(Mask(crc)));
63 | ASSERT_EQ(crc, Unmask(Mask(crc)));
64 | ASSERT_EQ(crc, Unmask(Unmask(Mask(Mask(crc)))));
65 | }
66 |
67 | } // namespace crc32c
68 | } // namespace leveldb
69 |
70 | int main(int argc, char** argv) {
71 | return leveldb::test::RunAllTests();
72 | }
73 |
--------------------------------------------------------------------------------
/leveldb/table/block_builder.h:
--------------------------------------------------------------------------------
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_TABLE_BLOCK_BUILDER_H_
6 | #define STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
7 |
8 | #include
9 |
10 | #include
11 | #include "leveldb/slice.h"
12 |
13 | namespace leveldb {
14 |
15 | struct Options;
16 |
17 | // 生成 block 的过程封装成 BlockBuilder 处理
18 | class BlockBuilder {
19 | public:
20 | explicit BlockBuilder(const Options* options);
21 |
22 | // Reset the contents as if the BlockBuilder was just constructed.
23 | void Reset();
24 |
25 | // REQUIRES: Finish() has not been called since the last call to Reset().
26 | // REQUIRES: key is larger than any previously added key
27 | void Add(const Slice& key, const Slice& value);
28 |
29 | // Finish building the block and return a slice that refers to the
30 | // block contents. The returned slice will remain valid for the
31 | // lifetime of this builder or until Reset() is called.
32 | Slice Finish();
33 |
34 | // Returns an estimate of the current (uncompressed) size of the block
35 | // we are building.
36 | size_t CurrentSizeEstimate() const;
37 |
38 | // Return true iff no entries have been added since the last Reset()
39 | bool empty() const {
40 | return buffer_.empty();
41 | }
42 |
43 | private:
44 | const Options* options_;
45 | std::string buffer_; // Destination buffer // 缓冲区
46 | std::vector restarts_; // Restart points // restart 数组
47 | int counter_; // Number of entries emitted since restart // restart 节点后的 entry 数目
48 | bool finished_; // Has Finish() been called? // 是否结束一个 block
49 | std::string last_key_;
50 |
51 | // No copying allowed
52 | BlockBuilder(const BlockBuilder&);
53 | void operator=(const BlockBuilder&);
54 | };
55 |
56 | } // namespace leveldb
57 |
58 | #endif // STORAGE_LEVELDB_TABLE_BLOCK_BUILDER_H_
59 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/write_batch.h:
--------------------------------------------------------------------------------
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 | // WriteBatch holds a collection of updates to apply atomically to a DB.
6 | //
7 | // The updates are applied in the order in which they are added
8 | // to the WriteBatch. For example, the value of "key" will be "v3"
9 | // after the following batch is written:
10 | //
11 | // batch.Put("key", "v1");
12 | // batch.Delete("key");
13 | // batch.Put("key", "v2");
14 | // batch.Put("key", "v3");
15 | //
16 | // Multiple threads can invoke const methods on a WriteBatch without
17 | // external synchronization, but if any of the threads may call a
18 | // non-const method, all threads accessing the same WriteBatch must use
19 | // external synchronization.
20 |
21 | // 会将 userkey 连同 SequnceNumber 和 ValueType 先做 encode,然后做 decode,将数据 insert 到指定的 Handler(memtable)上面。
22 |
23 | #ifndef STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_
24 | #define STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_
25 |
26 | #include
27 | #include "leveldb/status.h"
28 |
29 | namespace leveldb {
30 |
31 | class Slice;
32 |
33 | class WriteBatch {
34 | public:
35 | WriteBatch();
36 | ~WriteBatch();
37 |
38 | // Store the mapping "key->value" in the database.
39 | void Put(const Slice& key, const Slice& value);
40 |
41 | // If the database contains a mapping for "key", erase it. Else do nothing.
42 | void Delete(const Slice& key);
43 |
44 | // Clear all updates buffered in this batch.
45 | void Clear();
46 |
47 | // Support for iterating over the contents of a batch.
48 | class Handler {
49 | public:
50 | virtual ~Handler();
51 | virtual void Put(const Slice& key, const Slice& value) = 0;
52 | virtual void Delete(const Slice& key) = 0;
53 | };
54 | Status Iterate(Handler* handler) const;
55 |
56 | private:
57 | friend class WriteBatchInternal;
58 |
59 | std::string rep_; // See comment in write_batch.cc for the format of rep_
60 |
61 | // Intentionally copyable
62 | };
63 |
64 | } // namespace leveldb
65 |
66 | #endif // STORAGE_LEVELDB_INCLUDE_WRITE_BATCH_H_
67 |
--------------------------------------------------------------------------------
/leveldb/util/status.cc:
--------------------------------------------------------------------------------
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
6 | #include "port/port.h"
7 | #include "leveldb/status.h"
8 |
9 | namespace leveldb {
10 |
11 | const char* Status::CopyState(const char* state) {
12 | uint32_t size;
13 | memcpy(&size, state, sizeof(size));
14 | char* result = new char[size + 5];
15 | memcpy(result, state, size + 5);
16 | return result;
17 | }
18 |
19 | Status::Status(Code code, const Slice& msg, const Slice& msg2) {
20 | assert(code != kOk);
21 | const uint32_t len1 = msg.size();
22 | const uint32_t len2 = msg2.size();
23 | const uint32_t size = len1 + (len2 ? (2 + len2) : 0);
24 | char* result = new char[size + 5];
25 | memcpy(result, &size, sizeof(size));
26 | result[4] = static_cast(code);
27 | memcpy(result + 5, msg.data(), len1);
28 | if (len2) {
29 | result[5 + len1] = ':';
30 | result[6 + len1] = ' ';
31 | memcpy(result + 7 + len1, msg2.data(), len2);
32 | }
33 | state_ = result;
34 | }
35 |
36 | std::string Status::ToString() const {
37 | if (state_ == NULL) {
38 | return "OK";
39 | } else {
40 | char tmp[30];
41 | const char* type;
42 | switch (code()) {
43 | case kOk:
44 | type = "OK";
45 | break;
46 | case kNotFound:
47 | type = "NotFound: ";
48 | break;
49 | case kCorruption:
50 | type = "Corruption: ";
51 | break;
52 | case kNotSupported:
53 | type = "Not implemented: ";
54 | break;
55 | case kInvalidArgument:
56 | type = "Invalid argument: ";
57 | break;
58 | case kIOError:
59 | type = "IO error: ";
60 | break;
61 | default:
62 | snprintf(tmp, sizeof(tmp), "Unknown code(%d): ",
63 | static_cast(code()));
64 | type = tmp;
65 | break;
66 | }
67 | std::string result(type);
68 | uint32_t length;
69 | memcpy(&length, state_, sizeof(length));
70 | result.append(state_ + 5, length);
71 | return result;
72 | }
73 | }
74 |
75 | } // namespace leveldb
76 |
--------------------------------------------------------------------------------
/leveldb/db/table_cache.h:
--------------------------------------------------------------------------------
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 | // Thread-safe (provides internal synchronization)
6 |
7 | #ifndef STORAGE_LEVELDB_DB_TABLE_CACHE_H_
8 | #define STORAGE_LEVELDB_DB_TABLE_CACHE_H_
9 |
10 | #include
11 | #include
12 | #include "db/dbformat.h"
13 | #include "leveldb/cache.h"
14 | #include "leveldb/table.h"
15 | #include "port/port.h"
16 |
17 | namespace leveldb {
18 |
19 | class Env;
20 |
21 | class TableCache {
22 | public:
23 | TableCache(const std::string& dbname, const Options* options, int entries);
24 | ~TableCache();
25 |
26 | // Return an iterator for the specified file number (the corresponding
27 | // file length must be exactly "file_size" bytes). If "tableptr" is
28 | // non-NULL, also sets "*tableptr" to point to the Table object
29 | // underlying the returned iterator, or NULL if no Table object underlies
30 | // the returned iterator. The returned "*tableptr" object is owned by
31 | // the cache and should not be deleted, and is valid for as long as the
32 | // returned iterator is live.
33 | Iterator* NewIterator(const ReadOptions& options,
34 | uint64_t file_number,
35 | uint64_t file_size,
36 | Table** tableptr = NULL);
37 |
38 | // If a seek to internal key "k" in specified file finds an entry,
39 | // call (*handle_result)(arg, found_key, found_value).
40 | // 成功找到时调用回调函数
41 | Status Get(const ReadOptions& options,
42 | uint64_t file_number,
43 | uint64_t file_size,
44 | const Slice& k,
45 | void* arg,
46 | void (*handle_result)(void*, const Slice&, const Slice&));
47 |
48 | // Evict any entry for the specified file number
49 | void Evict(uint64_t file_number);
50 |
51 | private:
52 | Env* const env_;
53 | const std::string dbname_;
54 | const Options* options_;
55 | Cache* cache_;
56 |
57 | Status FindTable(uint64_t file_number, uint64_t file_size, Cache::Handle**);
58 | };
59 |
60 | } // namespace leveldb
61 |
62 | #endif // STORAGE_LEVELDB_DB_TABLE_CACHE_H_
63 |
--------------------------------------------------------------------------------
/leveldb/util/testutil.h:
--------------------------------------------------------------------------------
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_UTIL_TESTUTIL_H_
6 | #define STORAGE_LEVELDB_UTIL_TESTUTIL_H_
7 |
8 | #include "leveldb/env.h"
9 | #include "leveldb/slice.h"
10 | #include "util/random.h"
11 |
12 | namespace leveldb {
13 | namespace test {
14 |
15 | // Store in *dst a random string of length "len" and return a Slice that
16 | // references the generated data.
17 | extern Slice RandomString(Random* rnd, int len, std::string* dst);
18 |
19 | // Return a random key with the specified length that may contain interesting
20 | // characters (e.g. \x00, \xff, etc.).
21 | extern std::string RandomKey(Random* rnd, int len);
22 |
23 | // Store in *dst a string of length "len" that will compress to
24 | // "N*compressed_fraction" bytes and return a Slice that references
25 | // the generated data.
26 | extern Slice CompressibleString(Random* rnd, double compressed_fraction,
27 | size_t len, std::string* dst);
28 |
29 | // A wrapper that allows injection of errors.
30 | class ErrorEnv : public EnvWrapper {
31 | public:
32 | bool writable_file_error_;
33 | int num_writable_file_errors_;
34 |
35 | ErrorEnv() : EnvWrapper(Env::Default()),
36 | writable_file_error_(false),
37 | num_writable_file_errors_(0) { }
38 |
39 | virtual Status NewWritableFile(const std::string& fname,
40 | WritableFile** result) {
41 | if (writable_file_error_) {
42 | ++num_writable_file_errors_;
43 | *result = NULL;
44 | return Status::IOError(fname, "fake error");
45 | }
46 | return target()->NewWritableFile(fname, result);
47 | }
48 |
49 | virtual Status NewAppendableFile(const std::string& fname,
50 | WritableFile** result) {
51 | if (writable_file_error_) {
52 | ++num_writable_file_errors_;
53 | *result = NULL;
54 | return Status::IOError(fname, "fake error");
55 | }
56 | return target()->NewAppendableFile(fname, result);
57 | }
58 | };
59 |
60 | } // namespace test
61 | } // namespace leveldb
62 |
63 | #endif // STORAGE_LEVELDB_UTIL_TESTUTIL_H_
64 |
--------------------------------------------------------------------------------
/leveldb/util/arena.h:
--------------------------------------------------------------------------------
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_UTIL_ARENA_H_
6 | #define STORAGE_LEVELDB_UTIL_ARENA_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include "port/port.h"
13 |
14 | namespace leveldb {
15 |
16 | // memtable有阈值的限制(write_buffer_size),为了便于统计内存的使用,也为了内存使用效率,对memtable的内存使用实现了比较简单的arena管理(Arena)。
17 | class Arena {
18 | public:
19 | Arena();
20 | ~Arena();
21 |
22 | // Return a pointer to a newly allocated memory block of "bytes" bytes.
23 | char* Allocate(size_t bytes);
24 |
25 | // Allocate memory with the normal alignment guarantees provided by malloc
26 | char* AllocateAligned(size_t bytes);
27 |
28 | // Returns an estimate of the total memory usage of data allocated
29 | // by the arena.
30 | size_t MemoryUsage() const {
31 | return reinterpret_cast(memory_usage_.NoBarrier_Load());
32 | }
33 |
34 | private:
35 | char* AllocateFallback(size_t bytes);
36 | // 向系统申请 block_bytes 大小的内存
37 | char* AllocateNewBlock(size_t block_bytes);
38 |
39 | // Allocation state
40 | // 当前空闲内存 block 内的可用地址
41 | char* alloc_ptr_;
42 | // 当前空闲内存 block 内的可用大小
43 | size_t alloc_bytes_remaining_;
44 |
45 | // Array of new[] allocated memory blocks
46 | // 已经申请的内存 block
47 | std::vector blocks_;
48 |
49 | // Total memory usage of the arena.
50 | // 累计分配的内存大小,一个 memtable 对应一个 Arena
51 | // memtable 内的数据量就用这个值表示
52 | port::AtomicPointer memory_usage_;
53 |
54 | // No copying allowed
55 | Arena(const Arena&);
56 | void operator=(const Arena&);
57 | };
58 |
59 | inline char* Arena::Allocate(size_t bytes) {
60 | // The semantics of what to return are a bit messy if we allow
61 | // 0-byte allocations, so we disallow them here (we don't need
62 | // them for our internal use).
63 | assert(bytes > 0);
64 | // 如果申请的大小小于当前空闲 block 内可用大小,直接分配
65 | if (bytes <= alloc_bytes_remaining_) {
66 | char* result = alloc_ptr_;
67 | alloc_ptr_ += bytes;
68 | alloc_bytes_remaining_ -= bytes;
69 | return result;
70 | }
71 | return AllocateFallback(bytes);
72 | }
73 |
74 | } // namespace leveldb
75 |
76 | #endif // STORAGE_LEVELDB_UTIL_ARENA_H_
77 |
--------------------------------------------------------------------------------
/leveldb/util/random.h:
--------------------------------------------------------------------------------
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_UTIL_RANDOM_H_
6 | #define STORAGE_LEVELDB_UTIL_RANDOM_H_
7 |
8 | #include
9 |
10 | namespace leveldb {
11 |
12 | // A very simple random number generator. Not especially good at
13 | // generating truly random bits, but good enough for our needs in this
14 | // package.
15 | class Random {
16 | private:
17 | uint32_t seed_;
18 | public:
19 | explicit Random(uint32_t s) : seed_(s & 0x7fffffffu) {
20 | // Avoid bad seeds.
21 | if (seed_ == 0 || seed_ == 2147483647L) {
22 | seed_ = 1;
23 | }
24 | }
25 | uint32_t Next() {
26 | static const uint32_t M = 2147483647L; // 2^31-1
27 | static const uint64_t A = 16807; // bits 14, 8, 7, 5, 2, 1, 0
28 | // We are computing
29 | // seed_ = (seed_ * A) % M, where M = 2^31-1
30 | //
31 | // seed_ must not be zero or M, or else all subsequent computed values
32 | // will be zero or M respectively. For all other values, seed_ will end
33 | // up cycling through every number in [1,M-1]
34 | uint64_t product = seed_ * A;
35 |
36 | // Compute (product % M) using the fact that ((x << 31) % M) == x.
37 | seed_ = static_cast((product >> 31) + (product & M));
38 | // The first reduction may overflow by 1 bit, so we may need to
39 | // repeat. mod == M is not possible; using > allows the faster
40 | // sign-bit-based test.
41 | if (seed_ > M) {
42 | seed_ -= M;
43 | }
44 | return seed_;
45 | }
46 | // Returns a uniformly distributed value in the range [0..n-1]
47 | // REQUIRES: n > 0
48 | uint32_t Uniform(int n) { return Next() % n; }
49 |
50 | // Randomly returns true ~"1/n" of the time, and false otherwise.
51 | // REQUIRES: n > 0
52 | bool OneIn(int n) { return (Next() % n) == 0; }
53 |
54 | // Skewed: pick "base" uniformly from range [0,max_log] and then
55 | // return "base" random bits. The effect is to pick a number in the
56 | // range [0,2^max_log-1] with exponential bias towards smaller numbers.
57 | uint32_t Skewed(int max_log) {
58 | return Uniform(1 << Uniform(max_log + 1));
59 | }
60 | };
61 |
62 | } // namespace leveldb
63 |
64 | #endif // STORAGE_LEVELDB_UTIL_RANDOM_H_
65 |
--------------------------------------------------------------------------------
/leveldb/table/iterator_wrapper.h:
--------------------------------------------------------------------------------
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_TABLE_ITERATOR_WRAPPER_H_
6 | #define STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_
7 |
8 | #include "leveldb/iterator.h"
9 | #include "leveldb/slice.h"
10 |
11 | namespace leveldb {
12 |
13 | // A internal wrapper class with an interface similar to Iterator that
14 | // caches the valid() and key() results for an underlying iterator.
15 | // This can help avoid virtual function calls and also gives better
16 | // cache locality.
17 | // 对 Iterator 接口的简单封装,缓存了 key 和是否 valid,
18 | // 可以减少 virtual 函数调用
19 | class IteratorWrapper {
20 | public:
21 | IteratorWrapper(): iter_(NULL), valid_(false) { }
22 | explicit IteratorWrapper(Iterator* iter): iter_(NULL) {
23 | Set(iter);
24 | }
25 | ~IteratorWrapper() { delete iter_; }
26 | Iterator* iter() const { return iter_; }
27 |
28 | // Takes ownership of "iter" and will delete it when destroyed, or
29 | // when Set() is invoked again.
30 | void Set(Iterator* iter) {
31 | delete iter_;
32 | iter_ = iter;
33 | if (iter_ == NULL) {
34 | valid_ = false;
35 | } else {
36 | Update();
37 | }
38 | }
39 |
40 |
41 | // Iterator interface methods
42 | bool Valid() const { return valid_; }
43 | Slice key() const { assert(Valid()); return key_; }
44 | Slice value() const { assert(Valid()); return iter_->value(); }
45 | // Methods below require iter() != NULL
46 | Status status() const { assert(iter_); return iter_->status(); }
47 | void Next() { assert(iter_); iter_->Next(); Update(); }
48 | void Prev() { assert(iter_); iter_->Prev(); Update(); }
49 | void Seek(const Slice& k) { assert(iter_); iter_->Seek(k); Update(); }
50 | void SeekToFirst() { assert(iter_); iter_->SeekToFirst(); Update(); }
51 | void SeekToLast() { assert(iter_); iter_->SeekToLast(); Update(); }
52 |
53 | private:
54 | void Update() {
55 | valid_ = iter_->Valid();
56 | if (valid_) {
57 | key_ = iter_->key();
58 | }
59 | }
60 |
61 | Iterator* iter_;
62 | bool valid_;
63 | Slice key_;
64 | };
65 |
66 | } // namespace leveldb
67 |
68 | #endif // STORAGE_LEVELDB_TABLE_ITERATOR_WRAPPER_H_
69 |
--------------------------------------------------------------------------------
/leveldb/util/arena.cc:
--------------------------------------------------------------------------------
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 "util/arena.h"
6 | #include
7 |
8 | namespace leveldb {
9 |
10 | static const int kBlockSize = 4096; // 一个 block 4 kb
11 |
12 | Arena::Arena() : memory_usage_(0) {
13 | alloc_ptr_ = NULL; // First allocation will allocate a block
14 | alloc_bytes_remaining_ = 0;
15 | }
16 |
17 | Arena::~Arena() {
18 | for (size_t i = 0; i < blocks_.size(); i++) {
19 | delete[] blocks_[i];
20 | }
21 | }
22 |
23 | char* Arena::AllocateFallback(size_t bytes) {
24 | // 如果大于 1/4 的 block 大小,直接从系统申请内存
25 | if (bytes > kBlockSize / 4) {
26 | // Object is more than a quarter of our block size. Allocate it separately
27 | // to avoid wasting too much space in leftover bytes.
28 | char* result = AllocateNewBlock(bytes);
29 | return result;
30 | }
31 |
32 | // We waste the remaining space in the current block.
33 | // 申请新的 block,原有剩余的 block 丢弃
34 | alloc_ptr_ = AllocateNewBlock(kBlockSize);
35 | alloc_bytes_remaining_ = kBlockSize;
36 |
37 | char* result = alloc_ptr_;
38 | alloc_ptr_ += bytes;
39 | alloc_bytes_remaining_ -= bytes;
40 | return result;
41 | }
42 |
43 | char* Arena::AllocateAligned(size_t bytes) {
44 | const int align = (sizeof(void*) > 8) ? sizeof(void*) : 8;
45 | assert((align & (align-1)) == 0); // Pointer size should be a power of 2
46 | size_t current_mod = reinterpret_cast(alloc_ptr_) & (align-1);
47 | size_t slop = (current_mod == 0 ? 0 : align - current_mod);
48 | size_t needed = bytes + slop;
49 | char* result;
50 | if (needed <= alloc_bytes_remaining_) {
51 | result = alloc_ptr_ + slop;
52 | alloc_ptr_ += needed;
53 | alloc_bytes_remaining_ -= needed;
54 | } else {
55 | // AllocateFallback always returned aligned memory
56 | result = AllocateFallback(bytes);
57 | }
58 | assert((reinterpret_cast(result) & (align-1)) == 0);
59 | return result;
60 | }
61 |
62 | char* Arena::AllocateNewBlock(size_t block_bytes) {
63 | char* result = new char[block_bytes];
64 | blocks_.push_back(result);
65 | // 更新内存总大小
66 | memory_usage_.NoBarrier_Store(
67 | reinterpret_cast(MemoryUsage() + block_bytes + sizeof(char*)));
68 | return result;
69 | }
70 |
71 | } // namespace leveldb
72 |
--------------------------------------------------------------------------------
/leveldb/util/comparator.cc:
--------------------------------------------------------------------------------
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
6 | #include
7 | #include "leveldb/comparator.h"
8 | #include "leveldb/slice.h"
9 | #include "port/port.h"
10 | #include "util/logging.h"
11 |
12 | namespace leveldb {
13 |
14 | Comparator::~Comparator() { }
15 |
16 | namespace {
17 | class BytewiseComparatorImpl : public Comparator {
18 | public:
19 | BytewiseComparatorImpl() { }
20 |
21 | virtual const char* Name() const {
22 | return "leveldb.BytewiseComparator";
23 | }
24 |
25 | virtual int Compare(const Slice& a, const Slice& b) const {
26 | return a.compare(b);
27 | }
28 |
29 | virtual void FindShortestSeparator(
30 | std::string* start,
31 | const Slice& limit) const {
32 | // Find length of common prefix
33 | size_t min_length = std::min(start->size(), limit.size());
34 | size_t diff_index = 0;
35 | while ((diff_index < min_length) &&
36 | ((*start)[diff_index] == limit[diff_index])) {
37 | diff_index++;
38 | }
39 |
40 | if (diff_index >= min_length) {
41 | // Do not shorten if one string is a prefix of the other
42 | } else {
43 | uint8_t diff_byte = static_cast((*start)[diff_index]);
44 | if (diff_byte < static_cast(0xff) &&
45 | diff_byte + 1 < static_cast(limit[diff_index])) {
46 | (*start)[diff_index]++;
47 | start->resize(diff_index + 1);
48 | assert(Compare(*start, limit) < 0);
49 | }
50 | }
51 | }
52 |
53 | virtual void FindShortSuccessor(std::string* key) const {
54 | // Find first character that can be incremented
55 | size_t n = key->size();
56 | for (size_t i = 0; i < n; i++) {
57 | const uint8_t byte = (*key)[i];
58 | if (byte != static_cast(0xff)) {
59 | (*key)[i] = byte + 1;
60 | key->resize(i+1);
61 | return;
62 | }
63 | }
64 | // *key is a run of 0xffs. Leave it alone.
65 | }
66 | };
67 | } // namespace
68 |
69 | static port::OnceType once = LEVELDB_ONCE_INIT;
70 | static const Comparator* bytewise;
71 |
72 | static void InitModule() {
73 | bytewise = new BytewiseComparatorImpl;
74 | }
75 |
76 | const Comparator* BytewiseComparator() {
77 | port::InitOnce(&once, InitModule);
78 | return bytewise;
79 | }
80 |
81 | } // namespace leveldb
82 |
--------------------------------------------------------------------------------
/leveldb/table/filter_block.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 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 | // A filter block is stored near the end of a Table file. It contains
6 | // filters (e.g., bloom filters) for all data blocks in the table combined
7 | // into a single filter block.
8 |
9 | // filter 介绍可以看 http://dirlt.com/leveldb.html#orgheadline6
10 |
11 | #ifndef STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_
12 | #define STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_
13 |
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include "leveldb/slice.h"
19 | #include "util/hash.h"
20 |
21 | namespace leveldb {
22 |
23 | class FilterPolicy;
24 |
25 | // A FilterBlockBuilder is used to construct all of the filters for a
26 | // particular Table. It generates a single string which is stored as
27 | // a special block in the Table.
28 | //
29 | // The sequence of calls to FilterBlockBuilder must match the regexp:
30 | // (StartBlock AddKey*)* Finish
31 | class FilterBlockBuilder {
32 | public:
33 | explicit FilterBlockBuilder(const FilterPolicy*);
34 |
35 | void StartBlock(uint64_t block_offset);
36 | void AddKey(const Slice& key);
37 | Slice Finish();
38 |
39 | private:
40 | void GenerateFilter();
41 |
42 | const FilterPolicy* policy_;
43 | std::string keys_; // Flattened key contents
44 | std::vector start_; // Starting index in keys_ of each key
45 | std::string result_; // Filter data computed so far
46 | std::vector tmp_keys_; // policy_->CreateFilter() argument
47 | std::vector filter_offsets_;
48 |
49 | // No copying allowed
50 | FilterBlockBuilder(const FilterBlockBuilder&);
51 | void operator=(const FilterBlockBuilder&);
52 | };
53 |
54 | class FilterBlockReader {
55 | public:
56 | // REQUIRES: "contents" and *policy must stay live while *this is live.
57 | FilterBlockReader(const FilterPolicy* policy, const Slice& contents);
58 | bool KeyMayMatch(uint64_t block_offset, const Slice& key);
59 |
60 | private:
61 | const FilterPolicy* policy_;
62 | const char* data_; // Pointer to filter data (at block-start)
63 | const char* offset_; // Pointer to beginning of offset array (at block-end)
64 | size_t num_; // Number of entries in offset array
65 | size_t base_lg_; // Encoding parameter (see kFilterBaseLg in .cc file)
66 | };
67 |
68 | }
69 |
70 | #endif // STORAGE_LEVELDB_TABLE_FILTER_BLOCK_H_
71 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/comparator.h:
--------------------------------------------------------------------------------
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_INCLUDE_COMPARATOR_H_
6 | #define STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_
7 |
8 | #include
9 |
10 | namespace leveldb {
11 |
12 | class Slice;
13 |
14 | // A Comparator object provides a total order across slices that are
15 | // used as keys in an sstable or a database. A Comparator implementation
16 | // must be thread-safe since leveldb may invoke its methods concurrently
17 | // from multiple threads.
18 | class Comparator {
19 | public:
20 | virtual ~Comparator();
21 |
22 | // Three-way comparison. Returns value:
23 | // < 0 iff "a" < "b",
24 | // == 0 iff "a" == "b",
25 | // > 0 iff "a" > "b"
26 | virtual int Compare(const Slice& a, const Slice& b) const = 0;
27 |
28 | // The name of the comparator. Used to check for comparator
29 | // mismatches (i.e., a DB created with one comparator is
30 | // accessed using a different comparator.
31 | //
32 | // The client of this package should switch to a new name whenever
33 | // the comparator implementation changes in a way that will cause
34 | // the relative ordering of any two keys to change.
35 | //
36 | // Names starting with "leveldb." are reserved and should not be used
37 | // by any clients of this package.
38 | virtual const char* Name() const = 0;
39 |
40 | // Advanced functions: these are used to reduce the space requirements
41 | // for internal data structures like index blocks.
42 |
43 | // If *start < limit, changes *start to a short string in [start,limit).
44 | // Simple comparator implementations may return with *start unchanged,
45 | // i.e., an implementation of this method that does nothing is correct.
46 | // 获得大于 start 但小于 limit 的最小值
47 | virtual void FindShortestSeparator(
48 | std::string* start,
49 | const Slice& limit) const = 0;
50 |
51 | // Changes *key to a short string >= *key.
52 | // Simple comparator implementations may return with *key unchanged,
53 | // i.e., an implementation of this method that does nothing is correct.
54 | // 获得比 start 大的最小值
55 | virtual void FindShortSuccessor(std::string* key) const = 0;
56 | };
57 |
58 | // Return a builtin comparator that uses lexicographic byte-wise
59 | // ordering. The result remains the property of this module and
60 | // must not be deleted.
61 | extern const Comparator* BytewiseComparator();
62 |
63 | } // namespace leveldb
64 |
65 | #endif // STORAGE_LEVELDB_INCLUDE_COMPARATOR_H_
66 |
--------------------------------------------------------------------------------
/leveldb/db/builder.cc:
--------------------------------------------------------------------------------
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 "db/builder.h"
6 |
7 | #include "db/filename.h"
8 | #include "db/dbformat.h"
9 | #include "db/table_cache.h"
10 | #include "db/version_edit.h"
11 | #include "leveldb/db.h"
12 | #include "leveldb/env.h"
13 | #include "leveldb/iterator.h"
14 |
15 | namespace leveldb {
16 |
17 | // 函数作用见 builder.h
18 | Status BuildTable(const std::string& dbname,
19 | Env* env,
20 | const Options& options,
21 | TableCache* table_cache,
22 | Iterator* iter,
23 | FileMetaData* meta) {
24 | Status s;
25 | meta->file_size = 0;
26 | iter->SeekToFirst();
27 |
28 | // 获得 sstable 的文件名
29 | std::string fname = TableFileName(dbname, meta->number);
30 | if (iter->Valid()) {
31 | // 新的文件
32 | WritableFile* file;
33 | s = env->NewWritableFile(fname, &file);
34 | if (!s.ok()) {
35 | return s;
36 | }
37 |
38 | // 用 TableBuilder 来处理,迭代添加 kv 数据
39 | TableBuilder* builder = new TableBuilder(options, file);
40 | meta->smallest.DecodeFrom(iter->key());
41 | for (; iter->Valid(); iter->Next()) {
42 | Slice key = iter->key();
43 | meta->largest.DecodeFrom(key);
44 | builder->Add(key, iter->value());
45 | }
46 |
47 | // Finish and check for builder errors
48 | if (s.ok()) {
49 | // 完成
50 | s = builder->Finish();
51 | if (s.ok()) {
52 | meta->file_size = builder->FileSize();
53 | assert(meta->file_size > 0);
54 | }
55 | } else {
56 | builder->Abandon();
57 | }
58 | delete builder;
59 |
60 | // Finish and check for file errors
61 | // 同步并关闭文件
62 | if (s.ok()) {
63 | s = file->Sync();
64 | }
65 | if (s.ok()) {
66 | s = file->Close();
67 | }
68 | delete file;
69 | file = NULL;
70 |
71 | if (s.ok()) {
72 | // Verify that the table is usable
73 | // 验证可用,加入 cache
74 | Iterator* it = table_cache->NewIterator(ReadOptions(),
75 | meta->number,
76 | meta->file_size);
77 | s = it->status();
78 | delete it;
79 | }
80 | }
81 |
82 | // Check for input iterator errors
83 | if (!iter->status().ok()) {
84 | s = iter->status();
85 | }
86 |
87 | if (s.ok() && meta->file_size > 0) {
88 | // Keep it
89 | } else {
90 | env->DeleteFile(fname);
91 | }
92 | return s;
93 | }
94 |
95 | } // namespace leveldb
96 |
--------------------------------------------------------------------------------
/leveldb/util/env.cc:
--------------------------------------------------------------------------------
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 "leveldb/env.h"
6 |
7 | namespace leveldb {
8 |
9 | Env::~Env() {
10 | }
11 |
12 | Status Env::NewAppendableFile(const std::string& fname, WritableFile** result) {
13 | return Status::NotSupported("NewAppendableFile", fname);
14 | }
15 |
16 | SequentialFile::~SequentialFile() {
17 | }
18 |
19 | RandomAccessFile::~RandomAccessFile() {
20 | }
21 |
22 | WritableFile::~WritableFile() {
23 | }
24 |
25 | Logger::~Logger() {
26 | }
27 |
28 | FileLock::~FileLock() {
29 | }
30 |
31 | void Log(Logger* info_log, const char* format, ...) {
32 | if (info_log != NULL) {
33 | va_list ap;
34 | va_start(ap, format);
35 | info_log->Logv(format, ap);
36 | va_end(ap);
37 | }
38 | }
39 |
40 | static Status DoWriteStringToFile(Env* env, const Slice& data,
41 | const std::string& fname,
42 | bool should_sync) {
43 | WritableFile* file;
44 | Status s = env->NewWritableFile(fname, &file);
45 | if (!s.ok()) {
46 | return s;
47 | }
48 | s = file->Append(data);
49 | if (s.ok() && should_sync) {
50 | s = file->Sync();
51 | }
52 | if (s.ok()) {
53 | s = file->Close();
54 | }
55 | delete file; // Will auto-close if we did not close above
56 | if (!s.ok()) {
57 | env->DeleteFile(fname);
58 | }
59 | return s;
60 | }
61 |
62 | Status WriteStringToFile(Env* env, const Slice& data,
63 | const std::string& fname) {
64 | return DoWriteStringToFile(env, data, fname, false);
65 | }
66 |
67 | Status WriteStringToFileSync(Env* env, const Slice& data,
68 | const std::string& fname) {
69 | return DoWriteStringToFile(env, data, fname, true);
70 | }
71 |
72 | Status ReadFileToString(Env* env, const std::string& fname, std::string* data) {
73 | data->clear();
74 | SequentialFile* file;
75 | Status s = env->NewSequentialFile(fname, &file);
76 | if (!s.ok()) {
77 | return s;
78 | }
79 | static const int kBufferSize = 8192;
80 | char* space = new char[kBufferSize];
81 | while (true) {
82 | Slice fragment;
83 | s = file->Read(kBufferSize, &fragment, space);
84 | if (!s.ok()) {
85 | break;
86 | }
87 | data->append(fragment.data(), fragment.size());
88 | if (fragment.empty()) {
89 | break;
90 | }
91 | }
92 | delete[] space;
93 | delete file;
94 | return s;
95 | }
96 |
97 | EnvWrapper::~EnvWrapper() {
98 | }
99 |
100 | } // namespace leveldb
101 |
--------------------------------------------------------------------------------
/webbench/webbench.1:
--------------------------------------------------------------------------------
1 | .TH WEBBENCH 1 "14 Jan 2004"
2 | .\" NAME should be all caps, SECTION should be 1-8, maybe w/ subsection
3 | .\" other parms are allowed: see man(7), man(1)
4 | .SH NAME
5 | webbench \- simple forking web benchmark
6 | .SH SYNOPSIS
7 | .B webbench
8 | .I "[options] URL"
9 | .br
10 | .SH "AUTHOR"
11 | This program and manual page was written by Radim Kolar,
12 | for the
13 | .B Supreme Personality of Godhead
14 | (but may be used by others).
15 | .SH "DESCRIPTION"
16 | .B webbench
17 | is simple program for benchmarking HTTP servers or any
18 | other servers, which can be accessed via HTTP proxy. Unlike others
19 | benchmarks,
20 | .B webbench
21 | uses multiple processes for simulating traffic
22 | generated by multiple users. This allows better operating
23 | on SMP systems and on systems with slow or buggy implementation
24 | of select().
25 | .SH OPTIONS
26 | The programs follow the usual GNU command line syntax, with long
27 | options starting with two dashes (`-').
28 | A summary of options are included below.
29 | .TP
30 | .B \-?, \-h, \-\-help
31 | Show summary of options.
32 | .TP
33 | .B \-v, \-\-version
34 | Show version of program.
35 | .TP
36 | .B \-f, \-\-force
37 | Do not wait for any response from server. Close connection after
38 | request is send. This option produce quite a good denial of service
39 | attack.
40 | .TP
41 | .B \-9, \-\-http09
42 | Use HTTP/0.9 protocol, if possible.
43 | .TP
44 | .B \-1, \-\-http10
45 | Use HTTP/1.0 protocol, if possible.
46 | .TP
47 | .B \-2, \-\-http11
48 | Use HTTP/1.1 protocol (without
49 | .I Keep-Alive
50 | ), if possible.
51 | .TP
52 | .B \-r, \-\-reload
53 | Forces proxy to reload document. If proxy is not
54 | set, option has no effect.
55 | .TP
56 | .B \-t, \-\-time
57 | Run benchmark for
58 | .I
59 | seconds. Default value is 30.
60 | .TP
61 | .B \-p, \-\-proxy
62 | Send request via proxy server. Needed for supporting others protocols
63 | than HTTP.
64 | .TP
65 | .B \-\-get
66 | Use GET request method.
67 | .TP
68 | .B \-\-head
69 | Use HEAD request method.
70 | .TP
71 | .B \-\-options
72 | Use OPTIONS request method.
73 | .TP
74 | .B \-\-trace
75 | Use TRACE request method.
76 | .TP
77 | .B \-c, \-\-clients
78 | Use
79 | .I
80 | multiple clients for benchmark. Default value
81 | is 1.
82 | .SH "EXIT STATUS"
83 | .TP
84 | 0 - sucess
85 | .TP
86 | 1 - benchmark failed, can not connect to server
87 | .TP
88 | 2 - bad command line argument(s)
89 | .TP
90 | 3 - internal error, i.e. fork failed
91 | .SH "TODO"
92 | Include support for using
93 | .I Keep-Alive
94 | HTTP/1.1 connections.
95 | .SH "COPYING"
96 | Webbench is distributed under GPL. Copyright 1997-2004
97 | Radim Kolar (hsn@netmag.cz).
98 | UNIX sockets code taken from popclient 1.5 4/1/94
99 | public domain code, created by Virginia Tech Computing Center.
100 | .BR
101 | This man page is public domain.
102 |
--------------------------------------------------------------------------------
/leveldb/issues/issue178_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 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 | // Test for issue 178: a manual compaction causes deleted data to reappear.
6 | #include
7 | #include
8 | #include
9 |
10 | #include "leveldb/db.h"
11 | #include "leveldb/write_batch.h"
12 | #include "util/testharness.h"
13 |
14 | namespace {
15 |
16 | const int kNumKeys = 1100000;
17 |
18 | std::string Key1(int i) {
19 | char buf[100];
20 | snprintf(buf, sizeof(buf), "my_key_%d", i);
21 | return buf;
22 | }
23 |
24 | std::string Key2(int i) {
25 | return Key1(i) + "_xxx";
26 | }
27 |
28 | class Issue178 { };
29 |
30 | TEST(Issue178, Test) {
31 | // Get rid of any state from an old run.
32 | std::string dbpath = leveldb::test::TmpDir() + "/leveldb_cbug_test";
33 | DestroyDB(dbpath, leveldb::Options());
34 |
35 | // Open database. Disable compression since it affects the creation
36 | // of layers and the code below is trying to test against a very
37 | // specific scenario.
38 | leveldb::DB* db;
39 | leveldb::Options db_options;
40 | db_options.create_if_missing = true;
41 | db_options.compression = leveldb::kNoCompression;
42 | ASSERT_OK(leveldb::DB::Open(db_options, dbpath, &db));
43 |
44 | // create first key range
45 | leveldb::WriteBatch batch;
46 | for (size_t i = 0; i < kNumKeys; i++) {
47 | batch.Put(Key1(i), "value for range 1 key");
48 | }
49 | ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
50 |
51 | // create second key range
52 | batch.Clear();
53 | for (size_t i = 0; i < kNumKeys; i++) {
54 | batch.Put(Key2(i), "value for range 2 key");
55 | }
56 | ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
57 |
58 | // delete second key range
59 | batch.Clear();
60 | for (size_t i = 0; i < kNumKeys; i++) {
61 | batch.Delete(Key2(i));
62 | }
63 | ASSERT_OK(db->Write(leveldb::WriteOptions(), &batch));
64 |
65 | // compact database
66 | std::string start_key = Key1(0);
67 | std::string end_key = Key1(kNumKeys - 1);
68 | leveldb::Slice least(start_key.data(), start_key.size());
69 | leveldb::Slice greatest(end_key.data(), end_key.size());
70 |
71 | // commenting out the line below causes the example to work correctly
72 | db->CompactRange(&least, &greatest);
73 |
74 | // count the keys
75 | leveldb::Iterator* iter = db->NewIterator(leveldb::ReadOptions());
76 | size_t num_keys = 0;
77 | for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
78 | num_keys++;
79 | }
80 | delete iter;
81 | ASSERT_EQ(kNumKeys, num_keys) << "Bad number of keys";
82 |
83 | // close database
84 | delete db;
85 | DestroyDB(dbpath, leveldb::Options());
86 | }
87 |
88 | } // anonymous namespace
89 |
90 | int main(int argc, char** argv) {
91 | return leveldb::test::RunAllTests();
92 | }
93 |
--------------------------------------------------------------------------------
/leveldb/util/env_test.cc:
--------------------------------------------------------------------------------
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 "leveldb/env.h"
6 |
7 | #include "port/port.h"
8 | #include "util/testharness.h"
9 |
10 | namespace leveldb {
11 |
12 | static const int kDelayMicros = 100000;
13 |
14 | class EnvPosixTest {
15 | private:
16 | port::Mutex mu_;
17 | std::string events_;
18 |
19 | public:
20 | Env* env_;
21 | EnvPosixTest() : env_(Env::Default()) { }
22 | };
23 |
24 | static void SetBool(void* ptr) {
25 | reinterpret_cast(ptr)->NoBarrier_Store(ptr);
26 | }
27 |
28 | TEST(EnvPosixTest, RunImmediately) {
29 | port::AtomicPointer called (NULL);
30 | env_->Schedule(&SetBool, &called);
31 | Env::Default()->SleepForMicroseconds(kDelayMicros);
32 | ASSERT_TRUE(called.NoBarrier_Load() != NULL);
33 | }
34 |
35 | TEST(EnvPosixTest, RunMany) {
36 | port::AtomicPointer last_id (NULL);
37 |
38 | struct CB {
39 | port::AtomicPointer* last_id_ptr; // Pointer to shared slot
40 | uintptr_t id; // Order# for the execution of this callback
41 |
42 | CB(port::AtomicPointer* p, int i) : last_id_ptr(p), id(i) { }
43 |
44 | static void Run(void* v) {
45 | CB* cb = reinterpret_cast(v);
46 | void* cur = cb->last_id_ptr->NoBarrier_Load();
47 | ASSERT_EQ(cb->id-1, reinterpret_cast(cur));
48 | cb->last_id_ptr->Release_Store(reinterpret_cast(cb->id));
49 | }
50 | };
51 |
52 | // Schedule in different order than start time
53 | CB cb1(&last_id, 1);
54 | CB cb2(&last_id, 2);
55 | CB cb3(&last_id, 3);
56 | CB cb4(&last_id, 4);
57 | env_->Schedule(&CB::Run, &cb1);
58 | env_->Schedule(&CB::Run, &cb2);
59 | env_->Schedule(&CB::Run, &cb3);
60 | env_->Schedule(&CB::Run, &cb4);
61 |
62 | Env::Default()->SleepForMicroseconds(kDelayMicros);
63 | void* cur = last_id.Acquire_Load();
64 | ASSERT_EQ(4, reinterpret_cast(cur));
65 | }
66 |
67 | struct State {
68 | port::Mutex mu;
69 | int val;
70 | int num_running;
71 | };
72 |
73 | static void ThreadBody(void* arg) {
74 | State* s = reinterpret_cast(arg);
75 | s->mu.Lock();
76 | s->val += 1;
77 | s->num_running -= 1;
78 | s->mu.Unlock();
79 | }
80 |
81 | TEST(EnvPosixTest, StartThread) {
82 | State state;
83 | state.val = 0;
84 | state.num_running = 3;
85 | for (int i = 0; i < 3; i++) {
86 | env_->StartThread(&ThreadBody, &state);
87 | }
88 | while (true) {
89 | state.mu.Lock();
90 | int num = state.num_running;
91 | state.mu.Unlock();
92 | if (num == 0) {
93 | break;
94 | }
95 | Env::Default()->SleepForMicroseconds(kDelayMicros);
96 | }
97 | ASSERT_EQ(state.val, 3);
98 | }
99 |
100 | } // namespace leveldb
101 |
102 | int main(int argc, char** argv) {
103 | return leveldb::test::RunAllTests();
104 | }
105 |
--------------------------------------------------------------------------------
/leveldb/doc/log_format.txt:
--------------------------------------------------------------------------------
1 | The log file contents are a sequence of 32KB blocks. The only
2 | exception is that the tail of the file may contain a partial block.
3 |
4 | Each block consists of a sequence of records:
5 | block := record* trailer?
6 | record :=
7 | checksum: uint32 // crc32c of type and data[] ; little-endian
8 | length: uint16 // little-endian
9 | type: uint8 // One of FULL, FIRST, MIDDLE, LAST
10 | data: uint8[length]
11 |
12 | A record never starts within the last six bytes of a block (since it
13 | won't fit). Any leftover bytes here form the trailer, which must
14 | consist entirely of zero bytes and must be skipped by readers.
15 |
16 | Aside: if exactly seven bytes are left in the current block, and a new
17 | non-zero length record is added, the writer must emit a FIRST record
18 | (which contains zero bytes of user data) to fill up the trailing seven
19 | bytes of the block and then emit all of the user data in subsequent
20 | blocks.
21 |
22 | More types may be added in the future. Some Readers may skip record
23 | types they do not understand, others may report that some data was
24 | skipped.
25 |
26 | FULL == 1
27 | FIRST == 2
28 | MIDDLE == 3
29 | LAST == 4
30 |
31 | The FULL record contains the contents of an entire user record.
32 |
33 | FIRST, MIDDLE, LAST are types used for user records that have been
34 | split into multiple fragments (typically because of block boundaries).
35 | FIRST is the type of the first fragment of a user record, LAST is the
36 | type of the last fragment of a user record, and MIDDLE is the type of
37 | all interior fragments of a user record.
38 |
39 | Example: consider a sequence of user records:
40 | A: length 1000
41 | B: length 97270
42 | C: length 8000
43 | A will be stored as a FULL record in the first block.
44 |
45 | B will be split into three fragments: first fragment occupies the rest
46 | of the first block, second fragment occupies the entirety of the
47 | second block, and the third fragment occupies a prefix of the third
48 | block. This will leave six bytes free in the third block, which will
49 | be left empty as the trailer.
50 |
51 | C will be stored as a FULL record in the fourth block.
52 |
53 | ===================
54 |
55 | Some benefits over the recordio format:
56 |
57 | (1) We do not need any heuristics for resyncing - just go to next
58 | block boundary and scan. If there is a corruption, skip to the next
59 | block. As a side-benefit, we do not get confused when part of the
60 | contents of one log file are embedded as a record inside another log
61 | file.
62 |
63 | (2) Splitting at approximate boundaries (e.g., for mapreduce) is
64 | simple: find the next block boundary and skip records until we
65 | hit a FULL or FIRST record.
66 |
67 | (3) We do not need extra buffering for large records.
68 |
69 | Some downsides compared to recordio format:
70 |
71 | (1) No packing of tiny records. This could be fixed by adding a new
72 | record type, so it is a shortcoming of the current implementation,
73 | not necessarily the format.
74 |
75 | (2) No compression. Again, this could be fixed by adding new record types.
76 |
--------------------------------------------------------------------------------
/leveldb/util/posix_logger.h:
--------------------------------------------------------------------------------
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 | // Logger implementation that can be shared by all environments
6 | // where enough posix functionality is available.
7 |
8 | #ifndef STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
9 | #define STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
10 |
11 | #include
12 | #include
13 | #include
14 | #include
15 | #include "leveldb/env.h"
16 |
17 | namespace leveldb {
18 |
19 | class PosixLogger : public Logger {
20 | private:
21 | FILE* file_;
22 | uint64_t (*gettid_)(); // Return the thread id for the current thread
23 | public:
24 | PosixLogger(FILE* f, uint64_t (*gettid)()) : file_(f), gettid_(gettid) { }
25 | virtual ~PosixLogger() {
26 | fclose(file_);
27 | }
28 | virtual void Logv(const char* format, va_list ap) {
29 | const uint64_t thread_id = (*gettid_)();
30 |
31 | // We try twice: the first time with a fixed-size stack allocated buffer,
32 | // and the second time with a much larger dynamically allocated buffer.
33 | char buffer[500];
34 | for (int iter = 0; iter < 2; iter++) {
35 | char* base;
36 | int bufsize;
37 | if (iter == 0) {
38 | bufsize = sizeof(buffer);
39 | base = buffer;
40 | } else {
41 | bufsize = 30000;
42 | base = new char[bufsize];
43 | }
44 | char* p = base;
45 | char* limit = base + bufsize;
46 |
47 | struct timeval now_tv;
48 | gettimeofday(&now_tv, NULL);
49 | const time_t seconds = now_tv.tv_sec;
50 | struct tm t;
51 | localtime_r(&seconds, &t);
52 | p += snprintf(p, limit - p,
53 | "%04d/%02d/%02d-%02d:%02d:%02d.%06d %llx ",
54 | t.tm_year + 1900,
55 | t.tm_mon + 1,
56 | t.tm_mday,
57 | t.tm_hour,
58 | t.tm_min,
59 | t.tm_sec,
60 | static_cast(now_tv.tv_usec),
61 | static_cast(thread_id));
62 |
63 | // Print the message
64 | if (p < limit) {
65 | va_list backup_ap;
66 | va_copy(backup_ap, ap);
67 | p += vsnprintf(p, limit - p, format, backup_ap);
68 | va_end(backup_ap);
69 | }
70 |
71 | // Truncate to available space if necessary
72 | if (p >= limit) {
73 | if (iter == 0) {
74 | continue; // Try again with larger buffer
75 | } else {
76 | p = limit - 1;
77 | }
78 | }
79 |
80 | // Add newline if necessary
81 | if (p == base || p[-1] != '\n') {
82 | *p++ = '\n';
83 | }
84 |
85 | assert(p <= limit);
86 | fwrite(base, 1, p - base, file_);
87 | fflush(file_);
88 | if (base != buffer) {
89 | delete[] base;
90 | }
91 | break;
92 | }
93 | }
94 | };
95 |
96 | } // namespace leveldb
97 |
98 | #endif // STORAGE_LEVELDB_UTIL_POSIX_LOGGER_H_
99 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/filter_policy.h:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 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 | // A database can be configured with a custom FilterPolicy object.
6 | // This object is responsible for creating a small filter from a set
7 | // of keys. These filters are stored in leveldb and are consulted
8 | // automatically by leveldb to decide whether or not to read some
9 | // information from disk. In many cases, a filter can cut down the
10 | // number of disk seeks form a handful to a single disk seek per
11 | // DB::Get() call.
12 | //
13 | // Most people will want to use the builtin bloom filter support (see
14 | // NewBloomFilterPolicy() below).
15 |
16 | #ifndef STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_
17 | #define STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_
18 |
19 | #include
20 |
21 | namespace leveldb {
22 |
23 | class Slice;
24 |
25 | class FilterPolicy {
26 | public:
27 | virtual ~FilterPolicy();
28 |
29 | // Return the name of this policy. Note that if the filter encoding
30 | // changes in an incompatible way, the name returned by this method
31 | // must be changed. Otherwise, old incompatible filters may be
32 | // passed to methods of this type.
33 | virtual const char* Name() const = 0;
34 |
35 | // keys[0,n-1] contains a list of keys (potentially with duplicates)
36 | // that are ordered according to the user supplied comparator.
37 | // Append a filter that summarizes keys[0,n-1] to *dst.
38 | //
39 | // Warning: do not change the initial contents of *dst. Instead,
40 | // append the newly constructed filter to *dst.
41 | virtual void CreateFilter(const Slice* keys, int n, std::string* dst)
42 | const = 0;
43 |
44 | // "filter" contains the data appended by a preceding call to
45 | // CreateFilter() on this class. This method must return true if
46 | // the key was in the list of keys passed to CreateFilter().
47 | // This method may return true or false if the key was not on the
48 | // list, but it should aim to return false with a high probability.
49 | virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0;
50 | };
51 |
52 | // Return a new filter policy that uses a bloom filter with approximately
53 | // the specified number of bits per key. A good value for bits_per_key
54 | // is 10, which yields a filter with ~ 1% false positive rate.
55 | //
56 | // Callers must delete the result after any database that is using the
57 | // result has been closed.
58 | //
59 | // Note: if you are using a custom comparator that ignores some parts
60 | // of the keys being compared, you must not use NewBloomFilterPolicy()
61 | // and must provide your own FilterPolicy that also ignores the
62 | // corresponding parts of the keys. For example, if the comparator
63 | // ignores trailing spaces, it would be incorrect to use a
64 | // FilterPolicy (like NewBloomFilterPolicy) that does not ignore
65 | // trailing spaces in keys.
66 | extern const FilterPolicy* NewBloomFilterPolicy(int bits_per_key);
67 |
68 | }
69 |
70 | #endif // STORAGE_LEVELDB_INCLUDE_FILTER_POLICY_H_
71 |
--------------------------------------------------------------------------------
/memorypool/StackAlloc.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright (c) 2013 Cosku Acay, http://www.coskuacay.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 |
24 | /*-
25 | * A template class that implements a simple stack structure.
26 | * This demostrates how to use alloctor_traits (specifically with MemoryPool)
27 | */
28 |
29 | #ifndef STACK_ALLOC_H
30 | #define STACK_ALLOC_H
31 |
32 | #include
33 |
34 | template
35 | struct StackNode_
36 | {
37 | T data;
38 | StackNode_* prev;
39 | };
40 |
41 | /** T is the object to store in the stack, Alloc is the allocator to use */
42 | template >
43 | class StackAlloc
44 | {
45 | public:
46 | typedef StackNode_ Node;
47 | typedef typename Alloc::template rebind::other allocator;
48 |
49 | /** Default constructor */
50 | StackAlloc() {head_ = 0; }
51 | /** Default destructor */
52 | ~StackAlloc() { clear(); }
53 |
54 | /** Returns true if the stack is empty */
55 | bool empty() {return (head_ == 0);}
56 |
57 | /** Deallocate all elements and empty the stack */
58 | void clear() {
59 | Node* curr = head_;
60 | while (curr != 0)
61 | {
62 | Node* tmp = curr->prev;
63 | allocator_.destroy(curr);
64 | allocator_.deallocate(curr, 1);
65 | curr = tmp;
66 | }
67 | head_ = 0;
68 | }
69 |
70 | /** Put an element on the top of the stack */
71 | void push(T element) {
72 | Node* newNode = allocator_.allocate(1);
73 | allocator_.construct(newNode, Node());
74 | newNode->data = element;
75 | newNode->prev = head_;
76 | head_ = newNode;
77 | }
78 |
79 | /** Remove and return the topmost element on the stack */
80 | T pop() {
81 | T result = head_->data;
82 | Node* tmp = head_->prev;
83 | allocator_.destroy(head_);
84 | allocator_.deallocate(head_, 1);
85 | head_ = tmp;
86 | return result;
87 | }
88 |
89 | /** Return the topmost element */
90 | T top() { return (head_->data); }
91 |
92 | private:
93 | allocator allocator_;
94 | Node* head_;
95 | };
96 |
97 | #endif // STACK_ALLOC_H
98 |
--------------------------------------------------------------------------------
/leveldb/util/bloom.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 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 "leveldb/filter_policy.h"
6 |
7 | #include "leveldb/slice.h"
8 | #include "util/hash.h"
9 |
10 | namespace leveldb {
11 |
12 | namespace {
13 | static uint32_t BloomHash(const Slice& key) {
14 | return Hash(key.data(), key.size(), 0xbc9f1d34);
15 | }
16 |
17 | class BloomFilterPolicy : public FilterPolicy {
18 | private:
19 | size_t bits_per_key_;
20 | size_t k_;
21 |
22 | public:
23 | explicit BloomFilterPolicy(int bits_per_key)
24 | : bits_per_key_(bits_per_key) {
25 | // We intentionally round down to reduce probing cost a little bit
26 | k_ = static_cast(bits_per_key * 0.69); // 0.69 =~ ln(2)
27 | if (k_ < 1) k_ = 1;
28 | if (k_ > 30) k_ = 30;
29 | }
30 |
31 | virtual const char* Name() const {
32 | return "leveldb.BuiltinBloomFilter2";
33 | }
34 |
35 | virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
36 | // Compute bloom filter size (in both bits and bytes)
37 | size_t bits = n * bits_per_key_;
38 |
39 | // For small n, we can see a very high false positive rate. Fix it
40 | // by enforcing a minimum bloom filter length.
41 | if (bits < 64) bits = 64;
42 |
43 | size_t bytes = (bits + 7) / 8;
44 | bits = bytes * 8;
45 |
46 | const size_t init_size = dst->size();
47 | dst->resize(init_size + bytes, 0);
48 | dst->push_back(static_cast(k_)); // Remember # of probes in filter
49 | char* array = &(*dst)[init_size];
50 | for (int i = 0; i < n; i++) {
51 | // Use double-hashing to generate a sequence of hash values.
52 | // See analysis in [Kirsch,Mitzenmacher 2006].
53 | uint32_t h = BloomHash(keys[i]);
54 | const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
55 | for (size_t j = 0; j < k_; j++) {
56 | const uint32_t bitpos = h % bits;
57 | array[bitpos/8] |= (1 << (bitpos % 8));
58 | h += delta;
59 | }
60 | }
61 | }
62 |
63 | virtual bool KeyMayMatch(const Slice& key, const Slice& bloom_filter) const {
64 | const size_t len = bloom_filter.size();
65 | if (len < 2) return false;
66 |
67 | const char* array = bloom_filter.data();
68 | const size_t bits = (len - 1) * 8;
69 |
70 | // Use the encoded k so that we can read filters generated by
71 | // bloom filters created using different parameters.
72 | const size_t k = array[len-1];
73 | if (k > 30) {
74 | // Reserved for potentially new encodings for short bloom filters.
75 | // Consider it a match.
76 | return true;
77 | }
78 |
79 | uint32_t h = BloomHash(key);
80 | const uint32_t delta = (h >> 17) | (h << 15); // Rotate right 17 bits
81 | for (size_t j = 0; j < k; j++) {
82 | const uint32_t bitpos = h % bits;
83 | if ((array[bitpos/8] & (1 << (bitpos % 8))) == 0) return false;
84 | h += delta;
85 | }
86 | return true;
87 | }
88 | };
89 | }
90 |
91 | const FilterPolicy* NewBloomFilterPolicy(int bits_per_key) {
92 | return new BloomFilterPolicy(bits_per_key);
93 | }
94 |
95 | } // namespace leveldb
96 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/table.h:
--------------------------------------------------------------------------------
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_INCLUDE_TABLE_H_
6 | #define STORAGE_LEVELDB_INCLUDE_TABLE_H_
7 |
8 | #include
9 | #include "leveldb/iterator.h"
10 |
11 | namespace leveldb {
12 |
13 | class Block;
14 | class BlockHandle;
15 | class Footer;
16 | struct Options;
17 | class RandomAccessFile;
18 | struct ReadOptions;
19 | class TableCache;
20 |
21 | // A Table is a sorted map from strings to strings. Tables are
22 | // immutable and persistent. A Table may be safely accessed from
23 | // multiple threads without external synchronization.
24 | // sstable,访问线程安全
25 | class Table {
26 | public:
27 | // Attempt to open the table that is stored in bytes [0..file_size)
28 | // of "file", and read the metadata entries necessary to allow
29 | // retrieving data from the table.
30 | //
31 | // If successful, returns ok and sets "*table" to the newly opened
32 | // table. The client should delete "*table" when no longer needed.
33 | // If there was an error while initializing the table, sets "*table"
34 | // to NULL and returns a non-ok status. Does not take ownership of
35 | // "*source", but the client must ensure that "source" remains live
36 | // for the duration of the returned table's lifetime.
37 | //
38 | // *file must remain live while this Table is in use.
39 | static Status Open(const Options& options,
40 | RandomAccessFile* file,
41 | uint64_t file_size,
42 | Table** table);
43 |
44 | ~Table();
45 |
46 | // Returns a new iterator over the table contents.
47 | // The result of NewIterator() is initially invalid (caller must
48 | // call one of the Seek methods on the iterator before using it).
49 | Iterator* NewIterator(const ReadOptions&) const;
50 |
51 | // Given a key, return an approximate byte offset in the file where
52 | // the data for that key begins (or would begin if the key were
53 | // present in the file). The returned value is in terms of file
54 | // bytes, and so includes effects like compression of the underlying data.
55 | // E.g., the approximate offset of the last key in the table will
56 | // be close to the file length.
57 | uint64_t ApproximateOffsetOf(const Slice& key) const;
58 |
59 | private:
60 | struct Rep;
61 | Rep* rep_;
62 |
63 | explicit Table(Rep* rep) { rep_ = rep; }
64 | static Iterator* BlockReader(void*, const ReadOptions&, const Slice&);
65 |
66 | // Calls (*handle_result)(arg, ...) with the entry found after a call
67 | // to Seek(key). May not make such a call if filter policy says
68 | // that key is not present.
69 | friend class TableCache;
70 | Status InternalGet(
71 | const ReadOptions&, const Slice& key,
72 | void* arg,
73 | void (*handle_result)(void* arg, const Slice& k, const Slice& v));
74 |
75 |
76 | void ReadMeta(const Footer& footer);
77 | void ReadFilter(const Slice& filter_handle_value);
78 |
79 | // No copying allowed
80 | Table(const Table&);
81 | void operator=(const Table&);
82 | };
83 |
84 | } // namespace leveldb
85 |
86 | #endif // STORAGE_LEVELDB_INCLUDE_TABLE_H_
87 |
--------------------------------------------------------------------------------
/leveldb/db/memtable.h:
--------------------------------------------------------------------------------
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_DB_MEMTABLE_H_
6 | #define STORAGE_LEVELDB_DB_MEMTABLE_H_
7 |
8 | #include
9 | #include "leveldb/db.h"
10 | #include "db/dbformat.h"
11 | #include "db/skiplist.h"
12 | #include "util/arena.h"
13 |
14 | namespace leveldb {
15 |
16 | class InternalKeyComparator;
17 | class Mutex;
18 | class MemTableIterator;
19 |
20 | class MemTable {
21 | public:
22 | // MemTables are reference counted. The initial reference count
23 | // is zero and the caller must call Ref() at least once.
24 | // 靠引用计数,初始为 0,必须至少调用一次 Ref()
25 | explicit MemTable(const InternalKeyComparator& comparator);
26 |
27 | // Increase reference count.
28 | // 加引用计数
29 | void Ref() { ++refs_; }
30 |
31 | // Drop reference count. Delete if no more references exist.
32 | // 递减引用计数。为 0 时删除。
33 | void Unref() {
34 | --refs_;
35 | assert(refs_ >= 0);
36 | if (refs_ <= 0) {
37 | delete this;
38 | }
39 | }
40 |
41 | // Returns an estimate of the number of bytes of data in use by this
42 | // data structure. It is safe to call when MemTable is being modified.
43 | // 返回使用的字节数
44 | size_t ApproximateMemoryUsage();
45 |
46 | // Return an iterator that yields the contents of the memtable.
47 | //
48 | // The caller must ensure that the underlying MemTable remains live
49 | // while the returned iterator is live. The keys returned by this
50 | // iterator are internal keys encoded by AppendInternalKey in the
51 | // db/format.{h,cc} module.
52 | // 返回可以遍历 memtable 的迭代器
53 | Iterator* NewIterator();
54 |
55 | // Add an entry into memtable that maps key to value at the
56 | // specified sequence number and with the specified type.
57 | // Typically value will be empty if type==kTypeDeletion.
58 | // 往 memtable 添加键值对。
59 | // type 为 kTypeDeletion 时 value 为空。
60 | void Add(SequenceNumber seq, ValueType type,
61 | const Slice& key,
62 | const Slice& value);
63 |
64 | // If memtable contains a value for key, store it in *value and return true.
65 | // If memtable contains a deletion for key, store a NotFound() error
66 | // in *status and return true.
67 | // Else, return false.
68 | // key 存在 value 时,存储 value 到指针返回 true
69 | // memtable 中有对 key 的 deletion 时,存储 NotFound 到 status 并返回 true
70 | // 其他情况返回 false.
71 | bool Get(const LookupKey& key, std::string* value, Status* s);
72 |
73 | private:
74 | // 不允许外部调用析构函数
75 | ~MemTable(); // Private since only Unref() should be used to delete it
76 |
77 | struct KeyComparator {
78 | const InternalKeyComparator comparator;
79 | explicit KeyComparator(const InternalKeyComparator& c) : comparator(c) { }
80 | int operator()(const char* a, const char* b) const;
81 | };
82 | friend class MemTableIterator;
83 | friend class MemTableBackwardIterator;
84 |
85 | // 内部为 skiplist 实现
86 | typedef SkipList Table;
87 |
88 | KeyComparator comparator_;
89 | int refs_;
90 | Arena arena_;
91 | Table table_;
92 |
93 | // No copying allowed
94 | // 禁止拷贝构造
95 | MemTable(const MemTable&);
96 | void operator=(const MemTable&);
97 | };
98 |
99 | } // namespace leveldb
100 |
101 | #endif // STORAGE_LEVELDB_DB_MEMTABLE_H_
102 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/slice.h:
--------------------------------------------------------------------------------
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 | // Slice is a simple structure containing a pointer into some external
6 | // storage and a size. The user of a Slice must ensure that the slice
7 | // is not used after the corresponding external storage has been
8 |
9 | // deallocated.
10 | //
11 | // Multiple threads can invoke const methods on a Slice without
12 | // external synchronization, but if any of the threads may call a
13 | // non-const method, all threads accessing the same Slice must use
14 | // external synchronization.
15 |
16 | // Slice 只是一个包含了字符串指针和大小的结构
17 |
18 | #ifndef STORAGE_LEVELDB_INCLUDE_SLICE_H_
19 | #define STORAGE_LEVELDB_INCLUDE_SLICE_H_
20 |
21 | #include
22 | #include
23 | #include
24 | #include
25 |
26 | namespace leveldb {
27 |
28 | class Slice {
29 | public:
30 | // Create an empty slice.
31 | Slice() : data_(""), size_(0) { }
32 |
33 | // Create a slice that refers to d[0,n-1].
34 | Slice(const char* d, size_t n) : data_(d), size_(n) { }
35 |
36 | // Create a slice that refers to the contents of "s"
37 | Slice(const std::string& s) : data_(s.data()), size_(s.size()) { }
38 |
39 | // Create a slice that refers to s[0,strlen(s)-1]
40 | Slice(const char* s) : data_(s), size_(strlen(s)) { }
41 |
42 | // Return a pointer to the beginning of the referenced data
43 | const char* data() const { return data_; }
44 |
45 | // Return the length (in bytes) of the referenced data
46 | size_t size() const { return size_; }
47 |
48 | // Return true iff the length of the referenced data is zero
49 | bool empty() const { return size_ == 0; }
50 |
51 | // Return the ith byte in the referenced data.
52 | // REQUIRES: n < size()
53 | char operator[](size_t n) const {
54 | assert(n < size());
55 | return data_[n];
56 | }
57 |
58 | // Change this slice to refer to an empty array
59 | void clear() { data_ = ""; size_ = 0; }
60 |
61 | // Drop the first "n" bytes from this slice.
62 | void remove_prefix(size_t n) {
63 | assert(n <= size());
64 | data_ += n;
65 | size_ -= n;
66 | }
67 |
68 | // Return a string that contains the copy of the referenced data.
69 | std::string ToString() const { return std::string(data_, size_); }
70 |
71 | // Three-way comparison. Returns value:
72 | // < 0 iff "*this" < "b",
73 | // == 0 iff "*this" == "b",
74 | // > 0 iff "*this" > "b"
75 | int compare(const Slice& b) const;
76 |
77 | // Return true iff "x" is a prefix of "*this"
78 | bool starts_with(const Slice& x) const {
79 | return ((size_ >= x.size_) &&
80 | (memcmp(data_, x.data_, x.size_) == 0));
81 | }
82 |
83 | private:
84 | const char* data_;
85 | size_t size_;
86 |
87 | // Intentionally copyable
88 | };
89 |
90 | inline bool operator==(const Slice& x, const Slice& y) {
91 | return ((x.size() == y.size()) &&
92 | (memcmp(x.data(), y.data(), x.size()) == 0));
93 | }
94 |
95 | inline bool operator!=(const Slice& x, const Slice& y) {
96 | return !(x == y);
97 | }
98 |
99 | inline int Slice::compare(const Slice& b) const {
100 | const size_t min_len = (size_ < b.size_) ? size_ : b.size_;
101 | int r = memcmp(data_, b.data_, min_len);
102 | if (r == 0) {
103 | if (size_ < b.size_) r = -1;
104 | else if (size_ > b.size_) r = +1;
105 | }
106 | return r;
107 | }
108 |
109 | } // namespace leveldb
110 |
111 |
112 | #endif // STORAGE_LEVELDB_INCLUDE_SLICE_H_
113 |
--------------------------------------------------------------------------------
/leveldb/table/format.h:
--------------------------------------------------------------------------------
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_TABLE_FORMAT_H_
6 | #define STORAGE_LEVELDB_TABLE_FORMAT_H_
7 |
8 | #include
9 | #include
10 | #include "leveldb/slice.h"
11 | #include "leveldb/status.h"
12 | #include "leveldb/table_builder.h"
13 |
14 | namespace leveldb {
15 |
16 | class Block;
17 | class RandomAccessFile;
18 | struct ReadOptions;
19 |
20 | // BlockHandle is a pointer to the extent of a file that stores a data
21 | // block or a meta block.
22 | // block 的元信息(位于sstable的offset/size)封装成 BlockHandle
23 | class BlockHandle {
24 | public:
25 | BlockHandle();
26 |
27 | // The offset of the block in the file.
28 | uint64_t offset() const { return offset_; }
29 | void set_offset(uint64_t offset) { offset_ = offset; }
30 |
31 | // The size of the stored block
32 | uint64_t size() const { return size_; }
33 | void set_size(uint64_t size) { size_ = size; }
34 |
35 | void EncodeTo(std::string* dst) const;
36 | Status DecodeFrom(Slice* input);
37 |
38 | // Maximum encoding length of a BlockHandle
39 | enum { kMaxEncodedLength = 10 + 10 };
40 |
41 | private:
42 | uint64_t offset_;
43 | uint64_t size_;
44 | };
45 |
46 | // Footer encapsulates the fixed information stored at the tail
47 | // end of every table file.
48 | class Footer {
49 | public:
50 | Footer() { }
51 |
52 | // The block handle for the metaindex block of the table
53 | const BlockHandle& metaindex_handle() const { return metaindex_handle_; }
54 | void set_metaindex_handle(const BlockHandle& h) { metaindex_handle_ = h; }
55 |
56 | // The block handle for the index block of the table
57 | const BlockHandle& index_handle() const {
58 | return index_handle_;
59 | }
60 | void set_index_handle(const BlockHandle& h) {
61 | index_handle_ = h;
62 | }
63 |
64 | void EncodeTo(std::string* dst) const;
65 | Status DecodeFrom(Slice* input);
66 |
67 | // Encoded length of a Footer. Note that the serialization of a
68 | // Footer will always occupy exactly this many bytes. It consists
69 | // of two block handles and a magic number.
70 | enum {
71 | kEncodedLength = 2*BlockHandle::kMaxEncodedLength + 8
72 | };
73 |
74 | private:
75 | BlockHandle metaindex_handle_;
76 | BlockHandle index_handle_;
77 | };
78 |
79 | // kTableMagicNumber was picked by running
80 | // echo http://code.google.com/p/leveldb/ | sha1sum
81 | // and taking the leading 64 bits.
82 | static const uint64_t kTableMagicNumber = 0xdb4775248b80fb57ull;
83 |
84 | // 1-byte type + 32-bit crc
85 | static const size_t kBlockTrailerSize = 5;
86 |
87 | struct BlockContents {
88 | Slice data; // Actual contents of data
89 | bool cachable; // True iff data can be cached
90 | bool heap_allocated; // True iff caller should delete[] data.data()
91 | };
92 |
93 | // Read the block identified by "handle" from "file". On failure
94 | // return non-OK. On success fill *result and return OK.
95 | // 读取一个 block
96 | extern Status ReadBlock(RandomAccessFile* file,
97 | const ReadOptions& options,
98 | const BlockHandle& handle,
99 | BlockContents* result);
100 |
101 | // Implementation details follow. Clients should ignore,
102 |
103 | inline BlockHandle::BlockHandle()
104 | : offset_(~static_cast(0)),
105 | size_(~static_cast(0)) {
106 | }
107 |
108 | } // namespace leveldb
109 |
110 | #endif // STORAGE_LEVELDB_TABLE_FORMAT_H_
111 |
--------------------------------------------------------------------------------
/memorypool/C-11/MemoryPool.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright (c) 2013 Cosku Acay, http://www.coskuacay.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef MEMORY_POOL_H
24 | #define MEMORY_POOL_H
25 |
26 | #include
27 | #include
28 |
29 | template
30 | class MemoryPool
31 | {
32 | public:
33 | /* Member types */
34 | typedef T value_type;
35 | typedef T* pointer;
36 | typedef T& reference;
37 | typedef const T* const_pointer;
38 | typedef const T& const_reference;
39 | typedef size_t size_type;
40 | typedef ptrdiff_t difference_type;
41 | typedef std::false_type propagate_on_container_copy_assignment;
42 | typedef std::true_type propagate_on_container_move_assignment;
43 | typedef std::true_type propagate_on_container_swap;
44 |
45 | template struct rebind {
46 | typedef MemoryPool other;
47 | };
48 |
49 | /* Member functions */
50 | MemoryPool() noexcept;
51 | MemoryPool(const MemoryPool& memoryPool) noexcept;
52 | MemoryPool(MemoryPool&& memoryPool) noexcept;
53 | template MemoryPool(const MemoryPool& memoryPool) noexcept;
54 |
55 | ~MemoryPool() noexcept;
56 |
57 | MemoryPool& operator=(const MemoryPool& memoryPool) = delete;
58 | MemoryPool& operator=(MemoryPool&& memoryPool) noexcept;
59 |
60 | pointer address(reference x) const noexcept;
61 | const_pointer address(const_reference x) const noexcept;
62 |
63 | // Can only allocate one object at a time. n and hint are ignored
64 | pointer allocate(size_type n = 1, const_pointer hint = 0);
65 | void deallocate(pointer p, size_type n = 1);
66 |
67 | size_type max_size() const noexcept;
68 |
69 | template void construct(U* p, Args&&... args);
70 | template void destroy(U* p);
71 |
72 | template pointer newElement(Args&&... args);
73 | void deleteElement(pointer p);
74 |
75 | private:
76 | union Slot_ {
77 | value_type element;
78 | Slot_* next;
79 | };
80 |
81 | typedef char* data_pointer_;
82 | typedef Slot_ slot_type_;
83 | typedef Slot_* slot_pointer_;
84 |
85 | slot_pointer_ currentBlock_;
86 | slot_pointer_ currentSlot_;
87 | slot_pointer_ lastSlot_;
88 | slot_pointer_ freeSlots_;
89 |
90 | size_type padPointer(data_pointer_ p, size_type align) const noexcept;
91 | void allocateBlock();
92 |
93 | static_assert(BlockSize >= 2 * sizeof(slot_type_), "BlockSize too small.");
94 | };
95 |
96 | #include "MemoryPool.tcc"
97 |
98 | #endif // MEMORY_POOL_H
99 |
--------------------------------------------------------------------------------
/leveldb/db/filename.h:
--------------------------------------------------------------------------------
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 | // File names used by DB code
6 |
7 | #ifndef STORAGE_LEVELDB_DB_FILENAME_H_
8 | #define STORAGE_LEVELDB_DB_FILENAME_H_
9 |
10 | #include
11 | #include
12 | #include "leveldb/slice.h"
13 | #include "leveldb/status.h"
14 | #include "port/port.h"
15 |
16 | namespace leveldb {
17 |
18 | class Env;
19 |
20 | enum FileType {
21 | kLogFile, // binlog 文件,文件名为 [0-9]+.log,前缀数字为 FileNumber
22 | kDBLockFile, // lock 文件,一个 db 同时只能有一个 db 实例操作,通过对 LOCK 文件加文件锁(flock)实现主动保护。
23 | kTableFile, // sstable文件,文件名为 [0-9]+.sst
24 | kDescriptorFile, // db 元信息文件:MANIFEST-[0-9]+ ,每当 db 中的状态改变(VersionSet),会将这次改变(VersionEdit)追加到 descriptor 文件中。 后缀数字为 FileNumber。
25 | kCurrentFile, // CURRENT 文件,保存当前使用的descriptor文件的文件名
26 | kTempFile, // 临时文件:[0-9]+.dbtmp ,对 db 做修复(Repairer)时,会产生临时文件。前缀为 FileNumber。
27 | kInfoLogFile // Either the current one, or an old one // db 运行时打印日志的文件:LOG, 每次重新运行,如果已经存在 LOG 文件,会先将 LOG 文件重名成 LOG.old
28 | };
29 |
30 | // Return the name of the log file with the specified number
31 | // in the db named by "dbname". The result will be prefixed with
32 | // "dbname".
33 | extern std::string LogFileName(const std::string& dbname, uint64_t number);
34 |
35 | // Return the name of the sstable with the specified number
36 | // in the db named by "dbname". The result will be prefixed with
37 | // "dbname".
38 | extern std::string TableFileName(const std::string& dbname, uint64_t number);
39 |
40 | // Return the legacy file name for an sstable with the specified number
41 | // in the db named by "dbname". The result will be prefixed with
42 | // "dbname".
43 | extern std::string SSTTableFileName(const std::string& dbname, uint64_t number);
44 |
45 | // Return the name of the descriptor file for the db named by
46 | // "dbname" and the specified incarnation number. The result will be
47 | // prefixed with "dbname".
48 | extern std::string DescriptorFileName(const std::string& dbname,
49 | uint64_t number);
50 |
51 | // Return the name of the current file. This file contains the name
52 | // of the current manifest file. The result will be prefixed with
53 | // "dbname".
54 | extern std::string CurrentFileName(const std::string& dbname);
55 |
56 | // Return the name of the lock file for the db named by
57 | // "dbname". The result will be prefixed with "dbname".
58 | extern std::string LockFileName(const std::string& dbname);
59 |
60 | // Return the name of a temporary file owned by the db named "dbname".
61 | // The result will be prefixed with "dbname".
62 | extern std::string TempFileName(const std::string& dbname, uint64_t number);
63 |
64 | // Return the name of the info log file for "dbname".
65 | extern std::string InfoLogFileName(const std::string& dbname);
66 |
67 | // Return the name of the old info log file for "dbname".
68 | extern std::string OldInfoLogFileName(const std::string& dbname);
69 |
70 | // If filename is a leveldb file, store the type of the file in *type.
71 | // The number encoded in the filename is stored in *number. If the
72 | // filename was successfully parsed, returns true. Else return false.
73 | extern bool ParseFileName(const std::string& filename,
74 | uint64_t* number,
75 | FileType* type);
76 |
77 | // Make the CURRENT file point to the descriptor file with the
78 | // specified number.
79 | extern Status SetCurrentFile(Env* env, const std::string& dbname,
80 | uint64_t descriptor_number);
81 |
82 |
83 | } // namespace leveldb
84 |
85 | #endif // STORAGE_LEVELDB_DB_FILENAME_H_
86 |
--------------------------------------------------------------------------------
/leveldb/db/log_writer.cc:
--------------------------------------------------------------------------------
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 "db/log_writer.h"
6 |
7 | #include
8 | #include "leveldb/env.h"
9 | #include "util/coding.h"
10 | #include "util/crc32c.h"
11 |
12 | namespace leveldb {
13 | namespace log {
14 |
15 | static void InitTypeCrc(uint32_t* type_crc) {
16 | for (int i = 0; i <= kMaxRecordType; i++) {
17 | char t = static_cast(i);
18 | type_crc[i] = crc32c::Value(&t, 1);
19 | }
20 | }
21 |
22 | Writer::Writer(WritableFile* dest)
23 | : dest_(dest),
24 | block_offset_(0) {
25 | InitTypeCrc(type_crc_);
26 | }
27 |
28 | Writer::Writer(WritableFile* dest, uint64_t dest_length)
29 | : dest_(dest), block_offset_(dest_length % kBlockSize) {
30 | InitTypeCrc(type_crc_);
31 | }
32 |
33 | Writer::~Writer() {
34 | }
35 |
36 | Status Writer::AddRecord(const Slice& slice) {
37 | const char* ptr = slice.data();
38 | size_t left = slice.size();
39 |
40 | // Fragment the record if necessary and emit it. Note that if slice
41 | // is empty, we still want to iterate once to emit a single
42 | // zero-length record
43 | Status s;
44 | bool begin = true;
45 | do {
46 | const int leftover = kBlockSize - block_offset_;
47 | assert(leftover >= 0);
48 | // 剩余长度小于 record 头长度时,开始新的 block
49 | if (leftover < kHeaderSize) {
50 | // Switch to a new block
51 | if (leftover > 0) {
52 | // Fill the trailer (literal below relies on kHeaderSize being 7)
53 | assert(kHeaderSize == 7);
54 | // 注意这里的 leftover 最小是 0 最大是 6
55 | dest_->Append(Slice("\x00\x00\x00\x00\x00\x00", leftover));
56 | }
57 | block_offset_ = 0;
58 | }
59 |
60 | // Invariant: we never leave < kHeaderSize bytes in a block.
61 | assert(kBlockSize - block_offset_ - kHeaderSize >= 0);
62 |
63 | // record 可以写入当前 block 的长度
64 | const size_t avail = kBlockSize - block_offset_ - kHeaderSize;
65 | const size_t fragment_length = (left < avail) ? left : avail;
66 |
67 | // 计算写入的是哪一种 type
68 | RecordType type;
69 | const bool end = (left == fragment_length);
70 | if (begin && end) {
71 | type = kFullType;
72 | } else if (begin) {
73 | type = kFirstType;
74 | } else if (end) {
75 | type = kLastType;
76 | } else {
77 | type = kMiddleType;
78 | }
79 |
80 | s = EmitPhysicalRecord(type, ptr, fragment_length);
81 | ptr += fragment_length;
82 | left -= fragment_length;
83 | begin = false;
84 | } while (s.ok() && left > 0); // 循环直到写完 record
85 | return s;
86 | }
87 |
88 | // 写入 n 长度的 record
89 | Status Writer::EmitPhysicalRecord(RecordType t, const char* ptr, size_t n) {
90 | assert(n <= 0xffff); // Must fit in two bytes
91 | assert(block_offset_ + kHeaderSize + n <= kBlockSize);
92 |
93 | // Format the header
94 | // 构造 record 头部
95 | char buf[kHeaderSize];
96 | buf[4] = static_cast(n & 0xff);
97 | buf[5] = static_cast(n >> 8);
98 | buf[6] = static_cast(t);
99 |
100 | // Compute the crc of the record type and the payload.
101 | // 计算校验码
102 | uint32_t crc = crc32c::Extend(type_crc_[t], ptr, n);
103 | crc = crc32c::Mask(crc); // Adjust for storage
104 | EncodeFixed32(buf, crc);
105 |
106 | // Write the header and the payload
107 | // 写入 header 和 数据
108 | Status s = dest_->Append(Slice(buf, kHeaderSize));
109 | if (s.ok()) {
110 | s = dest_->Append(Slice(ptr, n));
111 | if (s.ok()) {
112 | s = dest_->Flush();
113 | }
114 | }
115 | block_offset_ += kHeaderSize + n;
116 | return s;
117 | }
118 |
119 | } // namespace log
120 | } // namespace leveldb
121 |
--------------------------------------------------------------------------------
/memorypool/C-98/MemoryPool.h:
--------------------------------------------------------------------------------
1 | /*-
2 | * Copyright (c) 2013 Cosku Acay, http://www.coskuacay.com
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a
5 | * copy of this software and associated documentation files (the "Software"),
6 | * to deal in the Software without restriction, including without limitation
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 | * and/or sell copies of the Software, and to permit persons to whom the
9 | * Software is furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
20 | * IN THE SOFTWARE.
21 | */
22 |
23 | #ifndef MEMORY_POOL_H
24 | #define MEMORY_POOL_H
25 |
26 | #include
27 | #include
28 |
29 | template
30 | class MemoryPool
31 | {
32 | public:
33 | /* Member types */
34 | typedef T value_type; // T 的 value 类型
35 | typedef T* pointer; // T 的 指针类型
36 | typedef T& reference; // T 的引用类型
37 | typedef const T* const_pointer; // T 的 const 指针类型
38 | typedef const T& const_reference; // T 的 const 引用类型
39 | typedef size_t size_type; // size_t 类型
40 | typedef ptrdiff_t difference_type; // 指针减法结果类型
41 |
42 | // 这个来源于 allocate 的标准
43 | template struct rebind {
44 | typedef MemoryPool other;
45 | };
46 |
47 | /* Member functions */
48 | /* 构造函数 */
49 | MemoryPool() throw();
50 | MemoryPool(const MemoryPool& memoryPool) throw();
51 | template MemoryPool(const MemoryPool& memoryPool) throw();
52 |
53 | /* 析构函数 */
54 | ~MemoryPool() throw();
55 |
56 | /* 元素取址 */
57 | pointer address(reference x) const throw();
58 | const_pointer address(const_reference x) const throw();
59 |
60 | // Can only allocate one object at a time. n and hint are ignored
61 | // 分配和收回一个元素的内存空间
62 | pointer allocate(size_type n = 1, const_pointer hint = 0);
63 | void deallocate(pointer p, size_type n = 1);
64 |
65 | // 最大大小
66 | size_type max_size() const throw();
67 |
68 | // 基于内存池的元素构造和析构
69 | void construct(pointer p, const_reference val);
70 | void destroy(pointer p);
71 |
72 | // 自带申请内存和释放内存的构造和析构
73 | pointer newElement(const_reference val);
74 | void deleteElement(pointer p);
75 |
76 | private:
77 | // union 结构体,用于存放元素或 next 指针
78 | union Slot_ {
79 | value_type element;
80 | Slot_* next;
81 | };
82 |
83 | typedef char* data_pointer_; // char* 指针,主要用于指向内存首地址
84 | typedef Slot_ slot_type_; // Slot_ 值类型
85 | typedef Slot_* slot_pointer_; // Slot_* 指针类型
86 |
87 | slot_pointer_ currentBlock_; // 内存块链表的头指针
88 | slot_pointer_ currentSlot_; // 元素链表的头指针
89 | slot_pointer_ lastSlot_; // 可存放元素的最后指针
90 | slot_pointer_ freeSlots_; // 元素构造后释放掉的内存链表头指针
91 |
92 | size_type padPointer(data_pointer_ p, size_type align) const throw(); // 计算对齐所需空间
93 | void allocateBlock(); // 申请内存块放进内存池
94 | /*
95 | static_assert(BlockSize >= 2 * sizeof(slot_type_), "BlockSize too small.");
96 | */
97 | };
98 |
99 | #include "MemoryPool.tcc"
100 |
101 | #endif // MEMORY_POOL_H
102 |
--------------------------------------------------------------------------------
/leveldb/db/autocompact_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2013 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 "leveldb/db.h"
6 | #include "db/db_impl.h"
7 | #include "leveldb/cache.h"
8 | #include "util/testharness.h"
9 | #include "util/testutil.h"
10 |
11 | namespace leveldb {
12 |
13 | class AutoCompactTest {
14 | public:
15 | std::string dbname_;
16 | Cache* tiny_cache_;
17 | Options options_;
18 | DB* db_;
19 |
20 | AutoCompactTest() {
21 | dbname_ = test::TmpDir() + "/autocompact_test";
22 | tiny_cache_ = NewLRUCache(100);
23 | options_.block_cache = tiny_cache_;
24 | DestroyDB(dbname_, options_);
25 | options_.create_if_missing = true;
26 | options_.compression = kNoCompression;
27 | ASSERT_OK(DB::Open(options_, dbname_, &db_));
28 | }
29 |
30 | ~AutoCompactTest() {
31 | delete db_;
32 | DestroyDB(dbname_, Options());
33 | delete tiny_cache_;
34 | }
35 |
36 | std::string Key(int i) {
37 | char buf[100];
38 | snprintf(buf, sizeof(buf), "key%06d", i);
39 | return std::string(buf);
40 | }
41 |
42 | uint64_t Size(const Slice& start, const Slice& limit) {
43 | Range r(start, limit);
44 | uint64_t size;
45 | db_->GetApproximateSizes(&r, 1, &size);
46 | return size;
47 | }
48 |
49 | void DoReads(int n);
50 | };
51 |
52 | static const int kValueSize = 200 * 1024;
53 | static const int kTotalSize = 100 * 1024 * 1024;
54 | static const int kCount = kTotalSize / kValueSize;
55 |
56 | // Read through the first n keys repeatedly and check that they get
57 | // compacted (verified by checking the size of the key space).
58 | void AutoCompactTest::DoReads(int n) {
59 | std::string value(kValueSize, 'x');
60 | DBImpl* dbi = reinterpret_cast(db_);
61 |
62 | // Fill database
63 | for (int i = 0; i < kCount; i++) {
64 | ASSERT_OK(db_->Put(WriteOptions(), Key(i), value));
65 | }
66 | ASSERT_OK(dbi->TEST_CompactMemTable());
67 |
68 | // Delete everything
69 | for (int i = 0; i < kCount; i++) {
70 | ASSERT_OK(db_->Delete(WriteOptions(), Key(i)));
71 | }
72 | ASSERT_OK(dbi->TEST_CompactMemTable());
73 |
74 | // Get initial measurement of the space we will be reading.
75 | const int64_t initial_size = Size(Key(0), Key(n));
76 | const int64_t initial_other_size = Size(Key(n), Key(kCount));
77 |
78 | // Read until size drops significantly.
79 | std::string limit_key = Key(n);
80 | for (int read = 0; true; read++) {
81 | ASSERT_LT(read, 100) << "Taking too long to compact";
82 | Iterator* iter = db_->NewIterator(ReadOptions());
83 | for (iter->SeekToFirst();
84 | iter->Valid() && iter->key().ToString() < limit_key;
85 | iter->Next()) {
86 | // Drop data
87 | }
88 | delete iter;
89 | // Wait a little bit to allow any triggered compactions to complete.
90 | Env::Default()->SleepForMicroseconds(1000000);
91 | uint64_t size = Size(Key(0), Key(n));
92 | fprintf(stderr, "iter %3d => %7.3f MB [other %7.3f MB]\n",
93 | read+1, size/1048576.0, Size(Key(n), Key(kCount))/1048576.0);
94 | if (size <= initial_size/10) {
95 | break;
96 | }
97 | }
98 |
99 | // Verify that the size of the key space not touched by the reads
100 | // is pretty much unchanged.
101 | const int64_t final_other_size = Size(Key(n), Key(kCount));
102 | ASSERT_LE(final_other_size, initial_other_size + 1048576);
103 | ASSERT_GE(final_other_size, initial_other_size/5 - 1048576);
104 | }
105 |
106 | TEST(AutoCompactTest, ReadAll) {
107 | DoReads(kCount);
108 | }
109 |
110 | TEST(AutoCompactTest, ReadHalf) {
111 | DoReads(kCount/2);
112 | }
113 |
114 | } // namespace leveldb
115 |
116 | int main(int argc, char** argv) {
117 | return leveldb::test::RunAllTests();
118 | }
119 |
--------------------------------------------------------------------------------
/leveldb/table/filter_block.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 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 "table/filter_block.h"
6 |
7 | #include "leveldb/filter_policy.h"
8 | #include "util/coding.h"
9 |
10 | namespace leveldb {
11 |
12 | // See doc/table_format.txt for an explanation of the filter block format.
13 |
14 | // Generate new filter every 2KB of data
15 | static const size_t kFilterBaseLg = 11;
16 | static const size_t kFilterBase = 1 << kFilterBaseLg;
17 |
18 | FilterBlockBuilder::FilterBlockBuilder(const FilterPolicy* policy)
19 | : policy_(policy) {
20 | }
21 |
22 | void FilterBlockBuilder::StartBlock(uint64_t block_offset) {
23 | uint64_t filter_index = (block_offset / kFilterBase);
24 | assert(filter_index >= filter_offsets_.size());
25 | while (filter_index > filter_offsets_.size()) {
26 | GenerateFilter();
27 | }
28 | }
29 |
30 | void FilterBlockBuilder::AddKey(const Slice& key) {
31 | Slice k = key;
32 | start_.push_back(keys_.size());
33 | keys_.append(k.data(), k.size());
34 | }
35 |
36 | Slice FilterBlockBuilder::Finish() {
37 | if (!start_.empty()) {
38 | GenerateFilter();
39 | }
40 |
41 | // Append array of per-filter offsets
42 | const uint32_t array_offset = result_.size();
43 | for (size_t i = 0; i < filter_offsets_.size(); i++) {
44 | PutFixed32(&result_, filter_offsets_[i]);
45 | }
46 |
47 | PutFixed32(&result_, array_offset);
48 | result_.push_back(kFilterBaseLg); // Save encoding parameter in result
49 | return Slice(result_);
50 | }
51 |
52 | void FilterBlockBuilder::GenerateFilter() {
53 | const size_t num_keys = start_.size();
54 | if (num_keys == 0) {
55 | // Fast path if there are no keys for this filter
56 | filter_offsets_.push_back(result_.size());
57 | return;
58 | }
59 |
60 | // Make list of keys from flattened key structure
61 | start_.push_back(keys_.size()); // Simplify length computation
62 | tmp_keys_.resize(num_keys);
63 | for (size_t i = 0; i < num_keys; i++) {
64 | const char* base = keys_.data() + start_[i];
65 | size_t length = start_[i+1] - start_[i];
66 | tmp_keys_[i] = Slice(base, length);
67 | }
68 |
69 | // Generate filter for current set of keys and append to result_.
70 | filter_offsets_.push_back(result_.size());
71 | policy_->CreateFilter(&tmp_keys_[0], static_cast(num_keys), &result_);
72 |
73 | tmp_keys_.clear();
74 | keys_.clear();
75 | start_.clear();
76 | }
77 |
78 | FilterBlockReader::FilterBlockReader(const FilterPolicy* policy,
79 | const Slice& contents)
80 | : policy_(policy),
81 | data_(NULL),
82 | offset_(NULL),
83 | num_(0),
84 | base_lg_(0) {
85 | size_t n = contents.size();
86 | if (n < 5) return; // 1 byte for base_lg_ and 4 for start of offset array
87 | base_lg_ = contents[n-1];
88 | uint32_t last_word = DecodeFixed32(contents.data() + n - 5);
89 | if (last_word > n - 5) return;
90 | data_ = contents.data();
91 | offset_ = data_ + last_word;
92 | num_ = (n - 5 - last_word) / 4;
93 | }
94 |
95 | bool FilterBlockReader::KeyMayMatch(uint64_t block_offset, const Slice& key) {
96 | uint64_t index = block_offset >> base_lg_;
97 | if (index < num_) {
98 | uint32_t start = DecodeFixed32(offset_ + index*4);
99 | uint32_t limit = DecodeFixed32(offset_ + index*4 + 4);
100 | if (start <= limit && limit <= static_cast(offset_ - data_)) {
101 | Slice filter = Slice(data_ + start, limit - start);
102 | return policy_->KeyMayMatch(key, filter);
103 | } else if (start == limit) {
104 | // Empty filters do not match any keys
105 | return false;
106 | }
107 | }
108 | return true; // Errors are treated as potential matches
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/iterator.h:
--------------------------------------------------------------------------------
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 | // An iterator yields a sequence of key/value pairs from a source.
6 | // The following class defines the interface. Multiple implementations
7 | // are provided by this library. In particular, iterators are provided
8 | // to access the contents of a Table or a DB.
9 | //
10 | // Multiple threads can invoke const methods on an Iterator without
11 | // external synchronization, but if any of the threads may call a
12 | // non-const method, all threads accessing the same Iterator must use
13 | // external synchronization.
14 |
15 | #ifndef STORAGE_LEVELDB_INCLUDE_ITERATOR_H_
16 | #define STORAGE_LEVELDB_INCLUDE_ITERATOR_H_
17 |
18 | #include "leveldb/slice.h"
19 | #include "leveldb/status.h"
20 |
21 | namespace leveldb {
22 |
23 | class Iterator {
24 | public:
25 | Iterator();
26 | virtual ~Iterator();
27 |
28 | // An iterator is either positioned at a key/value pair, or
29 | // not valid. This method returns true iff the iterator is valid.
30 | virtual bool Valid() const = 0;
31 |
32 | // Position at the first key in the source. The iterator is Valid()
33 | // after this call iff the source is not empty.
34 | virtual void SeekToFirst() = 0;
35 |
36 | // Position at the last key in the source. The iterator is
37 | // Valid() after this call iff the source is not empty.
38 | virtual void SeekToLast() = 0;
39 |
40 | // Position at the first key in the source that is at or past target.
41 | // The iterator is Valid() after this call iff the source contains
42 | // an entry that comes at or past target.
43 | virtual void Seek(const Slice& target) = 0;
44 |
45 | // Moves to the next entry in the source. After this call, Valid() is
46 | // true iff the iterator was not positioned at the last entry in the source.
47 | // REQUIRES: Valid()
48 | virtual void Next() = 0;
49 |
50 | // Moves to the previous entry in the source. After this call, Valid() is
51 | // true iff the iterator was not positioned at the first entry in source.
52 | // REQUIRES: Valid()
53 | virtual void Prev() = 0;
54 |
55 | // Return the key for the current entry. The underlying storage for
56 | // the returned slice is valid only until the next modification of
57 | // the iterator.
58 | // REQUIRES: Valid()
59 | virtual Slice key() const = 0;
60 |
61 | // Return the value for the current entry. The underlying storage for
62 | // the returned slice is valid only until the next modification of
63 | // the iterator.
64 | // REQUIRES: Valid()
65 | virtual Slice value() const = 0;
66 |
67 | // If an error has occurred, return it. Else return an ok status.
68 | virtual Status status() const = 0;
69 |
70 | // Clients are allowed to register function/arg1/arg2 triples that
71 | // will be invoked when this iterator is destroyed.
72 | //
73 | // Note that unlike all of the preceding methods, this method is
74 | // not abstract and therefore clients should not override it.
75 | typedef void (*CleanupFunction)(void* arg1, void* arg2);
76 | void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2);
77 |
78 | private:
79 | struct Cleanup {
80 | CleanupFunction function;
81 | void* arg1;
82 | void* arg2;
83 | Cleanup* next;
84 | };
85 | Cleanup cleanup_;
86 |
87 | // No copying allowed
88 | Iterator(const Iterator&);
89 | void operator=(const Iterator&);
90 | };
91 |
92 | // Return an empty iterator (yields nothing).
93 | extern Iterator* NewEmptyIterator();
94 |
95 | // Return an empty iterator with the specified status.
96 | extern Iterator* NewErrorIterator(const Status& status);
97 |
98 | } // namespace leveldb
99 |
100 | #endif // STORAGE_LEVELDB_INCLUDE_ITERATOR_H_
101 |
--------------------------------------------------------------------------------
/leveldb/db/filename_test.cc:
--------------------------------------------------------------------------------
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 "db/filename.h"
6 |
7 | #include "db/dbformat.h"
8 | #include "port/port.h"
9 | #include "util/logging.h"
10 | #include "util/testharness.h"
11 |
12 | namespace leveldb {
13 |
14 | class FileNameTest { };
15 |
16 | TEST(FileNameTest, Parse) {
17 | Slice db;
18 | FileType type;
19 | uint64_t number;
20 |
21 | // Successful parses
22 | static struct {
23 | const char* fname;
24 | uint64_t number;
25 | FileType type;
26 | } cases[] = {
27 | { "100.log", 100, kLogFile },
28 | { "0.log", 0, kLogFile },
29 | { "0.sst", 0, kTableFile },
30 | { "0.ldb", 0, kTableFile },
31 | { "CURRENT", 0, kCurrentFile },
32 | { "LOCK", 0, kDBLockFile },
33 | { "MANIFEST-2", 2, kDescriptorFile },
34 | { "MANIFEST-7", 7, kDescriptorFile },
35 | { "LOG", 0, kInfoLogFile },
36 | { "LOG.old", 0, kInfoLogFile },
37 | { "18446744073709551615.log", 18446744073709551615ull, kLogFile },
38 | };
39 | for (int i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
40 | std::string f = cases[i].fname;
41 | ASSERT_TRUE(ParseFileName(f, &number, &type)) << f;
42 | ASSERT_EQ(cases[i].type, type) << f;
43 | ASSERT_EQ(cases[i].number, number) << f;
44 | }
45 |
46 | // Errors
47 | static const char* errors[] = {
48 | "",
49 | "foo",
50 | "foo-dx-100.log",
51 | ".log",
52 | "",
53 | "manifest",
54 | "CURREN",
55 | "CURRENTX",
56 | "MANIFES",
57 | "MANIFEST",
58 | "MANIFEST-",
59 | "XMANIFEST-3",
60 | "MANIFEST-3x",
61 | "LOC",
62 | "LOCKx",
63 | "LO",
64 | "LOGx",
65 | "18446744073709551616.log",
66 | "184467440737095516150.log",
67 | "100",
68 | "100.",
69 | "100.lop"
70 | };
71 | for (int i = 0; i < sizeof(errors) / sizeof(errors[0]); i++) {
72 | std::string f = errors[i];
73 | ASSERT_TRUE(!ParseFileName(f, &number, &type)) << f;
74 | }
75 | }
76 |
77 | TEST(FileNameTest, Construction) {
78 | uint64_t number;
79 | FileType type;
80 | std::string fname;
81 |
82 | fname = CurrentFileName("foo");
83 | ASSERT_EQ("foo/", std::string(fname.data(), 4));
84 | ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
85 | ASSERT_EQ(0, number);
86 | ASSERT_EQ(kCurrentFile, type);
87 |
88 | fname = LockFileName("foo");
89 | ASSERT_EQ("foo/", std::string(fname.data(), 4));
90 | ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
91 | ASSERT_EQ(0, number);
92 | ASSERT_EQ(kDBLockFile, type);
93 |
94 | fname = LogFileName("foo", 192);
95 | ASSERT_EQ("foo/", std::string(fname.data(), 4));
96 | ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
97 | ASSERT_EQ(192, number);
98 | ASSERT_EQ(kLogFile, type);
99 |
100 | fname = TableFileName("bar", 200);
101 | ASSERT_EQ("bar/", std::string(fname.data(), 4));
102 | ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
103 | ASSERT_EQ(200, number);
104 | ASSERT_EQ(kTableFile, type);
105 |
106 | fname = DescriptorFileName("bar", 100);
107 | ASSERT_EQ("bar/", std::string(fname.data(), 4));
108 | ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
109 | ASSERT_EQ(100, number);
110 | ASSERT_EQ(kDescriptorFile, type);
111 |
112 | fname = TempFileName("tmp", 999);
113 | ASSERT_EQ("tmp/", std::string(fname.data(), 4));
114 | ASSERT_TRUE(ParseFileName(fname.c_str() + 4, &number, &type));
115 | ASSERT_EQ(999, number);
116 | ASSERT_EQ(kTempFile, type);
117 | }
118 |
119 | } // namespace leveldb
120 |
121 | int main(int argc, char** argv) {
122 | return leveldb::test::RunAllTests();
123 | }
124 |
--------------------------------------------------------------------------------
/leveldb/db/write_batch_test.cc:
--------------------------------------------------------------------------------
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 "leveldb/db.h"
6 |
7 | #include "db/memtable.h"
8 | #include "db/write_batch_internal.h"
9 | #include "leveldb/env.h"
10 | #include "util/logging.h"
11 | #include "util/testharness.h"
12 |
13 | namespace leveldb {
14 |
15 | static std::string PrintContents(WriteBatch* b) {
16 | InternalKeyComparator cmp(BytewiseComparator());
17 | MemTable* mem = new MemTable(cmp);
18 | mem->Ref();
19 | std::string state;
20 | Status s = WriteBatchInternal::InsertInto(b, mem);
21 | int count = 0;
22 | Iterator* iter = mem->NewIterator();
23 | for (iter->SeekToFirst(); iter->Valid(); iter->Next()) {
24 | ParsedInternalKey ikey;
25 | ASSERT_TRUE(ParseInternalKey(iter->key(), &ikey));
26 | switch (ikey.type) {
27 | case kTypeValue:
28 | state.append("Put(");
29 | state.append(ikey.user_key.ToString());
30 | state.append(", ");
31 | state.append(iter->value().ToString());
32 | state.append(")");
33 | count++;
34 | break;
35 | case kTypeDeletion:
36 | state.append("Delete(");
37 | state.append(ikey.user_key.ToString());
38 | state.append(")");
39 | count++;
40 | break;
41 | }
42 | state.append("@");
43 | state.append(NumberToString(ikey.sequence));
44 | }
45 | delete iter;
46 | if (!s.ok()) {
47 | state.append("ParseError()");
48 | } else if (count != WriteBatchInternal::Count(b)) {
49 | state.append("CountMismatch()");
50 | }
51 | mem->Unref();
52 | return state;
53 | }
54 |
55 | class WriteBatchTest { };
56 |
57 | TEST(WriteBatchTest, Empty) {
58 | WriteBatch batch;
59 | ASSERT_EQ("", PrintContents(&batch));
60 | ASSERT_EQ(0, WriteBatchInternal::Count(&batch));
61 | }
62 |
63 | TEST(WriteBatchTest, Multiple) {
64 | WriteBatch batch;
65 | batch.Put(Slice("foo"), Slice("bar"));
66 | batch.Delete(Slice("box"));
67 | batch.Put(Slice("baz"), Slice("boo"));
68 | WriteBatchInternal::SetSequence(&batch, 100);
69 | ASSERT_EQ(100, WriteBatchInternal::Sequence(&batch));
70 | ASSERT_EQ(3, WriteBatchInternal::Count(&batch));
71 | ASSERT_EQ("Put(baz, boo)@102"
72 | "Delete(box)@101"
73 | "Put(foo, bar)@100",
74 | PrintContents(&batch));
75 | }
76 |
77 | TEST(WriteBatchTest, Corruption) {
78 | WriteBatch batch;
79 | batch.Put(Slice("foo"), Slice("bar"));
80 | batch.Delete(Slice("box"));
81 | WriteBatchInternal::SetSequence(&batch, 200);
82 | Slice contents = WriteBatchInternal::Contents(&batch);
83 | WriteBatchInternal::SetContents(&batch,
84 | Slice(contents.data(),contents.size()-1));
85 | ASSERT_EQ("Put(foo, bar)@200"
86 | "ParseError()",
87 | PrintContents(&batch));
88 | }
89 |
90 | TEST(WriteBatchTest, Append) {
91 | WriteBatch b1, b2;
92 | WriteBatchInternal::SetSequence(&b1, 200);
93 | WriteBatchInternal::SetSequence(&b2, 300);
94 | WriteBatchInternal::Append(&b1, &b2);
95 | ASSERT_EQ("",
96 | PrintContents(&b1));
97 | b2.Put("a", "va");
98 | WriteBatchInternal::Append(&b1, &b2);
99 | ASSERT_EQ("Put(a, va)@200",
100 | PrintContents(&b1));
101 | b2.Clear();
102 | b2.Put("b", "vb");
103 | WriteBatchInternal::Append(&b1, &b2);
104 | ASSERT_EQ("Put(a, va)@200"
105 | "Put(b, vb)@201",
106 | PrintContents(&b1));
107 | b2.Delete("foo");
108 | WriteBatchInternal::Append(&b1, &b2);
109 | ASSERT_EQ("Put(a, va)@200"
110 | "Put(b, vb)@202"
111 | "Put(b, vb)@201"
112 | "Delete(foo)@203",
113 | PrintContents(&b1));
114 | }
115 |
116 | } // namespace leveldb
117 |
118 | int main(int argc, char** argv) {
119 | return leveldb::test::RunAllTests();
120 | }
121 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/table_builder.h:
--------------------------------------------------------------------------------
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 | // TableBuilder provides the interface used to build a Table
6 | // (an immutable and sorted map from keys to values).
7 | //
8 | // Multiple threads can invoke const methods on a TableBuilder without
9 | // external synchronization, but if any of the threads may call a
10 | // non-const method, all threads accessing the same TableBuilder must use
11 | // external synchronization.
12 |
13 | #ifndef STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_
14 | #define STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_
15 |
16 | #include
17 | #include "leveldb/options.h"
18 | #include "leveldb/status.h"
19 |
20 | namespace leveldb {
21 |
22 | class BlockBuilder;
23 | class BlockHandle;
24 | class WritableFile;
25 |
26 | // 生出 sstable 的过程封装成 TableBuilder 处理
27 | class TableBuilder {
28 | public:
29 | // Create a builder that will store the contents of the table it is
30 | // building in *file. Does not close the file. It is up to the
31 | // caller to close the file after calling Finish().
32 | TableBuilder(const Options& options, WritableFile* file);
33 |
34 | // REQUIRES: Either Finish() or Abandon() has been called.
35 | ~TableBuilder();
36 |
37 | // Change the options used by this builder. Note: only some of the
38 | // option fields can be changed after construction. If a field is
39 | // not allowed to change dynamically and its value in the structure
40 | // passed to the constructor is different from its value in the
41 | // structure passed to this method, this method will return an error
42 | // without changing any fields.
43 | // 修改 builder 中的 option
44 | Status ChangeOptions(const Options& options);
45 |
46 | // Add key,value to the table being constructed.
47 | // REQUIRES: key is after any previously added key according to comparator.
48 | // REQUIRES: Finish(), Abandon() have not been called
49 | // 往 table 中添加 kv, key 必须比之前的 key 大
50 | void Add(const Slice& key, const Slice& value);
51 |
52 | // Advanced operation: flush any buffered key/value pairs to file.
53 | // Can be used to ensure that two adjacent entries never live in
54 | // the same data block. Most clients should not need to use this method.
55 | // REQUIRES: Finish(), Abandon() have not been called
56 | // 把缓冲中的 kv 数据写入文件,一般不需要
57 | void Flush();
58 |
59 | // Return non-ok iff some error has been detected.
60 | // 检查状态
61 | Status status() const;
62 |
63 | // Finish building the table. Stops using the file passed to the
64 | // constructor after this function returns.
65 | // REQUIRES: Finish(), Abandon() have not been called
66 | // 完成 table 的写入
67 | Status Finish();
68 |
69 | // Indicate that the contents of this builder should be abandoned. Stops
70 | // using the file passed to the constructor after this function returns.
71 | // If the caller is not going to call Finish(), it must call Abandon()
72 | // before destroying this builder.
73 | // REQUIRES: Finish(), Abandon() have not been called
74 | // 丢弃 builder 的内容
75 | void Abandon();
76 |
77 | // Number of calls to Add() so far.
78 | // 目前写入的 entry 数量
79 | uint64_t NumEntries() const;
80 |
81 | // Size of the file generated so far. If invoked after a successful
82 | // Finish() call, returns the size of the final generated file.
83 | uint64_t FileSize() const;
84 |
85 | private:
86 | bool ok() const { return status().ok(); }
87 | void WriteBlock(BlockBuilder* block, BlockHandle* handle);
88 | void WriteRawBlock(const Slice& data, CompressionType, BlockHandle* handle);
89 |
90 | struct Rep;
91 | Rep* rep_;
92 |
93 | // No copying allowed
94 | TableBuilder(const TableBuilder&);
95 | void operator=(const TableBuilder&);
96 | };
97 |
98 | } // namespace leveldb
99 |
100 | #endif // STORAGE_LEVELDB_INCLUDE_TABLE_BUILDER_H_
101 |
--------------------------------------------------------------------------------
/leveldb/include/leveldb/status.h:
--------------------------------------------------------------------------------
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 | // A Status encapsulates the result of an operation. It may indicate success,
6 | // or it may indicate an error with an associated error message.
7 | //
8 | // Multiple threads can invoke const methods on a Status without
9 | // external synchronization, but if any of the threads may call a
10 | // non-const method, all threads accessing the same Status must use
11 | // external synchronization.
12 |
13 | #ifndef STORAGE_LEVELDB_INCLUDE_STATUS_H_
14 | #define STORAGE_LEVELDB_INCLUDE_STATUS_H_
15 |
16 | #include
17 | #include "leveldb/slice.h"
18 |
19 | namespace leveldb {
20 |
21 | class Status {
22 | public:
23 | // Create a success status.
24 | Status() : state_(NULL) { }
25 | ~Status() { delete[] state_; }
26 |
27 | // Copy the specified status.
28 | Status(const Status& s);
29 | void operator=(const Status& s);
30 |
31 | // Return a success status.
32 | static Status OK() { return Status(); }
33 |
34 | // Return error status of an appropriate type.
35 | static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) {
36 | return Status(kNotFound, msg, msg2);
37 | }
38 | static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) {
39 | return Status(kCorruption, msg, msg2);
40 | }
41 | static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) {
42 | return Status(kNotSupported, msg, msg2);
43 | }
44 | static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) {
45 | return Status(kInvalidArgument, msg, msg2);
46 | }
47 | static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) {
48 | return Status(kIOError, msg, msg2);
49 | }
50 |
51 | // Returns true iff the status indicates success.
52 | bool ok() const { return (state_ == NULL); }
53 |
54 | // Returns true iff the status indicates a NotFound error.
55 | bool IsNotFound() const { return code() == kNotFound; }
56 |
57 | // Returns true iff the status indicates a Corruption error.
58 | bool IsCorruption() const { return code() == kCorruption; }
59 |
60 | // Returns true iff the status indicates an IOError.
61 | bool IsIOError() const { return code() == kIOError; }
62 |
63 | // Returns true iff the status indicates a NotSupportedError.
64 | bool IsNotSupportedError() const { return code() == kNotSupported; }
65 |
66 | // Returns true iff the status indicates an InvalidArgument.
67 | bool IsInvalidArgument() const { return code() == kInvalidArgument; }
68 |
69 | // Return a string representation of this status suitable for printing.
70 | // Returns the string "OK" for success.
71 | std::string ToString() const;
72 |
73 | private:
74 | // OK status has a NULL state_. Otherwise, state_ is a new[] array
75 | // of the following form:
76 | // state_[0..3] == length of message
77 | // state_[4] == code
78 | // state_[5..] == message
79 | const char* state_;
80 |
81 | enum Code {
82 | kOk = 0,
83 | kNotFound = 1,
84 | kCorruption = 2,
85 | kNotSupported = 3,
86 | kInvalidArgument = 4,
87 | kIOError = 5
88 | };
89 |
90 | Code code() const {
91 | return (state_ == NULL) ? kOk : static_cast(state_[4]);
92 | }
93 |
94 | Status(Code code, const Slice& msg, const Slice& msg2);
95 | static const char* CopyState(const char* s);
96 | };
97 |
98 | inline Status::Status(const Status& s) {
99 | state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
100 | }
101 | inline void Status::operator=(const Status& s) {
102 | // The following condition catches both aliasing (when this == &s),
103 | // and the common case where both s and *this are ok.
104 | if (state_ != s.state_) {
105 | delete[] state_;
106 | state_ = (s.state_ == NULL) ? NULL : CopyState(s.state_);
107 | }
108 | }
109 |
110 | } // namespace leveldb
111 |
112 | #endif // STORAGE_LEVELDB_INCLUDE_STATUS_H_
113 |
--------------------------------------------------------------------------------
/threadpool/src/threadpool.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2013, Mathias Brossard .
3 | * All rights reserved.
4 | *
5 | * Redistribution and use in source and binary forms, with or without
6 | * modification, are permitted provided that the following conditions are
7 | * met:
8 | *
9 | * 1. Redistributions of source code must retain the above copyright
10 | * notice, this list of conditions and the following disclaimer.
11 | *
12 | * 2. Redistributions in binary form must reproduce the above copyright
13 | * notice, this list of conditions and the following disclaimer in the
14 | * documentation and/or other materials provided with the distribution.
15 | *
16 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #ifndef _THREADPOOL_H_
30 | #define _THREADPOOL_H_
31 |
32 | #ifdef __cplusplus
33 | /* 对于 C++ 编译器,指定用 C 的语法编译 */
34 | extern "C" {
35 | #endif
36 |
37 | /**
38 | * @file threadpool.h
39 | * @brief Threadpool Header File
40 | */
41 |
42 | /**
43 | * Increase this constants at your own risk
44 | * Large values might slow down your system
45 | */
46 | #define MAX_THREADS 64
47 | #define MAX_QUEUE 65536
48 |
49 | /* 简化变量定义 */
50 | typedef struct threadpool_t threadpool_t;
51 |
52 | /* 定义错误码 */
53 | typedef enum {
54 | threadpool_invalid = -1,
55 | threadpool_lock_failure = -2,
56 | threadpool_queue_full = -3,
57 | threadpool_shutdown = -4,
58 | threadpool_thread_failure = -5
59 | } threadpool_error_t;
60 |
61 | typedef enum {
62 | threadpool_graceful = 1
63 | } threadpool_destroy_flags_t;
64 |
65 | /* 以下是线程池三个对外 API */
66 |
67 | /**
68 | * @function threadpool_create
69 | * @brief Creates a threadpool_t object.
70 | * @param thread_count Number of worker threads.
71 | * @param queue_size Size of the queue.
72 | * @param flags Unused parameter.
73 | * @return a newly created thread pool or NULL
74 | */
75 | /**
76 | * 创建线程池,有 thread_count 个线程,容纳 queue_size 个的任务队列,flags 参数没有使用
77 | */
78 | threadpool_t *threadpool_create(int thread_count, int queue_size, int flags);
79 |
80 | /**
81 | * @function threadpool_add
82 | * @brief add a new task in the queue of a thread pool
83 | * @param pool Thread pool to which add the task.
84 | * @param function Pointer to the function that will perform the task.
85 | * @param argument Argument to be passed to the function.
86 | * @param flags Unused parameter.
87 | * @return 0 if all goes well, negative values in case of error (@see
88 | * threadpool_error_t for codes).
89 | */
90 | /**
91 | * 添加任务到线程池, pool 为线程池指针,routine 为函数指针, arg 为函数参数, flags 未使用
92 | */
93 | int threadpool_add(threadpool_t *pool, void (*routine)(void *),
94 | void *arg, int flags);
95 |
96 | /**
97 | * @function threadpool_destroy
98 | * @brief Stops and destroys a thread pool.
99 | * @param pool Thread pool to destroy.
100 | * @param flags Flags for shutdown
101 | *
102 | * Known values for flags are 0 (default) and threadpool_graceful in
103 | * which case the thread pool doesn't accept any new tasks but
104 | * processes all pending tasks before shutdown.
105 | */
106 | /**
107 | * 销毁线程池,flags 可以用来指定关闭的方式
108 | */
109 | int threadpool_destroy(threadpool_t *pool, int flags);
110 |
111 | #ifdef __cplusplus
112 | }
113 | #endif
114 |
115 | #endif /* _THREADPOOL_H_ */
116 |
117 |
--------------------------------------------------------------------------------
/leveldb/db/version_edit.h:
--------------------------------------------------------------------------------
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_DB_VERSION_EDIT_H_
6 | #define STORAGE_LEVELDB_DB_VERSION_EDIT_H_
7 |
8 | #include
9 | #include
10 | #include
11 | #include "db/dbformat.h"
12 |
13 | namespace leveldb {
14 |
15 | class VersionSet;
16 |
17 | // sstable 文件的元信息封装成 FileMetaData
18 | struct FileMetaData {
19 | int refs; // 引用计数
20 | int allowed_seeks; // Seeks allowed until compaction // compact 之前允许的 seek 次数
21 | uint64_t number; // FileNumer
22 | uint64_t file_size; // File size in bytes
23 | InternalKey smallest; // Smallest internal key served by table // sstable 文件的最小 key
24 | InternalKey largest; // Largest internal key served by table // sstable 文件的最大 key
25 |
26 | FileMetaData() : refs(0), allowed_seeks(1 << 30), file_size(0) { }
27 | };
28 |
29 | /**
30 | * compact 过程中会有一系列改变当前 Version 的操作(FileNumber 增加,删除 input 的 sstable,增加输出的 sstable……)
31 | * 为了缩小 Version 切换的时间点,将这些操作封装成 VersionEdit,
32 | * compact 完成时,将 VersionEdit 中的操作一次应用到当前 Version 即可得到最新状态的 Version。
33 | * 每次 compact 之后都会将对应的 VersionEdit encode 入 manifest 文件。
34 | */
35 | class VersionEdit {
36 | public:
37 | VersionEdit() { Clear(); }
38 | ~VersionEdit() { }
39 |
40 | void Clear();
41 |
42 | void SetComparatorName(const Slice& name) {
43 | has_comparator_ = true;
44 | comparator_ = name.ToString();
45 | }
46 | void SetLogNumber(uint64_t num) {
47 | has_log_number_ = true;
48 | log_number_ = num;
49 | }
50 | void SetPrevLogNumber(uint64_t num) {
51 | has_prev_log_number_ = true;
52 | prev_log_number_ = num;
53 | }
54 | void SetNextFile(uint64_t num) {
55 | has_next_file_number_ = true;
56 | next_file_number_ = num;
57 | }
58 | void SetLastSequence(SequenceNumber seq) {
59 | has_last_sequence_ = true;
60 | last_sequence_ = seq;
61 | }
62 | void SetCompactPointer(int level, const InternalKey& key) {
63 | compact_pointers_.push_back(std::make_pair(level, key));
64 | }
65 |
66 | // Add the specified file at the specified number.
67 | // REQUIRES: This version has not been saved (see VersionSet::SaveTo)
68 | // REQUIRES: "smallest" and "largest" are smallest and largest keys in file
69 | void AddFile(int level, uint64_t file,
70 | uint64_t file_size,
71 | const InternalKey& smallest,
72 | const InternalKey& largest) {
73 | FileMetaData f;
74 | f.number = file;
75 | f.file_size = file_size;
76 | f.smallest = smallest;
77 | f.largest = largest;
78 | new_files_.push_back(std::make_pair(level, f));
79 | }
80 |
81 | // Delete the specified "file" from the specified "level".
82 | void DeleteFile(int level, uint64_t file) {
83 | deleted_files_.insert(std::make_pair(level, file));
84 | }
85 |
86 | void EncodeTo(std::string* dst) const;
87 | Status DecodeFrom(const Slice& src);
88 |
89 | std::string DebugString() const;
90 |
91 | private:
92 | friend class VersionSet;
93 |
94 | typedef std::set< std::pair > DeletedFileSet;
95 |
96 | std::string comparator_;
97 | uint64_t log_number_; // log 的 FileNumber
98 | uint64_t prev_log_number_; // 辅助 log 的 FileNumber
99 | uint64_t next_file_number_; // 下一个可用的 FileNumber
100 | SequenceNumber last_sequence_; // 用过的最后一个 SequnceNumber
101 | bool has_comparator_; // 以下标识是否存在,验证使用
102 | bool has_log_number_;
103 | bool has_prev_log_number_;
104 | bool has_next_file_number_;
105 | bool has_last_sequence_;
106 |
107 | // 要更新的 level ==》 compact_pointer。
108 | std::vector< std::pair > compact_pointers_;
109 | // 要删除的 sstable 文件(compact 的 input)
110 | DeletedFileSet deleted_files_;
111 | // 新的文件(compact 的 output)
112 | std::vector< std::pair > new_files_;
113 | };
114 |
115 | } // namespace leveldb
116 |
117 | #endif // STORAGE_LEVELDB_DB_VERSION_EDIT_H_
118 |
--------------------------------------------------------------------------------
/leveldb/doc/table_format.txt:
--------------------------------------------------------------------------------
1 | File format
2 | ===========
3 |
4 |
5 | [data block 1]
6 | [data block 2]
7 | ...
8 | [data block N]
9 | [meta block 1]
10 | ...
11 | [meta block K]
12 | [metaindex block]
13 | [index block]
14 | [Footer] (fixed size; starts at file_size - sizeof(Footer))
15 |
16 |
17 | The file contains internal pointers. Each such pointer is called
18 | a BlockHandle and contains the following information:
19 | offset: varint64
20 | size: varint64
21 | See https://developers.google.com/protocol-buffers/docs/encoding#varints
22 | for an explanation of varint64 format.
23 |
24 | (1) The sequence of key/value pairs in the file are stored in sorted
25 | order and partitioned into a sequence of data blocks. These blocks
26 | come one after another at the beginning of the file. Each data block
27 | is formatted according to the code in block_builder.cc, and then
28 | optionally compressed.
29 |
30 | (2) After the data blocks we store a bunch of meta blocks. The
31 | supported meta block types are described below. More meta block types
32 | may be added in the future. Each meta block is again formatted using
33 | block_builder.cc and then optionally compressed.
34 |
35 | (3) A "metaindex" block. It contains one entry for every other meta
36 | block where the key is the name of the meta block and the value is a
37 | BlockHandle pointing to that meta block.
38 |
39 | (4) An "index" block. This block contains one entry per data block,
40 | where the key is a string >= last key in that data block and before
41 | the first key in the successive data block. The value is the
42 | BlockHandle for the data block.
43 |
44 | (6) At the very end of the file is a fixed length footer that contains
45 | the BlockHandle of the metaindex and index blocks as well as a magic number.
46 | metaindex_handle: char[p]; // Block handle for metaindex
47 | index_handle: char[q]; // Block handle for index
48 | padding: char[40-p-q]; // zeroed bytes to make fixed length
49 | // (40==2*BlockHandle::kMaxEncodedLength)
50 | magic: fixed64; // == 0xdb4775248b80fb57 (little-endian)
51 |
52 | "filter" Meta Block
53 | -------------------
54 |
55 | If a "FilterPolicy" was specified when the database was opened, a
56 | filter block is stored in each table. The "metaindex" block contains
57 | an entry that maps from "filter." to the BlockHandle for the filter
58 | block where "" is the string returned by the filter policy's
59 | "Name()" method.
60 |
61 | The filter block stores a sequence of filters, where filter i contains
62 | the output of FilterPolicy::CreateFilter() on all keys that are stored
63 | in a block whose file offset falls within the range
64 |
65 | [ i*base ... (i+1)*base-1 ]
66 |
67 | Currently, "base" is 2KB. So for example, if blocks X and Y start in
68 | the range [ 0KB .. 2KB-1 ], all of the keys in X and Y will be
69 | converted to a filter by calling FilterPolicy::CreateFilter(), and the
70 | resulting filter will be stored as the first filter in the filter
71 | block.
72 |
73 | The filter block is formatted as follows:
74 |
75 | [filter 0]
76 | [filter 1]
77 | [filter 2]
78 | ...
79 | [filter N-1]
80 |
81 | [offset of filter 0] : 4 bytes
82 | [offset of filter 1] : 4 bytes
83 | [offset of filter 2] : 4 bytes
84 | ...
85 | [offset of filter N-1] : 4 bytes
86 |
87 | [offset of beginning of offset array] : 4 bytes
88 | lg(base) : 1 byte
89 |
90 | The offset array at the end of the filter block allows efficient
91 | mapping from a data block offset to the corresponding filter.
92 |
93 | "stats" Meta Block
94 | ------------------
95 |
96 | This meta block contains a bunch of stats. The key is the name
97 | of the statistic. The value contains the statistic.
98 | TODO(postrelease): record following stats.
99 | data size
100 | index size
101 | key size (uncompressed)
102 | value size (uncompressed)
103 | number of entries
104 | number of data blocks
105 |
--------------------------------------------------------------------------------
/leveldb/table/filter_block_test.cc:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2012 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 "table/filter_block.h"
6 |
7 | #include "leveldb/filter_policy.h"
8 | #include "util/coding.h"
9 | #include "util/hash.h"
10 | #include "util/logging.h"
11 | #include "util/testharness.h"
12 | #include "util/testutil.h"
13 |
14 | namespace leveldb {
15 |
16 | // For testing: emit an array with one hash value per key
17 | class TestHashFilter : public FilterPolicy {
18 | public:
19 | virtual const char* Name() const {
20 | return "TestHashFilter";
21 | }
22 |
23 | virtual void CreateFilter(const Slice* keys, int n, std::string* dst) const {
24 | for (int i = 0; i < n; i++) {
25 | uint32_t h = Hash(keys[i].data(), keys[i].size(), 1);
26 | PutFixed32(dst, h);
27 | }
28 | }
29 |
30 | virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const {
31 | uint32_t h = Hash(key.data(), key.size(), 1);
32 | for (size_t i = 0; i + 4 <= filter.size(); i += 4) {
33 | if (h == DecodeFixed32(filter.data() + i)) {
34 | return true;
35 | }
36 | }
37 | return false;
38 | }
39 | };
40 |
41 | class FilterBlockTest {
42 | public:
43 | TestHashFilter policy_;
44 | };
45 |
46 | TEST(FilterBlockTest, EmptyBuilder) {
47 | FilterBlockBuilder builder(&policy_);
48 | Slice block = builder.Finish();
49 | ASSERT_EQ("\\x00\\x00\\x00\\x00\\x0b", EscapeString(block));
50 | FilterBlockReader reader(&policy_, block);
51 | ASSERT_TRUE(reader.KeyMayMatch(0, "foo"));
52 | ASSERT_TRUE(reader.KeyMayMatch(100000, "foo"));
53 | }
54 |
55 | TEST(FilterBlockTest, SingleChunk) {
56 | FilterBlockBuilder builder(&policy_);
57 | builder.StartBlock(100);
58 | builder.AddKey("foo");
59 | builder.AddKey("bar");
60 | builder.AddKey("box");
61 | builder.StartBlock(200);
62 | builder.AddKey("box");
63 | builder.StartBlock(300);
64 | builder.AddKey("hello");
65 | Slice block = builder.Finish();
66 | FilterBlockReader reader(&policy_, block);
67 | ASSERT_TRUE(reader.KeyMayMatch(100, "foo"));
68 | ASSERT_TRUE(reader.KeyMayMatch(100, "bar"));
69 | ASSERT_TRUE(reader.KeyMayMatch(100, "box"));
70 | ASSERT_TRUE(reader.KeyMayMatch(100, "hello"));
71 | ASSERT_TRUE(reader.KeyMayMatch(100, "foo"));
72 | ASSERT_TRUE(! reader.KeyMayMatch(100, "missing"));
73 | ASSERT_TRUE(! reader.KeyMayMatch(100, "other"));
74 | }
75 |
76 | TEST(FilterBlockTest, MultiChunk) {
77 | FilterBlockBuilder builder(&policy_);
78 |
79 | // First filter
80 | builder.StartBlock(0);
81 | builder.AddKey("foo");
82 | builder.StartBlock(2000);
83 | builder.AddKey("bar");
84 |
85 | // Second filter
86 | builder.StartBlock(3100);
87 | builder.AddKey("box");
88 |
89 | // Third filter is empty
90 |
91 | // Last filter
92 | builder.StartBlock(9000);
93 | builder.AddKey("box");
94 | builder.AddKey("hello");
95 |
96 | Slice block = builder.Finish();
97 | FilterBlockReader reader(&policy_, block);
98 |
99 | // Check first filter
100 | ASSERT_TRUE(reader.KeyMayMatch(0, "foo"));
101 | ASSERT_TRUE(reader.KeyMayMatch(2000, "bar"));
102 | ASSERT_TRUE(! reader.KeyMayMatch(0, "box"));
103 | ASSERT_TRUE(! reader.KeyMayMatch(0, "hello"));
104 |
105 | // Check second filter
106 | ASSERT_TRUE(reader.KeyMayMatch(3100, "box"));
107 | ASSERT_TRUE(! reader.KeyMayMatch(3100, "foo"));
108 | ASSERT_TRUE(! reader.KeyMayMatch(3100, "bar"));
109 | ASSERT_TRUE(! reader.KeyMayMatch(3100, "hello"));
110 |
111 | // Check third filter (empty)
112 | ASSERT_TRUE(! reader.KeyMayMatch(4100, "foo"));
113 | ASSERT_TRUE(! reader.KeyMayMatch(4100, "bar"));
114 | ASSERT_TRUE(! reader.KeyMayMatch(4100, "box"));
115 | ASSERT_TRUE(! reader.KeyMayMatch(4100, "hello"));
116 |
117 | // Check last filter
118 | ASSERT_TRUE(reader.KeyMayMatch(9000, "box"));
119 | ASSERT_TRUE(reader.KeyMayMatch(9000, "hello"));
120 | ASSERT_TRUE(! reader.KeyMayMatch(9000, "foo"));
121 | ASSERT_TRUE(! reader.KeyMayMatch(9000, "bar"));
122 | }
123 |
124 | } // namespace leveldb
125 |
126 | int main(int argc, char** argv) {
127 | return leveldb::test::RunAllTests();
128 | }
129 |
--------------------------------------------------------------------------------
/leveldb/db/dbformat_test.cc:
--------------------------------------------------------------------------------
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 "db/dbformat.h"
6 | #include "util/logging.h"
7 | #include "util/testharness.h"
8 |
9 | namespace leveldb {
10 |
11 | static std::string IKey(const std::string& user_key,
12 | uint64_t seq,
13 | ValueType vt) {
14 | std::string encoded;
15 | AppendInternalKey(&encoded, ParsedInternalKey(user_key, seq, vt));
16 | return encoded;
17 | }
18 |
19 | static std::string Shorten(const std::string& s, const std::string& l) {
20 | std::string result = s;
21 | InternalKeyComparator(BytewiseComparator()).FindShortestSeparator(&result, l);
22 | return result;
23 | }
24 |
25 | static std::string ShortSuccessor(const std::string& s) {
26 | std::string result = s;
27 | InternalKeyComparator(BytewiseComparator()).FindShortSuccessor(&result);
28 | return result;
29 | }
30 |
31 | static void TestKey(const std::string& key,
32 | uint64_t seq,
33 | ValueType vt) {
34 | std::string encoded = IKey(key, seq, vt);
35 |
36 | Slice in(encoded);
37 | ParsedInternalKey decoded("", 0, kTypeValue);
38 |
39 | ASSERT_TRUE(ParseInternalKey(in, &decoded));
40 | ASSERT_EQ(key, decoded.user_key.ToString());
41 | ASSERT_EQ(seq, decoded.sequence);
42 | ASSERT_EQ(vt, decoded.type);
43 |
44 | ASSERT_TRUE(!ParseInternalKey(Slice("bar"), &decoded));
45 | }
46 |
47 | class FormatTest { };
48 |
49 | TEST(FormatTest, InternalKey_EncodeDecode) {
50 | const char* keys[] = { "", "k", "hello", "longggggggggggggggggggggg" };
51 | const uint64_t seq[] = {
52 | 1, 2, 3,
53 | (1ull << 8) - 1, 1ull << 8, (1ull << 8) + 1,
54 | (1ull << 16) - 1, 1ull << 16, (1ull << 16) + 1,
55 | (1ull << 32) - 1, 1ull << 32, (1ull << 32) + 1
56 | };
57 | for (int k = 0; k < sizeof(keys) / sizeof(keys[0]); k++) {
58 | for (int s = 0; s < sizeof(seq) / sizeof(seq[0]); s++) {
59 | TestKey(keys[k], seq[s], kTypeValue);
60 | TestKey("hello", 1, kTypeDeletion);
61 | }
62 | }
63 | }
64 |
65 | TEST(FormatTest, InternalKeyShortSeparator) {
66 | // When user keys are same
67 | ASSERT_EQ(IKey("foo", 100, kTypeValue),
68 | Shorten(IKey("foo", 100, kTypeValue),
69 | IKey("foo", 99, kTypeValue)));
70 | ASSERT_EQ(IKey("foo", 100, kTypeValue),
71 | Shorten(IKey("foo", 100, kTypeValue),
72 | IKey("foo", 101, kTypeValue)));
73 | ASSERT_EQ(IKey("foo", 100, kTypeValue),
74 | Shorten(IKey("foo", 100, kTypeValue),
75 | IKey("foo", 100, kTypeValue)));
76 | ASSERT_EQ(IKey("foo", 100, kTypeValue),
77 | Shorten(IKey("foo", 100, kTypeValue),
78 | IKey("foo", 100, kTypeDeletion)));
79 |
80 | // When user keys are misordered
81 | ASSERT_EQ(IKey("foo", 100, kTypeValue),
82 | Shorten(IKey("foo", 100, kTypeValue),
83 | IKey("bar", 99, kTypeValue)));
84 |
85 | // When user keys are different, but correctly ordered
86 | ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
87 | Shorten(IKey("foo", 100, kTypeValue),
88 | IKey("hello", 200, kTypeValue)));
89 |
90 | // When start user key is prefix of limit user key
91 | ASSERT_EQ(IKey("foo", 100, kTypeValue),
92 | Shorten(IKey("foo", 100, kTypeValue),
93 | IKey("foobar", 200, kTypeValue)));
94 |
95 | // When limit user key is prefix of start user key
96 | ASSERT_EQ(IKey("foobar", 100, kTypeValue),
97 | Shorten(IKey("foobar", 100, kTypeValue),
98 | IKey("foo", 200, kTypeValue)));
99 | }
100 |
101 | TEST(FormatTest, InternalKeyShortestSuccessor) {
102 | ASSERT_EQ(IKey("g", kMaxSequenceNumber, kValueTypeForSeek),
103 | ShortSuccessor(IKey("foo", 100, kTypeValue)));
104 | ASSERT_EQ(IKey("\xff\xff", 100, kTypeValue),
105 | ShortSuccessor(IKey("\xff\xff", 100, kTypeValue)));
106 | }
107 |
108 | } // namespace leveldb
109 |
110 | int main(int argc, char** argv) {
111 | return leveldb::test::RunAllTests();
112 | }
113 |
--------------------------------------------------------------------------------
/leveldb/db/log_reader.h:
--------------------------------------------------------------------------------
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_DB_LOG_READER_H_
6 | #define STORAGE_LEVELDB_DB_LOG_READER_H_
7 |
8 | #include
9 |
10 | #include "db/log_format.h"
11 | #include "leveldb/slice.h"
12 | #include "leveldb/status.h"
13 |
14 | namespace leveldb {
15 |
16 | class SequentialFile;
17 |
18 | namespace log {
19 |
20 | // 只会在启动时进行读取
21 | class Reader {
22 | public:
23 | // Interface for reporting errors.
24 | class Reporter {
25 | public:
26 | virtual ~Reporter();
27 |
28 | // Some corruption was detected. "size" is the approximate number
29 | // of bytes dropped due to the corruption.
30 | virtual void Corruption(size_t bytes, const Status& status) = 0;
31 | };
32 |
33 | // Create a reader that will return log records from "*file".
34 | // "*file" must remain live while this Reader is in use.
35 | //
36 | // If "reporter" is non-NULL, it is notified whenever some data is
37 | // dropped due to a detected corruption. "*reporter" must remain
38 | // live while this Reader is in use.
39 | //
40 | // If "checksum" is true, verify checksums if available.
41 | //
42 | // The Reader will start reading at the first record located at physical
43 | // position >= initial_offset within the file.
44 | Reader(SequentialFile* file, Reporter* reporter, bool checksum,
45 | uint64_t initial_offset);
46 |
47 | ~Reader();
48 |
49 | // Read the next record into *record. Returns true if read
50 | // successfully, false if we hit end of the input. May use
51 | // "*scratch" as temporary storage. The contents filled in *record
52 | // will only be valid until the next mutating operation on this
53 | // reader or the next mutation to *scratch.
54 | bool ReadRecord(Slice* record, std::string* scratch);
55 |
56 | // Returns the physical offset of the last record returned by ReadRecord.
57 | //
58 | // Undefined before the first call to ReadRecord.
59 | uint64_t LastRecordOffset();
60 |
61 | private:
62 | SequentialFile* const file_; // 打开的顺序读文件
63 | Reporter* const reporter_; // 用于报告错误
64 | bool const checksum_; // 是否进行校验
65 | char* const backing_store_; // 用作 buffer_ 的内存
66 | Slice buffer_; // 用于缓存一个 block
67 | bool eof_; // Last Read() indicated EOF by returning < kBlockSize
68 |
69 | // Offset of the last record returned by ReadRecord.
70 | uint64_t last_record_offset_; // 读过的最后一条 record 偏移
71 | // Offset of the first location past the end of buffer_.
72 | uint64_t end_of_buffer_offset_; // 读取到buffer_之后顺序文件偏移
73 |
74 | // Offset at which to start looking for the first record to return
75 | uint64_t const initial_offset_; // 第一条 record 偏移量
76 |
77 | // True if we are resynchronizing after a seek (initial_offset_ > 0). In
78 | // particular, a run of kMiddleType and kLastType records can be silently
79 | // skipped in this mode
80 | bool resyncing_;
81 |
82 | // Extend record types with the following special values
83 | enum {
84 | kEof = kMaxRecordType + 1,
85 | // Returned whenever we find an invalid physical record.
86 | // Currently there are three situations in which this happens:
87 | // * The record has an invalid CRC (ReadPhysicalRecord reports a drop)
88 | // * The record is a 0-length record (No drop is reported)
89 | // * The record is below constructor's initial_offset (No drop is reported)
90 | kBadRecord = kMaxRecordType + 2
91 | };
92 |
93 | // Skips all blocks that are completely before "initial_offset_".
94 | //
95 | // Returns true on success. Handles reporting.
96 | bool SkipToInitialBlock();
97 |
98 | // Return type, or one of the preceding special values
99 | unsigned int ReadPhysicalRecord(Slice* result);
100 |
101 | // Reports dropped bytes to the reporter.
102 | // buffer_ must be updated to remove the dropped bytes prior to invocation.
103 | void ReportCorruption(uint64_t bytes, const char* reason);
104 | void ReportDrop(uint64_t bytes, const Status& reason);
105 |
106 | // No copying allowed
107 | Reader(const Reader&);
108 | void operator=(const Reader&);
109 | };
110 |
111 | } // namespace log
112 | } // namespace leveldb
113 |
114 | #endif // STORAGE_LEVELDB_DB_LOG_READER_H_
115 |
--------------------------------------------------------------------------------