├── .gitignore ├── Makefile ├── README.md ├── src ├── database.cpp ├── database.h ├── environment.cpp ├── environment.h ├── error_messages.h ├── include │ ├── phpcpp │ │ ├── argument.h │ │ ├── base.h │ │ ├── byref.h │ │ ├── byval.h │ │ ├── class.h │ │ ├── classinfo.h │ │ ├── environment.h │ │ ├── error.h │ │ ├── extension.h │ │ ├── function.h │ │ ├── global.h │ │ ├── globals.h │ │ ├── hashmember.h │ │ ├── hiddenpointer.h │ │ ├── member.h │ │ ├── members.h │ │ ├── method.h │ │ ├── parameters.h │ │ ├── phpcpp.h │ │ ├── properties.h │ │ ├── protected.h │ │ ├── public.h │ │ ├── type.h │ │ └── value.h │ ├── rocksdb │ │ ├── arena.h │ │ ├── c.h │ │ ├── cache.h │ │ ├── compaction_filter.h │ │ ├── comparator.h │ │ ├── db.h │ │ ├── env.h │ │ ├── filter_policy.h │ │ ├── flush_block_policy.h │ │ ├── iterator.h │ │ ├── ldb_tool.h │ │ ├── memtablerep.h │ │ ├── merge_operator.h │ │ ├── options.h │ │ ├── perf_context.h │ │ ├── slice.h │ │ ├── slice_transform.h │ │ ├── statistics.h │ │ ├── status.h │ │ ├── table.h │ │ ├── table_properties.h │ │ ├── transaction_log.h │ │ ├── types.h │ │ ├── universal_compaction.h │ │ └── write_batch.h │ └── utilities │ │ ├── stackable_db.h │ │ └── utility_db.h ├── includes.h └── main.cpp ├── test.sh ├── test └── test.php └── test_valgrind.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | bin 3 | my_rock_db 4 | .settings 5 | .cproject 6 | .project 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SOURCE_DIR=src 2 | CC=g++ 3 | OPTIONS=-std=c++11 -fPIC -shared 4 | LIB=-lrocksdb -lpthread -lrt -lsnappy -lgflags -lz -lbz2 -lphpcpp 5 | INC=-I./$(SOURCE_DIR)/include 6 | INPUT=$(SOURCE_DIR)/*.cpp 7 | OUTPUT_DIR=bin 8 | OUTPUT_FILE=rocksdb_php.so 9 | 10 | all: 11 | mkdir -p $(OUTPUT_DIR) 12 | $(CC) $(OPTIONS) $(INPUT) $(LIB) $(INC) -o $(OUTPUT_DIR)/$(OUTPUT_FILE) 13 | 14 | clean: 15 | rm -rf $(OUTPUT_DIR)/$(OUTPUT_FILE) 16 | mkdir -p $(OUTPUT_DIR) 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | RocksDB PHP Extension 4 | === 5 | RocksDB is a new embedded database for storing key-value pairs developed by Facebook. This project hosts a PHP extension for RocksDB. More information on RocksDB can be found here: 6 | 7 | https://github.com/facebook/rocksdb 8 | 9 | ###Simple Example 10 | Open(true); 13 | if($result) 14 | die("Unable to open rocksdb!"); 15 | 16 | $rocksdb->Put("my_awesome_key", "my_awesome_value"); 17 | $value = $rocksdb->Get("my_awesome_key"); 18 | 19 | echo $value . "\n"; 20 | ?> 21 | 22 | Check `test/test.php` for more examples. 23 | 24 | ##Platforms 25 | RocksDB is said to compile on Linux and Mac OS X. So far, I haven't seen anyone getting it to build on Windows, but it should work. 26 | My build environment is: 27 | 28 | * Ubuntu 13.10 x64 29 | * GCC 4.8.1 30 | 31 | All documentation, instructions and guides assume my configuration. If you were able to get it working on another platform, please let me know. 32 | 33 | ## Notes 34 | I use a custom version of PHP-CPP, because I added basic exception support. Please checkout the fork, until my 35 | pull request has been accepted: 36 | 37 | git clone https://github.com/Photonios/PHP-CPP 38 | 39 | ## Build 40 | #### Building RocksDB PHP Extension 41 | Before trying to build the RocksDB PHP extension, make sure you have installed all dependencies listed below. After that, you can simply checkout the code: 42 | 43 | git clone https://github.com/Photonios/rocksdb-php.git 44 | 45 | Then, run make: 46 | 47 | make 48 | 49 | The PHP extension, which is a shared/dynamiclly linked library can be found in the `bin` directory. 50 | 51 | #### Building PHP 52 | The RocksDB PHP extension is being written against PHP 5.5.3. To be able to build the RocksDB PHP extension, you need to install the following packages: 53 | 54 | sudo apt-get install php5-dev 55 | sudo apt-get install php5-cli 56 | 57 | #### Building PHP-CPP 58 | PHP-CPP is a C++ library which makes developing PHP extensions from C++ possible. It's also, way easier then using the native PHP C API. PHP-CPP can be found here: 59 | 60 | https://github.com/EmielBruijntjes/PHP-CPP 61 | 62 | To build, clone the repository: 63 | 64 | git clone https://github.com/EmielBruijntjes/PHP-CPP.git php-cpp 65 | 66 | Go into the 'php-cpp' directory and run: 67 | 68 | make 69 | 70 | After that, 'libphpcpp.so' should be present in the 'src' directory. To install the library, do one of the following thins: 71 | 72 | * Add the path where you cloned PHP-CPP to LD_LIBRARY_PATH (`export LD_LIBRARY_PATH+=/path/to/php-cpp/src`) 73 | * Create a new file in `/etc/ld.so.conf.d` with the `.conf` extension, where the path to the PHP-CPP src directory is on a single line 74 | * Copy the file `libphpcpp.so` to `/usr/lib` 75 | 76 | #### Building RocksDB 77 | To build the RocksDB PHP Extension, you first need to build RocksDB. Clone the RocksDB git repository using: 78 | 79 | git clone https://github.com/facebook/rocksdb.git 80 | 81 | To be able to build RocksDB, you first need to install all dependencies, this can be done using apt-get: 82 | 83 | sudo apt-get install libsnappy-dev 84 | sudo apt-get install zlib1g-dev 85 | sudo apt-get install libbz2-dev 86 | sudo apt-get install libgflags2 87 | sudo apt-get install libgflags-dev 88 | 89 | Or run: 90 | 91 | sudo apt-get install libsnappy-dev zlib1g-dev libbz2-dev libgflags2 libgflags-dev 92 | 93 | After you've install all dependencies, you can simply run: 94 | 95 | make clean 96 | CFLAGS=-fPIC CXXFLAGS=-fPIC make 97 | 98 | To build and run all unit tests: 99 | 100 | make check 101 | 102 | To install the RocksDB library you can do either of these three things: 103 | 104 | * Add the path where you cloned RocksDB to LD_LIBRARY_PATH (`export LD_LIBRARY_PATH+=/path/to/rocksdb`) 105 | * Create a new file in `/etc/ld.so.conf.d` with the `.conf` extension, where the path to RocksDB is on a single line 106 | * Copy the files `librocksdb.a` and `libmemenv.a` to `/usr/lib` 107 | 108 | Choose whatever you like :) 109 | 110 | ## Installation 111 | After you build the RocksDB PHP extension, you should have a `.so` file in the `bin` directory. Execute: 112 | 113 | php --ini 114 | 115 | To find out where your PHP configuration file is located. It should output something liek this: 116 | 117 | Loaded Configuration File: /etc/php5/cli/php.ini 118 | 119 | Find the line that starts with `extension=`, if it's commented out, uncomment it and set the path to your extension, like this: 120 | 121 | extension=/iam_awesome/cookies/dance/in/the/rain/rocksdb-php.so 122 | 123 | Then, enjoy :D 124 | -------------------------------------------------------------------------------- /src/database.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "database.h" 3 | #include "error_messages.h" 4 | 5 | namespace RocksDB 6 | { 7 | 8 | Database::Database() : 9 | m_db_path (), 10 | m_rdb (NULL), 11 | m_last_error (), 12 | m_is_open (false) 13 | { 14 | 15 | } 16 | 17 | void Database::__construct(Php::Parameters ¶ms) 18 | { 19 | if(params.empty() || !params[0].isString()) 20 | Php::ThrowError(ErrorMessages::InvalidParamExpectedString); 21 | 22 | m_db_path = params[0].stringValue(); 23 | } 24 | 25 | void Database::__destruct() 26 | { 27 | Close(); 28 | } 29 | 30 | Php::Value Database::Open(Php::Parameters ¶ms) 31 | { 32 | if(IsOpen()) 33 | { 34 | m_last_error = ErrorMessages::AlreadyActiveConnection; 35 | return false; 36 | } 37 | 38 | bool create_if_missing = false; 39 | 40 | if(params.empty() || !params[0].isBool()) 41 | create_if_missing = false; 42 | else 43 | create_if_missing = params[0].boolValue(); 44 | 45 | rocksdb::Options options; 46 | options.create_if_missing = create_if_missing; 47 | 48 | rocksdb::Status status = rocksdb::DB::Open(options, m_db_path, &m_rdb); 49 | 50 | if(!status.ok()) 51 | { 52 | m_last_error = status.ToString(); 53 | m_is_open = false; 54 | return false; 55 | } 56 | 57 | m_is_open = true; 58 | 59 | return true; 60 | } 61 | 62 | Php::Value Database::GetLastError() 63 | { 64 | return m_last_error; 65 | } 66 | 67 | Php::Value Database::IsOpen() 68 | { 69 | if(m_rdb == NULL) 70 | return false; 71 | 72 | return m_is_open; 73 | } 74 | 75 | Php::Value Database::GetDbPath() 76 | { 77 | return m_db_path; 78 | } 79 | 80 | Php::Value Database::Close() 81 | { 82 | if(m_rdb == NULL) 83 | { 84 | m_last_error = ErrorMessages::NoActiveConnection; 85 | return false; 86 | } 87 | 88 | delete m_rdb; 89 | return true; 90 | } 91 | 92 | Php::Value Database::Get(Php::Parameters ¶ms) 93 | { 94 | if(params.empty()) 95 | Php::ThrowError(ErrorMessages::ExpectedOneParameter); 96 | 97 | if(!IsOpen()) 98 | { 99 | m_last_error = ErrorMessages::NoActiveConnection; 100 | return false; 101 | } 102 | 103 | std::string key = params[0].stringValue(); 104 | std::string value; 105 | 106 | rocksdb::Status status = m_rdb->Get(rocksdb::ReadOptions(), key, &value); 107 | 108 | if(!status.ok()) 109 | { 110 | m_last_error = status.ToString(); 111 | return false; 112 | } 113 | 114 | return value; 115 | } 116 | 117 | Php::Value Database::Put(Php::Parameters ¶ms) 118 | { 119 | if(params.empty() || params.size() < 2) 120 | Php::ThrowError(ErrorMessages::ExpectedTwoParamters); 121 | 122 | if(!IsOpen()) 123 | { 124 | m_last_error = ErrorMessages::NoActiveConnection; 125 | return false; 126 | } 127 | 128 | std::string key = params[0].stringValue(); 129 | std::string value = params[1].stringValue(); 130 | 131 | m_rdb->Put(rocksdb::WriteOptions(), key, value); 132 | 133 | return true; 134 | } 135 | 136 | } // namespace RocksDB 137 | -------------------------------------------------------------------------------- /src/database.h: -------------------------------------------------------------------------------- 1 | #ifndef ROCKSDB_DATABSE_H_ 2 | #define ROCKSDB_DATABSE_H_ 3 | 4 | namespace RocksDB 5 | { 6 | 7 | /*! 8 | * \brief The PHP wrapper for the rocksdb::DB class. Represents a single RocksDB database. 9 | * \author Swen Kooij 10 | */ 11 | class Database : public Php::Base 12 | { 13 | public: 14 | /*! 15 | * \brief Initializes a new instance of the Database class. 16 | * \note This is NOT the PHP constructor. 17 | */ 18 | Database(); 19 | 20 | /*! 21 | * \brief The PHP constructor, the method that gets called when 22 | * a new instance of this object is being created. 23 | * \param db_path The path to a RocksDB file that needs to be opened. 24 | */ 25 | void __construct(Php::Parameters ¶ms); 26 | 27 | /*! 28 | * \brief The PHP destructor, the method that gets called 29 | * when this instance is destroyed. 30 | */ 31 | void __destruct(); 32 | 33 | /*! 34 | * \brief Opens the 'connection' with the earlier specified RocksDB file. 35 | * \param create_if_missing A boolean indicating whether the database should be created it it does not exists. 36 | * \returns A boolean indicating whether opening the database successful. 37 | */ 38 | Php::Value Open(Php::Parameters ¶ms); 39 | 40 | /*! 41 | * \brief Gets the last error that was thrown, as a string. A textual message 42 | * describing the error. 43 | * \returns A string, describing the error. If no error occurred, an empty string will be returned. 44 | */ 45 | Php::Value GetLastError(); 46 | 47 | /*! 48 | * \brief Checks whether there's an active connection with a database. 49 | * \returns A boolean indicating whether there's an active connection with a database. 50 | */ 51 | Php::Value IsOpen(); 52 | 53 | /*! 54 | * \brief Gets the path to the currently opened database. 55 | */ 56 | Php::Value GetDbPath(); 57 | 58 | /*! 59 | * \brief Closes the current connection to the database. 60 | * \returns A boolean indicating whether closing the connection was sucessful, it 61 | * returns false when there's no active connection. 62 | */ 63 | Php::Value Close(); 64 | 65 | /*! 66 | * \brief Gets the value of the specified key. 67 | * \param key The name of the key to get the value for, this has to be a string. 68 | * \returns The textual value stored under the specified key, if no key exists with 69 | * the specified name,false will be returned. If there are any 70 | * other reasons why you're getting false, check GetLastError(); 71 | */ 72 | Php::Value Get(Php::Parameters ¶ms); 73 | 74 | /*! 75 | * \brief Sets the value of the specified key. 76 | * \param key The name of the key to put the value of. 77 | * \param value The new value for this key. 78 | * \returns A boolean indicating whether the put was sucessful, when it failed, 79 | * there's probably no active db connection, check GetLastError(); 80 | */ 81 | Php::Value Put(Php::Parameters ¶ms); 82 | 83 | private: 84 | /*! 85 | * \brief The path to the RocksDB database this instance represents. 86 | */ 87 | std::string m_db_path; 88 | 89 | /*! 90 | * \brief Holds the textual representation of the error that was last thrown. 91 | */ 92 | std::string m_last_error; 93 | 94 | /*! 95 | * \brief Represents the 'connection' with the selected RocksDB file. 96 | */ 97 | rocksdb::DB* m_rdb; 98 | 99 | /*! 100 | * \brief Indicates whether there's an active 'connection' with a database. 101 | */ 102 | bool m_is_open; 103 | }; 104 | 105 | } // namespace RocksDB 106 | 107 | #endif /* ROCKSDB_DATABSE_H_ */ 108 | -------------------------------------------------------------------------------- /src/environment.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "environment.h" 3 | 4 | -------------------------------------------------------------------------------- /src/environment.h: -------------------------------------------------------------------------------- 1 | #ifndef ROCKSDB_ENVIRONMENT_H_ 2 | #define ROCKSDB_ENVIRONMENT_H_ 3 | 4 | namespace RocksDB 5 | { 6 | 7 | /*! 8 | * \brief Implements the 'Php::Environment' class, allows access to the environment, 9 | * and thus allows us to set global variables/constants. 10 | * \author Swen Kooij 11 | */ 12 | class Environment : public Php::Environment 13 | { 14 | }; 15 | 16 | } // namespace RocksDB 17 | 18 | #endif /* ROCKSDB_ENVIRONMENT_H_ */ 19 | -------------------------------------------------------------------------------- /src/error_messages.h: -------------------------------------------------------------------------------- 1 | #ifndef ROCKSDB_ERROR_MESSAGES_H_ 2 | #define ROCKSDB_ERROR_MESSAGES_H_ 3 | 4 | namespace RocksDB 5 | { 6 | 7 | namespace ErrorMessages 8 | { 9 | const std::string InvalidParamExpectedString = "Invalid parameter 0, expected string."; 10 | const std::string AlreadyActiveConnection = "There already is an active connection with a database."; 11 | const std::string NoActiveConnection = "There is no active database connection to close."; 12 | const std::string ExpectedOneParameter = "Expected at least one parameter."; 13 | const std::string ExpectedTwoParamters = "Expected at least two parameters."; 14 | } 15 | 16 | } // namespace RocksDB 17 | 18 | #endif /* ROCKSDB_ERROR_MESSAGES_H_ */ 19 | -------------------------------------------------------------------------------- /src/include/phpcpp/argument.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Argument.h 3 | * 4 | * Class holds information about an argument that is passed to a function. 5 | * You'll need this class when you're defining your own functions. 6 | * 7 | * The constructor of the argument is protected. Use the ByVal or ByRef 8 | * classes instead. 9 | * 10 | * @author Emiel Bruijntjes 11 | * @copyright 2013 Copernica BV 12 | */ 13 | 14 | /** 15 | * Forward declaration 16 | */ 17 | struct _zend_arg_info; 18 | 19 | /** 20 | * Set up namespace 21 | */ 22 | namespace Php { 23 | 24 | /** 25 | * Class definition 26 | */ 27 | class Argument 28 | { 29 | public: 30 | /** 31 | * Copy constructor 32 | * @param argument 33 | */ 34 | Argument(const Argument &argument); 35 | 36 | /** 37 | * Move constructor 38 | * @param argument 39 | */ 40 | Argument(Argument &&argument); 41 | 42 | /** 43 | * Destructor 44 | */ 45 | virtual ~Argument(); 46 | 47 | protected: 48 | /** 49 | * Constructor 50 | * @param name Name of the argument 51 | * @param type Argument type 52 | * @param required Is this argument required? 53 | * @param byref Is this a reference argument 54 | */ 55 | Argument(const char *name, Type type, bool required = true, bool byref = false); 56 | 57 | /** 58 | * Constructor 59 | * @param name Name of the argument 60 | * @param classname Name of the class 61 | * @param nullable Can it be null? 62 | * @param required Is this argument required? 63 | * @param byref Is this a reference argument? 64 | */ 65 | Argument(const char *name, const char *classname, bool nullable = true, bool required = true, bool byref = false); 66 | 67 | public: 68 | /** 69 | * Fill an arg_info structure with data 70 | * @param info 71 | * @internal 72 | */ 73 | void fill(struct _zend_arg_info *info) const; 74 | 75 | private: 76 | /** 77 | * The argument info 78 | * @var zend_arg_info 79 | */ 80 | struct _zend_arg_info *_info; 81 | 82 | /** 83 | * Is this a required argument 84 | * @var bool 85 | */ 86 | bool _required; 87 | }; 88 | 89 | /** 90 | * End of namespace 91 | */ 92 | } 93 | 94 | -------------------------------------------------------------------------------- /src/include/phpcpp/base.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Base class for defining your own objects 3 | * 4 | * @author Emiel Bruijntjes 5 | * @copyright 2013 Copernica BV 6 | */ 7 | 8 | /** 9 | * Namespace 10 | */ 11 | namespace Php { 12 | 13 | /** 14 | * Class definition 15 | */ 16 | class Base 17 | { 18 | public: 19 | /** 20 | * Constructor 21 | */ 22 | Base() {} 23 | 24 | /** 25 | * Virtual destructor 26 | */ 27 | virtual ~Base() {} 28 | 29 | /** 30 | * The pseudo constructor that is called from PHP after the object is constructed 31 | * @param environment 32 | * @param parameters 33 | */ 34 | virtual void __construct(Environment &environment, const Parameters ¶meters) 35 | { 36 | // call all other possible implementations 37 | __construct(environment); 38 | __construct(parameters); 39 | __construct(); 40 | } 41 | 42 | /** 43 | * The pseudo constructor that is called from PHP after the object is constructed 44 | * @param environment 45 | */ 46 | virtual void __construct(Environment &environment) {} 47 | 48 | /** 49 | * The pseudo constructor that is called from PHP after the object is constructed 50 | * @param parameters 51 | */ 52 | virtual void __construct(const Parameters ¶meters) {} 53 | 54 | /** 55 | * The pseudo constructor that is called from PHP after the object is constructed 56 | */ 57 | virtual void __construct() {} 58 | 59 | /** 60 | * The pseudo destructor that is called from PHP right before the object is destructed 61 | * @param environment 62 | */ 63 | virtual void __destruct(Environment &environment) 64 | { 65 | // call the other implementation 66 | __destruct(); 67 | } 68 | 69 | /** 70 | * The pseudo destructor that is called from PHP right before the object is destructed 71 | */ 72 | virtual void __destruct() {} 73 | 74 | /** 75 | * Get access to a property by name 76 | * @param string 77 | * @return Property 78 | */ 79 | // Property operator[](const char *name); 80 | 81 | /** 82 | * Alternative way to access a property 83 | * @param string 84 | * @return Property 85 | */ 86 | // Property operator[](const std::string &name); 87 | 88 | protected: 89 | /** 90 | * All properties of the object 91 | * @var Properties 92 | */ 93 | // Properties _properties; 94 | 95 | private: 96 | }; 97 | 98 | /** 99 | * Definition of a method 100 | */ 101 | typedef void (Base::*method_callback_0)(); 102 | typedef void (Base::*method_callback_1)(Parameters &); 103 | typedef void (Base::*method_callback_2)(Environment &); 104 | typedef void (Base::*method_callback_3)(Environment &, Parameters &); 105 | typedef Value (Base::*method_callback_4)(); 106 | typedef Value (Base::*method_callback_5)(Parameters &); 107 | typedef Value (Base::*method_callback_6)(Environment &); 108 | typedef Value (Base::*method_callback_7)(Environment &, Parameters &); 109 | 110 | /** 111 | * End of namespace 112 | */ 113 | } 114 | 115 | -------------------------------------------------------------------------------- /src/include/phpcpp/byref.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ByRef.h 3 | * 4 | * Overridden Argument class to specify by-reference function arguments 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class ByRef : public Argument 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param name Name of the argument 24 | * @param type Argument type 25 | * @param required Is this argument required? 26 | */ 27 | ByRef(const char *name, Type type, bool required = true) : Argument(name, type, required, true) {} 28 | 29 | /** 30 | * Constructor 31 | * @param name Name of the argument 32 | * @param classname Name of the class 33 | * @param nullable Can it be null? 34 | * @param required Is this argument required? 35 | */ 36 | ByRef(const char *name, const char *classname, bool nullable = true, bool required = true) : Argument(name, classname, nullable, required, true) {} 37 | 38 | /** 39 | * Copy constructor 40 | * @param argument 41 | */ 42 | ByRef(const ByRef &argument) : Argument(argument) {} 43 | 44 | /** 45 | * Move constructor 46 | * @param argument 47 | */ 48 | ByRef(ByRef &&argument) : Argument(argument) {} 49 | 50 | /** 51 | * Destructor 52 | */ 53 | virtual ~ByRef() {} 54 | }; 55 | 56 | /** 57 | * End of namespace 58 | */ 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/include/phpcpp/byval.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ByVal.h 3 | * 4 | * Overridden Argument class to specify by-value function arguments 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class ByVal : public Argument 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param name Name of the argument 24 | * @param type Argument type 25 | * @param required Is this argument required? 26 | */ 27 | ByVal(const char *name, Type type, bool required = true) : Argument(name, type, required, false) {} 28 | 29 | /** 30 | * Constructor 31 | * @param name Name of the argument 32 | * @param classname Name of the class 33 | * @param nullable Can it be null? 34 | * @param required Is this argument required? 35 | */ 36 | ByVal(const char *name, const char *classname, bool nullable = true, bool required = true) : Argument(name, classname, nullable, required, false) {} 37 | 38 | /** 39 | * Copy constructor 40 | * @param argument 41 | */ 42 | ByVal(const ByVal &argument) : Argument(argument) {} 43 | 44 | /** 45 | * Move constructor 46 | * @param argument 47 | */ 48 | ByVal(ByVal &&argument) : Argument(argument) {} 49 | 50 | /** 51 | * Destructor 52 | */ 53 | virtual ~ByVal() {} 54 | }; 55 | 56 | /** 57 | * End of namespace 58 | */ 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/include/phpcpp/class.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Class.h 3 | * 4 | * When a class is registered in the extension, you need this helper class 5 | * for that. 6 | * 7 | * The use of it is simple: 8 | * 9 | * Extension::add(Class); 10 | * 11 | * Note that YourClass must extend from Php::Object 12 | * 13 | * @author Emiel Bruijntjes 14 | * @copyright 2013 Copernica BV 15 | */ 16 | 17 | /** 18 | * Forward declarations 19 | */ 20 | struct _zend_class_entry; 21 | 22 | /** 23 | * Set up namespace 24 | */ 25 | namespace Php { 26 | 27 | /** 28 | * Class definition of the class 29 | */ 30 | template 31 | class Class 32 | { 33 | public: 34 | /** 35 | * Constructor 36 | */ 37 | Class() {} 38 | 39 | /** 40 | * Constructor with initializer list to define the properties 41 | * @param members 42 | */ 43 | Class(const std::initializer_list &members) : _members(members) {} 44 | 45 | /** 46 | * Move constructor 47 | * @param that 48 | */ 49 | Class(Class &&that) : _members(std::move(that._members)) {} 50 | 51 | /** 52 | * Copy constructor 53 | */ 54 | Class(const Class &that) : _members(that._members) {} 55 | 56 | /** 57 | * Destructor 58 | */ 59 | virtual ~Class() {} 60 | 61 | /** 62 | * Construct an instance 63 | * @return Base 64 | */ 65 | Base* construct() 66 | { 67 | // allocate the object 68 | return new T(); 69 | } 70 | 71 | /** 72 | * Initialize the class 73 | * This will declare all members 74 | * @param entry 75 | */ 76 | void initialize(struct _zend_class_entry *entry) 77 | { 78 | // loop through the members 79 | for (auto iter = _members.begin(); iter != _members.end(); iter++) 80 | { 81 | iter->declare(entry); 82 | } 83 | } 84 | 85 | /** 86 | * Retrieve the functions 87 | * @param classname 88 | * @return zend_function_entry* 89 | */ 90 | struct _zend_function_entry *methods(const char *classname) 91 | { 92 | return _members.methods(classname); 93 | } 94 | 95 | protected: 96 | /** 97 | * The initial arguments 98 | * @var Members 99 | */ 100 | Members _members; 101 | 102 | }; 103 | 104 | /** 105 | * End of namespace 106 | */ 107 | } 108 | 109 | -------------------------------------------------------------------------------- /src/include/phpcpp/classinfo.h: -------------------------------------------------------------------------------- 1 | /** 2 | * ClassInfo.h 3 | * 4 | * Internal class that is constructed by the library and that contains 5 | * the information about a class, including its name. 6 | * 7 | * Users of the PHP-CPP libraries are not supposed to interact with 8 | * this class, or instantiate objects of this class. 9 | * 10 | * @author Emiel Bruijntjes 11 | * @copyright 2013 Copernica BV 12 | */ 13 | 14 | /** 15 | * Forward declarations 16 | */ 17 | struct _zend_class_entry; 18 | 19 | /** 20 | * Namespace 21 | */ 22 | namespace Php { 23 | 24 | /** 25 | * Forward declarations 26 | */ 27 | class InternalFunction; 28 | 29 | /** 30 | * Virtual base class of the classInfo 31 | * 32 | * We need this virtual base class to store pointers to class objects, 33 | * without knowing in advance what sort of object they will hold 34 | */ 35 | class _ClassInfo 36 | { 37 | public: 38 | /** 39 | * Constructor 40 | * @param name 41 | */ 42 | _ClassInfo(const char *name); 43 | 44 | /** 45 | * Destructor 46 | */ 47 | virtual ~_ClassInfo(); 48 | 49 | /** 50 | * Initialize the class 51 | */ 52 | void initialize(); 53 | 54 | /** 55 | * Construct the C++ object 56 | * @return Base 57 | */ 58 | virtual Base *construct() = 0; 59 | 60 | /** 61 | * Initialize the class 62 | * @param entry 63 | */ 64 | virtual void initialize(struct _zend_class_entry *entry) = 0; 65 | 66 | /** 67 | * Retrieve the methods 68 | * @return zend_function_entry[] 69 | */ 70 | virtual struct _zend_function_entry *methods() = 0; 71 | 72 | protected: 73 | /** 74 | * The class entry 75 | * @var zend_class_entry 76 | */ 77 | struct _zend_class_entry *_entry; 78 | 79 | /** 80 | * The name 81 | * @var string 82 | */ 83 | std::string _name; 84 | 85 | /** 86 | * Constructor function 87 | * @var InternalFunction 88 | */ 89 | InternalFunction *_constructor; 90 | 91 | /** 92 | * Destructor function 93 | * @var InternalFunction 94 | */ 95 | InternalFunction *_destructor; 96 | 97 | }; 98 | 99 | /** 100 | * Class definition 101 | */ 102 | template 103 | class ClassInfo : public _ClassInfo 104 | { 105 | public: 106 | /** 107 | * Constructor 108 | * @param name Name of the class 109 | * @param type The class type 110 | */ 111 | ClassInfo(const char *name, const Class &type) : _ClassInfo(name), _type(type) 112 | { 113 | } 114 | 115 | /** 116 | * Destructor 117 | */ 118 | virtual ~ClassInfo() {} 119 | 120 | /** 121 | * Construct the object 122 | * @return Base 123 | */ 124 | virtual Base *construct() 125 | { 126 | return _type.construct(); 127 | } 128 | 129 | /** 130 | * Initialize the class 131 | * @param entry 132 | */ 133 | virtual void initialize(struct _zend_class_entry *entry) 134 | { 135 | // pass to the entry 136 | _type.initialize(entry); 137 | } 138 | 139 | /** 140 | * Retrieve the methods 141 | * @return zend_function_entry[] 142 | */ 143 | virtual struct _zend_function_entry *methods() 144 | { 145 | // ask class object 146 | return _type.methods(_name.c_str()); 147 | } 148 | 149 | private: 150 | /** 151 | * The class object 152 | * @var Class 153 | */ 154 | Class _type; 155 | 156 | }; 157 | 158 | /** 159 | * End of namespace 160 | */ 161 | } 162 | 163 | -------------------------------------------------------------------------------- /src/include/phpcpp/environment.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Environment.h 3 | * 4 | * During the lifetime of the extension, multiple requests can be handled 5 | * by it. For every request that is handled, an environment object is created. 6 | * 7 | * The base class for the environment is defined in this file. If you'd like 8 | * to add state variables to the environment you can override this class and 9 | * add the extra features you'd like. If you override this method, you should 10 | * also override Extension::createEnvironment() to return an instance of a 11 | * different class. 12 | * 13 | * @author Emiel Bruijntjes 14 | * @copyright 2013 Copernica BV 15 | */ 16 | 17 | /** 18 | * Set up namespace 19 | */ 20 | namespace Php { 21 | 22 | /** 23 | * Forward definitions 24 | */ 25 | class Extension; 26 | class Global; 27 | 28 | /** 29 | * Class definition 30 | */ 31 | class Environment 32 | { 33 | public: 34 | /** 35 | * Constructor 36 | * @param extension 37 | */ 38 | Environment(Extension *extension) : _extension(extension) {} 39 | 40 | /** 41 | * Disable copy and move operations 42 | */ 43 | Environment(const Environment &environment) = delete; 44 | Environment(Environment &&environment) = delete; 45 | 46 | /** 47 | * Destructor 48 | */ 49 | virtual ~Environment() {} 50 | 51 | /** 52 | * Initialize the request 53 | * 54 | * This method is called directly after the object was destructed. You can 55 | * override this method to add your own initialization code. 56 | * 57 | * @return bool 58 | */ 59 | virtual bool initialize() 60 | { 61 | return true; 62 | } 63 | 64 | /** 65 | * Finalize the request 66 | * 67 | * This method is called right before the object is destructed. Note that 68 | * the object is going to be destructed anyway, even if this method returns 69 | * false 70 | * 71 | * @return bool 72 | */ 73 | virtual bool finalize() 74 | { 75 | return true; 76 | } 77 | 78 | /** 79 | * Get access to the user supplied data 80 | * @return void* 81 | */ 82 | virtual void *data() 83 | { 84 | return _data; 85 | } 86 | 87 | /** 88 | * Change the user supplied data 89 | * @param data 90 | */ 91 | virtual void setData(void *data) 92 | { 93 | _data = data; 94 | } 95 | 96 | /** 97 | * Get access to a global variable 98 | * @param name 99 | * @return Global 100 | */ 101 | Global operator[](const char *name); 102 | 103 | /** 104 | * Get access to a global variable 105 | * @param name 106 | * @return Global 107 | */ 108 | Global operator[](const std::string &name); 109 | 110 | /** 111 | * Call a function in PHP 112 | * We have ten variants of this function, depending on the number of parameters 113 | * @param name Name of the function 114 | * @return Value 115 | */ 116 | Value call(const Value &name); 117 | Value call(const Value &name, Value p0); 118 | Value call(const Value &name, Value p0, Value p1); 119 | Value call(const Value &name, Value p0, Value p1, Value p2); 120 | Value call(const Value &name, Value p0, Value p1, Value p2, Value p3); 121 | Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4); 122 | Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5); 123 | Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6); 124 | Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7); 125 | Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8); 126 | Value call(const Value &name, Value p0, Value p1, Value p2, Value p3, Value p4, Value p5, Value p6, Value p7, Value p8, Value p9); 127 | 128 | private: 129 | /** 130 | * Call function with a number of parameters 131 | * @param name Function name 132 | * @param argc Number of parameters 133 | * @param argv The parameters 134 | * @return Value 135 | */ 136 | Value exec(const Value &name, int argc, struct _zval_struct ***params); 137 | 138 | protected: 139 | /** 140 | * The extension that this environment belongs to 141 | * @var Extension* 142 | */ 143 | Extension *_extension; 144 | 145 | /** 146 | * Pointer to user supplied data 147 | * @var void* 148 | */ 149 | void *_data = NULL; 150 | }; 151 | 152 | /** 153 | * End of namespace 154 | */ 155 | } 156 | 157 | -------------------------------------------------------------------------------- /src/include/phpcpp/error.h: -------------------------------------------------------------------------------- 1 | /** 2 | * error.h 3 | * 4 | * Contains 'static' function that can be used to report errors. For now throwing an Exception (zend default) 5 | * is enough. In the future, we might want to implement extensive exception support. 6 | * 7 | * @author Swen Kooij 8 | * @copyright 2013 Swen Kooij 9 | */ 10 | 11 | /** 12 | * Setup namespace 13 | */ 14 | namespace Php 15 | { 16 | /** 17 | * Throws an Exception (Zend Default) with the specified message. 18 | * @param error_msg A string, describing the reason of failure. 19 | */ 20 | void ThrowError(const std::string &error_msg); 21 | } 22 | -------------------------------------------------------------------------------- /src/include/phpcpp/extension.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Extension.h 3 | * 4 | * The extension class is the starting point of your PHP extension. This class 5 | * is instantiated the moment the PHP engine starts - for example when the 6 | * apache process starts - and will be used for all subsequent requests that 7 | * are handled by Apache. 8 | * 9 | * For some environments (for example CLI scripts and FastCGI calls) only one 10 | * request is handled by an extension instance, but for others (when PHP runs 11 | * as module in a webserver) many requests are handled by the same extension 12 | * instance. 13 | * 14 | * This is a template class. You need to pass in the type of an object 15 | * that you use for storing request specific state information. 16 | * 17 | * @author Emiel Bruijntjes 18 | * @copyright 2013 Copernica BV 19 | */ 20 | 21 | /** 22 | * Structures referenced in this class 23 | */ 24 | struct _zend_module_entry; 25 | 26 | /** 27 | * Set up namespace 28 | */ 29 | namespace Php { 30 | 31 | /** 32 | * Optional callback types for starting and stopping the request 33 | */ 34 | typedef bool (*request_callback)(Environment &); 35 | 36 | /** 37 | * A couple of predefined native callback functions that can be registered. 38 | * These are functions that optional accept a Request and/or Parameters object, 39 | * and that either return void or a Value object. 40 | */ 41 | typedef void (*native_callback_0)(); 42 | typedef void (*native_callback_1)(Parameters &); 43 | typedef void (*native_callback_2)(Environment &); 44 | typedef void (*native_callback_3)(Environment &, Parameters &); 45 | typedef Value (*native_callback_4)(); 46 | typedef Value (*native_callback_5)(Parameters &); 47 | typedef Value (*native_callback_6)(Environment &); 48 | typedef Value (*native_callback_7)(Environment &, Parameters &); 49 | 50 | /** 51 | * Class definition 52 | */ 53 | class Extension 54 | { 55 | public: 56 | /** 57 | * Constructor that defines a number of functions right away 58 | * @param name Extension name 59 | * @param version Extension version string 60 | * @param callback Function that is called when request starts 61 | * @param callback Function that is called when request ends 62 | */ 63 | Extension(const char *name = NULL, const char *version = NULL, request_callback start = NULL, request_callback stop = NULL); 64 | 65 | /** 66 | * No copy'ing and no moving 67 | */ 68 | Extension(const Extension &extension) = delete; 69 | Extension(Extension &&extension) = delete; 70 | 71 | /** 72 | * Destructor 73 | */ 74 | virtual ~Extension(); 75 | 76 | /** 77 | * Initialize the extension. 78 | * 79 | * This method is called after the extension has been loaded, constructed 80 | * and after the compatibility has been checked, but before the requests 81 | * are handled. You can override this method to add your own initialization. 82 | * 83 | * The default behavior of this function is to enable all classes that are 84 | * defined in this extension, so that they are also available in PHP. 85 | * 86 | * The method should return true on success, and false on failure (in which 87 | * case the extension will not be used) 88 | * 89 | * @return bool 90 | */ 91 | virtual bool initialize(); 92 | 93 | /** 94 | * Finalize the extension 95 | * 96 | * This method gets called after all requests were handled, and right before 97 | * the Apache module or CLI script will exit. You can override it to add 98 | * your own cleanup code. 99 | * 100 | * @return bool 101 | */ 102 | virtual bool finalize() 103 | { 104 | return true; 105 | } 106 | 107 | /** 108 | * Create a new environment 109 | * 110 | * You can override this method if you've created your own environment class, 111 | * and you'd like to use an instance of that class instead. The returned 112 | * object must have been created on the heap. 113 | * 114 | * @return Environment* 115 | */ 116 | virtual Environment *createEnvironment() 117 | { 118 | // allocate the environment 119 | return new Environment(this); 120 | } 121 | 122 | /** 123 | * Destruct an environment 124 | * 125 | * This is the counterpart of the createEnvironment method. 126 | * 127 | * @param Environment 128 | */ 129 | virtual void deleteEnvironment(Environment *environment) 130 | { 131 | // destruct the environment 132 | delete environment; 133 | } 134 | 135 | /** 136 | * Start a request 137 | * 138 | * This method is called when the zend engine is about to start a new 139 | * request. Internally, it calls the request() method to instantiate 140 | * a new request object, and after that it initializes the request. 141 | * 142 | * @return boolean 143 | */ 144 | virtual bool startRequest(Environment &environment) 145 | { 146 | // ok if no callback was set 147 | if (!_start) return true; 148 | 149 | // call the callback function 150 | return _start(environment); 151 | } 152 | 153 | /** 154 | * End a request 155 | * 156 | * This method is called when the Zend engine is ready with a request. 157 | * Internally, it destructs the request 158 | * 159 | * @return boolean 160 | */ 161 | virtual bool endRequest(Environment &environment) 162 | { 163 | // ok if no callback is set 164 | if (!_stop) return true; 165 | 166 | // call callback 167 | return _stop(environment); 168 | } 169 | 170 | /** 171 | * Add a function to the extension 172 | * 173 | * It is only possible to create functions during the initialization of 174 | * the library, before the Extension::module() method is called. 175 | * 176 | * Note that the function must have been allocated on the HEAP (using 177 | * "new") and that the object will be destructed (using "delete") 178 | * by the extension object (you thus do not have to destruct it 179 | * yourself!) 180 | * 181 | * @param function The function to add 182 | * @return Function The added function 183 | */ 184 | Function *add(Function *function); 185 | 186 | /** 187 | * Add a native function directly to the extension 188 | * @param name Name of the function 189 | * @param function The function to add 190 | * @param arguments Optional argument specification 191 | * @return Function The added function 192 | */ 193 | Function *add(const char *name, native_callback_0 function, const std::initializer_list &arguments = {}); 194 | Function *add(const char *name, native_callback_1 function, const std::initializer_list &arguments = {}); 195 | Function *add(const char *name, native_callback_2 function, const std::initializer_list &arguments = {}); 196 | Function *add(const char *name, native_callback_3 function, const std::initializer_list &arguments = {}); 197 | Function *add(const char *name, native_callback_4 function, const std::initializer_list &arguments = {}); 198 | Function *add(const char *name, native_callback_5 function, const std::initializer_list &arguments = {}); 199 | Function *add(const char *name, native_callback_6 function, const std::initializer_list &arguments = {}); 200 | Function *add(const char *name, native_callback_7 function, const std::initializer_list &arguments = {}); 201 | 202 | /** 203 | * Add a native class to the extension 204 | * @param name Name of the class 205 | * @param type The class implementation 206 | */ 207 | template 208 | void add(const char *name, const Class &type) 209 | { 210 | // construct info 211 | ClassInfo *info = new ClassInfo(name, type); 212 | 213 | // add class 214 | _classes.insert(std::unique_ptr<_ClassInfo>(info)); 215 | } 216 | 217 | /** 218 | * Retrieve the module entry 219 | * 220 | * This is the memory address that should be exported by the get_module() 221 | * function. 222 | * 223 | * @return _zend_module_entry 224 | */ 225 | _zend_module_entry *module(); 226 | 227 | 228 | private: 229 | /** 230 | * Set of function objects defined in the library 231 | * @var set 232 | */ 233 | std::set> _functions; 234 | 235 | /** 236 | * Set of classes defined in the library 237 | * @var set 238 | */ 239 | std::set> _classes; 240 | 241 | /** 242 | * The information that is passed to the Zend engine 243 | * 244 | * Although it would be slightly faster to not make this a pointer, this 245 | * would require that client code also includes the PHP header files, which 246 | * we try to prevent with the PHP-CPP library, so we allocate it dynamically. 247 | * 248 | * @var zend_module_entry 249 | */ 250 | _zend_module_entry *_entry; 251 | 252 | /** 253 | * Callback that is called before each request 254 | * @var request_callback 255 | */ 256 | request_callback _start; 257 | 258 | /** 259 | * Callback that is called after each request 260 | * @var request_callback 261 | */ 262 | request_callback _stop; 263 | 264 | }; 265 | 266 | /** 267 | * End of namespace 268 | */ 269 | } 270 | 271 | 272 | -------------------------------------------------------------------------------- /src/include/phpcpp/function.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Function.h 3 | * 4 | * Object represents a callable function that is defined with the CPP API. 5 | * After you've instantiated the extension, you can add function objects to 6 | * it. 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2013 Copernica BV 10 | */ 11 | 12 | /** 13 | * Forward definitions 14 | */ 15 | struct _zend_function_entry; 16 | struct _zend_internal_function_info; 17 | 18 | /** 19 | * Set up namespace 20 | */ 21 | namespace Php { 22 | 23 | /** 24 | * Class definition 25 | */ 26 | class Function 27 | { 28 | public: 29 | /** 30 | * Constructor 31 | * @param name Name of the function 32 | * @param min Min number of arguments 33 | * @param max Max number of arguments 34 | */ 35 | Function(const char *name, const std::initializer_list &arguments = {}); 36 | 37 | /** 38 | * No copy and move constructors 39 | * @param function The other function 40 | */ 41 | Function(const Function &function) = delete; 42 | Function(Function &&function) = delete; 43 | 44 | /** 45 | * Destructor 46 | */ 47 | virtual ~Function(); 48 | 49 | /** 50 | * No assignment operator 51 | * @param function The other function 52 | * @return Function 53 | */ 54 | Function &operator=(const Function &function) = delete; 55 | 56 | /** 57 | * Comparison 58 | * @param function The other function 59 | * @return bool 60 | */ 61 | bool operator<(const Function &function) const 62 | { 63 | return strcmp(name(), function.name()) < 0; 64 | } 65 | 66 | /** 67 | * Comparison 68 | * @param function The other function 69 | * @return bool 70 | */ 71 | bool operator>(const Function &function) const 72 | { 73 | return strcmp(name(), function.name()) > 0; 74 | } 75 | 76 | /** 77 | * Comparison 78 | * @param function The other function 79 | * @return bool 80 | */ 81 | bool operator==(const Function &function) const 82 | { 83 | return strcmp(name(), function.name()) == 0; 84 | } 85 | 86 | /** 87 | * Function name 88 | * @return const char * 89 | */ 90 | const char *name() const 91 | { 92 | return _ptr.text(); 93 | } 94 | 95 | /** 96 | * Method that gets called every time the function is executed 97 | * @param environment Environment object 98 | * @param params The parameters that were passed 99 | * @return Variable Return value 100 | */ 101 | virtual Value invoke(Environment &environment, Parameters ¶ms) 102 | { 103 | return nullptr; 104 | } 105 | 106 | 107 | protected: 108 | /** 109 | * Suggestion for the return type 110 | * @var Type 111 | */ 112 | Type _type = nullType; 113 | 114 | /** 115 | * Required number of arguments 116 | * @var integer 117 | */ 118 | int _required; 119 | 120 | /** 121 | * Total number of arguments 122 | * @var integer 123 | */ 124 | int _argc; 125 | 126 | /** 127 | * The arguments 128 | * @var zend_arg_info[] 129 | */ 130 | struct _zend_arg_info *_argv; 131 | 132 | /** 133 | * The object address is stored in a hidden pointer, so that we have access to the function object 134 | * @var HiddenPointer 135 | */ 136 | HiddenPointer _ptr; 137 | 138 | protected: 139 | /** 140 | * Fill a function entry 141 | * @param entry Entry to be filled 142 | * @param classname Optional class name 143 | * @param pub Is this a public property? 144 | */ 145 | void fill(struct _zend_function_entry *entry, const char *classname=NULL, bool pub=true) const; 146 | 147 | /** 148 | * Fill function info 149 | * @param info Info object to be filled 150 | * @param classname Optional class name 151 | */ 152 | void fill(struct _zend_internal_function_info *info, const char *classname=NULL) const; 153 | 154 | /** 155 | * Extension has access to the private members 156 | */ 157 | friend class Extension; 158 | 159 | }; 160 | 161 | /** 162 | * End of namespace 163 | */ 164 | } 165 | 166 | -------------------------------------------------------------------------------- /src/include/phpcpp/global.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Global variable 3 | * 4 | * A global variable is a value that - once updated - also updates 5 | * the global scope 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2013 Copernica BV 9 | */ 10 | 11 | /** 12 | * Forward definitions 13 | */ 14 | struct _zval_struct; 15 | 16 | /** 17 | * Namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Class definition 23 | */ 24 | class Global : public Value 25 | { 26 | public: 27 | /** 28 | * No copy constructor 29 | * @param global 30 | */ 31 | Global(const Global &global) = delete; 32 | 33 | /** 34 | * Move constructor 35 | * @param global 36 | */ 37 | Global(Global &&global) : Value(std::move(global)), _name(std::move(global._name)), _exists(global._exists) {} 38 | 39 | /** 40 | * Destructor 41 | */ 42 | virtual ~Global() {} 43 | 44 | /** 45 | * Assignment operator 46 | * @param global 47 | * @return Global 48 | */ 49 | /* 50 | Global &operator=(const Global &global) 51 | { 52 | // skip self assignment 53 | if (&global == this) return *this; 54 | 55 | // call base 56 | Value::operator=(global); 57 | 58 | // copy name and exists setting 59 | _name = global._name; 60 | _exists = global._exists; 61 | 62 | // done 63 | return *this; 64 | } 65 | */ 66 | 67 | /** 68 | * Move operator 69 | * @param global 70 | * @return Global 71 | */ 72 | /* 73 | Global &operator=(Global &&global) 74 | { 75 | // skip self assignment 76 | if (&global == this) return *this; 77 | 78 | // call base 79 | Value::operator=(std::move(global)); 80 | 81 | // copy name and exists setting 82 | _name = std::move(global._name); 83 | _exists = global._exists; 84 | 85 | // done 86 | return *this; 87 | } 88 | */ 89 | 90 | /** 91 | * Assignment operator 92 | * @param value 93 | * @return Global 94 | */ 95 | template 96 | Global &operator=(const T &value) 97 | { 98 | Value::operator=(value); 99 | return update(); 100 | } 101 | 102 | /** 103 | * Set a certain property 104 | * Calling this method will turn the value into an array 105 | * @param index Index of the property to set 106 | * @param value Value to set 107 | * @return Value The value that was set 108 | */ 109 | virtual const Value &set(int index, const Value &value) override 110 | { 111 | // update current object 112 | update(); 113 | 114 | // call base 115 | return Value::set(index, value); 116 | } 117 | 118 | /** 119 | * Set a certain property 120 | * Calling this method will turn the value into an array 121 | * @param key Key of the property to set 122 | * @param size Size of the key 123 | * @param value Value to set 124 | * @return Value The value that was set 125 | */ 126 | virtual const Value &set(const char *key, int size, const Value &value) override 127 | { 128 | // update current object 129 | update(); 130 | 131 | // call base 132 | return Value::set(key, size, value); 133 | } 134 | 135 | 136 | protected: 137 | /** 138 | * Function that is called when the value is updated 139 | * @return Value 140 | */ 141 | Global &update(); 142 | 143 | private: 144 | /** 145 | * Constructor for non-existing var 146 | * @param name 147 | */ 148 | Global(const char *name) : Value(), _name(name), _exists(false) {} 149 | 150 | /** 151 | * Alternative constructor for non-existing var 152 | * @param name 153 | */ 154 | Global(const std::string &name) : Value(), _name(name), _exists(false) {} 155 | 156 | /** 157 | * Constructor to wrap zval for existing global bar 158 | * @param name 159 | * @param val 160 | */ 161 | Global(const char *name, struct _zval_struct *val) : Value(val, true), _name(name), _exists(true) {} 162 | 163 | /** 164 | * Alternative constructor to wrap zval 165 | * @param name 166 | * @param val 167 | */ 168 | Global(const std::string &name, struct _zval_struct *val) : Value(val, true), _name(name), _exists(true) {} 169 | 170 | /** 171 | * Name of the variable 172 | * @var string 173 | */ 174 | std::string _name; 175 | 176 | /** 177 | * Does it already exist? 178 | * @var bool 179 | */ 180 | bool _exists; 181 | 182 | /** 183 | * The environment can access the private method from this class 184 | */ 185 | friend class Environment; 186 | }; 187 | 188 | /** 189 | * End of namespace 190 | */ 191 | } 192 | 193 | 194 | -------------------------------------------------------------------------------- /src/include/phpcpp/globals.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Globals.h 3 | * 4 | * Variables and structured required by the Zend engine to work 5 | * with global variables 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2013 Copernica BV 9 | */ 10 | 11 | /** 12 | * Namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * The way how PHP C API deals with "global" variables is stupid. 18 | * 19 | * This is supposed to turn into a structure that is going to be 20 | * instantiated for each parallel running request, and for which the 21 | * PHP engine allocates a certain amount of memory, and a magic 22 | * pointer that is passed and should be forwarded to every thinkable 23 | * PHP function. 24 | * 25 | * We don't like this architecture. We have our own environment object 26 | * that makes much more sense, and that we use. However, we need 27 | * to assign this object somewhere, so that's what we do in this 28 | * one and only global variable 29 | */ 30 | ZEND_BEGIN_MODULE_GLOBALS(phpcpp) 31 | Php::Environment *environment; 32 | ZEND_END_MODULE_GLOBALS(phpcpp) 33 | 34 | /** 35 | * And now we're going to define a macro. This also is a ridiculous 36 | * architecture from PHP to get access to a variable from the 37 | * structure above. 38 | */ 39 | #ifdef ZTS 40 | #define PHPCPP_G(v) TSRMG(phpcpp_globals_id, phpcpp_globals *, v) 41 | #else 42 | #define PHPCPP_G(v) (phpcpp_globals.v) 43 | #endif 44 | 45 | /** 46 | * We're almost there, we now need to declare an instance of the 47 | * structure defined above (if building for a single thread) or some 48 | * sort of impossible to understand magic pointer-to-a-pointer (for 49 | * multi-threading builds). We make this a static variable because 50 | * this already is bad enough. 51 | */ 52 | extern ZEND_DECLARE_MODULE_GLOBALS(phpcpp) 53 | 54 | /** 55 | * End of namespace 56 | */ 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/include/phpcpp/hashmember.h: -------------------------------------------------------------------------------- 1 | /** 2 | * HashMember.h 3 | * 4 | * When you're accessing members in an array or an object, you're 5 | * doing this via an internal member object. This is an object that 6 | * keeps track of the array to which it belongs, and that will update 7 | * the array when the member is modified 8 | * 9 | * You are not supposed to instantiate this class. An instance of it is 10 | * created when you call Value::operator[] 11 | * 12 | * @author Emiel Bruijntjes 13 | * @copyright 2013 Copernica BV 14 | */ 15 | 16 | /** 17 | * Set up namespace 18 | */ 19 | namespace Php { 20 | 21 | /** 22 | * Forward definitions 23 | */ 24 | class Value; 25 | 26 | /** 27 | * Member class 28 | */ 29 | template 30 | class HashMember 31 | { 32 | public: 33 | /** 34 | * Destructor 35 | */ 36 | virtual ~HashMember() {} 37 | 38 | /** 39 | * Assign a value object to the array 40 | * @param value 41 | * @return Member 42 | */ 43 | HashMember &operator=(const Value &value) 44 | { 45 | // set property in parent array 46 | _base.set(_index, value); 47 | 48 | // if there is a parent, it should sets its value too 49 | if (_parent) _parent->operator=(_base); 50 | 51 | // done 52 | return *this; 53 | } 54 | 55 | /** 56 | * Retrieve the original value 57 | * @return Value 58 | */ 59 | Value value() const 60 | { 61 | return _base.get(_index); 62 | } 63 | 64 | /** 65 | * Cast to a value object 66 | * @return Value 67 | */ 68 | operator Value () const 69 | { 70 | return _base.get(_index); 71 | } 72 | 73 | /** 74 | * Cast to a integer 75 | * @return int16_t 76 | */ 77 | operator int16_t () const 78 | { 79 | return _base.get(_index).numericValue(); 80 | } 81 | 82 | /** 83 | * Cast to a integer 84 | * @return int32_t 85 | */ 86 | operator int32_t () const 87 | { 88 | return _base.get(_index).numericValue(); 89 | } 90 | 91 | /** 92 | * Cast to a integer 93 | * @return int64_t 94 | */ 95 | operator int64_t () const 96 | { 97 | return _base.get(_index).numericValue(); 98 | } 99 | 100 | /** 101 | * Cast to a boolean 102 | * @return boolean 103 | */ 104 | operator bool () const 105 | { 106 | return _base.get(_index).boolValue(); 107 | } 108 | 109 | /** 110 | * Cast to a string 111 | * @return string 112 | */ 113 | operator std::string () const 114 | { 115 | return _base.get(_index).stringValue(); 116 | } 117 | 118 | /** 119 | * Cast to byte array 120 | * @return const char * 121 | */ 122 | operator const char * () const 123 | { 124 | return _base.get(_index).rawValue(); 125 | } 126 | 127 | /** 128 | * Cast to a floating point 129 | * @return double 130 | */ 131 | operator double () const 132 | { 133 | return _base.get(_index).decimalValue(); 134 | } 135 | 136 | /** 137 | * Array access operator 138 | * This can be used for accessing arrays 139 | * @param index 140 | * @return HashMember 141 | */ 142 | HashMember operator[](int index) 143 | { 144 | return _base.get(_index)[index].add(this); 145 | } 146 | 147 | /** 148 | * Array access operator 149 | * This can be used for accessing associative arrays 150 | * @param key 151 | * @return HashMember 152 | */ 153 | HashMember operator[](const std::string &key) 154 | { 155 | return _base.get(_index)[key].add(this); 156 | } 157 | 158 | /** 159 | * Array access operator 160 | * This can be used for accessing associative arrays 161 | * @param key 162 | * @return HashMember 163 | */ 164 | HashMember operator[](const char *key) 165 | { 166 | return _base.get(_index)[key].add(this); 167 | } 168 | 169 | private: 170 | /** 171 | * Constructor 172 | * @param base Base value 173 | * @param index Index in the array 174 | */ 175 | HashMember(const Value *base, Type index) : _base(*base), _index(index) {} 176 | 177 | /** 178 | * Protected copy constructor 179 | * @param value Other element 180 | */ 181 | HashMember(const HashMember &member) : _base(member._base), _index(member._index), _parent(member._parent) {} 182 | 183 | /** 184 | * Add parent 185 | * @param parent 186 | * @return HashMember 187 | */ 188 | HashMember &add(HashMember *parent) 189 | { 190 | _parent = parent; 191 | return *this; 192 | } 193 | 194 | /** 195 | * The original index 196 | * @var Type 197 | */ 198 | Type _index; 199 | 200 | /** 201 | * Base value 202 | * @var Value 203 | */ 204 | Value _base; 205 | 206 | /** 207 | * Parent member (in case of nested members) 208 | * @var HashMember 209 | */ 210 | HashMember *_parent = nullptr; 211 | 212 | /** 213 | * Only value objects may construct members 214 | */ 215 | friend class Value; 216 | friend class Properties; 217 | 218 | }; 219 | 220 | /** 221 | * Custom output stream operator 222 | * @param stream 223 | * @param value 224 | * @return ostream 225 | */ 226 | std::ostream &operator<<(std::ostream &stream, const HashMember &value); 227 | std::ostream &operator<<(std::ostream &stream, const HashMember &value); 228 | 229 | 230 | /** 231 | * End of namespace 232 | */ 233 | } 234 | 235 | -------------------------------------------------------------------------------- /src/include/phpcpp/hiddenpointer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * HiddenPointer.h 3 | * 4 | * Helper class that we use to hide a pointer in a string. We do this 5 | * by creating a string buffer that is a littlebit bigger, and put 6 | * the hidden pointer in front of the name 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2013 Copernica BV 10 | */ 11 | 12 | /** 13 | * Set up namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Class definition 19 | */ 20 | template 21 | class HiddenPointer 22 | { 23 | public: 24 | /** 25 | * Constructor to hide the pointer in a buffer 26 | * @param pointer The pointer to hide 27 | * @param text The visible text 28 | * @param size Optional text size 29 | */ 30 | HiddenPointer(Type *pointer, const char *text, int size=-1) 31 | { 32 | // calculate size 33 | if (size < 0) size = strlen(text); 34 | 35 | // reserve enough room for the text and the pointer 36 | _data.reserve(size + sizeof(Type *)); 37 | 38 | // store the pointer 39 | _data.assign(std::string((const char *)&pointer, sizeof(Type *))); 40 | 41 | // append the text 42 | _data.append(text, size); 43 | 44 | // store pointers 45 | _pointer = pointer; 46 | _text = _data.c_str() + sizeof(Type *); 47 | } 48 | 49 | /** 50 | * Hide pointer in buffer 51 | * @param pointer 52 | * @param text 53 | */ 54 | HiddenPointer(Type *pointer, const std::string &text) : HiddenPointer(pointer, text.c_str(), text.size()) {} 55 | 56 | /** 57 | * Constructor to retrieve the object given a buffer 58 | * @param text The visible text 59 | * @param size Size of the text 60 | */ 61 | HiddenPointer(const char *text, int size=-1) 62 | { 63 | // calculate size 64 | if (size < 0) size = strlen(text); 65 | 66 | // the pointer is stored right in front of the name 67 | _pointer = *((Type **)(text - sizeof(Type *))); 68 | _text = text; 69 | } 70 | 71 | /** 72 | * Copy constructor 73 | * @param that 74 | */ 75 | HiddenPointer(const HiddenPointer &that) : _pointer(that._pointer), _text(that._text), _data(that._data) 76 | { 77 | // if data is filled, the text is located inside the data 78 | if (_data.size() > 0) _text = _data.c_str() + sizeof(Type *); 79 | } 80 | 81 | /** 82 | * Destructor 83 | */ 84 | virtual ~HiddenPointer() {} 85 | 86 | /** 87 | * Assignment operator 88 | * @param that 89 | * @return HiddenPointer 90 | */ 91 | HiddenPointer operator=(const HiddenPointer &that) 92 | { 93 | // skip self assignment 94 | if (&that == this) return *this; 95 | 96 | // copy members 97 | _pointer = that._pointer; 98 | _text = that._text; 99 | _data = that._data; 100 | 101 | // if data is filled, the text is located inside the data 102 | if (_data.size() > 0) _text = _data.c_str() + sizeof(Type *); 103 | } 104 | 105 | /** 106 | * Retrieve the pointer 107 | * @return Type* 108 | */ 109 | Type *pointer() const 110 | { 111 | return _pointer; 112 | } 113 | 114 | /** 115 | * Change the pointer 116 | * @param Type* 117 | */ 118 | void setPointer(Type *pointer) 119 | { 120 | // store pointer 121 | _pointer = pointer; 122 | 123 | // overwrite in data 124 | _data.replace(0, sizeof(Type *), (const char *)&_pointer, sizeof(Type *)); 125 | 126 | // for safety reasons, we recalculate text pointer 127 | _text = _data.c_str() + sizeof(Type *); 128 | } 129 | 130 | /** 131 | * Retrieve the text 132 | * @return const char * 133 | */ 134 | const char *text() const 135 | { 136 | return _text; 137 | } 138 | 139 | /** 140 | * Change the text 141 | * @param text 142 | * @param size 143 | */ 144 | void setText(const char *text, int size=-1) 145 | { 146 | // check if size was set 147 | if (size < 0) size = strlen(text); 148 | 149 | // reserve enough room for the text and the pointer 150 | _data.reserve(size + sizeof(Type *)); 151 | 152 | // store the pointer 153 | _data.assign(std::string((const char *)&_pointer, sizeof(Type *))); 154 | 155 | // append the text 156 | _data.append(text, size); 157 | 158 | // store new text 159 | _text = _data.c_str() + sizeof(Type *); 160 | } 161 | 162 | /** 163 | * Cast to the pointer 164 | * @return Type* 165 | */ 166 | operator Type* () const 167 | { 168 | return _pointer; 169 | } 170 | 171 | /** 172 | * Cast to text 173 | * @return const char * 174 | */ 175 | operator const char * () const 176 | { 177 | return _text; 178 | } 179 | 180 | /** 181 | * Length of the text 182 | * @return int 183 | */ 184 | int length() const 185 | { 186 | return _data.size() - sizeof(Type *); 187 | } 188 | 189 | private: 190 | /** 191 | * The actual pointer 192 | * @var Type* 193 | */ 194 | Type *_pointer; 195 | 196 | /** 197 | * The original text 198 | * @var text 199 | */ 200 | const char *_text; 201 | 202 | /** 203 | * Optional data buffer 204 | * @var string 205 | */ 206 | std::string _data; 207 | 208 | }; 209 | 210 | /** 211 | * End of namespace 212 | */ 213 | } 214 | 215 | -------------------------------------------------------------------------------- /src/include/phpcpp/member.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Member.h 3 | * 4 | * Base class for elements of a class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Forward declarations 12 | */ 13 | struct _zend_class_entry; 14 | 15 | /** 16 | * Namespace 17 | */ 18 | namespace Php { 19 | 20 | /** 21 | * Forward declarations 22 | */ 23 | class MemberInfo; 24 | 25 | /** 26 | * Class definition 27 | */ 28 | class Member 29 | { 30 | public: 31 | /** 32 | * Constructor 33 | * @param name Name of the member 34 | * @param pub Is this a public property (otherwise it is protected) 35 | */ 36 | Member(const char *name, bool pub); 37 | 38 | /** 39 | * Constructor 40 | * @param name Name of the member 41 | * @param pub Is this a public property (otherwise it is protected) 42 | * @param value The value to add 43 | */ 44 | Member(const char *name, bool pub, std::nullptr_t value); 45 | 46 | /** 47 | * Constructor 48 | * @param name Name of the member 49 | * @param pub Is this a public property (otherwise it is protected) 50 | * @param value The value to add 51 | */ 52 | Member(const char *name, bool pub, int value); 53 | 54 | /** 55 | * Constructor 56 | * @param name Name of the member 57 | * @param pub Is this a public property (otherwise it is protected) 58 | * @param value The value to add 59 | */ 60 | Member(const char *name, bool pub, long value); 61 | 62 | /** 63 | * Constructor 64 | * @param name Name of the member 65 | * @param pub Is this a public property (otherwise it is protected) 66 | * @param value The value to add 67 | */ 68 | Member(const char *name, bool pub, bool value); 69 | 70 | /** 71 | * Constructor 72 | * @param name Name of the member 73 | * @param pub Is this a public property (otherwise it is protected) 74 | * @param value The value to add 75 | */ 76 | Member(const char *name, bool pub, char value); 77 | 78 | /** 79 | * Constructor 80 | * @param name Name of the member 81 | * @param pub Is this a public property (otherwise it is protected) 82 | * @param value The value to add 83 | */ 84 | Member(const char *name, bool pub, const std::string &value); 85 | 86 | /** 87 | * Constructor 88 | * @param name Name of the member 89 | * @param pub Is this a public property (otherwise it is protected) 90 | * @param value The value to add 91 | * @param size String length 92 | */ 93 | Member(const char *name, bool pub, const char *value, int size = -1); 94 | 95 | /** 96 | * Constructor 97 | * @param name Name of the member 98 | * @param pub Is this a public property (otherwise it is protected) 99 | * @param value The value to add 100 | */ 101 | Member(const char *name, bool pub, double value); 102 | 103 | /** 104 | * Constructor 105 | * @param name Name of the method 106 | * @param pub Is this a public method (otherwise it is protected) 107 | * @param method The method to add 108 | */ 109 | Member(const char *name, bool pub, const _Method &method, const std::initializer_list &arguments = {}); 110 | 111 | /** 112 | * Copy constructor 113 | * @param member The member to copy 114 | */ 115 | Member(const Member &member); 116 | 117 | /** 118 | * Move constructor 119 | * @param member The member to move 120 | */ 121 | Member(Member &&member); 122 | 123 | /** 124 | * Destructor 125 | */ 126 | virtual ~Member(); 127 | 128 | /** 129 | * Internal method to declare the property 130 | * @param zend_class_entry 131 | * @internal 132 | */ 133 | void declare(struct _zend_class_entry *entry); 134 | 135 | /** 136 | * Internal method to fill a function entry 137 | * @param zend_function_entry 138 | * @param classname 139 | * @internal 140 | */ 141 | void fill(struct _zend_function_entry *entry, const char *classname); 142 | 143 | /** 144 | * Is this a property member 145 | * @return bool 146 | */ 147 | bool isProperty(); 148 | 149 | /** 150 | * Is this a method member 151 | * @return bool 152 | */ 153 | bool isMethod(); 154 | 155 | 156 | private: 157 | /** 158 | * Name of the member 159 | * @var string 160 | */ 161 | std::string _name; 162 | 163 | /** 164 | * Is this a public property 165 | * @var bool 166 | */ 167 | bool _public; 168 | 169 | /** 170 | * The implementation for the member 171 | * @var MemberInfo 172 | */ 173 | MemberInfo *_info; 174 | 175 | 176 | }; 177 | 178 | /** 179 | * End of namespace 180 | */ 181 | } 182 | 183 | -------------------------------------------------------------------------------- /src/include/phpcpp/members.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Members.h 3 | * 4 | * Internal helper class that holds all members of a class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class Members : public std::vector 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param arguments 24 | */ 25 | Members(const std::initializer_list &members) : std::vector(members), _methods(NULL) {} 26 | 27 | /** 28 | * Destructor 29 | */ 30 | virtual ~Members(); 31 | 32 | /** 33 | * Get access to the methods 34 | * @param classname 35 | * @return Methods 36 | */ 37 | struct _zend_function_entry *methods(const char *classname); 38 | 39 | private: 40 | /** 41 | * Number of methods 42 | * @return integer 43 | */ 44 | int methods(); 45 | 46 | /** 47 | * Array of method structures used internally in the Zend engine 48 | * @var zend_function_entry 49 | */ 50 | struct _zend_function_entry *_methods; 51 | }; 52 | 53 | /** 54 | * End of namespace 55 | */ 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/include/phpcpp/method.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Method.h 3 | */ 4 | 5 | /** 6 | * Namespace 7 | */ 8 | namespace Php { 9 | 10 | /** 11 | * A very generic function pointer 12 | */ 13 | typedef void (*function_ptr)(); 14 | 15 | /** 16 | * Base class of the method 17 | */ 18 | class _Method 19 | { 20 | public: 21 | /** 22 | * Copy constructor 23 | * @param method 24 | */ 25 | _Method(const _Method &method) : _type(method._type), _callback(method._callback) {} 26 | 27 | /** 28 | * Destructor 29 | * @param type 30 | * @param callback 31 | */ 32 | virtual ~_Method() {} 33 | 34 | /** 35 | * Invoke the method 36 | * @param environment 37 | * @param parameters 38 | * @return Value 39 | */ 40 | Value invoke(Environment &environment, Parameters ¶meters) 41 | { 42 | // the object to call a method on 43 | Base *base = parameters.object(); 44 | 45 | // find out which method to call, and call it 46 | switch (_type) { 47 | case 0: (base->*_callback.m0)(); return Value(); 48 | case 1: (base->*_callback.m1)(parameters); return Value(); 49 | case 2: (base->*_callback.m2)(environment); return Value(); 50 | case 3: (base->*_callback.m3)(environment, parameters); return Value(); 51 | case 4: return (base->*_callback.m4)(); 52 | case 5: return (base->*_callback.m5)(parameters); 53 | case 6: return (base->*_callback.m6)(environment); 54 | case 7: return (base->*_callback.m7)(environment, parameters); 55 | default: return Value(); 56 | } 57 | } 58 | 59 | protected: 60 | /** 61 | * Protected constructor to prevent that anyone instantiates this object 62 | */ 63 | _Method(method_callback_0 callback) : _type(0) { _callback.m0 = callback; } 64 | _Method(method_callback_1 callback) : _type(1) { _callback.m1 = callback; } 65 | _Method(method_callback_2 callback) : _type(2) { _callback.m2 = callback; } 66 | _Method(method_callback_3 callback) : _type(3) { _callback.m3 = callback; } 67 | _Method(method_callback_4 callback) : _type(4) { _callback.m4 = callback; } 68 | _Method(method_callback_5 callback) : _type(5) { _callback.m5 = callback; } 69 | _Method(method_callback_6 callback) : _type(6) { _callback.m6 = callback; } 70 | _Method(method_callback_7 callback) : _type(7) { _callback.m7 = callback; } 71 | 72 | private: 73 | /** 74 | * Callback type 75 | * @var int 76 | */ 77 | int _type; 78 | 79 | /** 80 | * The actual callback 81 | * @var void* 82 | */ 83 | union { 84 | method_callback_0 m0; 85 | method_callback_1 m1; 86 | method_callback_2 m2; 87 | method_callback_3 m3; 88 | method_callback_4 m4; 89 | method_callback_5 m5; 90 | method_callback_6 m6; 91 | method_callback_7 m7; 92 | } _callback; 93 | }; 94 | 95 | /** 96 | * Actual template class of the method 97 | */ 98 | template 99 | class Method : public _Method 100 | { 101 | public: 102 | /** 103 | * Constructor 104 | * @param callback 105 | */ 106 | Method(void(T::*callback)()) : _Method(static_cast(callback)) {} 107 | Method(void(T::*callback)(Parameters&)) : _Method(static_cast(callback)) {} 108 | Method(void(T::*callback)(Environment&)) : _Method(static_cast(callback)) {} 109 | Method(void(T::*callback)(Environment&,Parameters&)) : _Method(static_cast(callback)) {} 110 | Method(Value(T::*callback)()) : _Method(static_cast(callback)) {} 111 | Method(Value(T::*callback)(Parameters&)) : _Method(static_cast(callback)) {} 112 | Method(Value(T::*callback)(Environment&)) : _Method(static_cast(callback)) {} 113 | Method(Value(T::*callback)(Environment&,Parameters&)) : _Method(static_cast(callback)) {} 114 | 115 | /** 116 | * Destructor 117 | */ 118 | virtual ~Method() {} 119 | 120 | }; 121 | 122 | /** 123 | * End of namespace 124 | */ 125 | } 126 | 127 | 128 | -------------------------------------------------------------------------------- /src/include/phpcpp/parameters.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Parameters.h 3 | * 4 | * Wrapper around parameters that are passed to a 5 | 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Forward declarations 17 | */ 18 | class Base; 19 | 20 | /** 21 | * Class definition 22 | */ 23 | class Parameters : public std::vector 24 | { 25 | public: 26 | /** 27 | * Constructor 28 | * @param this_ptr Optional this_ptr 29 | * @param argc Number of arguments 30 | * @param tsrm_ls 31 | */ 32 | Parameters(struct _zval_struct *this_ptr, int argc);// TSRMLS_DC); 33 | 34 | /** 35 | * Destructor 36 | */ 37 | virtual ~Parameters() {} 38 | 39 | /** 40 | * The the object that is called 41 | * @return Base 42 | */ 43 | Base *object(); 44 | 45 | private: 46 | /** 47 | * The this pointer 48 | * @var zval 49 | */ 50 | struct _zval_struct *_this; 51 | }; 52 | 53 | /** 54 | * End of namespace 55 | */ 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/include/phpcpp/phpcpp.h: -------------------------------------------------------------------------------- 1 | /** 2 | * phpcpp.h 3 | * 4 | * Library to build PHP extensions with CPP 5 | * 6 | * @copyright 2013 CopernicA BV 7 | * @author Emiel Bruijntjes 8 | */ 9 | 10 | /** 11 | * Other C and C++ libraries that PhpCpp depends on 12 | */ 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | /** 22 | * Include all headers files that are related to this library 23 | */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | /** 48 | * Macro to export a function 49 | */ 50 | #if defined(__GNUC__) && __GNUC__ >= 4 51 | # define PHPCPP_EXPORT __attribute__ ((visibility("default"))) 52 | #else 53 | # define PHPCPP_EXPORT 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /src/include/phpcpp/properties.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Properties.h 3 | * 4 | * The properties of a class are accessible using the protected _properties 5 | * member. This is a class that implements the [] operator, so that all 6 | * properties can be accessed using ["name"]. 7 | * 8 | * @author Emiel Bruijntjes 9 | * @copyright 2013 Copernica BV 10 | */ 11 | 12 | /** 13 | * Namespace 14 | */ 15 | namespace Php { 16 | 17 | /** 18 | * Class properties 19 | */ 20 | class Properties 21 | { 22 | public: 23 | /** 24 | * Destructor 25 | */ 26 | virtual ~Properties() {} 27 | 28 | /** 29 | * Get access to a property by name 30 | * @param name 31 | * @return HashMember 32 | */ 33 | HashMember operator[](const char *name) 34 | { 35 | // map to value 36 | return _value[name]; 37 | } 38 | 39 | /** 40 | * Another way to get access to a property 41 | * @param name 42 | * @return HashMember 43 | */ 44 | HashMember operator[](const std::string &name) 45 | { 46 | // map to value 47 | return _value[name]; 48 | } 49 | 50 | private: 51 | /** 52 | * Private constructor - outside users are not supposed to instantiate this object 53 | * @param zval 54 | */ 55 | Properties(struct _zval_struct *zval) : _value(zval) {} 56 | 57 | /** 58 | * The value object 59 | * @var Value 60 | */ 61 | Value _value; 62 | 63 | /** 64 | * Only the base class can create properties 65 | */ 66 | friend class Base; 67 | }; 68 | 69 | /** 70 | * End of namespace 71 | */ 72 | } 73 | -------------------------------------------------------------------------------- /src/include/phpcpp/protected.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Protected.h 3 | * 4 | * Class for adding public properties to a class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class Protected : public Member 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param name Name of the property 24 | * @param value Default value of the property 25 | */ 26 | Protected(const char *name) : Member(name, false) {} 27 | Protected(const char *name, std::nullptr_t value) : Member(name, false, value) {} 28 | Protected(const char *name, int value) : Member(name, false, value) {} 29 | Protected(const char *name, long value) : Member(name, false, value) {} 30 | Protected(const char *name, bool value) : Member(name, false, value) {} 31 | Protected(const char *name, char value) : Member(name, false, value) {} 32 | Protected(const char *name, const std::string &value) : Member(name, false, value) {} 33 | Protected(const char *name, const char *value, int size=-1) : Member(name, false, value, size) {} 34 | Protected(const char *name, double value) : Member(name, false, value) {} 35 | 36 | /** 37 | * Constructor 38 | * @param name Name of the property 39 | * @param method Method to add 40 | * @param arguments Optional argument information 41 | */ 42 | Protected(const char *name, const _Method &method, const std::initializer_list &arguments = {}) : Member(name, false, method, arguments) {} 43 | 44 | /** 45 | * Destructor 46 | */ 47 | virtual ~Protected() {} 48 | 49 | }; 50 | 51 | /** 52 | * End of namespace 53 | */ 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/include/phpcpp/public.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Public.h 3 | * 4 | * Class for adding public properties to a class 5 | * 6 | * @author Emiel Bruijntjes 7 | * @copyright 2013 Copernica BV 8 | */ 9 | 10 | /** 11 | * Namespace 12 | */ 13 | namespace Php { 14 | 15 | /** 16 | * Class definition 17 | */ 18 | class Public : public Member 19 | { 20 | public: 21 | /** 22 | * Constructor 23 | * @param name Name of the property 24 | * @param value Default value of the property 25 | */ 26 | Public(const char *name) : Member(name, true) {} 27 | Public(const char *name, std::nullptr_t value) : Member(name, true, value) {} 28 | Public(const char *name, int value) : Member(name, true, value) {} 29 | Public(const char *name, long value) : Member(name, true, value) {} 30 | Public(const char *name, bool value) : Member(name, true, value) {} 31 | Public(const char *name, char value) : Member(name, true, value) {} 32 | Public(const char *name, const std::string &value) : Member(name, true, value) {} 33 | Public(const char *name, const char *value, int size=-1) : Member(name, true, value, size) {} 34 | Public(const char *name, double value) : Member(name, true, value) {} 35 | 36 | /** 37 | * Constructor 38 | * @param name Name of the property 39 | * @param method Method to add 40 | * @param arguments Optional argument information 41 | */ 42 | Public(const char *name, const _Method &method, const std::initializer_list &arguments = {}) : Member(name, true, method, arguments) {} 43 | 44 | /** 45 | * Destructor 46 | */ 47 | virtual ~Public() {} 48 | 49 | 50 | }; 51 | 52 | /** 53 | * End of namespace 54 | */ 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/include/phpcpp/type.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Type.h 3 | * 4 | * In this file an enumeration type is defined with all supporteded variable 5 | * types. 6 | * 7 | * @author Emiel Bruijntjes 8 | * @copyright 2013 Copernica BV 9 | */ 10 | 11 | /** 12 | * Set up namespace 13 | */ 14 | namespace Php { 15 | 16 | /** 17 | * Supported types for variables 18 | * The values are the same as the ones used internally in Zend 19 | */ 20 | typedef enum _Type { 21 | nullType = 0, 22 | numericType = 1, 23 | floatType = 2, 24 | boolType = 3, 25 | arrayType = 4, 26 | objectType = 5, 27 | stringType = 6, 28 | resourceType = 7, 29 | constantType = 8, 30 | constantArrayType = 9, 31 | callableType = 10 32 | } Type; 33 | 34 | /** 35 | * End of namespace 36 | */ 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/include/rocksdb/arena.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // Arena class defines memory allocation methods. It's used by memtable and 10 | // skiplist. 11 | 12 | #ifndef STORAGE_ROCKSDB_INCLUDE_ARENA_H_ 13 | #define STORAGE_ROCKSDB_INCLUDE_ARENA_H_ 14 | 15 | #include 16 | #include 17 | 18 | namespace rocksdb { 19 | 20 | class Arena { 21 | public: 22 | Arena() {}; 23 | virtual ~Arena() {}; 24 | 25 | // Return a pointer to a newly allocated memory block of "bytes" bytes. 26 | virtual char* Allocate(size_t bytes) = 0; 27 | 28 | // Allocate memory with the normal alignment guarantees provided by malloc. 29 | virtual char* AllocateAligned(size_t bytes) = 0; 30 | 31 | // Returns an estimate of the total memory used by arena. 32 | virtual const size_t ApproximateMemoryUsage() = 0; 33 | 34 | // Returns the total number of bytes in all blocks allocated so far. 35 | virtual const size_t MemoryAllocatedBytes() = 0; 36 | 37 | private: 38 | // No copying allowed 39 | Arena(const Arena&); 40 | void operator=(const Arena&); 41 | }; 42 | 43 | } // namespace rocksdb 44 | 45 | #endif // STORAGE_ROCKSDB_INCLUDE_ARENA_H_ 46 | -------------------------------------------------------------------------------- /src/include/rocksdb/c.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | This source code is licensed under the BSD-style license found in the 3 | LICENSE file in the root directory of this source tree. An additional grant 4 | of patent rights can be found in the PATENTS file in the same directory. 5 | Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | Use of this source code is governed by a BSD-style license that can be 7 | found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | 9 | C bindings for leveldb. May be useful as a stable ABI that can be 10 | used by programs that keep leveldb in a shared library, or for 11 | a JNI api. 12 | 13 | Does not support: 14 | . getters for the option types 15 | . custom comparators that implement key shortening 16 | . capturing post-write-snapshot 17 | . custom iter, db, env, cache implementations using just the C bindings 18 | 19 | Some conventions: 20 | 21 | (1) We expose just opaque struct pointers and functions to clients. 22 | This allows us to change internal representations without having to 23 | recompile clients. 24 | 25 | (2) For simplicity, there is no equivalent to the Slice type. Instead, 26 | the caller has to pass the pointer and length as separate 27 | arguments. 28 | 29 | (3) Errors are represented by a null-terminated c string. NULL 30 | means no error. All operations that can raise an error are passed 31 | a "char** errptr" as the last argument. One of the following must 32 | be true on entry: 33 | *errptr == NULL 34 | *errptr points to a malloc()ed null-terminated error message 35 | On success, a leveldb routine leaves *errptr unchanged. 36 | On failure, leveldb frees the old value of *errptr and 37 | set *errptr to a malloc()ed error message. 38 | 39 | (4) Bools have the type unsigned char (0 == false; rest == true) 40 | 41 | (5) All of the pointer arguments must be non-NULL. 42 | */ 43 | 44 | #ifndef STORAGE_ROCKSDB_INCLUDE_C_H_ 45 | #define STORAGE_ROCKSDB_INCLUDE_C_H_ 46 | 47 | #ifdef __cplusplus 48 | extern "C" { 49 | #endif 50 | 51 | #include 52 | #include 53 | #include 54 | 55 | /* Exported types */ 56 | 57 | typedef struct leveldb_t leveldb_t; 58 | typedef struct leveldb_cache_t leveldb_cache_t; 59 | typedef struct leveldb_comparator_t leveldb_comparator_t; 60 | typedef struct leveldb_env_t leveldb_env_t; 61 | typedef struct leveldb_filelock_t leveldb_filelock_t; 62 | typedef struct leveldb_filterpolicy_t leveldb_filterpolicy_t; 63 | typedef struct leveldb_iterator_t leveldb_iterator_t; 64 | typedef struct leveldb_logger_t leveldb_logger_t; 65 | typedef struct leveldb_options_t leveldb_options_t; 66 | typedef struct leveldb_randomfile_t leveldb_randomfile_t; 67 | typedef struct leveldb_readoptions_t leveldb_readoptions_t; 68 | typedef struct leveldb_seqfile_t leveldb_seqfile_t; 69 | typedef struct leveldb_snapshot_t leveldb_snapshot_t; 70 | typedef struct leveldb_writablefile_t leveldb_writablefile_t; 71 | typedef struct leveldb_writebatch_t leveldb_writebatch_t; 72 | typedef struct leveldb_writeoptions_t leveldb_writeoptions_t; 73 | 74 | /* DB operations */ 75 | 76 | extern leveldb_t* leveldb_open( 77 | const leveldb_options_t* options, 78 | const char* name, 79 | char** errptr); 80 | 81 | extern void leveldb_close(leveldb_t* db); 82 | 83 | extern void leveldb_put( 84 | leveldb_t* db, 85 | const leveldb_writeoptions_t* options, 86 | const char* key, size_t keylen, 87 | const char* val, size_t vallen, 88 | char** errptr); 89 | 90 | extern void leveldb_delete( 91 | leveldb_t* db, 92 | const leveldb_writeoptions_t* options, 93 | const char* key, size_t keylen, 94 | char** errptr); 95 | 96 | extern void leveldb_write( 97 | leveldb_t* db, 98 | const leveldb_writeoptions_t* options, 99 | leveldb_writebatch_t* batch, 100 | char** errptr); 101 | 102 | /* Returns NULL if not found. A malloc()ed array otherwise. 103 | Stores the length of the array in *vallen. */ 104 | extern char* leveldb_get( 105 | leveldb_t* db, 106 | const leveldb_readoptions_t* options, 107 | const char* key, size_t keylen, 108 | size_t* vallen, 109 | char** errptr); 110 | 111 | extern leveldb_iterator_t* leveldb_create_iterator( 112 | leveldb_t* db, 113 | const leveldb_readoptions_t* options); 114 | 115 | extern const leveldb_snapshot_t* leveldb_create_snapshot( 116 | leveldb_t* db); 117 | 118 | extern void leveldb_release_snapshot( 119 | leveldb_t* db, 120 | const leveldb_snapshot_t* snapshot); 121 | 122 | /* Returns NULL if property name is unknown. 123 | Else returns a pointer to a malloc()-ed null-terminated value. */ 124 | extern char* leveldb_property_value( 125 | leveldb_t* db, 126 | const char* propname); 127 | 128 | extern void leveldb_approximate_sizes( 129 | leveldb_t* db, 130 | int num_ranges, 131 | const char* const* range_start_key, const size_t* range_start_key_len, 132 | const char* const* range_limit_key, const size_t* range_limit_key_len, 133 | uint64_t* sizes); 134 | 135 | extern void leveldb_compact_range( 136 | leveldb_t* db, 137 | const char* start_key, size_t start_key_len, 138 | const char* limit_key, size_t limit_key_len); 139 | 140 | /* Management operations */ 141 | 142 | extern void leveldb_destroy_db( 143 | const leveldb_options_t* options, 144 | const char* name, 145 | char** errptr); 146 | 147 | extern void leveldb_repair_db( 148 | const leveldb_options_t* options, 149 | const char* name, 150 | char** errptr); 151 | 152 | /* Iterator */ 153 | 154 | extern void leveldb_iter_destroy(leveldb_iterator_t*); 155 | extern unsigned char leveldb_iter_valid(const leveldb_iterator_t*); 156 | extern void leveldb_iter_seek_to_first(leveldb_iterator_t*); 157 | extern void leveldb_iter_seek_to_last(leveldb_iterator_t*); 158 | extern void leveldb_iter_seek(leveldb_iterator_t*, const char* k, size_t klen); 159 | extern void leveldb_iter_next(leveldb_iterator_t*); 160 | extern void leveldb_iter_prev(leveldb_iterator_t*); 161 | extern const char* leveldb_iter_key(const leveldb_iterator_t*, size_t* klen); 162 | extern const char* leveldb_iter_value(const leveldb_iterator_t*, size_t* vlen); 163 | extern void leveldb_iter_get_error(const leveldb_iterator_t*, char** errptr); 164 | 165 | /* Write batch */ 166 | 167 | extern leveldb_writebatch_t* leveldb_writebatch_create(); 168 | extern void leveldb_writebatch_destroy(leveldb_writebatch_t*); 169 | extern void leveldb_writebatch_clear(leveldb_writebatch_t*); 170 | extern void leveldb_writebatch_put( 171 | leveldb_writebatch_t*, 172 | const char* key, size_t klen, 173 | const char* val, size_t vlen); 174 | extern void leveldb_writebatch_delete( 175 | leveldb_writebatch_t*, 176 | const char* key, size_t klen); 177 | extern void leveldb_writebatch_iterate( 178 | leveldb_writebatch_t*, 179 | void* state, 180 | void (*put)(void*, const char* k, size_t klen, const char* v, size_t vlen), 181 | void (*deleted)(void*, const char* k, size_t klen)); 182 | 183 | /* Options */ 184 | 185 | extern leveldb_options_t* leveldb_options_create(); 186 | extern void leveldb_options_destroy(leveldb_options_t*); 187 | extern void leveldb_options_set_comparator( 188 | leveldb_options_t*, 189 | leveldb_comparator_t*); 190 | extern void leveldb_options_set_compression_per_level( 191 | leveldb_options_t* opt, 192 | int* level_values, 193 | size_t num_levels); 194 | extern void leveldb_options_set_filter_policy( 195 | leveldb_options_t*, 196 | leveldb_filterpolicy_t*); 197 | extern void leveldb_options_set_create_if_missing( 198 | leveldb_options_t*, unsigned char); 199 | extern void leveldb_options_set_error_if_exists( 200 | leveldb_options_t*, unsigned char); 201 | extern void leveldb_options_set_paranoid_checks( 202 | leveldb_options_t*, unsigned char); 203 | extern void leveldb_options_set_env(leveldb_options_t*, leveldb_env_t*); 204 | extern void leveldb_options_set_info_log(leveldb_options_t*, leveldb_logger_t*); 205 | extern void leveldb_options_set_write_buffer_size(leveldb_options_t*, size_t); 206 | extern void leveldb_options_set_max_open_files(leveldb_options_t*, int); 207 | extern void leveldb_options_set_cache(leveldb_options_t*, leveldb_cache_t*); 208 | extern void leveldb_options_set_block_size(leveldb_options_t*, size_t); 209 | extern void leveldb_options_set_block_restart_interval(leveldb_options_t*, int); 210 | extern void leveldb_options_set_compression_options( 211 | leveldb_options_t* opt, int w_bits, int level, int strategy); 212 | 213 | enum { 214 | leveldb_no_compression = 0, 215 | leveldb_snappy_compression = 1 216 | }; 217 | extern void leveldb_options_set_compression(leveldb_options_t*, int); 218 | 219 | /* Comparator */ 220 | 221 | extern leveldb_comparator_t* leveldb_comparator_create( 222 | void* state, 223 | void (*destructor)(void*), 224 | int (*compare)( 225 | void*, 226 | const char* a, size_t alen, 227 | const char* b, size_t blen), 228 | const char* (*name)(void*)); 229 | extern void leveldb_comparator_destroy(leveldb_comparator_t*); 230 | 231 | /* Filter policy */ 232 | 233 | extern leveldb_filterpolicy_t* leveldb_filterpolicy_create( 234 | void* state, 235 | void (*destructor)(void*), 236 | char* (*create_filter)( 237 | void*, 238 | const char* const* key_array, const size_t* key_length_array, 239 | int num_keys, 240 | size_t* filter_length), 241 | unsigned char (*key_may_match)( 242 | void*, 243 | const char* key, size_t length, 244 | const char* filter, size_t filter_length), 245 | const char* (*name)(void*)); 246 | extern void leveldb_filterpolicy_destroy(leveldb_filterpolicy_t*); 247 | 248 | extern leveldb_filterpolicy_t* leveldb_filterpolicy_create_bloom( 249 | int bits_per_key); 250 | 251 | /* Read options */ 252 | 253 | extern leveldb_readoptions_t* leveldb_readoptions_create(); 254 | extern void leveldb_readoptions_destroy(leveldb_readoptions_t*); 255 | extern void leveldb_readoptions_set_verify_checksums( 256 | leveldb_readoptions_t*, 257 | unsigned char); 258 | extern void leveldb_readoptions_set_fill_cache( 259 | leveldb_readoptions_t*, unsigned char); 260 | extern void leveldb_readoptions_set_snapshot( 261 | leveldb_readoptions_t*, 262 | const leveldb_snapshot_t*); 263 | 264 | /* Write options */ 265 | 266 | extern leveldb_writeoptions_t* leveldb_writeoptions_create(); 267 | extern void leveldb_writeoptions_destroy(leveldb_writeoptions_t*); 268 | extern void leveldb_writeoptions_set_sync( 269 | leveldb_writeoptions_t*, unsigned char); 270 | 271 | /* Cache */ 272 | 273 | extern leveldb_cache_t* leveldb_cache_create_lru(size_t capacity); 274 | extern void leveldb_cache_destroy(leveldb_cache_t* cache); 275 | 276 | /* Env */ 277 | 278 | extern leveldb_env_t* leveldb_create_default_env(); 279 | extern void leveldb_env_destroy(leveldb_env_t*); 280 | 281 | #ifdef __cplusplus 282 | } /* end extern "C" */ 283 | #endif 284 | 285 | #endif /* STORAGE_ROCKSDB_INCLUDE_C_H_ */ 286 | -------------------------------------------------------------------------------- /src/include/rocksdb/cache.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // A Cache is an interface that maps keys to values. It has internal 10 | // synchronization and may be safely accessed concurrently from 11 | // multiple threads. It may automatically evict entries to make room 12 | // for new entries. Values have a specified charge against the cache 13 | // capacity. For example, a cache where the values are variable 14 | // length strings, may use the length of the string as the charge for 15 | // the string. 16 | // 17 | // A builtin cache implementation with a least-recently-used eviction 18 | // policy is provided. Clients may use their own implementations if 19 | // they want something more sophisticated (like scan-resistance, a 20 | // custom eviction policy, variable cache sizing, etc.) 21 | 22 | #ifndef STORAGE_ROCKSDB_INCLUDE_CACHE_H_ 23 | #define STORAGE_ROCKSDB_INCLUDE_CACHE_H_ 24 | 25 | #include 26 | #include 27 | #include "rocksdb/slice.h" 28 | 29 | namespace rocksdb { 30 | 31 | using std::shared_ptr; 32 | 33 | class Cache; 34 | 35 | // Create a new cache with a fixed size capacity. The cache is sharded 36 | // to 2^numShardBits shards, by hash of the key. The total capacity 37 | // is divided and evenly assigned to each shard. Inside each shard, 38 | // the eviction is done in two passes: first try to free spaces by 39 | // evicting entries that are among the most least used removeScanCountLimit 40 | // entries and do not have reference other than by the cache itself, in 41 | // the least-used order. If not enough space is freed, further free the 42 | // entries in least used order. 43 | // 44 | // The functions without parameter numShardBits and/or removeScanCountLimit 45 | // use default values. removeScanCountLimit's default value is 0, which 46 | // means a strict LRU order inside each shard. 47 | extern shared_ptr NewLRUCache(size_t capacity); 48 | extern shared_ptr NewLRUCache(size_t capacity, int numShardBits); 49 | extern shared_ptr NewLRUCache(size_t capacity, int numShardBits, 50 | int removeScanCountLimit); 51 | 52 | class Cache { 53 | public: 54 | Cache() { } 55 | 56 | // Destroys all existing entries by calling the "deleter" 57 | // function that was passed to the constructor. 58 | virtual ~Cache(); 59 | 60 | // Opaque handle to an entry stored in the cache. 61 | struct Handle { }; 62 | 63 | // Insert a mapping from key->value into the cache and assign it 64 | // the specified charge against the total cache capacity. 65 | // 66 | // Returns a handle that corresponds to the mapping. The caller 67 | // must call this->Release(handle) when the returned mapping is no 68 | // longer needed. 69 | // 70 | // When the inserted entry is no longer needed, the key and 71 | // value will be passed to "deleter". 72 | virtual Handle* Insert(const Slice& key, void* value, size_t charge, 73 | void (*deleter)(const Slice& key, void* value)) = 0; 74 | 75 | // If the cache has no mapping for "key", returns nullptr. 76 | // 77 | // Else return a handle that corresponds to the mapping. The caller 78 | // must call this->Release(handle) when the returned mapping is no 79 | // longer needed. 80 | virtual Handle* Lookup(const Slice& key) = 0; 81 | 82 | // Release a mapping returned by a previous Lookup(). 83 | // REQUIRES: handle must not have been released yet. 84 | // REQUIRES: handle must have been returned by a method on *this. 85 | virtual void Release(Handle* handle) = 0; 86 | 87 | // Return the value encapsulated in a handle returned by a 88 | // successful Lookup(). 89 | // REQUIRES: handle must not have been released yet. 90 | // REQUIRES: handle must have been returned by a method on *this. 91 | virtual void* Value(Handle* handle) = 0; 92 | 93 | // If the cache contains entry for key, erase it. Note that the 94 | // underlying entry will be kept around until all existing handles 95 | // to it have been released. 96 | virtual void Erase(const Slice& key) = 0; 97 | 98 | // Return a new numeric id. May be used by multiple clients who are 99 | // sharing the same cache to partition the key space. Typically the 100 | // client will allocate a new id at startup and prepend the id to 101 | // its cache keys. 102 | virtual uint64_t NewId() = 0; 103 | 104 | // returns the maximum configured capacity of the cache 105 | virtual size_t GetCapacity() = 0; 106 | 107 | private: 108 | void LRU_Remove(Handle* e); 109 | void LRU_Append(Handle* e); 110 | void Unref(Handle* e); 111 | 112 | struct Rep; 113 | Rep* rep_; 114 | 115 | // No copying allowed 116 | Cache(const Cache&); 117 | void operator=(const Cache&); 118 | }; 119 | 120 | } // namespace rocksdb 121 | 122 | #endif // STORAGE_ROCKSDB_UTIL_CACHE_H_ 123 | -------------------------------------------------------------------------------- /src/include/rocksdb/compaction_filter.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2013 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | 9 | #ifndef STORAGE_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_ 10 | #define STORAGE_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_ 11 | 12 | #include 13 | 14 | namespace rocksdb { 15 | 16 | class Slice; 17 | 18 | // CompactionFilter allows an application to modify/delete a key-value at 19 | // the time of compaction. 20 | 21 | class CompactionFilter { 22 | public: 23 | 24 | // Context information of a compaction run 25 | struct Context { 26 | // Does this compaction run include all data files 27 | bool is_full_compaction; 28 | }; 29 | 30 | virtual ~CompactionFilter() {} 31 | 32 | // The compaction process invokes this 33 | // method for kv that is being compacted. A return value 34 | // of false indicates that the kv should be preserved in the 35 | // output of this compaction run and a return value of true 36 | // indicates that this key-value should be removed from the 37 | // output of the compaction. The application can inspect 38 | // the existing value of the key and make decision based on it. 39 | // 40 | // When the value is to be preserved, the application has the option 41 | // to modify the existing_value and pass it back through new_value. 42 | // value_changed needs to be set to true in this case. 43 | virtual bool Filter(int level, 44 | const Slice& key, 45 | const Slice& existing_value, 46 | std::string* new_value, 47 | bool* value_changed) const = 0; 48 | 49 | // Returns a name that identifies this compaction filter. 50 | // The name will be printed to LOG file on start up for diagnosis. 51 | virtual const char* Name() const = 0; 52 | }; 53 | 54 | // Each compaction will create a new CompactionFilter allowing the 55 | // application to know about different campactions 56 | class CompactionFilterFactory { 57 | public: 58 | virtual ~CompactionFilterFactory() { }; 59 | 60 | virtual std::unique_ptr CreateCompactionFilter( 61 | const CompactionFilter::Context& context) = 0; 62 | 63 | // Returns a name that identifies this compaction filter factory. 64 | virtual const char* Name() const = 0; 65 | }; 66 | 67 | // Default implementaion of CompactionFilterFactory which does not 68 | // return any filter 69 | class DefaultCompactionFilterFactory : public CompactionFilterFactory { 70 | public: 71 | virtual std::unique_ptr 72 | CreateCompactionFilter(const CompactionFilter::Context& context) override { 73 | return std::unique_ptr(nullptr); 74 | } 75 | 76 | virtual const char* Name() const override { 77 | return "DefaultCompactionFilterFactory"; 78 | } 79 | }; 80 | 81 | } // namespace rocksdb 82 | 83 | #endif // STORAGE_ROCKSDB_INCLUDE_COMPACTION_FILTER_H_ 84 | -------------------------------------------------------------------------------- /src/include/rocksdb/comparator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | 9 | #ifndef STORAGE_ROCKSDB_INCLUDE_COMPARATOR_H_ 10 | #define STORAGE_ROCKSDB_INCLUDE_COMPARATOR_H_ 11 | 12 | #include 13 | 14 | namespace rocksdb { 15 | 16 | class Slice; 17 | 18 | // A Comparator object provides a total order across slices that are 19 | // used as keys in an sstable or a database. A Comparator implementation 20 | // must be thread-safe since rocksdb may invoke its methods concurrently 21 | // from multiple threads. 22 | class Comparator { 23 | public: 24 | virtual ~Comparator(); 25 | 26 | // Three-way comparison. Returns value: 27 | // < 0 iff "a" < "b", 28 | // == 0 iff "a" == "b", 29 | // > 0 iff "a" > "b" 30 | virtual int Compare(const Slice& a, const Slice& b) const = 0; 31 | 32 | // The name of the comparator. Used to check for comparator 33 | // mismatches (i.e., a DB created with one comparator is 34 | // accessed using a different comparator. 35 | // 36 | // The client of this package should switch to a new name whenever 37 | // the comparator implementation changes in a way that will cause 38 | // the relative ordering of any two keys to change. 39 | // 40 | // Names starting with "rocksdb." are reserved and should not be used 41 | // by any clients of this package. 42 | virtual const char* Name() const = 0; 43 | 44 | // Advanced functions: these are used to reduce the space requirements 45 | // for internal data structures like index blocks. 46 | 47 | // If *start < limit, changes *start to a short string in [start,limit). 48 | // Simple comparator implementations may return with *start unchanged, 49 | // i.e., an implementation of this method that does nothing is correct. 50 | virtual void FindShortestSeparator( 51 | std::string* start, 52 | const Slice& limit) const = 0; 53 | 54 | // Changes *key to a short string >= *key. 55 | // Simple comparator implementations may return with *key unchanged, 56 | // i.e., an implementation of this method that does nothing is correct. 57 | virtual void FindShortSuccessor(std::string* key) const = 0; 58 | }; 59 | 60 | // Return a builtin comparator that uses lexicographic byte-wise 61 | // ordering. The result remains the property of this module and 62 | // must not be deleted. 63 | extern const Comparator* BytewiseComparator(); 64 | 65 | } // namespace rocksdb 66 | 67 | #endif // STORAGE_ROCKSDB_INCLUDE_COMPARATOR_H_ 68 | -------------------------------------------------------------------------------- /src/include/rocksdb/db.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | 9 | #ifndef STORAGE_ROCKSDB_INCLUDE_DB_H_ 10 | #define STORAGE_ROCKSDB_INCLUDE_DB_H_ 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include "rocksdb/iterator.h" 17 | #include "rocksdb/options.h" 18 | #include "rocksdb/types.h" 19 | #include "rocksdb/transaction_log.h" 20 | 21 | namespace rocksdb { 22 | 23 | using std::unique_ptr; 24 | 25 | // Update Makefile if you change these 26 | static const int kMajorVersion = 2; 27 | static const int kMinorVersion = 0; 28 | 29 | struct Options; 30 | struct ReadOptions; 31 | struct WriteOptions; 32 | struct FlushOptions; 33 | class WriteBatch; 34 | 35 | // Metadata associated with each SST file. 36 | struct LiveFileMetaData { 37 | std::string name; // Name of the file 38 | int level; // Level at which this file resides. 39 | size_t size; // File size in bytes. 40 | std::string smallestkey; // Smallest user defined key in the file. 41 | std::string largestkey; // Largest user defined key in the file. 42 | SequenceNumber smallest_seqno; // smallest seqno in file 43 | SequenceNumber largest_seqno; // largest seqno in file 44 | }; 45 | 46 | // Abstract handle to particular state of a DB. 47 | // A Snapshot is an immutable object and can therefore be safely 48 | // accessed from multiple threads without any external synchronization. 49 | class Snapshot { 50 | protected: 51 | virtual ~Snapshot(); 52 | }; 53 | 54 | // A range of keys 55 | struct Range { 56 | Slice start; // Included in the range 57 | Slice limit; // Not included in the range 58 | 59 | Range() { } 60 | Range(const Slice& s, const Slice& l) : start(s), limit(l) { } 61 | }; 62 | 63 | // A DB is a persistent ordered map from keys to values. 64 | // A DB is safe for concurrent access from multiple threads without 65 | // any external synchronization. 66 | class DB { 67 | public: 68 | // Open the database with the specified "name". 69 | // Stores a pointer to a heap-allocated database in *dbptr and returns 70 | // OK on success. 71 | // Stores nullptr in *dbptr and returns a non-OK status on error. 72 | // Caller should delete *dbptr when it is no longer needed. 73 | static Status Open(const Options& options, 74 | const std::string& name, 75 | DB** dbptr); 76 | 77 | // Open the database for read only. All DB interfaces 78 | // that modify data, like put/delete, will return error. 79 | // If the db is opened in read only mode, then no compactions 80 | // will happen. 81 | static Status OpenForReadOnly(const Options& options, 82 | const std::string& name, DB** dbptr, 83 | bool error_if_log_file_exist = false); 84 | 85 | DB() { } 86 | virtual ~DB(); 87 | 88 | // Set the database entry for "key" to "value". 89 | // Returns OK on success, and a non-OK status on error. 90 | // Note: consider setting options.sync = true. 91 | virtual Status Put(const WriteOptions& options, 92 | const Slice& key, 93 | const Slice& value) = 0; 94 | 95 | // Remove the database entry (if any) for "key". Returns OK on 96 | // success, and a non-OK status on error. It is not an error if "key" 97 | // did not exist in the database. 98 | // Note: consider setting options.sync = true. 99 | virtual Status Delete(const WriteOptions& options, const Slice& key) = 0; 100 | 101 | // Merge the database entry for "key" with "value". Returns OK on success, 102 | // and a non-OK status on error. The semantics of this operation is 103 | // determined by the user provided merge_operator when opening DB. 104 | // Note: consider setting options.sync = true. 105 | virtual Status Merge(const WriteOptions& options, 106 | const Slice& key, 107 | const Slice& value) = 0; 108 | 109 | // Apply the specified updates to the database. 110 | // Returns OK on success, non-OK on failure. 111 | // Note: consider setting options.sync = true. 112 | virtual Status Write(const WriteOptions& options, WriteBatch* updates) = 0; 113 | 114 | // If the database contains an entry for "key" store the 115 | // corresponding value in *value and return OK. 116 | // 117 | // If there is no entry for "key" leave *value unchanged and return 118 | // a status for which Status::IsNotFound() returns true. 119 | // 120 | // May return some other Status on an error. 121 | virtual Status Get(const ReadOptions& options, 122 | const Slice& key, 123 | std::string* value) = 0; 124 | 125 | // If keys[i] does not exist in the database, then the i'th returned 126 | // status will be one for which Status::IsNotFound() is true, and 127 | // (*values)[i] will be set to some arbitrary value (often ""). Otherwise, 128 | // the i'th returned status will have Status::ok() true, and (*values)[i] 129 | // will store the value associated with keys[i]. 130 | // 131 | // (*values) will always be resized to be the same size as (keys). 132 | // Similarly, the number of returned statuses will be the number of keys. 133 | // Note: keys will not be "de-duplicated". Duplicate keys will return 134 | // duplicate values in order. 135 | virtual std::vector MultiGet(const ReadOptions& options, 136 | const std::vector& keys, 137 | std::vector* values) = 0; 138 | 139 | // If the key definitely does not exist in the database, then this method 140 | // returns false, else true. If the caller wants to obtain value when the key 141 | // is found in memory, a bool for 'value_found' must be passed. 'value_found' 142 | // will be true on return if value has been set properly. 143 | // This check is potentially lighter-weight than invoking DB::Get(). One way 144 | // to make this lighter weight is to avoid doing any IOs. 145 | // Default implementation here returns true and sets 'value_found' to false 146 | virtual bool KeyMayExist(const ReadOptions& options, 147 | const Slice& key, 148 | std::string* value, 149 | bool* value_found = nullptr) { 150 | if (value_found != nullptr) { 151 | *value_found = false; 152 | } 153 | return true; 154 | } 155 | 156 | // Return a heap-allocated iterator over the contents of the database. 157 | // The result of NewIterator() is initially invalid (caller must 158 | // call one of the Seek methods on the iterator before using it). 159 | // 160 | // Caller should delete the iterator when it is no longer needed. 161 | // The returned iterator should be deleted before this db is deleted. 162 | virtual Iterator* NewIterator(const ReadOptions& options) = 0; 163 | 164 | // Return a handle to the current DB state. Iterators created with 165 | // this handle will all observe a stable snapshot of the current DB 166 | // state. The caller must call ReleaseSnapshot(result) when the 167 | // snapshot is no longer needed. 168 | virtual const Snapshot* GetSnapshot() = 0; 169 | 170 | // Release a previously acquired snapshot. The caller must not 171 | // use "snapshot" after this call. 172 | virtual void ReleaseSnapshot(const Snapshot* snapshot) = 0; 173 | 174 | // DB implementations can export properties about their state 175 | // via this method. If "property" is a valid property understood by this 176 | // DB implementation, fills "*value" with its current value and returns 177 | // true. Otherwise returns false. 178 | // 179 | // 180 | // Valid property names include: 181 | // 182 | // "rocksdb.num-files-at-level" - return the number of files at level , 183 | // where is an ASCII representation of a level number (e.g. "0"). 184 | // "rocksdb.stats" - returns a multi-line string that describes statistics 185 | // about the internal operation of the DB. 186 | // "rocksdb.sstables" - returns a multi-line string that describes all 187 | // of the sstables that make up the db contents. 188 | virtual bool GetProperty(const Slice& property, std::string* value) = 0; 189 | 190 | // For each i in [0,n-1], store in "sizes[i]", the approximate 191 | // file system space used by keys in "[range[i].start .. range[i].limit)". 192 | // 193 | // Note that the returned sizes measure file system space usage, so 194 | // if the user data compresses by a factor of ten, the returned 195 | // sizes will be one-tenth the size of the corresponding user data size. 196 | // 197 | // The results may not include the sizes of recently written data. 198 | virtual void GetApproximateSizes(const Range* range, int n, 199 | uint64_t* sizes) = 0; 200 | 201 | // Compact the underlying storage for the key range [*begin,*end]. 202 | // In particular, deleted and overwritten versions are discarded, 203 | // and the data is rearranged to reduce the cost of operations 204 | // needed to access the data. This operation should typically only 205 | // be invoked by users who understand the underlying implementation. 206 | // 207 | // begin==nullptr is treated as a key before all keys in the database. 208 | // end==nullptr is treated as a key after all keys in the database. 209 | // Therefore the following call will compact the entire database: 210 | // db->CompactRange(nullptr, nullptr); 211 | // Note that after the entire database is compacted, all data are pushed 212 | // down to the last level containing any data. If the total data size 213 | // after compaction is reduced, that level might not be appropriate for 214 | // hosting all the files. In this case, client could set reduce_level 215 | // to true, to move the files back to the minimum level capable of holding 216 | // the data set or a given level (specified by non-negative target_level). 217 | virtual void CompactRange(const Slice* begin, const Slice* end, 218 | bool reduce_level = false, 219 | int target_level = -1) = 0; 220 | 221 | // Number of levels used for this DB. 222 | virtual int NumberLevels() = 0; 223 | 224 | // Maximum level to which a new compacted memtable is pushed if it 225 | // does not create overlap. 226 | virtual int MaxMemCompactionLevel() = 0; 227 | 228 | // Number of files in level-0 that would stop writes. 229 | virtual int Level0StopWriteTrigger() = 0; 230 | 231 | // Flush all mem-table data. 232 | virtual Status Flush(const FlushOptions& options) = 0; 233 | 234 | // Prevent file deletions. Compactions will continue to occur, 235 | // but no obsolete files will be deleted. Calling this multiple 236 | // times have the same effect as calling it once. 237 | virtual Status DisableFileDeletions() = 0; 238 | 239 | // Allow compactions to delete obselete files. 240 | virtual Status EnableFileDeletions() = 0; 241 | 242 | // GetLiveFiles followed by GetSortedWalFiles can generate a lossless backup 243 | 244 | // THIS METHOD IS DEPRECATED. Use the GetTableMetaData to get more 245 | // detailed information on the live files. 246 | // Retrieve the list of all files in the database. The files are 247 | // relative to the dbname and are not absolute paths. The valid size of the 248 | // manifest file is returned in manifest_file_size. The manifest file is an 249 | // ever growing file, but only the portion specified by manifest_file_size is 250 | // valid for this snapshot. 251 | // Setting flush_memtable to true does Flush before recording the live files. 252 | // Setting flush_memtable to false is useful when we don't want to wait for 253 | // flush which may have to wait for compaction to complete taking an 254 | // indeterminate time. But this will have to use GetSortedWalFiles after 255 | // GetLiveFiles to compensate for memtables missed in this snapshot due to the 256 | // absence of Flush, by WAL files to recover the database consistently later 257 | virtual Status GetLiveFiles(std::vector&, 258 | uint64_t* manifest_file_size, 259 | bool flush_memtable = true) = 0; 260 | 261 | // Retrieve the sorted list of all wal files with earliest file first 262 | virtual Status GetSortedWalFiles(VectorLogPtr& files) = 0; 263 | 264 | // The sequence number of the most recent transaction. 265 | virtual SequenceNumber GetLatestSequenceNumber() const = 0; 266 | 267 | // Sets iter to an iterator that is positioned at a write-batch containing 268 | // seq_number. If the sequence number is non existent, it returns an iterator 269 | // at the first available seq_no after the requested seq_no 270 | // Returns Status::Ok if iterator is valid 271 | // Must set WAL_ttl_seconds or WAL_size_limit_MB to large values to 272 | // use this api, else the WAL files will get 273 | // cleared aggressively and the iterator might keep getting invalid before 274 | // an update is read. 275 | virtual Status GetUpdatesSince(SequenceNumber seq_number, 276 | unique_ptr* iter) = 0; 277 | 278 | // Delete the file name from the db directory and update the internal state to 279 | // reflect that. Supports deletion of sst and log files only. 'name' must be 280 | // path relative to the db directory. eg. 000001.sst, /archive/000003.log 281 | virtual Status DeleteFile(std::string name) = 0; 282 | 283 | // Returns a list of all table files with their level, start key 284 | // and end key 285 | virtual void GetLiveFilesMetaData( 286 | std::vector *metadata) { 287 | } 288 | 289 | private: 290 | // No copying allowed 291 | DB(const DB&); 292 | void operator=(const DB&); 293 | }; 294 | 295 | // Destroy the contents of the specified database. 296 | // Be very careful using this method. 297 | Status DestroyDB(const std::string& name, const Options& options); 298 | 299 | // If a DB cannot be opened, you may attempt to call this method to 300 | // resurrect as much of the contents of the database as possible. 301 | // Some data may be lost, so be careful when calling this function 302 | // on a database that contains important information. 303 | Status RepairDB(const std::string& dbname, const Options& options); 304 | 305 | } // namespace rocksdb 306 | 307 | #endif // STORAGE_ROCKSDB_INCLUDE_DB_H_ 308 | -------------------------------------------------------------------------------- /src/include/rocksdb/filter_policy.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2012 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // A database can be configured with a custom FilterPolicy object. 10 | // This object is responsible for creating a small filter from a set 11 | // of keys. These filters are stored in rocksdb and are consulted 12 | // automatically by rocksdb to decide whether or not to read some 13 | // information from disk. In many cases, a filter can cut down the 14 | // number of disk seeks form a handful to a single disk seek per 15 | // DB::Get() call. 16 | // 17 | // Most people will want to use the builtin bloom filter support (see 18 | // NewBloomFilterPolicy() below). 19 | 20 | #ifndef STORAGE_ROCKSDB_INCLUDE_FILTER_POLICY_H_ 21 | #define STORAGE_ROCKSDB_INCLUDE_FILTER_POLICY_H_ 22 | 23 | #include 24 | 25 | namespace rocksdb { 26 | 27 | class Slice; 28 | 29 | class FilterPolicy { 30 | public: 31 | virtual ~FilterPolicy(); 32 | 33 | // Return the name of this policy. Note that if the filter encoding 34 | // changes in an incompatible way, the name returned by this method 35 | // must be changed. Otherwise, old incompatible filters may be 36 | // passed to methods of this type. 37 | virtual const char* Name() const = 0; 38 | 39 | // keys[0,n-1] contains a list of keys (potentially with duplicates) 40 | // that are ordered according to the user supplied comparator. 41 | // Append a filter that summarizes keys[0,n-1] to *dst. 42 | // 43 | // Warning: do not change the initial contents of *dst. Instead, 44 | // append the newly constructed filter to *dst. 45 | virtual void CreateFilter(const Slice* keys, int n, std::string* dst) 46 | const = 0; 47 | 48 | // "filter" contains the data appended by a preceding call to 49 | // CreateFilter() on this class. This method must return true if 50 | // the key was in the list of keys passed to CreateFilter(). 51 | // This method may return true or false if the key was not on the 52 | // list, but it should aim to return false with a high probability. 53 | virtual bool KeyMayMatch(const Slice& key, const Slice& filter) const = 0; 54 | }; 55 | 56 | // Return a new filter policy that uses a bloom filter with approximately 57 | // the specified number of bits per key. A good value for bits_per_key 58 | // is 10, which yields a filter with ~ 1% false positive rate. 59 | // 60 | // Callers must delete the result after any database that is using the 61 | // result has been closed. 62 | // 63 | // Note: if you are using a custom comparator that ignores some parts 64 | // of the keys being compared, you must not use NewBloomFilterPolicy() 65 | // and must provide your own FilterPolicy that also ignores the 66 | // corresponding parts of the keys. For example, if the comparator 67 | // ignores trailing spaces, it would be incorrect to use a 68 | // FilterPolicy (like NewBloomFilterPolicy) that does not ignore 69 | // trailing spaces in keys. 70 | extern const FilterPolicy* NewBloomFilterPolicy(int bits_per_key); 71 | 72 | } 73 | 74 | #endif // STORAGE_ROCKSDB_INCLUDE_FILTER_POLICY_H_ 75 | -------------------------------------------------------------------------------- /src/include/rocksdb/flush_block_policy.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | 6 | #pragma once 7 | 8 | #include 9 | 10 | namespace rocksdb { 11 | 12 | class Slice; 13 | class BlockBuilder; 14 | 15 | // FlushBlockPolicy provides a configurable way to determine when to flush a 16 | // block in the block based tables, 17 | class FlushBlockPolicy { 18 | public: 19 | // Keep track of the key/value sequences and return the boolean value to 20 | // determine if table builder should flush current data block. 21 | virtual bool Update(const Slice& key, 22 | const Slice& value) = 0; 23 | 24 | virtual ~FlushBlockPolicy() { } 25 | }; 26 | 27 | class FlushBlockPolicyFactory { 28 | public: 29 | // Return the name of the flush block policy. 30 | virtual const char* Name() const = 0; 31 | 32 | // Return a new block flush policy that flushes data blocks by data size. 33 | // FlushBlockPolicy may need to access the metadata of the data block 34 | // builder to determine when to flush the blocks. 35 | // 36 | // Callers must delete the result after any database that is using the 37 | // result has been closed. 38 | virtual FlushBlockPolicy* NewFlushBlockPolicy( 39 | const BlockBuilder& data_block_builder) const = 0; 40 | 41 | virtual ~FlushBlockPolicyFactory() { } 42 | }; 43 | 44 | class FlushBlockBySizePolicyFactory : public FlushBlockPolicyFactory { 45 | public: 46 | FlushBlockBySizePolicyFactory(const uint64_t block_size, 47 | const uint64_t block_size_deviation) : 48 | block_size_(block_size), 49 | block_size_deviation_(block_size_deviation) { 50 | } 51 | 52 | virtual const char* Name() const override { 53 | return "FlushBlockBySizePolicyFactory"; 54 | } 55 | 56 | virtual FlushBlockPolicy* NewFlushBlockPolicy( 57 | const BlockBuilder& data_block_builder) const override; 58 | 59 | private: 60 | const uint64_t block_size_; 61 | const uint64_t block_size_deviation_; 62 | }; 63 | 64 | } // rocksdb 65 | -------------------------------------------------------------------------------- /src/include/rocksdb/iterator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // An iterator yields a sequence of key/value pairs from a source. 10 | // The following class defines the interface. Multiple implementations 11 | // are provided by this library. In particular, iterators are provided 12 | // to access the contents of a Table or a DB. 13 | // 14 | // Multiple threads can invoke const methods on an Iterator without 15 | // external synchronization, but if any of the threads may call a 16 | // non-const method, all threads accessing the same Iterator must use 17 | // external synchronization. 18 | 19 | #ifndef STORAGE_ROCKSDB_INCLUDE_ITERATOR_H_ 20 | #define STORAGE_ROCKSDB_INCLUDE_ITERATOR_H_ 21 | 22 | #include "rocksdb/slice.h" 23 | #include "rocksdb/status.h" 24 | 25 | namespace rocksdb { 26 | 27 | class Iterator { 28 | public: 29 | Iterator(); 30 | virtual ~Iterator(); 31 | 32 | // An iterator is either positioned at a key/value pair, or 33 | // not valid. This method returns true iff the iterator is valid. 34 | virtual bool Valid() const = 0; 35 | 36 | // Position at the first key in the source. The iterator is Valid() 37 | // after this call iff the source is not empty. 38 | virtual void SeekToFirst() = 0; 39 | 40 | // Position at the last key in the source. The iterator is 41 | // Valid() after this call iff the source is not empty. 42 | virtual void SeekToLast() = 0; 43 | 44 | // Position at the first key in the source that at or past target 45 | // The iterator is Valid() after this call iff the source contains 46 | // an entry that comes at or past target. 47 | virtual void Seek(const Slice& target) = 0; 48 | 49 | // Moves to the next entry in the source. After this call, Valid() is 50 | // true iff the iterator was not positioned at the last entry in the source. 51 | // REQUIRES: Valid() 52 | virtual void Next() = 0; 53 | 54 | // Moves to the previous entry in the source. After this call, Valid() is 55 | // true iff the iterator was not positioned at the first entry in source. 56 | // REQUIRES: Valid() 57 | virtual void Prev() = 0; 58 | 59 | // Return the key for the current entry. The underlying storage for 60 | // the returned slice is valid only until the next modification of 61 | // the iterator. 62 | // REQUIRES: Valid() 63 | virtual Slice key() const = 0; 64 | 65 | // Return the value for the current entry. The underlying storage for 66 | // the returned slice is valid only until the next modification of 67 | // the iterator. 68 | // REQUIRES: !AtEnd() && !AtStart() 69 | virtual Slice value() const = 0; 70 | 71 | // If an error has occurred, return it. Else return an ok status. 72 | // If non-blocking IO is requested and this operation cannot be 73 | // satisfied without doing some IO, then this returns Status::Incomplete(). 74 | virtual Status status() const = 0; 75 | 76 | // Clients are allowed to register function/arg1/arg2 triples that 77 | // will be invoked when this iterator is destroyed. 78 | // 79 | // Note that unlike all of the preceding methods, this method is 80 | // not abstract and therefore clients should not override it. 81 | typedef void (*CleanupFunction)(void* arg1, void* arg2); 82 | void RegisterCleanup(CleanupFunction function, void* arg1, void* arg2); 83 | 84 | private: 85 | struct Cleanup { 86 | CleanupFunction function; 87 | void* arg1; 88 | void* arg2; 89 | Cleanup* next; 90 | }; 91 | Cleanup cleanup_; 92 | 93 | // No copying allowed 94 | Iterator(const Iterator&); 95 | void operator=(const Iterator&); 96 | }; 97 | 98 | // Return an empty iterator (yields nothing). 99 | extern Iterator* NewEmptyIterator(); 100 | 101 | // Return an empty iterator with the specified status. 102 | extern Iterator* NewErrorIterator(const Status& status); 103 | 104 | } // namespace rocksdb 105 | 106 | #endif // STORAGE_ROCKSDB_INCLUDE_ITERATOR_H_ 107 | -------------------------------------------------------------------------------- /src/include/rocksdb/ldb_tool.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | #ifndef STORAGE_ROCKSDB_INCLUDE_LDB_TOOL_H 6 | #define STORAGE_ROCKSDB_INCLUDE_LDB_TOOL_H 7 | #include "rocksdb/options.h" 8 | 9 | namespace rocksdb { 10 | 11 | class LDBTool { 12 | public: 13 | void Run(int argc, char** argv, Options = Options()); 14 | }; 15 | 16 | } // namespace rocksdb 17 | 18 | #endif // STORAGE_ROCKSDB_INCLUDE_LDB_TOOL_H 19 | -------------------------------------------------------------------------------- /src/include/rocksdb/memtablerep.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // 6 | // This file contains the interface that must be implemented by any collection 7 | // to be used as the backing store for a MemTable. Such a collection must 8 | // satisfy the following properties: 9 | // (1) It does not store duplicate items. 10 | // (2) It uses MemTableRep::KeyComparator to compare items for iteration and 11 | // equality. 12 | // (3) It can be accessed concurrently by multiple readers and can support 13 | // during reads. However, it needn't support multiple concurrent writes. 14 | // (4) Items are never deleted. 15 | // The liberal use of assertions is encouraged to enforce (1). 16 | // 17 | // The factory will be passed an Arena object when a new MemTableRep is 18 | // requested. The API for this object is in rocksdb/arena.h. 19 | // 20 | // Users can implement their own memtable representations. We include four 21 | // types built in: 22 | // - SkipListRep: This is the default; it is backed by a skip list. 23 | // - TransformRep: This is backed by an custom hash map. 24 | // On construction, they are given a SliceTransform object. This 25 | // object is applied to the user key of stored items which indexes into the 26 | // hash map to yield a skiplist containing all records that share the same 27 | // user key under the transform function. 28 | // - UnsortedRep: A subclass of TransformRep where the transform function is 29 | // the identity function. Optimized for point lookups. 30 | // - PrefixHashRep: A subclass of TransformRep where the transform function is 31 | // a fixed-size prefix extractor. If you use PrefixHashRepFactory, the transform 32 | // must be identical to options.prefix_extractor, otherwise it will be discarded 33 | // and the default will be used. It is optimized for ranged scans over a 34 | // prefix. 35 | // - VectorRep: This is backed by an unordered std::vector. On iteration, the 36 | // vector is sorted. It is intelligent about sorting; once the MarkReadOnly() 37 | // has been called, the vector will only be sorted once. It is optimized for 38 | // random-write-heavy workloads. 39 | // 40 | // The last four implementations are designed for situations in which 41 | // iteration over the entire collection is rare since doing so requires all the 42 | // keys to be copied into a sorted data structure. 43 | 44 | #ifndef STORAGE_ROCKSDB_DB_MEMTABLEREP_H_ 45 | #define STORAGE_ROCKSDB_DB_MEMTABLEREP_H_ 46 | 47 | #include 48 | #include "rocksdb/arena.h" 49 | #include "rocksdb/slice.h" 50 | #include "rocksdb/slice_transform.h" 51 | 52 | namespace rocksdb { 53 | 54 | class MemTableRep { 55 | public: 56 | // KeyComparator provides a means to compare keys, which are internal keys 57 | // concatenated with values. 58 | class KeyComparator { 59 | public: 60 | // Compare a and b. Return a negative value if a is less than b, 0 if they 61 | // are equal, and a positive value if a is greater than b 62 | virtual int operator()(const char* a, const char* b) const = 0; 63 | 64 | virtual ~KeyComparator() { } 65 | }; 66 | 67 | // Insert key into the collection. (The caller will pack key and value into a 68 | // single buffer and pass that in as the parameter to Insert) 69 | // REQUIRES: nothing that compares equal to key is currently in the 70 | // collection. 71 | virtual void Insert(const char* key) = 0; 72 | 73 | // Returns true iff an entry that compares equal to key is in the collection. 74 | virtual bool Contains(const char* key) const = 0; 75 | 76 | // Notify this table rep that it will no longer be added to. By default, does 77 | // nothing. 78 | virtual void MarkReadOnly() { } 79 | 80 | // Report an approximation of how much memory has been used other than memory 81 | // that was allocated through the arena. 82 | virtual size_t ApproximateMemoryUsage() = 0; 83 | 84 | virtual ~MemTableRep() { } 85 | 86 | // Iteration over the contents of a skip collection 87 | class Iterator { 88 | public: 89 | // Initialize an iterator over the specified collection. 90 | // The returned iterator is not valid. 91 | // explicit Iterator(const MemTableRep* collection); 92 | virtual ~Iterator() { }; 93 | 94 | // Returns true iff the iterator is positioned at a valid node. 95 | virtual bool Valid() const = 0; 96 | 97 | // Returns the key at the current position. 98 | // REQUIRES: Valid() 99 | virtual const char* key() const = 0; 100 | 101 | // Advances to the next position. 102 | // REQUIRES: Valid() 103 | virtual void Next() = 0; 104 | 105 | // Advances to the previous position. 106 | // REQUIRES: Valid() 107 | virtual void Prev() = 0; 108 | 109 | // Advance to the first entry with a key >= target 110 | virtual void Seek(const char* target) = 0; 111 | 112 | // Position at the first entry in collection. 113 | // Final state of iterator is Valid() iff collection is not empty. 114 | virtual void SeekToFirst() = 0; 115 | 116 | // Position at the last entry in collection. 117 | // Final state of iterator is Valid() iff collection is not empty. 118 | virtual void SeekToLast() = 0; 119 | }; 120 | 121 | // Return an iterator over the keys in this representation. 122 | virtual std::shared_ptr GetIterator() = 0; 123 | 124 | // Return an iterator over at least the keys with the specified user key. The 125 | // iterator may also allow access to other keys, but doesn't have to. Default: 126 | // GetIterator(). 127 | virtual std::shared_ptr GetIterator(const Slice& user_key) { 128 | return GetIterator(); 129 | } 130 | 131 | // Return an iterator over at least the keys with the specified prefix. The 132 | // iterator may also allow access to other keys, but doesn't have to. Default: 133 | // GetIterator(). 134 | virtual std::shared_ptr GetPrefixIterator(const Slice& prefix) { 135 | return GetIterator(); 136 | } 137 | 138 | // Return an iterator that has a special Seek semantics. The result of 139 | // a Seek might only include keys with the same prefix as the target key. 140 | virtual std::shared_ptr GetDynamicPrefixIterator() { 141 | return GetIterator(); 142 | } 143 | 144 | protected: 145 | // When *key is an internal key concatenated with the value, returns the 146 | // user key. 147 | virtual Slice UserKey(const char* key) const; 148 | }; 149 | 150 | // This is the base class for all factories that are used by RocksDB to create 151 | // new MemTableRep objects 152 | class MemTableRepFactory { 153 | public: 154 | virtual ~MemTableRepFactory() { }; 155 | virtual std::shared_ptr CreateMemTableRep( 156 | MemTableRep::KeyComparator&, Arena*) = 0; 157 | virtual const char* Name() const = 0; 158 | }; 159 | 160 | // This creates MemTableReps that are backed by an std::vector. On iteration, 161 | // the vector is sorted. This is useful for workloads where iteration is very 162 | // rare and writes are generally not issued after reads begin. 163 | // 164 | // Parameters: 165 | // count: Passed to the constructor of the underlying std::vector of each 166 | // VectorRep. On initialization, the underlying array will be at least count 167 | // bytes reserved for usage. 168 | class VectorRepFactory : public MemTableRepFactory { 169 | const size_t count_; 170 | public: 171 | explicit VectorRepFactory(size_t count = 0) : count_(count) { } 172 | virtual std::shared_ptr CreateMemTableRep( 173 | MemTableRep::KeyComparator&, Arena*) override; 174 | virtual const char* Name() const override { 175 | return "VectorRepFactory"; 176 | } 177 | }; 178 | 179 | // This uses a skip list to store keys. It is the default. 180 | class SkipListFactory : public MemTableRepFactory { 181 | public: 182 | virtual std::shared_ptr CreateMemTableRep( 183 | MemTableRep::KeyComparator&, Arena*) override; 184 | virtual const char* Name() const override { 185 | return "SkipListFactory"; 186 | } 187 | }; 188 | 189 | // TransformReps are backed by an unordered map of buffers to buckets. When 190 | // looking up a key, the user key is extracted and a user-supplied transform 191 | // function (see rocksdb/slice_transform.h) is applied to get the key into the 192 | // unordered map. This allows the user to bin user keys based on arbitrary 193 | // criteria. Two example implementations are UnsortedRepFactory and 194 | // PrefixHashRepFactory. 195 | // 196 | // Iteration over the entire collection is implemented by dumping all the keys 197 | // into an std::set. Thus, these data structures are best used when iteration 198 | // over the entire collection is rare. 199 | // 200 | // Parameters: 201 | // transform: The SliceTransform to bucket user keys on. TransformRepFactory 202 | // owns the pointer. 203 | // bucket_count: Passed to the constructor of the underlying 204 | // std::unordered_map of each TransformRep. On initialization, the 205 | // underlying array will be at least bucket_count size. 206 | // num_locks: Number of read-write locks to have for the rep. Each bucket is 207 | // hashed onto a read-write lock which controls access to that lock. More 208 | // locks means finer-grained concurrency but more memory overhead. 209 | class TransformRepFactory : public MemTableRepFactory { 210 | public: 211 | explicit TransformRepFactory(const SliceTransform* transform, 212 | size_t bucket_count, size_t num_locks = 1000) 213 | : transform_(transform), 214 | bucket_count_(bucket_count), 215 | num_locks_(num_locks) { } 216 | 217 | virtual ~TransformRepFactory() { delete transform_; } 218 | 219 | virtual std::shared_ptr CreateMemTableRep( 220 | MemTableRep::KeyComparator&, Arena*) override; 221 | 222 | virtual const char* Name() const override { 223 | return "TransformRepFactory"; 224 | } 225 | 226 | const SliceTransform* GetTransform() { return transform_; } 227 | 228 | protected: 229 | const SliceTransform* transform_; 230 | const size_t bucket_count_; 231 | const size_t num_locks_; 232 | }; 233 | 234 | // UnsortedReps bin user keys based on an identity function transform -- that 235 | // is, transform(key) = key. This optimizes for point look-ups. 236 | // 237 | // Parameters: See TransformRepFactory. 238 | class UnsortedRepFactory : public TransformRepFactory { 239 | public: 240 | explicit UnsortedRepFactory(size_t bucket_count = 0, size_t num_locks = 1000) 241 | : TransformRepFactory(NewNoopTransform(), 242 | bucket_count, 243 | num_locks) { } 244 | virtual const char* Name() const override { 245 | return "UnsortedRepFactory"; 246 | } 247 | }; 248 | 249 | // PrefixHashReps bin user keys based on a fixed-size prefix. This optimizes for 250 | // short ranged scans over a given prefix. 251 | // 252 | // Parameters: See TransformRepFactory. 253 | class PrefixHashRepFactory : public TransformRepFactory { 254 | public: 255 | explicit PrefixHashRepFactory(const SliceTransform* prefix_extractor, 256 | size_t bucket_count = 0, size_t num_locks = 1000) 257 | : TransformRepFactory(prefix_extractor, bucket_count, num_locks) 258 | { } 259 | 260 | virtual std::shared_ptr CreateMemTableRep( 261 | MemTableRep::KeyComparator&, Arena*) override; 262 | 263 | virtual const char* Name() const override { 264 | return "PrefixHashRepFactory"; 265 | } 266 | }; 267 | 268 | // The same as TransformRepFactory except it doesn't use locks. 269 | // Experimental, will replace TransformRepFactory once we are sure 270 | // it performs better 271 | extern MemTableRepFactory* NewHashSkipListRepFactory( 272 | const SliceTransform* transform, size_t bucket_count = 1000000); 273 | 274 | } 275 | 276 | #endif // STORAGE_ROCKSDB_DB_MEMTABLEREP_H_ 277 | -------------------------------------------------------------------------------- /src/include/rocksdb/merge_operator.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | 6 | #ifndef STORAGE_ROCKSDB_INCLUDE_MERGE_OPERATOR_H_ 7 | #define STORAGE_ROCKSDB_INCLUDE_MERGE_OPERATOR_H_ 8 | 9 | #include 10 | #include 11 | #include "rocksdb/slice.h" 12 | 13 | namespace rocksdb { 14 | 15 | class Slice; 16 | class Logger; 17 | 18 | // The Merge Operator 19 | // 20 | // Essentially, a MergeOperator specifies the SEMANTICS of a merge, which only 21 | // client knows. It could be numeric addition, list append, string 22 | // concatenation, edit data structure, ... , anything. 23 | // The library, on the other hand, is concerned with the exercise of this 24 | // interface, at the right time (during get, iteration, compaction...) 25 | // 26 | // To use merge, the client needs to provide an object implementing one of 27 | // the following interfaces: 28 | // a) AssociativeMergeOperator - for most simple semantics (always take 29 | // two values, and merge them into one value, which is then put back 30 | // into rocksdb); numeric addition and string concatenation are examples; 31 | // 32 | // b) MergeOperator - the generic class for all the more abstract / complex 33 | // operations; one method (FullMerge) to merge a Put/Delete value with a 34 | // merge operand; and another method (PartialMerge) that merges two 35 | // operands together. this is especially useful if your key values have a 36 | // complex structure but you would still like to support client-specific 37 | // incremental updates. 38 | // 39 | // AssociativeMergeOperator is simpler to implement. MergeOperator is simply 40 | // more powerful. 41 | // 42 | // Refer to rocksdb-merge wiki for more details and example implementations. 43 | // 44 | class MergeOperator { 45 | public: 46 | virtual ~MergeOperator() {} 47 | 48 | // Gives the client a way to express the read -> modify -> write semantics 49 | // key: (IN) The key that's associated with this merge operation. 50 | // Client could multiplex the merge operator based on it 51 | // if the key space is partitioned and different subspaces 52 | // refer to different types of data which have different 53 | // merge operation semantics 54 | // existing: (IN) null indicates that the key does not exist before this op 55 | // operand_list:(IN) the sequence of merge operations to apply, front() first. 56 | // new_value:(OUT) Client is responsible for filling the merge result here 57 | // logger: (IN) Client could use this to log errors during merge. 58 | // 59 | // Return true on success. 60 | // All values passed in will be client-specific values. So if this method 61 | // returns false, it is because client specified bad data or there was 62 | // internal corruption. This will be treated as an error by the library. 63 | // 64 | // Also make use of the *logger for error messages. 65 | virtual bool FullMerge(const Slice& key, 66 | const Slice* existing_value, 67 | const std::deque& operand_list, 68 | std::string* new_value, 69 | Logger* logger) const = 0; 70 | 71 | // This function performs merge(left_op, right_op) 72 | // when both the operands are themselves merge operation types 73 | // that you would have passed to a DB::Merge() call in the same order 74 | // (i.e.: DB::Merge(key,left_op), followed by DB::Merge(key,right_op)). 75 | // 76 | // PartialMerge should combine them into a single merge operation that is 77 | // saved into *new_value, and then it should return true. 78 | // *new_value should be constructed such that a call to 79 | // DB::Merge(key, *new_value) would yield the same result as a call 80 | // to DB::Merge(key, left_op) followed by DB::Merge(key, right_op). 81 | // 82 | // If it is impossible or infeasible to combine the two operations, 83 | // leave new_value unchanged and return false. The library will 84 | // internally keep track of the operations, and apply them in the 85 | // correct order once a base-value (a Put/Delete/End-of-Database) is seen. 86 | // 87 | // TODO: Presently there is no way to differentiate between error/corruption 88 | // and simply "return false". For now, the client should simply return 89 | // false in any case it cannot perform partial-merge, regardless of reason. 90 | // If there is corruption in the data, handle it in the FullMerge() function, 91 | // and return false there. 92 | virtual bool PartialMerge(const Slice& key, 93 | const Slice& left_operand, 94 | const Slice& right_operand, 95 | std::string* new_value, 96 | Logger* logger) const = 0; 97 | 98 | // The name of the MergeOperator. Used to check for MergeOperator 99 | // mismatches (i.e., a DB created with one MergeOperator is 100 | // accessed using a different MergeOperator) 101 | // TODO: the name is currently not stored persistently and thus 102 | // no checking is enforced. Client is responsible for providing 103 | // consistent MergeOperator between DB opens. 104 | virtual const char* Name() const = 0; 105 | }; 106 | 107 | // The simpler, associative merge operator. 108 | class AssociativeMergeOperator : public MergeOperator { 109 | public: 110 | virtual ~AssociativeMergeOperator() {} 111 | 112 | // Gives the client a way to express the read -> modify -> write semantics 113 | // key: (IN) The key that's associated with this merge operation. 114 | // existing_value:(IN) null indicates the key does not exist before this op 115 | // value: (IN) the value to update/merge the existing_value with 116 | // new_value: (OUT) Client is responsible for filling the merge result here 117 | // logger: (IN) Client could use this to log errors during merge. 118 | // 119 | // Return true on success. 120 | // All values passed in will be client-specific values. So if this method 121 | // returns false, it is because client specified bad data or there was 122 | // internal corruption. The client should assume that this will be treated 123 | // as an error by the library. 124 | virtual bool Merge(const Slice& key, 125 | const Slice* existing_value, 126 | const Slice& value, 127 | std::string* new_value, 128 | Logger* logger) const = 0; 129 | 130 | 131 | private: 132 | // Default implementations of the MergeOperator functions 133 | virtual bool FullMerge(const Slice& key, 134 | const Slice* existing_value, 135 | const std::deque& operand_list, 136 | std::string* new_value, 137 | Logger* logger) const override; 138 | 139 | virtual bool PartialMerge(const Slice& key, 140 | const Slice& left_operand, 141 | const Slice& right_operand, 142 | std::string* new_value, 143 | Logger* logger) const override; 144 | }; 145 | 146 | } // namespace rocksdb 147 | 148 | #endif // STORAGE_ROCKSDB_INCLUDE_MERGE_OPERATOR_H_ 149 | -------------------------------------------------------------------------------- /src/include/rocksdb/perf_context.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | 6 | #ifndef STORAGE_ROCKSDB_INCLUDE_PERF_CONTEXT_H 7 | #define STORAGE_ROCKSDB_INCLUDE_PERF_CONTEXT_H 8 | 9 | #include 10 | 11 | namespace rocksdb { 12 | 13 | enum PerfLevel { 14 | kDisable = 0, // disable perf stats 15 | kEnableCount = 1, // enable only count stats 16 | kEnableTime = 2 // enable time stats too 17 | }; 18 | 19 | // set the perf stats level 20 | void SetPerfLevel(PerfLevel level); 21 | 22 | // A thread local context for gathering performance counter efficiently 23 | // and transparently. 24 | 25 | struct PerfContext { 26 | 27 | void Reset(); // reset all performance counters to zero 28 | 29 | uint64_t user_key_comparison_count; // total number of user key comparisons 30 | uint64_t block_cache_hit_count; // total number of block cache hits 31 | uint64_t block_read_count; // total number of block reads (with IO) 32 | uint64_t block_read_byte; // total number of bytes from block reads 33 | uint64_t block_read_time; // total time spent on block reads 34 | uint64_t block_checksum_time; // total time spent on block checksum 35 | uint64_t block_decompress_time; // total time spent on block decompression 36 | // total number of internal keys skipped over during iteration (overwritten or 37 | // deleted, to be more specific, hidden by a put or delete of the same key) 38 | uint64_t internal_key_skipped_count; 39 | // total number of deletes skipped over during iteration 40 | uint64_t internal_delete_skipped_count; 41 | uint64_t wal_write_time; // total time spent on writing to WAL 42 | }; 43 | 44 | extern __thread PerfContext perf_context; 45 | 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/include/rocksdb/slice.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // Slice is a simple structure containing a pointer into some external 10 | // storage and a size. The user of a Slice must ensure that the slice 11 | // is not used after the corresponding external storage has been 12 | // deallocated. 13 | // 14 | // Multiple threads can invoke const methods on a Slice without 15 | // external synchronization, but if any of the threads may call a 16 | // non-const method, all threads accessing the same Slice must use 17 | // external synchronization. 18 | 19 | #ifndef STORAGE_ROCKSDB_INCLUDE_SLICE_H_ 20 | #define STORAGE_ROCKSDB_INCLUDE_SLICE_H_ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | namespace rocksdb { 28 | 29 | class Slice { 30 | public: 31 | // Create an empty slice. 32 | Slice() : data_(""), size_(0) { } 33 | 34 | // Create a slice that refers to d[0,n-1]. 35 | Slice(const char* d, size_t n) : data_(d), size_(n) { } 36 | 37 | // Create a slice that refers to the contents of "s" 38 | /* implicit */ 39 | Slice(const std::string& s) : data_(s.data()), size_(s.size()) { } 40 | 41 | // Create a slice that refers to s[0,strlen(s)-1] 42 | /* implicit */ 43 | Slice(const char* s) : data_(s), size_(strlen(s)) { } 44 | 45 | // Return a pointer to the beginning of the referenced data 46 | const char* data() const { return data_; } 47 | 48 | // Return the length (in bytes) of the referenced data 49 | size_t size() const { return size_; } 50 | 51 | // Return true iff the length of the referenced data is zero 52 | bool empty() const { return size_ == 0; } 53 | 54 | // Return the ith byte in the referenced data. 55 | // REQUIRES: n < size() 56 | char operator[](size_t n) const { 57 | assert(n < size()); 58 | return data_[n]; 59 | } 60 | 61 | // Change this slice to refer to an empty array 62 | void clear() { data_ = ""; size_ = 0; } 63 | 64 | // Drop the first "n" bytes from this slice. 65 | void remove_prefix(size_t n) { 66 | assert(n <= size()); 67 | data_ += n; 68 | size_ -= n; 69 | } 70 | 71 | // Return a string that contains the copy of the referenced data. 72 | std::string ToString(bool hex = false) const { 73 | if (hex) { 74 | std::string result; 75 | char buf[10]; 76 | for (size_t i = 0; i < size_; i++) { 77 | snprintf(buf, 10, "%02X", (unsigned char)data_[i]); 78 | result += buf; 79 | } 80 | return result; 81 | } else { 82 | return std::string(data_, size_); 83 | } 84 | } 85 | 86 | // Three-way comparison. Returns value: 87 | // < 0 iff "*this" < "b", 88 | // == 0 iff "*this" == "b", 89 | // > 0 iff "*this" > "b" 90 | int compare(const Slice& b) const; 91 | 92 | // Return true iff "x" is a prefix of "*this" 93 | bool starts_with(const Slice& x) const { 94 | return ((size_ >= x.size_) && 95 | (memcmp(data_, x.data_, x.size_) == 0)); 96 | } 97 | 98 | // private: make these public for rocksdbjni access 99 | const char* data_; 100 | size_t size_; 101 | 102 | // Intentionally copyable 103 | }; 104 | 105 | // A set of Slices that are virtually concatenated together. 'parts' points 106 | // to an array of Slices. The number of elements in the array is 'num_parts'. 107 | struct SliceParts { 108 | SliceParts(const Slice* parts, int num_parts) : 109 | parts(parts), num_parts(num_parts) { } 110 | 111 | const Slice* parts; 112 | int num_parts; 113 | }; 114 | 115 | inline bool operator==(const Slice& x, const Slice& y) { 116 | return ((x.size() == y.size()) && 117 | (memcmp(x.data(), y.data(), x.size()) == 0)); 118 | } 119 | 120 | inline bool operator!=(const Slice& x, const Slice& y) { 121 | return !(x == y); 122 | } 123 | 124 | inline int Slice::compare(const Slice& b) const { 125 | const int min_len = (size_ < b.size_) ? size_ : b.size_; 126 | int r = memcmp(data_, b.data_, min_len); 127 | if (r == 0) { 128 | if (size_ < b.size_) r = -1; 129 | else if (size_ > b.size_) r = +1; 130 | } 131 | return r; 132 | } 133 | 134 | } // namespace rocksdb 135 | 136 | #endif // STORAGE_ROCKSDB_INCLUDE_SLICE_H_ 137 | -------------------------------------------------------------------------------- /src/include/rocksdb/slice_transform.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2012 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // Class for specifying user-defined functions which perform a 10 | // transformation on a slice. It is not required that every slice 11 | // belong to the domain and/or range of a function. Subclasses should 12 | // define InDomain and InRange to determine which slices are in either 13 | // of these sets respectively. 14 | 15 | #ifndef STORAGE_ROCKSDB_INCLUDE_SLICE_TRANSFORM_H_ 16 | #define STORAGE_ROCKSDB_INCLUDE_SLICE_TRANSFORM_H_ 17 | 18 | #include 19 | 20 | namespace rocksdb { 21 | 22 | class Slice; 23 | 24 | class SliceTransform { 25 | public: 26 | virtual ~SliceTransform() {}; 27 | 28 | // Return the name of this transformation. 29 | virtual const char* Name() const = 0; 30 | 31 | // transform a src in domain to a dst in the range 32 | virtual Slice Transform(const Slice& src) const = 0; 33 | 34 | // determine whether this is a valid src upon the function applies 35 | virtual bool InDomain(const Slice& src) const = 0; 36 | 37 | // determine whether dst=Transform(src) for some src 38 | virtual bool InRange(const Slice& dst) const = 0; 39 | }; 40 | 41 | extern const SliceTransform* NewFixedPrefixTransform(size_t prefix_len); 42 | 43 | extern const SliceTransform* NewNoopTransform(); 44 | 45 | } 46 | 47 | #endif // STORAGE_ROCKSDB_INCLUDE_SLICE_TRANSFORM_H_ 48 | -------------------------------------------------------------------------------- /src/include/rocksdb/statistics.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | 6 | #ifndef STORAGE_ROCKSDB_INCLUDE_STATISTICS_H_ 7 | #define STORAGE_ROCKSDB_INCLUDE_STATISTICS_H_ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace rocksdb { 18 | 19 | /** 20 | * Keep adding ticker's here. 21 | * Any ticker should have a value less than TICKER_ENUM_MAX. 22 | * Add a new ticker by assigning it the current value of TICKER_ENUM_MAX 23 | * Add a string representation in TickersNameMap below. 24 | * And incrementing TICKER_ENUM_MAX. 25 | */ 26 | enum Tickers { 27 | // total block cache misses 28 | // REQUIRES: BLOCK_CACHE_MISS == BLOCK_CACHE_INDEX_MISS + 29 | // BLOCK_CACHE_FILTER_MISS + 30 | // BLOCK_CACHE_DATA_MISS; 31 | BLOCK_CACHE_MISS, 32 | // total block cache hit 33 | // REQUIRES: BLOCK_CACHE_HIT == BLOCK_CACHE_INDEX_HIT + 34 | // BLOCK_CACHE_FILTER_HIT + 35 | // BLOCK_CACHE_DATA_HIT; 36 | BLOCK_CACHE_HIT, 37 | // # of blocks added to block cache. 38 | BLOCK_CACHE_ADD, 39 | // # of times cache miss when accessing index block from block cache. 40 | BLOCK_CACHE_INDEX_MISS, 41 | // # of times cache hit when accessing index block from block cache. 42 | BLOCK_CACHE_INDEX_HIT, 43 | // # of times cache miss when accessing filter block from block cache. 44 | BLOCK_CACHE_FILTER_MISS, 45 | // # of times cache hit when accessing filter block from block cache. 46 | BLOCK_CACHE_FILTER_HIT, 47 | // # of times cache miss when accessing data block from block cache. 48 | BLOCK_CACHE_DATA_MISS, 49 | // # of times cache hit when accessing data block from block cache. 50 | BLOCK_CACHE_DATA_HIT, 51 | // # of times bloom filter has avoided file reads. 52 | BLOOM_FILTER_USEFUL, 53 | 54 | /** 55 | * COMPACTION_KEY_DROP_* count the reasons for key drop during compaction 56 | * There are 3 reasons currently. 57 | */ 58 | COMPACTION_KEY_DROP_NEWER_ENTRY, // key was written with a newer value. 59 | COMPACTION_KEY_DROP_OBSOLETE, // The key is obsolete. 60 | COMPACTION_KEY_DROP_USER, // user compaction function has dropped the key. 61 | 62 | // Number of keys written to the database via the Put and Write call's 63 | NUMBER_KEYS_WRITTEN, 64 | // Number of Keys read, 65 | NUMBER_KEYS_READ, 66 | // Number keys updated, if inplace update is enabled 67 | NUMBER_KEYS_UPDATED, 68 | // Bytes written / read 69 | BYTES_WRITTEN, 70 | BYTES_READ, 71 | NO_FILE_CLOSES, 72 | NO_FILE_OPENS, 73 | NO_FILE_ERRORS, 74 | // Time system had to wait to do LO-L1 compactions 75 | STALL_L0_SLOWDOWN_MICROS, 76 | // Time system had to wait to move memtable to L1. 77 | STALL_MEMTABLE_COMPACTION_MICROS, 78 | // write throttle because of too many files in L0 79 | STALL_L0_NUM_FILES_MICROS, 80 | RATE_LIMIT_DELAY_MILLIS, 81 | 82 | NO_ITERATORS, // number of iterators currently open 83 | 84 | // Number of MultiGet calls, keys read, and bytes read 85 | NUMBER_MULTIGET_CALLS, 86 | NUMBER_MULTIGET_KEYS_READ, 87 | NUMBER_MULTIGET_BYTES_READ, 88 | 89 | // Number of deletes records that were not required to be 90 | // written to storage because key does not exist 91 | NUMBER_FILTERED_DELETES, 92 | NUMBER_MERGE_FAILURES, 93 | SEQUENCE_NUMBER, 94 | 95 | // number of times bloom was checked before creating iterator on a 96 | // file, and the number of times the check was useful in avoiding 97 | // iterator creation (and thus likely IOPs). 98 | BLOOM_FILTER_PREFIX_CHECKED, 99 | BLOOM_FILTER_PREFIX_USEFUL, 100 | 101 | // Number of times we had to reseek inside an iteration to skip 102 | // over large number of keys with same userkey. 103 | NUMBER_OF_RESEEKS_IN_ITERATION, 104 | 105 | // Record the number of calls to GetUpadtesSince. Useful to keep track of 106 | // transaction log iterator refreshes 107 | GET_UPDATES_SINCE_CALLS, 108 | 109 | BLOCK_CACHE_COMPRESSED_MISS, // miss in the compressed block cache 110 | BLOCK_CACHE_COMPRESSED_HIT, // hit in the compressed block cache 111 | 112 | TICKER_ENUM_MAX 113 | }; 114 | 115 | // The order of items listed in Tickers should be the same as 116 | // the order listed in TickersNameMap 117 | const std::vector> TickersNameMap = { 118 | { BLOCK_CACHE_MISS, "rocksdb.block.cache.miss" }, 119 | { BLOCK_CACHE_HIT, "rocksdb.block.cache.hit" }, 120 | { BLOCK_CACHE_ADD, "rocksdb.block.cache.add" }, 121 | { BLOCK_CACHE_INDEX_MISS, "rocksdb.block.cache.index.miss" }, 122 | { BLOCK_CACHE_INDEX_HIT, "rocksdb.block.cache.index.hit" }, 123 | { BLOCK_CACHE_FILTER_MISS, "rocksdb.block.cache.filter.miss" }, 124 | { BLOCK_CACHE_FILTER_HIT, "rocksdb.block.cache.filter.hit" }, 125 | { BLOCK_CACHE_DATA_MISS, "rocksdb.block.cache.data.miss" }, 126 | { BLOCK_CACHE_DATA_HIT, "rocksdb.block.cache.data.hit" }, 127 | { BLOOM_FILTER_USEFUL, "rocksdb.bloom.filter.useful" }, 128 | { COMPACTION_KEY_DROP_NEWER_ENTRY, "rocksdb.compaction.key.drop.new" }, 129 | { COMPACTION_KEY_DROP_OBSOLETE, "rocksdb.compaction.key.drop.obsolete" }, 130 | { COMPACTION_KEY_DROP_USER, "rocksdb.compaction.key.drop.user" }, 131 | { NUMBER_KEYS_WRITTEN, "rocksdb.number.keys.written" }, 132 | { NUMBER_KEYS_READ, "rocksdb.number.keys.read" }, 133 | { NUMBER_KEYS_UPDATED, "rocksdb.number.keys.updated" }, 134 | { BYTES_WRITTEN, "rocksdb.bytes.written" }, 135 | { BYTES_READ, "rocksdb.bytes.read" }, 136 | { NO_FILE_CLOSES, "rocksdb.no.file.closes" }, 137 | { NO_FILE_OPENS, "rocksdb.no.file.opens" }, 138 | { NO_FILE_ERRORS, "rocksdb.no.file.errors" }, 139 | { STALL_L0_SLOWDOWN_MICROS, "rocksdb.l0.slowdown.micros" }, 140 | { STALL_MEMTABLE_COMPACTION_MICROS, "rocksdb.memtable.compaction.micros" }, 141 | { STALL_L0_NUM_FILES_MICROS, "rocksdb.l0.num.files.stall.micros" }, 142 | { RATE_LIMIT_DELAY_MILLIS, "rocksdb.rate.limit.delay.millis" }, 143 | { NO_ITERATORS, "rocksdb.num.iterators" }, 144 | { NUMBER_MULTIGET_CALLS, "rocksdb.number.multiget.get" }, 145 | { NUMBER_MULTIGET_KEYS_READ, "rocksdb.number.multiget.keys.read" }, 146 | { NUMBER_MULTIGET_BYTES_READ, "rocksdb.number.multiget.bytes.read" }, 147 | { NUMBER_FILTERED_DELETES, "rocksdb.number.deletes.filtered" }, 148 | { NUMBER_MERGE_FAILURES, "rocksdb.number.merge.failures" }, 149 | { SEQUENCE_NUMBER, "rocksdb.sequence.number" }, 150 | { BLOOM_FILTER_PREFIX_CHECKED, "rocksdb.bloom.filter.prefix.checked" }, 151 | { BLOOM_FILTER_PREFIX_USEFUL, "rocksdb.bloom.filter.prefix.useful" }, 152 | { NUMBER_OF_RESEEKS_IN_ITERATION, "rocksdb.number.reseeks.iteration" }, 153 | { GET_UPDATES_SINCE_CALLS, "rocksdb.getupdatessince.calls" }, 154 | { BLOCK_CACHE_COMPRESSED_MISS, "rocksdb.block.cachecompressed.miss" }, 155 | { BLOCK_CACHE_COMPRESSED_HIT, "rocksdb.block.cachecompressed.hit" } 156 | }; 157 | 158 | /** 159 | * Keep adding histogram's here. 160 | * Any histogram whould have value less than HISTOGRAM_ENUM_MAX 161 | * Add a new Histogram by assigning it the current value of HISTOGRAM_ENUM_MAX 162 | * Add a string representation in HistogramsNameMap below 163 | * And increment HISTOGRAM_ENUM_MAX 164 | */ 165 | enum Histograms { 166 | DB_GET, 167 | DB_WRITE, 168 | COMPACTION_TIME, 169 | TABLE_SYNC_MICROS, 170 | COMPACTION_OUTFILE_SYNC_MICROS, 171 | WAL_FILE_SYNC_MICROS, 172 | MANIFEST_FILE_SYNC_MICROS, 173 | // TIME SPENT IN IO DURING TABLE OPEN 174 | TABLE_OPEN_IO_MICROS, 175 | DB_MULTIGET, 176 | READ_BLOCK_COMPACTION_MICROS, 177 | READ_BLOCK_GET_MICROS, 178 | WRITE_RAW_BLOCK_MICROS, 179 | 180 | STALL_L0_SLOWDOWN_COUNT, 181 | STALL_MEMTABLE_COMPACTION_COUNT, 182 | STALL_L0_NUM_FILES_COUNT, 183 | HARD_RATE_LIMIT_DELAY_COUNT, 184 | SOFT_RATE_LIMIT_DELAY_COUNT, 185 | NUM_FILES_IN_SINGLE_COMPACTION, 186 | HISTOGRAM_ENUM_MAX, 187 | }; 188 | 189 | const std::vector> HistogramsNameMap = { 190 | { DB_GET, "rocksdb.db.get.micros" }, 191 | { DB_WRITE, "rocksdb.db.write.micros" }, 192 | { COMPACTION_TIME, "rocksdb.compaction.times.micros" }, 193 | { TABLE_SYNC_MICROS, "rocksdb.table.sync.micros" }, 194 | { COMPACTION_OUTFILE_SYNC_MICROS, "rocksdb.compaction.outfile.sync.micros" }, 195 | { WAL_FILE_SYNC_MICROS, "rocksdb.wal.file.sync.micros" }, 196 | { MANIFEST_FILE_SYNC_MICROS, "rocksdb.manifest.file.sync.micros" }, 197 | { TABLE_OPEN_IO_MICROS, "rocksdb.table.open.io.micros" }, 198 | { DB_MULTIGET, "rocksdb.db.multiget.micros" }, 199 | { READ_BLOCK_COMPACTION_MICROS, "rocksdb.read.block.compaction.micros" }, 200 | { READ_BLOCK_GET_MICROS, "rocksdb.read.block.get.micros" }, 201 | { WRITE_RAW_BLOCK_MICROS, "rocksdb.write.raw.block.micros" }, 202 | { STALL_L0_SLOWDOWN_COUNT, "rocksdb.l0.slowdown.count"}, 203 | { STALL_MEMTABLE_COMPACTION_COUNT, "rocksdb.memtable.compaction.count"}, 204 | { STALL_L0_NUM_FILES_COUNT, "rocksdb.num.files.stall.count"}, 205 | { HARD_RATE_LIMIT_DELAY_COUNT, "rocksdb.hard.rate.limit.delay.count"}, 206 | { SOFT_RATE_LIMIT_DELAY_COUNT, "rocksdb.soft.rate.limit.delay.count"}, 207 | { NUM_FILES_IN_SINGLE_COMPACTION, "rocksdb.numfiles.in.singlecompaction" }, 208 | }; 209 | 210 | struct HistogramData { 211 | double median; 212 | double percentile95; 213 | double percentile99; 214 | double average; 215 | double standard_deviation; 216 | }; 217 | 218 | 219 | class Histogram { 220 | public: 221 | // clear's the histogram 222 | virtual void Clear() = 0; 223 | virtual ~Histogram(); 224 | // Add a value to be recorded in the histogram. 225 | virtual void Add(uint64_t value) = 0; 226 | 227 | virtual std::string ToString() const = 0; 228 | 229 | // Get statistics 230 | virtual double Median() const = 0; 231 | virtual double Percentile(double p) const = 0; 232 | virtual double Average() const = 0; 233 | virtual double StandardDeviation() const = 0; 234 | virtual void Data(HistogramData * const data) const = 0; 235 | 236 | }; 237 | 238 | /** 239 | * A dumb ticker which keeps incrementing through its life time. 240 | * Thread safe. Locking managed by implementation of this interface. 241 | */ 242 | class Ticker { 243 | public: 244 | Ticker() : count_(0) { } 245 | 246 | inline void setTickerCount(uint64_t count) { 247 | count_ = count; 248 | } 249 | 250 | inline void recordTick(int count = 1) { 251 | count_ += count; 252 | } 253 | 254 | inline uint64_t getCount() { 255 | return count_; 256 | } 257 | 258 | private: 259 | std::atomic_uint_fast64_t count_; 260 | }; 261 | 262 | // Analyze the performance of a db 263 | class Statistics { 264 | public: 265 | 266 | virtual long getTickerCount(Tickers tickerType) = 0; 267 | virtual void recordTick(Tickers tickerType, uint64_t count = 0) = 0; 268 | virtual void setTickerCount(Tickers tickerType, uint64_t count) = 0; 269 | virtual void measureTime(Histograms histogramType, uint64_t time) = 0; 270 | 271 | virtual void histogramData(Histograms type, HistogramData * const data) = 0; 272 | // String representation of the statistic object. 273 | std::string ToString(); 274 | }; 275 | 276 | // Create a concrete DBStatistics object 277 | std::shared_ptr CreateDBStatistics(); 278 | 279 | // Ease of Use functions 280 | inline void RecordTick(std::shared_ptr statistics, 281 | Tickers ticker, 282 | uint64_t count = 1) { 283 | assert(HistogramsNameMap.size() == HISTOGRAM_ENUM_MAX); 284 | assert(TickersNameMap.size() == TICKER_ENUM_MAX); 285 | if (statistics) { 286 | statistics->recordTick(ticker, count); 287 | } 288 | } 289 | 290 | inline void SetTickerCount(std::shared_ptr statistics, 291 | Tickers ticker, 292 | uint64_t count) { 293 | assert(HistogramsNameMap.size() == HISTOGRAM_ENUM_MAX); 294 | assert(TickersNameMap.size() == TICKER_ENUM_MAX); 295 | if (statistics) { 296 | statistics->setTickerCount(ticker, count); 297 | } 298 | } 299 | 300 | } // namespace rocksdb 301 | 302 | #endif // STORAGE_ROCKSDB_INCLUDE_STATISTICS_H_ 303 | -------------------------------------------------------------------------------- /src/include/rocksdb/status.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // A Status encapsulates the result of an operation. It may indicate success, 10 | // or it may indicate an error with an associated error message. 11 | // 12 | // Multiple threads can invoke const methods on a Status without 13 | // external synchronization, but if any of the threads may call a 14 | // non-const method, all threads accessing the same Status must use 15 | // external synchronization. 16 | 17 | #ifndef STORAGE_ROCKSDB_INCLUDE_STATUS_H_ 18 | #define STORAGE_ROCKSDB_INCLUDE_STATUS_H_ 19 | 20 | #include 21 | #include "rocksdb/slice.h" 22 | 23 | namespace rocksdb { 24 | 25 | class Status { 26 | public: 27 | // Create a success status. 28 | Status() : state_(nullptr) { } 29 | ~Status() { delete[] state_; } 30 | 31 | // Copy the specified status. 32 | Status(const Status& s); 33 | void operator=(const Status& s); 34 | 35 | // Return a success status. 36 | static Status OK() { return Status(); } 37 | 38 | // Return error status of an appropriate type. 39 | static Status NotFound(const Slice& msg, const Slice& msg2 = Slice()) { 40 | return Status(kNotFound, msg, msg2); 41 | } 42 | static Status Corruption(const Slice& msg, const Slice& msg2 = Slice()) { 43 | return Status(kCorruption, msg, msg2); 44 | } 45 | static Status NotSupported(const Slice& msg, const Slice& msg2 = Slice()) { 46 | return Status(kNotSupported, msg, msg2); 47 | } 48 | static Status InvalidArgument(const Slice& msg, const Slice& msg2 = Slice()) { 49 | return Status(kInvalidArgument, msg, msg2); 50 | } 51 | static Status IOError(const Slice& msg, const Slice& msg2 = Slice()) { 52 | return Status(kIOError, msg, msg2); 53 | } 54 | static Status MergeInProgress(const Slice& msg, const Slice& msg2 = Slice()) { 55 | return Status(kMergeInProgress, msg, msg2); 56 | } 57 | static Status Incomplete(const Slice& msg, const Slice& msg2 = Slice()) { 58 | return Status(kIncomplete, msg, msg2); 59 | } 60 | 61 | // Returns true iff the status indicates success. 62 | bool ok() const { return (state_ == nullptr); } 63 | 64 | // Returns true iff the status indicates a NotFound error. 65 | bool IsNotFound() const { return code() == kNotFound; } 66 | 67 | // Returns true iff the status indicates a Corruption error. 68 | bool IsCorruption() const { return code() == kCorruption; } 69 | 70 | // Returns true iff the status indicates a NotSupported error. 71 | bool IsNotSupported() const { return code() == kNotSupported; } 72 | 73 | // Returns true iff the status indicates an InvalidArgument error. 74 | bool IsInvalidArgument() const { return code() == kInvalidArgument; } 75 | 76 | // Returns true iff the status indicates an IOError. 77 | bool IsIOError() const { return code() == kIOError; } 78 | 79 | // Returns true iff the status indicates an MergeInProgress. 80 | bool IsMergeInProgress() const { return code() == kMergeInProgress; } 81 | 82 | // Returns true iff the status indicates Incomplete 83 | bool IsIncomplete() const { return code() == kIncomplete; } 84 | 85 | // Return a string representation of this status suitable for printing. 86 | // Returns the string "OK" for success. 87 | std::string ToString() const; 88 | 89 | private: 90 | // OK status has a nullptr state_. Otherwise, state_ is a new[] array 91 | // of the following form: 92 | // state_[0..3] == length of message 93 | // state_[4] == code 94 | // state_[5..] == message 95 | const char* state_; 96 | 97 | enum Code { 98 | kOk = 0, 99 | kNotFound = 1, 100 | kCorruption = 2, 101 | kNotSupported = 3, 102 | kInvalidArgument = 4, 103 | kIOError = 5, 104 | kMergeInProgress = 6, 105 | kIncomplete = 7 106 | }; 107 | 108 | Code code() const { 109 | return (state_ == nullptr) ? kOk : static_cast(state_[4]); 110 | } 111 | 112 | Status(Code code, const Slice& msg, const Slice& msg2); 113 | static const char* CopyState(const char* s); 114 | }; 115 | 116 | inline Status::Status(const Status& s) { 117 | state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_); 118 | } 119 | inline void Status::operator=(const Status& s) { 120 | // The following condition catches both aliasing (when this == &s), 121 | // and the common case where both s and *this are ok. 122 | if (state_ != s.state_) { 123 | delete[] state_; 124 | state_ = (s.state_ == nullptr) ? nullptr : CopyState(s.state_); 125 | } 126 | } 127 | 128 | } // namespace rocksdb 129 | 130 | #endif // STORAGE_ROCKSDB_INCLUDE_STATUS_H_ 131 | -------------------------------------------------------------------------------- /src/include/rocksdb/table.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // 6 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 7 | // Use of this source code is governed by a BSD-style license that can be 8 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 9 | 10 | #pragma once 11 | #include 12 | #include 13 | #include "rocksdb/env.h" 14 | #include "rocksdb/iterator.h" 15 | #include "rocksdb/table_properties.h" 16 | #include "rocksdb/options.h" 17 | 18 | namespace rocksdb { 19 | 20 | struct Options; 21 | class RandomAccessFile; 22 | struct ReadOptions; 23 | class TableCache; 24 | class WritableFile; 25 | 26 | using std::unique_ptr; 27 | 28 | // TableBuilder provides the interface used to build a Table 29 | // (an immutable and sorted map from keys to values). 30 | // 31 | // Multiple threads can invoke const methods on a TableBuilder without 32 | // external synchronization, but if any of the threads may call a 33 | // non-const method, all threads accessing the same TableBuilder must use 34 | // external synchronization. 35 | class TableBuilder { 36 | public: 37 | // REQUIRES: Either Finish() or Abandon() has been called. 38 | virtual ~TableBuilder() {} 39 | 40 | // Add key,value to the table being constructed. 41 | // REQUIRES: key is after any previously added key according to comparator. 42 | // REQUIRES: Finish(), Abandon() have not been called 43 | virtual void Add(const Slice& key, const Slice& value) = 0; 44 | 45 | // Return non-ok iff some error has been detected. 46 | virtual Status status() const = 0; 47 | 48 | // Finish building the table. 49 | // REQUIRES: Finish(), Abandon() have not been called 50 | virtual Status Finish() = 0; 51 | 52 | // Indicate that the contents of this builder should be abandoned. 53 | // If the caller is not going to call Finish(), it must call Abandon() 54 | // before destroying this builder. 55 | // REQUIRES: Finish(), Abandon() have not been called 56 | virtual void Abandon() = 0; 57 | 58 | // Number of calls to Add() so far. 59 | virtual uint64_t NumEntries() const = 0; 60 | 61 | // Size of the file generated so far. If invoked after a successful 62 | // Finish() call, returns the size of the final generated file. 63 | virtual uint64_t FileSize() const = 0; 64 | }; 65 | 66 | // A Table is a sorted map from strings to strings. Tables are 67 | // immutable and persistent. A Table may be safely accessed from 68 | // multiple threads without external synchronization. 69 | class TableReader { 70 | public: 71 | virtual ~TableReader() {} 72 | 73 | // Determine whether there is a chance that the current table file 74 | // contains the key a key starting with iternal_prefix. The specific 75 | // table implementation can use bloom filter and/or other heuristic 76 | // to filter out this table as a whole. 77 | virtual bool PrefixMayMatch(const Slice& internal_prefix) = 0; 78 | 79 | // Returns a new iterator over the table contents. 80 | // The result of NewIterator() is initially invalid (caller must 81 | // call one of the Seek methods on the iterator before using it). 82 | virtual Iterator* NewIterator(const ReadOptions&) = 0; 83 | 84 | // Given a key, return an approximate byte offset in the file where 85 | // the data for that key begins (or would begin if the key were 86 | // present in the file). The returned value is in terms of file 87 | // bytes, and so includes effects like compression of the underlying data. 88 | // E.g., the approximate offset of the last key in the table will 89 | // be close to the file length. 90 | virtual uint64_t ApproximateOffsetOf(const Slice& key) = 0; 91 | 92 | // Returns true if the block for the specified key is in cache. 93 | // REQUIRES: key is in this table. 94 | virtual bool TEST_KeyInCache(const ReadOptions& options, 95 | const Slice& key) = 0; 96 | 97 | // Set up the table for Compaction. Might change some parameters with 98 | // posix_fadvise 99 | virtual void SetupForCompaction() = 0; 100 | 101 | virtual TableProperties& GetTableProperties() = 0; 102 | 103 | // Calls (*result_handler)(handle_context, ...) repeatedly, starting with 104 | // the entry found after a call to Seek(key), until result_handler returns 105 | // false, where k is the actual internal key for a row found and v as the 106 | // value of the key. didIO is true if I/O is involved in the operation. May 107 | // not make such a call if filter policy says that key is not present. 108 | // 109 | // mark_key_may_exist_handler needs to be called when it is configured to be 110 | // memory only and the key is not found in the block cache, with 111 | // the parameter to be handle_context. 112 | // 113 | // readOptions is the options for the read 114 | // key is the key to search for 115 | virtual Status Get( 116 | const ReadOptions& readOptions, 117 | const Slice& key, 118 | void* handle_context, 119 | bool (*result_handler)(void* handle_context, const Slice& k, 120 | const Slice& v, bool didIO), 121 | void (*mark_key_may_exist_handler)(void* handle_context) = nullptr) = 0; 122 | }; 123 | 124 | // A base class for table factories 125 | class TableFactory { 126 | public: 127 | virtual ~TableFactory() {} 128 | 129 | // The type of the table. 130 | // 131 | // The client of this package should switch to a new name whenever 132 | // the table format implementation changes. 133 | // 134 | // Names starting with "rocksdb." are reserved and should not be used 135 | // by any clients of this package. 136 | virtual const char* Name() const = 0; 137 | 138 | // Returns a Table object table that can fetch data from file specified 139 | // in parameter file. It's the caller's responsibility to make sure 140 | // file is in the correct format. 141 | // 142 | // GetTableReader() is called in two places: 143 | // (1) TableCache::FindTable() calls the function when table cache miss 144 | // and cache the table object returned. 145 | // (1) SstFileReader (for SST Dump) opens the table and dump the table 146 | // contents using the interator of the table. 147 | // options and soptions are options. options is the general options. 148 | // Multiple configured can be accessed from there, including and not 149 | // limited to block cache and key comparators. 150 | // file is a file handler to handle the file for the table 151 | // file_size is the physical file size of the file 152 | // table_reader is the output table reader 153 | virtual Status GetTableReader( 154 | const Options& options, const EnvOptions& soptions, 155 | unique_ptr && file, uint64_t file_size, 156 | unique_ptr* table_reader) const = 0; 157 | 158 | // Return a table builder to write to a file for this table type. 159 | // 160 | // It is called in several places: 161 | // (1) When flushing memtable to a level-0 output file, it creates a table 162 | // builder (In DBImpl::WriteLevel0Table(), by calling BuildTable()) 163 | // (2) During compaction, it gets the builder for writing compaction output 164 | // files in DBImpl::OpenCompactionOutputFile(). 165 | // (3) When recovering from transaction logs, it creates a table builder to 166 | // write to a level-0 output file (In DBImpl::WriteLevel0TableForRecovery, 167 | // by calling BuildTable()) 168 | // (4) When running Repairer, it creates a table builder to convert logs to 169 | // SST files (In Repairer::ConvertLogToTable() by calling BuildTable()) 170 | // 171 | // options is the general options. Multiple configured can be acceseed from 172 | // there, including and not limited to compression options. 173 | // file is a handle of a writable file. It is the caller's responsibility to 174 | // keep the file open and close the file after closing the table builder. 175 | // compression_type is the compression type to use in this table. 176 | virtual TableBuilder* GetTableBuilder( 177 | const Options& options, WritableFile* file, 178 | CompressionType compression_type) const = 0; 179 | }; 180 | } // namespace rocksdb 181 | -------------------------------------------------------------------------------- /src/include/rocksdb/table_properties.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | #pragma once 6 | 7 | #include 8 | #include 9 | 10 | #include "rocksdb/status.h" 11 | 12 | namespace rocksdb { 13 | 14 | // TableProperties contains a bunch of read-only properties of its associated 15 | // table. 16 | struct TableProperties { 17 | public: 18 | // Other than basic table properties, each table may also have the user 19 | // collected properties. 20 | // The value of the user-collected properties are encoded as raw bytes -- 21 | // users have to interprete these values by themselves. 22 | typedef 23 | std::unordered_map 24 | UserCollectedProperties; 25 | 26 | // the total size of all data blocks. 27 | uint64_t data_size = 0; 28 | // the size of index block. 29 | uint64_t index_size = 0; 30 | // the size of filter block. 31 | uint64_t filter_size = 0; 32 | // total raw key size 33 | uint64_t raw_key_size = 0; 34 | // total raw value size 35 | uint64_t raw_value_size = 0; 36 | // the number of blocks in this table 37 | uint64_t num_data_blocks = 0; 38 | // the number of entries in this table 39 | uint64_t num_entries = 0; 40 | 41 | // The name of the filter policy used in this table. 42 | // If no filter policy is used, `filter_policy_name` will be an empty string. 43 | std::string filter_policy_name; 44 | 45 | // user collected properties 46 | UserCollectedProperties user_collected_properties; 47 | 48 | // convert this object to a human readable form 49 | // @prop_delim: delimiter for each property. 50 | std::string ToString( 51 | const std::string& prop_delim = "; ", 52 | const std::string& kv_delim = "=") const; 53 | }; 54 | 55 | // `TablePropertiesCollector` provides the mechanism for users to collect 56 | // their own interested properties. This class is essentially a collection 57 | // of callback functions that will be invoked during table building. 58 | class TablePropertiesCollector { 59 | public: 60 | virtual ~TablePropertiesCollector() { } 61 | 62 | // Add() will be called when a new key/value pair is inserted into the table. 63 | // @params key the original key that is inserted into the table. 64 | // @params value the original value that is inserted into the table. 65 | virtual Status Add(const Slice& key, const Slice& value) = 0; 66 | 67 | // Finish() will be called when a table has already been built and is ready 68 | // for writing the properties block. 69 | // @params properties User will add their collected statistics to 70 | // `properties`. 71 | virtual Status Finish( 72 | TableProperties::UserCollectedProperties* properties) = 0; 73 | 74 | // The name of the properties collector can be used for debugging purpose. 75 | virtual const char* Name() const = 0; 76 | 77 | // Return the human-readable properties, where the key is property name and 78 | // the value is the human-readable form of value. 79 | virtual TableProperties::UserCollectedProperties 80 | GetReadableProperties() const = 0; 81 | }; 82 | 83 | // Extra properties 84 | // Below is a list of non-basic properties that are collected by database 85 | // itself. Especially some properties regarding to the internal keys (which 86 | // is unknown to `table`). 87 | extern uint64_t GetDeletedKeys( 88 | const TableProperties::UserCollectedProperties& props); 89 | 90 | } // namespace rocksdb 91 | -------------------------------------------------------------------------------- /src/include/rocksdb/transaction_log.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | 6 | #ifndef STORAGE_ROCKSDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_ 7 | #define STORAGE_ROCKSDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_ 8 | 9 | #include "rocksdb/status.h" 10 | #include "rocksdb/types.h" 11 | #include "rocksdb/write_batch.h" 12 | #include 13 | #include 14 | 15 | namespace rocksdb { 16 | 17 | class LogFile; 18 | typedef std::vector> VectorLogPtr; 19 | 20 | enum WalFileType { 21 | /* Indicates that WAL file is in archive directory. WAL files are moved from 22 | * the main db directory to archive directory once they are not live and stay 23 | * there until cleaned up. Files are cleaned depending on archive size 24 | * (Options::WAL_size_limit_MB) and time since last cleaning 25 | * (Options::WAL_ttl_seconds). 26 | */ 27 | kArchivedLogFile = 0, 28 | 29 | /* Indicates that WAL file is live and resides in the main db directory */ 30 | kAliveLogFile = 1 31 | } ; 32 | 33 | class LogFile { 34 | public: 35 | LogFile() {} 36 | virtual ~LogFile() {} 37 | 38 | // Returns log file's pathname relative to the main db dir 39 | // Eg. For a live-log-file = /000003.log 40 | // For an archived-log-file = /archive/000003.log 41 | virtual std::string PathName() const = 0; 42 | 43 | 44 | // Primary identifier for log file. 45 | // This is directly proportional to creation time of the log file 46 | virtual uint64_t LogNumber() const = 0; 47 | 48 | // Log file can be either alive or archived 49 | virtual WalFileType Type() const = 0; 50 | 51 | // Starting sequence number of writebatch written in this log file 52 | virtual SequenceNumber StartSequence() const = 0; 53 | 54 | // Size of log file on disk in Bytes 55 | virtual uint64_t SizeFileBytes() const = 0; 56 | }; 57 | 58 | struct BatchResult { 59 | SequenceNumber sequence = SequenceNumber(); 60 | std::unique_ptr writeBatchPtr; 61 | }; 62 | 63 | // A TransactionLogIterator is used to iterate over the transactions in a db. 64 | // One run of the iterator is continuous, i.e. the iterator will stop at the 65 | // beginning of any gap in sequences 66 | class TransactionLogIterator { 67 | public: 68 | TransactionLogIterator() {} 69 | virtual ~TransactionLogIterator() {} 70 | 71 | // An iterator is either positioned at a WriteBatch or not valid. 72 | // This method returns true if the iterator is valid. 73 | // Can read data from a valid iterator. 74 | virtual bool Valid() = 0; 75 | 76 | // Moves the iterator to the next WriteBatch. 77 | // REQUIRES: Valid() to be true. 78 | virtual void Next() = 0; 79 | 80 | // Returns ok if the iterator is valid. 81 | // Returns the Error when something has gone wrong. 82 | virtual Status status() = 0; 83 | 84 | // If valid return's the current write_batch and the sequence number of the 85 | // earliest transaction contained in the batch. 86 | // ONLY use if Valid() is true and status() is OK. 87 | virtual BatchResult GetBatch() = 0; 88 | }; 89 | } // namespace rocksdb 90 | 91 | #endif // STORAGE_ROCKSDB_INCLUDE_TRANSACTION_LOG_ITERATOR_H_ 92 | -------------------------------------------------------------------------------- /src/include/rocksdb/types.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | 6 | #ifndef STORAGE_ROCKSDB_INCLUDE_TYPES_H_ 7 | #define STORAGE_ROCKSDB_INCLUDE_TYPES_H_ 8 | 9 | #include 10 | 11 | namespace rocksdb { 12 | 13 | // Define all public custom types here. 14 | 15 | // Represents a sequence number in a WAL file. 16 | typedef uint64_t SequenceNumber; 17 | 18 | } // namespace rocksdb 19 | 20 | #endif // STORAGE_ROCKSDB_INCLUDE_TYPES_H_ 21 | -------------------------------------------------------------------------------- /src/include/rocksdb/universal_compaction.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | 6 | #ifndef STORAGE_ROCKSDB_UNIVERSAL_COMPACTION_OPTIONS_H 7 | #define STORAGE_ROCKSDB_UNIVERSAL_COMPACTION_OPTIONS_H 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include "rocksdb/slice.h" 16 | #include "rocksdb/statistics.h" 17 | 18 | namespace rocksdb { 19 | 20 | // 21 | // Algorithm used to make a compaction request stop picking new files 22 | // into a single compaction run 23 | // 24 | enum CompactionStopStyle { 25 | kCompactionStopStyleSimilarSize, // pick files of similar size 26 | kCompactionStopStyleTotalSize // total size of picked files > next file 27 | }; 28 | 29 | class CompactionOptionsUniversal { 30 | public: 31 | 32 | // Percentage flexibilty while comparing file size. If the candidate file(s) 33 | // size is 1% smaller than the next file's size, then include next file into 34 | // this candidate set. // Default: 1 35 | unsigned int size_ratio; 36 | 37 | // The minimum number of files in a single compaction run. Default: 2 38 | unsigned int min_merge_width; 39 | 40 | // The maximum number of files in a single compaction run. Default: UINT_MAX 41 | unsigned int max_merge_width; 42 | 43 | // The size amplification is defined as the amount (in percentage) of 44 | // additional storage needed to store a single byte of data in the database. 45 | // For example, a size amplification of 2% means that a database that 46 | // contains 100 bytes of user-data may occupy upto 102 bytes of 47 | // physical storage. By this definition, a fully compacted database has 48 | // a size amplification of 0%. Rocksdb uses the following heuristic 49 | // to calculate size amplification: it assumes that all files excluding 50 | // the earliest file contribute to the size amplification. 51 | // Default: 200, which means that a 100 byte database could require upto 52 | // 300 bytes of storage. 53 | unsigned int max_size_amplification_percent; 54 | 55 | // If this option is set to be -1 (the default value), all the output files 56 | // will follow compression type specified. 57 | // 58 | // If this option is not negative, we will try to make sure compressed 59 | // size is just above this value. In normal cases, at least this percentage 60 | // of data will be compressed. 61 | // When we are compacting to a new file, here is the criteria whether 62 | // it needs to be compressed: assuming here are the list of files sorted 63 | // by generation time: 64 | // A1...An B1...Bm C1...Ct 65 | // where A1 is the newest and Ct is the oldest, and we are going to compact 66 | // B1...Bm, we calculate the total size of all the files as total_size, as 67 | // well as the total size of C1...Ct as total_C, the compaction output file 68 | // will be compressed iff 69 | // total_C / total_size < this percentage 70 | int compression_size_percent; 71 | 72 | // The algorithm used to stop picking files into a single compaction run 73 | // Default: kCompactionStopStyleTotalSize 74 | CompactionStopStyle stop_style; 75 | 76 | // Default set of parameters 77 | CompactionOptionsUniversal() : 78 | size_ratio(1), 79 | min_merge_width(2), 80 | max_merge_width(UINT_MAX), 81 | max_size_amplification_percent(200), 82 | compression_size_percent(-1), 83 | stop_style(kCompactionStopStyleTotalSize) { 84 | } 85 | }; 86 | 87 | } // namespace rocksdb 88 | 89 | #endif // STORAGE_ROCKSDB_UNIVERSAL_COMPACTION_OPTIONS_H 90 | -------------------------------------------------------------------------------- /src/include/rocksdb/write_batch.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, Facebook, Inc. All rights reserved. 2 | // This source code is licensed under the BSD-style license found in the 3 | // LICENSE file in the root directory of this source tree. An additional grant 4 | // of patent rights can be found in the PATENTS file in the same directory. 5 | // Copyright (c) 2011 The LevelDB Authors. All rights reserved. 6 | // Use of this source code is governed by a BSD-style license that can be 7 | // found in the LICENSE file. See the AUTHORS file for names of contributors. 8 | // 9 | // WriteBatch holds a collection of updates to apply atomically to a DB. 10 | // 11 | // The updates are applied in the order in which they are added 12 | // to the WriteBatch. For example, the value of "key" will be "v3" 13 | // after the following batch is written: 14 | // 15 | // batch.Put("key", "v1"); 16 | // batch.Delete("key"); 17 | // batch.Put("key", "v2"); 18 | // batch.Put("key", "v3"); 19 | // 20 | // Multiple threads can invoke const methods on a WriteBatch without 21 | // external synchronization, but if any of the threads may call a 22 | // non-const method, all threads accessing the same WriteBatch must use 23 | // external synchronization. 24 | 25 | #ifndef STORAGE_ROCKSDB_INCLUDE_WRITE_BATCH_H_ 26 | #define STORAGE_ROCKSDB_INCLUDE_WRITE_BATCH_H_ 27 | 28 | #include 29 | #include "rocksdb/status.h" 30 | 31 | namespace rocksdb { 32 | 33 | class Slice; 34 | struct SliceParts; 35 | 36 | class WriteBatch { 37 | public: 38 | WriteBatch(); 39 | ~WriteBatch(); 40 | 41 | // Store the mapping "key->value" in the database. 42 | void Put(const Slice& key, const Slice& value); 43 | 44 | // Variant of Put() that gathers output like writev(2). The key and value 45 | // that will be written to the database are concatentations of arrays of 46 | // slices. 47 | void Put(const SliceParts& key, const SliceParts& value); 48 | 49 | // Merge "value" with the existing value of "key" in the database. 50 | // "key->merge(existing, value)" 51 | void Merge(const Slice& key, const Slice& value); 52 | 53 | // If the database contains a mapping for "key", erase it. Else do nothing. 54 | void Delete(const Slice& key); 55 | 56 | // Append a blob of arbitrary size to the records in this batch. The blob will 57 | // be stored in the transaction log but not in any other file. In particular, 58 | // it will not be persisted to the SST files. When iterating over this 59 | // WriteBatch, WriteBatch::Handler::LogData will be called with the contents 60 | // of the blob as it is encountered. Blobs, puts, deletes, and merges will be 61 | // encountered in the same order in thich they were inserted. The blob will 62 | // NOT consume sequence number(s) and will NOT increase the count of the batch 63 | // 64 | // Example application: add timestamps to the transaction log for use in 65 | // replication. 66 | void PutLogData(const Slice& blob); 67 | 68 | // Clear all updates buffered in this batch. 69 | void Clear(); 70 | 71 | // Support for iterating over the contents of a batch. 72 | class Handler { 73 | public: 74 | virtual ~Handler(); 75 | virtual void Put(const Slice& key, const Slice& value) = 0; 76 | // Merge and LogData are not pure virtual. Otherwise, we would break 77 | // existing clients of Handler on a source code level. The default 78 | // implementation of Merge simply throws a runtime exception. 79 | virtual void Merge(const Slice& key, const Slice& value); 80 | // The default implementation of LogData does nothing. 81 | virtual void LogData(const Slice& blob); 82 | virtual void Delete(const Slice& key) = 0; 83 | // Continue is called by WriteBatch::Iterate. If it returns false, 84 | // iteration is halted. Otherwise, it continues iterating. The default 85 | // implementation always returns true. 86 | virtual bool Continue(); 87 | }; 88 | Status Iterate(Handler* handler) const; 89 | 90 | // Retrieve the serialized version of this batch. 91 | std::string Data() { return rep_; } 92 | 93 | // Returns the number of updates in the batch 94 | int Count() const; 95 | 96 | // Constructor with a serialized string object 97 | explicit WriteBatch(std::string rep): rep_(rep) {} 98 | 99 | private: 100 | friend class WriteBatchInternal; 101 | 102 | std::string rep_; // See comment in write_batch.cc for the format of rep_ 103 | 104 | // Intentionally copyable 105 | }; 106 | 107 | } // namespace rocksdb 108 | 109 | #endif // STORAGE_ROCKSDB_INCLUDE_WRITE_BATCH_H_ 110 | -------------------------------------------------------------------------------- /src/include/utilities/stackable_db.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 | #pragma once 6 | #include "rocksdb/db.h" 7 | 8 | namespace rocksdb { 9 | 10 | // This class contains APIs to stack rocksdb wrappers.Eg. Stack TTL over base d 11 | class StackableDB : public DB { 12 | public: 13 | explicit StackableDB(StackableDB* sdb) : sdb_(sdb) {} 14 | 15 | // Returns the DB object that is the lowermost component in the stack of DBs 16 | virtual DB* GetRawDB() { 17 | return sdb_->GetRawDB(); 18 | } 19 | 20 | // convert a DB to StackableDB 21 | // TODO: This function does not work yet. Passing nullptr to StackableDB in 22 | // NewStackableDB's constructor will cause segfault on object's usage 23 | static StackableDB* DBToStackableDB(DB* db) { 24 | class NewStackableDB : public StackableDB { 25 | public: 26 | NewStackableDB(DB* db) 27 | : StackableDB(nullptr), 28 | db_(db) {} 29 | 30 | DB* GetRawDB() { 31 | return db_; 32 | } 33 | 34 | private: 35 | DB* db_; 36 | }; 37 | return new NewStackableDB(db); 38 | } 39 | 40 | virtual Status Put(const WriteOptions& options, 41 | const Slice& key, 42 | const Slice& val) override { 43 | return sdb_->Put(options, key, val); 44 | } 45 | 46 | virtual Status Get(const ReadOptions& options, 47 | const Slice& key, 48 | std::string* value) override { 49 | return sdb_->Get(options, key, value); 50 | } 51 | 52 | virtual std::vector MultiGet(const ReadOptions& options, 53 | const std::vector& keys, 54 | std::vector* values) 55 | override { 56 | return sdb_->MultiGet(options, keys, values); 57 | } 58 | 59 | virtual bool KeyMayExist(const ReadOptions& options, 60 | const Slice& key, 61 | std::string* value, 62 | bool* value_found = nullptr) override { 63 | return sdb_->KeyMayExist(options, key, value, value_found); 64 | } 65 | 66 | virtual Status Delete(const WriteOptions& wopts, const Slice& key) override { 67 | return sdb_->Delete(wopts, key); 68 | } 69 | 70 | virtual Status Merge(const WriteOptions& options, 71 | const Slice& key, 72 | const Slice& value) override { 73 | return sdb_->Merge(options, key, value); 74 | } 75 | 76 | 77 | virtual Status Write(const WriteOptions& opts, WriteBatch* updates) 78 | override { 79 | return sdb_->Write(opts, updates); 80 | } 81 | 82 | virtual Iterator* NewIterator(const ReadOptions& opts) override { 83 | return sdb_->NewIterator(opts); 84 | } 85 | 86 | virtual const Snapshot* GetSnapshot() override { 87 | return sdb_->GetSnapshot(); 88 | } 89 | 90 | virtual void ReleaseSnapshot(const Snapshot* snapshot) override { 91 | return sdb_->ReleaseSnapshot(snapshot); 92 | } 93 | 94 | virtual bool GetProperty(const Slice& property, std::string* value) 95 | override { 96 | return sdb_->GetProperty(property, value); 97 | } 98 | 99 | virtual void GetApproximateSizes(const Range* r, int n, uint64_t* sizes) 100 | override { 101 | return sdb_->GetApproximateSizes(r, n, sizes); 102 | } 103 | 104 | virtual void CompactRange(const Slice* begin, const Slice* end, 105 | bool reduce_level = false, 106 | int target_level = -1) override { 107 | return sdb_->CompactRange(begin, end, reduce_level, target_level); 108 | } 109 | 110 | virtual int NumberLevels() override { 111 | return sdb_->NumberLevels(); 112 | } 113 | 114 | virtual int MaxMemCompactionLevel() override { 115 | return sdb_->MaxMemCompactionLevel(); 116 | } 117 | 118 | virtual int Level0StopWriteTrigger() override { 119 | return sdb_->Level0StopWriteTrigger(); 120 | } 121 | 122 | virtual Status Flush(const FlushOptions& fopts) override { 123 | return sdb_->Flush(fopts); 124 | } 125 | 126 | virtual Status DisableFileDeletions() override { 127 | return sdb_->DisableFileDeletions(); 128 | } 129 | 130 | virtual Status EnableFileDeletions() override { 131 | return sdb_->EnableFileDeletions(); 132 | } 133 | 134 | virtual Status GetLiveFiles(std::vector& vec, uint64_t* mfs, 135 | bool flush_memtable = true) override { 136 | return sdb_->GetLiveFiles(vec, mfs, flush_memtable); 137 | } 138 | 139 | virtual SequenceNumber GetLatestSequenceNumber() const override { 140 | return sdb_->GetLatestSequenceNumber(); 141 | } 142 | 143 | virtual Status GetSortedWalFiles(VectorLogPtr& files) override { 144 | return sdb_->GetSortedWalFiles(files); 145 | } 146 | 147 | virtual Status DeleteFile(std::string name) override { 148 | return sdb_->DeleteFile(name); 149 | } 150 | 151 | virtual Status GetUpdatesSince(SequenceNumber seq_number, 152 | unique_ptr* iter) 153 | override { 154 | return sdb_->GetUpdatesSince(seq_number, iter); 155 | } 156 | 157 | protected: 158 | StackableDB* sdb_; 159 | }; 160 | 161 | } // namespace rocksdb 162 | -------------------------------------------------------------------------------- /src/include/utilities/utility_db.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 | #pragma once 6 | #include "stackable_db.h" 7 | 8 | namespace rocksdb { 9 | 10 | // This class contains APIs to open rocksdb with specific support eg. TTL 11 | class UtilityDB { 12 | 13 | public: 14 | // Open the database with TTL support. 15 | // 16 | // USE-CASES: 17 | // This API should be used to open the db when key-values inserted are 18 | // meant to be removed from the db in a non-strict 'ttl' amount of time 19 | // Therefore, this guarantees that key-values inserted will remain in the 20 | // db for >= ttl amount of time and the db will make efforts to remove the 21 | // key-values as soon as possible after ttl seconds of their insertion. 22 | // 23 | // BEHAVIOUR: 24 | // TTL is accepted in seconds 25 | // (int32_t)Timestamp(creation) is suffixed to values in Put internally 26 | // Expired TTL values deleted in compaction only:(Timestamp+ttl=5 31 | // read_only=true opens in the usual read-only mode. Compactions will not be 32 | // triggered(neither manual nor automatic), so no expired entries removed 33 | // 34 | // CONSTRAINTS: 35 | // Not specifying/passing or non-positive TTL behaves like TTL = infinity 36 | // 37 | // !!!WARNING!!!: 38 | // Calling DB::Open directly to re-open a db created by this API will get 39 | // corrupt values(timestamp suffixed) and no ttl effect will be there 40 | // during the second Open, so use this API consistently to open the db 41 | // Be careful when passing ttl with a small positive value because the 42 | // whole database may be deleted in a small amount of time 43 | static Status OpenTtlDB(const Options& options, 44 | const std::string& name, 45 | StackableDB** dbptr, 46 | int32_t ttl = 0, 47 | bool read_only = false); 48 | }; 49 | 50 | } // namespace rocksdb 51 | -------------------------------------------------------------------------------- /src/includes.h: -------------------------------------------------------------------------------- 1 | #ifndef ROCKSDB_INCLUDES_H_ 2 | #define ROCKSDB_INCLUDES_H_ 3 | 4 | #include 5 | #include 6 | 7 | #endif /* ROCKSDB_INCLUDES_H_ */ 8 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "includes.h" 2 | #include "database.h" 3 | 4 | extern "C" 5 | { 6 | PHPCPP_EXPORT void* get_module() 7 | { 8 | static Php::Extension rocksdb_extension("RocksDB PHP Extension", "1.0"); 9 | 10 | rocksdb_extension.add("RocksDB", Php::Class( 11 | { 12 | Php::Public("__construct", Php::Method(&RocksDB::Database::__construct)), 13 | Php::Public("Open", Php::Method(&RocksDB::Database::Open)), 14 | Php::Public("GetLastError", Php::Method(&RocksDB::Database::GetLastError)), 15 | Php::Public("IsOpen", Php::Method(&RocksDB::Database::IsOpen)), 16 | Php::Public("GetDbPath", Php::Method(&RocksDB::Database::GetDbPath)), 17 | Php::Public("Get", Php::Method(&RocksDB::Database::Get)), 18 | Php::Public("Put", Php::Method(&RocksDB::Database::Put)), 19 | Php::Public("Close", Php::Method(&RocksDB::Database::Close)) 20 | })); 21 | 22 | return rocksdb_extension.module(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | php test/test.php 4 | -------------------------------------------------------------------------------- /test/test.php: -------------------------------------------------------------------------------- 1 | #!/usr/bin/php -q 2 | 3 | Open(true)) 7 | echo "Open DB: ok\n"; 8 | else 9 | die("Open DB: failed -> " . $rockdb->GetLastError() . "\n"); 10 | 11 | // Get the database path and verify that we opened the database successfully 12 | echo "DB Path: " . $rockdb->GetDbPath() . "\n"; 13 | echo "Is Open: " . $rockdb->IsOpen() . "\n"; 14 | 15 | // Store the value 'my_awesome_value' under the 'my_awesome_key' 16 | $result = $rockdb->Put('my_awesome_key', 'my_awesome_value'); 17 | if($result) 18 | echo "Put: my_awesome_key -> my_awesome_value\n"; 19 | else 20 | die("Put: failed -> " . $rockdb->GetLastError() . "\n"); 21 | 22 | // Get the value for 'my_awesome_key' 23 | $value = $rockdb->Get('my_awesome_key'); 24 | if(!$value) 25 | echo "Get: failed -> " . $rockdb->GetLastError() . "\n"; 26 | else 27 | die("Get: my_awesome_key -> " . $value . "\n"); 28 | 29 | die("Close: " . $rockdb->Close() . "\n"); 30 | ?> 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /test_valgrind.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export USE_ZEND_ALLOC=0 4 | export ZEND_DONT_UNLOAD_MODULES=1 5 | valgrind --tool=memcheck --leak-check=full --num-callers=30 php test/test.php 6 | 7 | --------------------------------------------------------------------------------