Skip to content

Commit

Permalink
Merge pull request #2 from citrusleaf/Phase-I
Browse files Browse the repository at this point in the history
More KV methods, persistent connections, shm, unit tests, Slim-based test app
  • Loading branch information
rbotzer committed May 27, 2015
2 parents 1288573 + 18b1631 commit 5be1d8e
Show file tree
Hide file tree
Showing 358 changed files with 7,539 additions and 765 deletions.
55 changes: 34 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,50 @@
# Aerospike HHVM Client
This is a prototype of [HHVM Native Interface](https://github.com/facebook/hhvm/wiki/Extension-API) for Aerospike Client.


Currently tested on Ubuntu 14.04 LTS 64 bit

## Install HHVM
wget -O - http://dl.hhvm.com/conf/hhvm.gpg.key | \
sudo apt-key add -
echo deb http://dl.hhvm.com/ubuntu trusty main | \
sudo tee /etc/apt/sources.list.d/hhvm.list
sudo apt-get update
sudo apt-get install hhvm-dev
The HHVM manual provides [installation](http://docs.hhvm.com/manual/en/install-intro.install.php)
and [prebuilt packages](https://github.com/facebook/hhvm/wiki/Prebuilt-Packages-for-HHVM).

## Install Aerospike C client
Follow the [installation steps](http://www.aerospike.com/download/client/c/3.1.11/) for installing the underlying C client or you may choose to build it from [source](https://github.com/aerospike/aerospike-client-c).
Get the [latest Aerospike C Client](http://www.aerospike.com/download/client/c/latest/)
library, and install the development package contained in the tar archive.
Alternatively, you can build the C client [from source](https://github.com/aerospike/aerospike-client-c).

## Build and install Aerospike HHVM client
Edit config.cmake file in the source and modify the following line:
For example, on Ubuntu, you would download the tarball, extract it, then:

set(LIBAEROSPIKE, /usr/local)
sudo dpkg -i aerospike-client-c-devel-3.1.16.ubuntu12.04.x86_64.deb

Replace '/usr/local' with the correct C client installation path (i.e. path to lib/libaerospike.so and include/aerospike)
## Build and install Aerospike HHVM client

cd src/aerospike
hphpize
cmake . && make;
cmake . && make
sudo make install

## Test
Edit tests/aerospike.php and modify the following lines:
The `make install` step should state the path where the extension is installed.
You will use that path in the next step ([Configure](#configure)).

vagrant@ubuntu-14:/vagrant/aerospike-client-hhvm/src/aerospike$ sudo make install
[100%] Built target aerospike-hhvm
Install the project...
-- Install configuration: "Debug"
-- Installing: /usr/lib/x86_64-linux-gnu/hhvm/extensions/20150212/aerospike-hhvm.so

$SERVER_IP = "localhost"
$SERVER_PORT = 3000;

Replace "localhost" and 3000 with the IP address and port of your Aerospike
server.
If during the build you see an error that complains about the location of Aerospike
header files (for example, `fatal error: aerospike/aerospike_key.h: No such
file or directory`) you will need to edit the `config.cmake` file.

hhvm -d extension_dir=. -d hhvm.extensions[]=aerospike-hhvm.so tests/aerospike.php
* Edit the target\_link\_libraries to the path containing the C client
(`libaerospike.so`).
* Edit include\_directories to the directory which contains the C client's
header files.

## Configure
Add the extension to HHVM by editing /etc/hhvm/php.ini as follows:

hhvm.extensions[] = /path/to/aerospike-hhvm.so

## Test
Run the unit tests as described in [tests/README](tests/README.md)
9 changes: 0 additions & 9 deletions config.cmake

This file was deleted.

48 changes: 48 additions & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@

# Overview

The Aerospike <a href="http://www.aerospike.com/docs/architecture/clients.html"
target="_doc">PHP client</a> enables your PHP application to work with an
<a href="http://www.aerospike.com/docs/architecture/distribution.html"
target="_doc">Aerospike cluster</a> as its
<a href="http://www.aerospike.com/docs/guide/kvs.html" target="_doc">key-value store</a>.

The <a href="http://www.aerospike.com/docs/architecture/data-model.html" target="_doc">Data Model</a>
document gives further details on how data is organized in the cluster.

## Client API
The Aerospike PHP client API is described in the following sections:

### [Runtime Configuration](aerospike_config.md)
### [Aerospike Class](aerospike.md)
### [Lifecycle and Connection Methods](apiref_connection.md)
### [Error Handling Methods](apiref_error.md)
### [Key-Value Methods](apiref_kv.md)

## Implementation Status
So far the *Runtime Configuration*, *Lifecycle and Connection Methods*, *Error*
*Handling and Logging Methods*, and *Key-Value Methods* have been implemented.

We expect the specification of the PHP client to closely describe our next
release, including the unimplemented methods. However, it is possible that
some changes to the client spec will occur.

## Persistent Connections

Initializing the C-client to connect to a specified cluster is a costly
operation, so ideally the C-client should be reused for the multiple requests
made against the same PHP process (as is the case for mod_php and fastCGI).

The PHP developer can determine whether the Aerospike class constructor will
use persistent connections or not by way of an optional boolean argument.
After the first time Aerospike::__construct() is called within the process, the
extension will attempt to reuse the persistent connection.

When persistent connections are used the methods _reconnect()_ and _close()_ do
not actually close the connection. Those methods only apply to instances of
class Aerospike which use non-persistent connections.

## Further Reading

- [How does the Aerospike client find a node](https://discuss.aerospike.com/t/how-does-aerospike-client-find-a-node/706)
- [How would hash collisions be handled](https://discuss.aerospike.com/t/what-will-aerospike-do-if-hash-collision-for-a-key/779)
241 changes: 241 additions & 0 deletions doc/aerospike.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@

# The Aerospike class
The Aerospike PHP client API may be described as follows:

## Introduction

The main Aerospike class

```php

class Aerospike
{
// The key policy can be determined by setting OPT_POLICY_KEY to one of
const POLICY_KEY_DIGEST; // hashes (ns,set,key) data into a unique record ID (default)
const POLICY_KEY_SEND; // also send, store, and get the actual (ns,set,key) with each record

// The generation policy can be set using OPT_POLICY_GEN to one of
const POLICY_GEN_IGNORE; // write a record, regardless of generation
const POLICY_GEN_EQ; // write a record, ONLY if given value is equal to the current record generation
const POLICY_GEN_GT; // write a record, ONLY if given value is greater-than the current record generation

// The retry policy can be determined by setting OPT_POLICY_RETRY to one of
const POLICY_RETRY_NONE; // do not retry an operation (default)
const POLICY_RETRY_ONCE; // allow for a single retry on an operation

// By default writes will try to create or replace records and bins
// behaving similar to an array in PHP. Setting
// OPT_POLICY_EXISTS with one of these values will overwrite this.
// POLICY_EXISTS_IGNORE (aka CREATE_OR_UPDATE) is the default value
const POLICY_EXISTS_IGNORE; // interleave bins of a record if it exists
const POLICY_EXISTS_CREATE; // create a record ONLY if it DOES NOT exist
const POLICY_EXISTS_UPDATE; // update a record ONLY if it exists
const POLICY_EXISTS_REPLACE; // replace a record ONLY if it exists
const POLICY_EXISTS_CREATE_OR_REPLACE; // overwrite the bins if record exists

// Replica and consistency guarantee options
// See: http://www.aerospike.com/docs/client/c/usage/consistency.html
const POLICY_REPLICA_MASTER; // read from the partition master replica node (default)
const POLICY_REPLICA_ANY; // read from either the master or prole node
const POLICY_CONSISTENCY_ONE; // involve a single replica in the read operation (default)
const POLICY_CONSISTENCY_ALL; // involve all replicas in the read operation
const POLICY_COMMIT_LEVEL_ALL; // return success after committing all replicas (default)
const POLICY_COMMIT_LEVEL_MASTER; // return success after committing the master replica

// Determines a handler for writing values of unsupported type into bins
// Set OPT_SERIALIZER to one of the following:
const SERIALIZER_NONE;
const SERIALIZER_PHP; // default handler
const SERIALIZER_JSON;
const SERIALIZER_USER;

// OPT_SCAN_PRIORITY can be set to one of the following:
const SCAN_PRIORITY_AUTO; //The cluster will auto adjust the scan priority
const SCAN_PRIORITY_LOW; //Low priority scan.
const SCAN_PRIORITY_MEDIUM; //Medium priority scan.
const SCAN_PRIORITY_HIGH; //High priority scan.

// Options can be assigned values that modify default behavior
const OPT_CONNECT_TIMEOUT; // value in milliseconds, default: 1000
const OPT_READ_TIMEOUT; // value in milliseconds, default: 1000
const OPT_WRITE_TIMEOUT; // value in milliseconds, default: 1000
const OPT_POLICY_RETRY; // set to a Aerospike::POLICY_RETRY_* value
const OPT_POLICY_EXISTS; // set to a Aerospike::POLICY_EXISTS_* value
const OPT_SERIALIZER; // set the unsupported type handler
const OPT_SCAN_PRIORITY; // set to a Aerospike::SCAN_PRIORITY_* value
const OPT_SCAN_PERCENTAGE; // integer value 1-100, default: 100
const OPT_SCAN_CONCURRENTLY; // boolean value, default: false
const OPT_SCAN_NOBINS; // boolean value, default: false
const OPT_POLICY_KEY; // records store the digest unique ID, optionally also its (ns,set,key) inputs
const OPT_POLICY_GEN; // set to array( Aerospike::POLICY_GEN_* [, $gen_value ] )
const OPT_POLICY_REPLICA; // set to one of Aerospike::POLICY_REPLICA_*
const OPT_POLICY_CONSISTENCY; // set to one of Aerospike::POLICY_CONSISTENCY_*
const OPT_POLICY_COMMIT_LEVEL;// set to one of Aerospike::POLICY_COMMIT_LEVEL_*

// Aerospike Status Codes:
//
// Each Aerospike API method invocation returns a status code
// depending upon the success or failure condition of the call.
//
// The error status codes map to the C client
// src/include/aerospike/as_status.h

// Client status codes:
//
const ERR_PARAM ; // Invalid client parameter
const ERR_CLIENT ; // Generic client error

// Server status codes:
//
const OK ; // Success status
const ERR_SERVER ; // Generic server error
const ERR_SERVER_FULL ; // Node running out of memory/storage
const ERR_DEVICE_OVERLOAD ; // Node storage lagging write load
const ERR_TIMEOUT ; // Client or server side timeout error
const ERR_CLUSTER ; // Generic cluster discovery and connection error
const ERR_CLUSTER_CHANGE ; // Cluster state changed during the request
const ERR_REQUEST_INVALID ; // Invalid request protocol or protocol field
const ERR_UNSUPPORTED_FEATURE;
const ERR_NO_XDR ; // XDR not available for the cluster
// Record specific:
const ERR_NAMESPACE_NOT_FOUND;
const ERR_RECORD_NOT_FOUND ;
const ERR_RECORD_EXISTS ; // Record already exists
const ERR_RECORD_GENERATION ; // Write policy regarding generation violated
const ERR_RECORD_TOO_BIG ; // Record written cannot fit in storage write block
const ERR_RECORD_BUSY ; // Hot key: too many concurrent requests for the record
const ERR_RECORD_KEY_MISMATCH; // Digest incompatibility?
// Bin specific:
const ERR_BIN_NAME ; // Name too long or exceeds the unique name quota for the namespace
const ERR_BIN_NOT_FOUND ;
const ERR_BIN_EXISTS ; // Bin already exists
const ERR_BIN_INCOMPATIBLE_TYPE;
// Query and Scan operations:
const ERR_SCAN_ABORTED ; // Scan aborted by the user
const ERR_QUERY ; // Generic query error
const ERR_QUERY_END ; // Out of records to query
const ERR_QUERY_ABORTED ; // Query aborted by the user
const ERR_QUERY_QUEUE_FULL ;
// Index operations:
const ERR_INDEX ; // Generic secondary index error
const ERR_INDEX_OOM ; // Index out of memory
const ERR_INDEX_NOT_FOUND ;
const ERR_INDEX_FOUND ;
const ERR_INDEX_NOT_READABLE ;
const ERR_INDEX_NAME_MAXLEN ;
const ERR_INDEX_MAXCOUNT ; // Max number of indexes reached
// UDF operations:
const ERR_UDF ; // Generic UDF error
const ERR_UDF_NOT_FOUND ; // UDF does not exist
const ERR_LUA_FILE_NOT_FOUND ; // Source file for the module not found

// Status values returned by scanInfo()
const SCAN_STATUS_UNDEF; // Scan status is undefined.
const SCAN_STATUS_INPROGRESS; // Scan is currently running.
const SCAN_STATUS_ABORTED; // Scan was aborted due to failure or the user.
const SCAN_STATUS_COMPLETED; // Scan completed successfully.

// Logger
const LOG_LEVEL_OFF ;
const LOG_LEVEL_ERROR;
const LOG_LEVEL_WARN ;
const LOG_LEVEL_INFO ;
const LOG_LEVEL_DEBUG;
const LOG_LEVEL_TRACE;

// Query Predicate Operators
const string OP_EQ = '=';
const string OP_BETWEEN = 'BETWEEN';

// Multi-operation operators map to the C client
// src/include/aerospike/as_operations.h
const OPERATOR_WRITE;
const OPERATOR_READ;
const OPERATOR_INCR;
const OPERATOR_PREPEND;
const OPERATOR_APPEND;
const OPERATOR_TOUCH;

// UDF types
const UDF_TYPE_LUA;

// bin types
const INDEX_TYPE_STRING;
const INDEX_TYPE_INTEGER;


// lifecycle and connection methods
public __construct ( array $config [, boolean $persistent_connection = true [, array $options]] )
public __destruct ( void )
public boolean isConnected ( void )
public close ( void )
public reconnect ( void )

// error handling methods
public string error ( void )
public int errorno ( void )
// TBD
public setLogLevel ( int $log_level )
public setLogHandler ( callback $log_handler )

// key-value methods
public array initKey ( string $ns, string $set, int|string $pk [, boolean $is_digest = false ] )
public string getKeyDigest ( string $ns, string $set, int|string $pk )
public int put ( array $key, array $bins [, int $ttl = 0 [, array $options ]] )
public int get ( array $key, array &$record [, array $filter [, array $options ]] )
public int exists ( array $key, array &$metadata [, array $options ] )
public int touch ( array $key, int $ttl = 0 [, array $options ] )
public int remove ( array $key [, array $options ] )
public int removeBin ( array $key, array $bins [, array $options ] )
public int increment ( array $key, string $bin, int $offset [, array $options ] )
public int append ( array $key, string $bin, string $value [, array $options ] )
public int prepend ( array $key, string $bin, string $value [, array $options ] )
public int operate ( array $key, array $operations [, array &$returned ] )

// unsupported type handler methods
// TBD
public static setSerializer ( callback $serialize_cb )
public static setDeserializer ( callback $unserialize_cb )

// batch operation methods
public int getMany ( array $keys, array &$records [, array $filter [, array $options]] )
public int existsMany ( array $keys, array &$metadata [, array $options ] )

// UDF methods
// TBD
public int register ( string $path, string $module [, int $language = Aerospike::UDF_TYPE_LUA] )
public int deregister ( string $module )
public int listRegistered ( array &$modules [, int $language ] )
public int getRegistered ( string $module, string &$code )
public int apply ( array $key, string $module, string $function[, array $args [, mixed &$returned [, array $options ]]] )
public int aggregate ( string $ns, string $set, array $where, string $module, string $function, array $args, mixed &$returned [, array $options ] )
public int scanApply ( string $ns, string $set, string $module, string $function, array $args, int &$scan_id [, array $options ] )
public int scanInfo ( integer $scan_id, array &$info [, array $options ] )

// query and scan methods
// TBD
public int query ( string $ns, string $set, array $where, callback $record_cb [, array $select [, array $options ]] )
public int scan ( string $ns, string $set, callback $record_cb [, array $select [, array $options ]] )
public array predicateEquals ( string $bin, int|string $val )
public array predicateBetween ( string $bin, int $min, int $max )

// admin methods
// TBD
public int createIndex ( string $ns, string $set, string $bin, int $type, string $name [, array $options ] )
public int dropIndex ( string $ns, string $name [, array $options ] )

// info methods
// TBD
public int info ( string $request, string &$response [, array $host [, array options ] ] )
public array infoMany ( string $request [, array $config [, array options ]] )
public array getNodes ( void )
}
```

### [Runtime Configuration](aerospike_config.md)
### [Lifecycle and Connection Methods](apiref_connection.md)
### [Error Handling and Logging Methods](apiref_error.md)
### [Key-Value Methods](apiref_kv.md)

An overview of the development of the client is at the top level
[README](README.md).
Loading

0 comments on commit 5be1d8e

Please sign in to comment.