ID | IEP-9 |
Author | Pavel Tupitsyn |
Sponsor | Pavel Tupitsyn |
Created | 20-NOV-2017 |
Status | COMPLETED |
This page includes low-level protocol documentation that might be outdated and is not maintained. Refer to the official protocol documentation here: https://apacheignite.readme.io/docs/binary-client-protocol
Implement thin Ignite client in any programming language / platform using a well-defined binary connectiona protocol.
"Thin" here means that we do not start an Ignite node in order to communicate with the cluster, we do not implement discovery/communication spi logic, as opposed to currently available Ignite Client Mode.
Every Ignite node listens on a TCP port. Thin client implementations connect to any node in the cluster through TCP socket and perform Ignite operations using a well-defined binary protocol.
Server-side connection parameters are defined in ClientConnectorConfiguration
class. Default port is 10800. Connector is enabled by default, no configuration changes needed.
Byte order is little-endian. Strings are UTF-8 with int prefix (no null terminator). All data types in this proposal are Java-like (byte = 8 bits, short = 2 bytes, int = 4 bytes, long = 8 bytes).
User data, such as cache keys and values, is represented in Ignite Binary Object format. Binary Object can be a primitive (predefined type) or a complex object.
Primitives (predefined types)
Primitives are represented as a type code + value:
byte | Type code |
... | Value |
Available primitives are listed below:
Name | Type Code | Size (bytes) |
---|---|---|
byte | 1 | 1 |
short | 2 | 2 |
int | 3 | 4 |
long | 4 | 8 |
float | 5 | 4 |
double | 6 | 8 |
char | 7 | 2 |
bool | 8 | 1 |
string | 9 | 4 bytes Utf8 byte count + Utf8 bytes |
UUID (Guid) | 10 | 16 |
date | 11 | 8 (milliseconds from 1 Jan 1970) |
byte array | 12 | 4 bytes length + length |
short array | 13 | 4 bytes length + length * 2 |
int array | 14 | 4 bytes length + length * 4 |
long array | 15 | 4 bytes length + length * 8 |
float array | 16 | 4 bytes length + length * 4 |
double array | 17 | 4 bytes length + length * 8 |
char array | 18 | 4 bytes length + length * 2 |
bool array | 19 | 4 bytes length + length |
string array | 20 | 4 bytes length + variable length strings, see above. Nulls (byte 101) are allowed. |
UUID (Guid) array | 21 | 4 bytes length + length * 16. Nulls (byte 101) are allowed. |
date array | 22 | 4 bytes length + length * 8. Nulls (byte 101) are allowed. |
object array | 23 | 4 bytes length + 4 bytes element type id + variable size binary objects |
map | 25 | 4 bytes length + byte type (1 = HASH_MAP, 2 = LINKED_HASH_MAP) + length * (BinaryObject + BinaryObject) |
NULL | 101 | 0 |
Complex Objects
Complex objects consist of a 24-byte header, set of fields (binary objects), and a schema (field ids and positions).
Header | |
---|---|
byte | Object type code, always 103 |
byte | Version, always 1 |
short | Flags, USER_TYPE = 1, HAS_SCHEMA = 2 |
int | Type id, Java-style hash code of the type name |
int | Hash code, Java-style hash of contents without header, necessary for comparisons |
int | Length, including header |
int | Schema Id |
int | Schema offset from the header start, position where fields end |
BinaryObject * n | Fields |
(int + int) * n | Schema, fieldId (Java-style hash of field name) + offset (from header start) |
Wrapped Binary Objects
One ore more binary objects can be wrapped in an array. This allows reading, storing, passing and writing objects efficiently without understanding their contents, performing simple byte copy.
All cache operations return complex objects inside a wrapper (but not primitives).
byte | Type code, always 27 |
int | Byte array size |
n bytes | Payload |
int | Offset of the object within array (array can contain an object graph, this offset points to the root object) |
All messages, request and response, including handshake, start with int
message length (excluding these first 4 bytes). E.g. empty message would be represented by 4 zero bytes.
int | Length of Payload |
... | Payload |
Length is omitted in all message descriptions below for brevity.
The first message upon connection establishment must be a handshake. Handshake ensures that client and server versions are compatible.
Request | |
byte | Handshake code, always 1 |
short | Version major |
short | Version minor |
short | Version patch |
byte | Client code, always 2 |
Response (success) | |
byte | Success flag, 1 |
Response (failure) | |
byte | Success flag, 0 |
short | Server version major |
short | Server version minor |
short | Server version patch |
string | Error message |
Upon successful handshake client can start performing operations by sending a request with specific op code. Each operation has it's own request and response format, with a common header.
Request | |
short | Operation code |
long | Request id, generated by client and returned as-is in response |
... | Operation-specific data |
Response | |
long | Request id (see above) |
int | Status code (0 for success, otherwise error code) |
string | Error message (present only when status is not 0) |
... | Operation-specific data |
Operation codes and request ids are omitted everywhere below for brevity.
OP_CACHE_GET = 1000
Retrieves a value from cache by key.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
Response | |
BinaryObject | value |
Cache flags
GET and all other cache operations include flags byte.
1 | KEEP_BINARY | Indicates wether IgniteCache.withKeepBinary should be called on the server side. This flag has effect only for OP_QUERY_SCAN when Java filter is used. Other operations ignore the flag and call withKeepBinary anyway. |
OP_CACHE_GET_ALL = 1003
Retrieves multiple values from cache given multiple keys.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
int | key count |
BinaryObject * count | keys |
Response | |
int | result count |
(BinaryObject + BinaryObject) * count | Resulting key-value pairs. Keys that are not present in the cache are not included. |
OP_CACHE_PUT = 1001
Puts a value with a given key to cache (overwriting existing value if any).
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
BinaryObject | value |
Empy response.
OP_CACHE_PUT_ALL = 1004
Puts multiple key-value pairs to cache (overwriting existing associations if any).
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
int | Key-value pair count |
(BinaryObject + BinaryObject) * count | Key-value pairs |
Empy response.
OP_CACHE_CONTAINS_KEY = 1011
Returns a value indicating whether given key is present in cache.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
Response | |
bool | True when key is present, false otherwise |
OP_CACHE_CONTAINS_KEYS = 1012
Returns a value indicating whether all given keys are present in cache.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
int | key count |
BinaryObject * count | keys |
Response | |
bool | True when keys are present, false otherwise |
OP_CACHE_GET_AND_PUT = 1005
Puts a value with a given key to cache, returning previous value for that key.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
BinaryObject | value |
Response | |
BinaryObject | Existing value for the specified key, or null |
OP_CACHE_GET_AND_REPLACE = 1006
Puts a value with a given key to cache, returning previous value for that key, if and only if there is a value currently mapped for that key.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
BinaryObject | value |
Response | |
BinaryObject | Existing value for the specified key |
OP_CACHE_GET_AND_REMOVE = 1007
Removes the cache entry with specified key, returning the value.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
Response | |
BinaryObject | Existing value for the specified key, or null |
OP_CACHE_PUT_IF_ABSENT = 1002
Puts a value with a given key to cache only if the key does not already exist.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
BinaryObject | value |
Response | |
bool | success flag |
OP_CACHE_GET_AND_PUT_IF_ABSENT = 1008
Puts a value with a given key to cache only if the key does not already exist.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
BinaryObject | value |
Response | |
BinaryObject | Previously contained value regardless of whether put happened or not. |
OP_CACHE_REPLACE = 1009
Puts a value with a given key to cache only if the key already exists.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
BinaryObject | value |
Response | |
bool | value indicating whether replace happened |
OP_CACHE_REPLACE_IF_EQUALS = 1010
Puts a value with a given key to cache only if the key already exists and value equals provided value.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
BinaryObject | value |
BinaryObject | new value |
Response | |
bool | value indicating whether replace happened |
OP_CACHE_CLEAR = 1013
Clears the cache without notifying listeners or cache writers.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
Empy response.
OP_CACHE_CLEAR_KEY = 1014
Clears the cache key without notifying listeners or cache writers.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
Empy response.
OP_CACHE_CLEAR_KEYS = 1015
Clears the cache keys without notifying listeners or cache writers.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
int | Key count |
BinaryObject * count | keys |
Empy response.
OP_CACHE_REMOVE_KEY = 1016
Removes an entry with a given key, notifying listeners and cache writers.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
Response | |
bool | value indicating whether remove happened |
OP_CACHE_REMOVE_IF_EQUALS = 1017
Removes an entry with a given key if provided value is equal to actual value, notifying listeners and cache writers.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
BinaryObject | key |
BinaryObject | value |
Response | |
bool | value indicating whether remove happened |
OP_CACHE_GET_SIZE = 1020
Gets the cache size.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
int | Peek mode count. Can be 0, which means ALL. |
byte * count | Peek modes. ALL = 0, NEAR = 1, PRIMARY = 2, BACKUP = 3 |
Response | |
long | Cache size |
OP_CACHE_REMOVE_KEYS = 1018
Removes entries with given keys, notifying listeners and cache writers.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
int | key count |
BinaryObject * count | keys |
Empty response.
OP_CACHE_REMOVE_ALL = 1019
Removes all entries from cache, notifying listeners and cache writers.
Request | |
int | Cache ID: Java-style hash code of the cache name |
byte | flags |
Empty response.
OP_CACHE_CREATE_WITH_NAME = 1051
Creates a cache with a given name. Cache template can be applied if there is '*' in the cache name. Throws exception if a cache with specified name already exists.
Request | |
string | Cache name |
Empty response.
OP_CACHE_GET_OR_CREATE_WITH_NAME = 1052
Creates a cache with a given name. Cache template can be applied if there is '*' in the cache name. Does nothing if the cache exists.
Request | |
string | Cache name |
Empty response.
OP_CACHE_DESTROY = 1056
Destroys cache with a given name.
Request | |
int | Cache ID |
Empty response.
OP_CACHE_GET_NAMES = 1050
Gets existing cache names.
Empty request.
Response | |
int | Cache count |
string * count | Cache names |
OP_CACHE_GET_CONFIGURATION = 1055
Gets cache configuration
Request | |
int | Cache ID: Java-style hash code of the cache name |
Response | |
CacheConfiguration | See below |
Cache configuration is sent by server in the following format:
CacheConfiguration | |||||||||||||||||||||||||||||||||||||||||||||||
int | Length of the configuration, in bytes | ||||||||||||||||||||||||||||||||||||||||||||||
int | CacheAtomicityMode, TRANSACTIONAL = 0, ATOMIC = 1 | ||||||||||||||||||||||||||||||||||||||||||||||
int | Backups | ||||||||||||||||||||||||||||||||||||||||||||||
int | CacheMode, LOCAL = 0, REPLICATED = 1, PARTITIONED = 2 | ||||||||||||||||||||||||||||||||||||||||||||||
bool | CopyOnRead | ||||||||||||||||||||||||||||||||||||||||||||||
string | DataRegionName | ||||||||||||||||||||||||||||||||||||||||||||||
bool | EagerTtl | ||||||||||||||||||||||||||||||||||||||||||||||
bool | StatisticsEnabled | ||||||||||||||||||||||||||||||||||||||||||||||
string | GroupName | ||||||||||||||||||||||||||||||||||||||||||||||
long | DefaultLockTimeout (milliseconds) | ||||||||||||||||||||||||||||||||||||||||||||||
int | MaxConcurrentAsyncOperations | ||||||||||||||||||||||||||||||||||||||||||||||
int | MaxQueryIterators | ||||||||||||||||||||||||||||||||||||||||||||||
string | Name | ||||||||||||||||||||||||||||||||||||||||||||||
bool | IsOnheapcacheEnabled | ||||||||||||||||||||||||||||||||||||||||||||||
int | PartitionLossPolicy, READ_ONLY_SAFE = 0, READ_ONLY_ALL = 1, READ_WRITE_SAFE = 2, READ_WRITE_ALL = 3, IGNORE = 4 | ||||||||||||||||||||||||||||||||||||||||||||||
int | QueryDetailMetricsSize | ||||||||||||||||||||||||||||||||||||||||||||||
int | QueryParallelism | ||||||||||||||||||||||||||||||||||||||||||||||
bool | ReadFromBackup | ||||||||||||||||||||||||||||||||||||||||||||||
int | RebalanceBatchSize | ||||||||||||||||||||||||||||||||||||||||||||||
long | RebalanceBatchesPrefetchCount | ||||||||||||||||||||||||||||||||||||||||||||||
long | RebalanceDelay (milliseconds) | ||||||||||||||||||||||||||||||||||||||||||||||
int | RebalanceMode, SYNC = 0, ASYNC = 1, NONE = 2 | ||||||||||||||||||||||||||||||||||||||||||||||
int | RebalanceOrder | ||||||||||||||||||||||||||||||||||||||||||||||
long | RebalanceThrottle (milliseconds) | ||||||||||||||||||||||||||||||||||||||||||||||
long | RebalanceTimeout (milliseconds) | ||||||||||||||||||||||||||||||||||||||||||||||
bool | SqlEscapeAll | ||||||||||||||||||||||||||||||||||||||||||||||
int | SqlIndexInlineMaxSize | ||||||||||||||||||||||||||||||||||||||||||||||
string | SqlSchema | ||||||||||||||||||||||||||||||||||||||||||||||
int | WriteSynchronizationMode, FULL_SYNC = 0, FULL_ASYNC = 1, PRIMARY_SYNC = 2 | ||||||||||||||||||||||||||||||||||||||||||||||
int | CacheKeyConfiguration count | ||||||||||||||||||||||||||||||||||||||||||||||
CacheKeyConfiguration * count |
| ||||||||||||||||||||||||||||||||||||||||||||||
int | QueryEntity count | ||||||||||||||||||||||||||||||||||||||||||||||
QueryEntity * count |
|
OP_CACHE_CREATE_WITH_CONFIGURATION = 1053
Creates cache with provided configuration. Throws an exception if the name is already in use.
Request | |
int | Length of the configuration, in bytes |
short | Number of configuration properties |
(short + ...) * n | Configuration property data |
Any number of configuration properties can be provided. Name is required.
Cache configuration data is specified in key-value form, where key is `short` property id and value is property-specific data. Table below describes all available properties.
Property code | Property type | Description | |||||||||||||||||||||||||||||||||||||||||||||||
2 | int | CacheAtomicityMode, TRANSACTIONAL = 0, ATOMIC = 1 | |||||||||||||||||||||||||||||||||||||||||||||||
3 | int | Backups | |||||||||||||||||||||||||||||||||||||||||||||||
1 | int | CacheMode, LOCAL = 0, REPLICATED = 1, PARTITIONED = 2 | |||||||||||||||||||||||||||||||||||||||||||||||
5 | bool | CopyOnRead | |||||||||||||||||||||||||||||||||||||||||||||||
100 | string | DataRegionName | |||||||||||||||||||||||||||||||||||||||||||||||
405 | bool | EagerTtl | |||||||||||||||||||||||||||||||||||||||||||||||
406 | bool | StatisticsEnabled | |||||||||||||||||||||||||||||||||||||||||||||||
400 | string | GroupName | |||||||||||||||||||||||||||||||||||||||||||||||
402 | long | DefaultLockTimeout (milliseconds) | |||||||||||||||||||||||||||||||||||||||||||||||
403 | int | MaxConcurrentAsyncOperations | |||||||||||||||||||||||||||||||||||||||||||||||
206 | int | MaxQueryIterators | |||||||||||||||||||||||||||||||||||||||||||||||
0 | string | Name | |||||||||||||||||||||||||||||||||||||||||||||||
101 | bool | IsOnheapcacheEnabled | |||||||||||||||||||||||||||||||||||||||||||||||
404 | int | PartitionLossPolicy, READ_ONLY_SAFE = 0, READ_ONLY_ALL = 1, READ_WRITE_SAFE = 2, READ_WRITE_ALL = 3, IGNORE = 4 | |||||||||||||||||||||||||||||||||||||||||||||||
202 | int | QueryDetailMetricsSize | |||||||||||||||||||||||||||||||||||||||||||||||
201 | int | QueryParallelism | |||||||||||||||||||||||||||||||||||||||||||||||
6 | bool | ReadFromBackup | |||||||||||||||||||||||||||||||||||||||||||||||
303 | int | RebalanceBatchSize | |||||||||||||||||||||||||||||||||||||||||||||||
304 | long | RebalanceBatchesPrefetchCount | |||||||||||||||||||||||||||||||||||||||||||||||
301 | long | RebalanceDelay (milliseconds) | |||||||||||||||||||||||||||||||||||||||||||||||
300 | int | RebalanceMode, SYNC = 0, ASYNC = 1, NONE = 2 | |||||||||||||||||||||||||||||||||||||||||||||||
305 | int | RebalanceOrder | |||||||||||||||||||||||||||||||||||||||||||||||
306 | long | RebalanceThrottle (milliseconds) | |||||||||||||||||||||||||||||||||||||||||||||||
302 | long | RebalanceTimeout (milliseconds) | |||||||||||||||||||||||||||||||||||||||||||||||
205 | bool | SqlEscapeAll | |||||||||||||||||||||||||||||||||||||||||||||||
204 | int | SqlIndexInlineMaxSize | |||||||||||||||||||||||||||||||||||||||||||||||
203 | string | SqlSchema | |||||||||||||||||||||||||||||||||||||||||||||||
4 | int | WriteSynchronizationMode, FULL_SYNC = 0, FULL_ASYNC = 1, PRIMARY_SYNC = 2 | |||||||||||||||||||||||||||||||||||||||||||||||
401 | int + CacheKeyConfiguration * count | CacheKeyConfiguration count
| |||||||||||||||||||||||||||||||||||||||||||||||
200 | int + QueryEntity * count |
|
Empty response.
OP_CACHE_GET_OR_CREATE_WITH_CONFIGURATION = 1054
Creates cache with provided configuration. Does nothing if the name is already in use. Same request format as above. Empty response.
OP_QUERY_SQL = 2002
Performs SQL query.
Request | |
int | Cache ID: Java-style hash code of the cache name |
string | Query entity type name |
string | SQL |
int | Argument count |
BinaryObject * count | Arguments |
bool | Distributed joins |
bool | Local query |
bool | Replicated only |
int | Cursor page size |
long | Timeout (milliseconds) |
Response includes first page of results.
Response | |
long | Cursor id. Can be closed with OP_RESOURCE_CLOSE. |
int | Row count for the first page |
(Object + Object) * count | Cache entries, key + value |
bool | Indicates whether more results are available to be fetched with OP_QUERY_SQL_CURSOR_GET_PAGE. When true, query cursor is closed automatically. |
OP_QUERY_SQL_CURSOR_GET_PAGE = 2003
Retrieves next SQL query cursor page by cursor id from OP_QUERY_SQL.
Request | |
long | Cursor id |
Response | |
long | Cursor id |
int | Row count |
(Object + Object) * count | Cache entries, key + value |
bool | Indicates whether more results are available to be fetched with OP_QUERY_SQL_CURSOR_GET_PAGE. When true, query cursor is closed automatically. |
OP_RESOURCE_CLOSE = 0
Closes a resource, such as query cursor.
Request | |
long | Resource id |
Empty response.
OP_QUERY_SQL_FIELDS = 2004
Performs SQL fields query
Request | |
int | Cache ID: Java-style hash code of the cache name |
string | Default schema for the query, can be null |
int | Query cursor page size |
int | Max rows |
string | SQL |
int | Argument count |
BinaryObject * count | Arguments |
byte | Statement type, ANY = 0, SELECT = 1, UPDATE = 2 |
bool | Distributed joins |
bool | Local |
bool | Replicated Only |
bool | Enforce Join Order |
bool | Colocated |
bool | Lazy |
long | Timeout (milliseconds) |
bool | Include field names |
Response | |
long | Cursor id. Can be closed with OP_RESOURCE_CLOSE. |
int | Field (column) count |
Optionally, when IncludeFieldNames is true in request string * count | Column names |
int | First page row count |
BinaryObject * columnCount | Column (field) values |
bool | Indicates whether more results are available to be retrieved with OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE |
OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE = 2005
Retrieves next query page.
Request | |
long | Cursor id |
Response | |
int | Row count |
BinaryObject * columnCount | Column values |
bool | Indicates whether more results are available to be retrieved with OP_QUERY_SQL_FIELDS_CURSOR_GET_PAGE |
OP_GET_BINARY_TYPE_NAME = 3000
Gets the platform-specific full binary type name by id. For example, .NET and Java can map to the same type Foo, but classes will be Apache.Ignite.Foo in .NET and org.apache.ignite.Foo in Java.
Names are registered with OP_REGISTER_BINARY_TYPE_NAME.
Request | |
byte | Platform id, JAVA = 0, DOTNET = 1 |
int | Type id |
Response | |
string | Binary type name |
OP_GET_BINARY_TYPE = 3002
Gets the binary type information by id.
Request | |
int | Type id |
Response | |||||||||
bool | False: binary type does not exist, response end. True: binary type exists, response as follows. | ||||||||
int | Type id | ||||||||
string | Type name | ||||||||
string | Affinity key field name | ||||||||
int | BinaryField count | ||||||||
BinaryField * count |
| ||||||||
bool | Is enum | ||||||||
int (if isEnum) | Enum field count | ||||||||
(string + int) * count (if isEnum) | Enum values | ||||||||
int | Schema count | ||||||||
(int (schema id) + int (field count) + int (field id) * n) * count | Binary schemas, set of (schemaId + fieldIds) pairs |
OP_REGISTER_BINARY_TYPE_NAME = 3001
Registers the platform-specific full binary type name by id. For example, .NET and Java can map to the same type Foo, but classes will be Apache.Ignite.Foo in .NET and org.apache.ignite.Foo in Java.
Request | |
byte | Platform id, JAVA = 0, DOTNET = 1 |
int | Type id |
string | Type name |
Empty response.
OP_PUT_BINARY_TYPE = 3003
Registers binary type information in cluster.
Request | |||||||||
int | Type id | ||||||||
string | Type name | ||||||||
string | Affinity key field name | ||||||||
int | BinaryField count | ||||||||
BinaryField * count |
| ||||||||
bool | Is enum | ||||||||
int (if isEnum) | Enum field count | ||||||||
(string + int) * count (if isEnum) | Enum values | ||||||||
int | Schema count | ||||||||
(int (schema id) + int (field count) + int (field id) * n) * count | Binary schemas, set of (schemaId + fieldIds) pairs |
Empty response.
OP_QUERY_SCAN = 2000
Performs scan query.
Request | |
int | Cache ID: Java-style hash code of the cache name |
BinaryObject | Filter object |
byte (if filter object is not null) | Filter platform, JAVA = 1, DOTNET = 2, CPP = 3 |
int | Cursor page size |
int | Partition to query (negative to query entire cache) |
bool | Local flag |
Response | |
long | Cursor id |
int | Row count for the first page |
(Object + Object) * count | Cache entries, key + value |
bool | Indicates whether more results are available to be fetched with OP_QUERY_SCAN_CURSOR_GET_PAGE |
OP_QUERY_SCAN_CURSOR_GET_PAGE = 2001
Retrieves next SQL query cursor page by cursor id from OP_QUERY_SCAN.
Request | |
long | Cursor id |
Response | |
long | Cursor id |
int | Row count |
(Object + Object) * count | Cache entries, key + value |
bool | Indicates whether more results are available to be fetched with OP_QUERY_SCAN_CURSOR_GET_PAGE. When true, query cursor is closed automatically. |
As an example let's see how to connect to Ignite instance on a local machine and retrieve an int value for a given int key, in pseudocode.
var socket = openSocket("127.0.0.1:10800"); // Message length socket.writeInt(8); // Handshake operation socket.writeByte(1); // Protocol version 1.0.0 socket.writeShort(1); socket.writeShort(0); socket.writeShort(0); // Client type: thin client socket.writeByte(2); // Receive result var resLen = socket.readInt(); assert resLen == 1; // Success message length is 1 var res = socket.readByte(); assert res == 1; // Success code // END HANDSHAKE // Perform OP_CACHE_GET // Message length socket.writeInt(20) // Op code = OP_CACHE_GET socket.writeShort(1000); // Request id (can be anything; does not matter for simple blocking socket IO) var reqId = 1; socket.writeLong(reqId); // Cache id var cacheName = "myCache"; var cacheId = javaHashCode(cacheName); socket.writeInt(cacheId); // Flags = none socket.writeByte(0); // Cache key socket.writeByte(3); // Integer type code socket.writeInt(1); // Our cache value // Read result var len = socket.readInt(); assert len == 17; // requestId (8) + status code (4) + int object (1 + 4) var resReqId = socket.readLong(); assert reqId == resReqId; var statusCode = socket.readInt(); assert statusCode == 0; // Success var resTypeCode = socket.readByte(); assert restypeCode == 3; // Integer var res = socket.readInt(); print(res); // Resulting cache value
An example of writing a custom object with a single integer field, in pseudocode:
// Header socket.writeByte(103); // Binary object type code socket.writeByte(1); // Binary object format version socket.writeShort(1 + 2); // Flags, user type + has schema socket.writeInt(1512523596); // Type id, Java-style hash code of "MyType" socket.writeInt(0); // Hash code, 0 for simplicity socket.writeInt(24 + 5 + 8); // Object length, header + int field (byte type + 4 bytes value) + schema (4 bytes id + 4 bytes offset) socket.writeInt(0); // Schema id, for simplicity socket.writeInt(24 + 5); // Schema offset, header size + one int field // Fields socket.writeByte(3); // Field type, int socket.writeInt(42); // Field value // Schema socket.writeInt(1515208398); // Field id, Java hash of "myfield" socket.writeInt(24); // Field position from object start, right after 24-byte header
Reading binary object and retrieving field value:
// Header assert socket.readByte() == 103; assert socket.readByte() == 1; assert socket.readByte() == 1 + 2; var typeId = socket.ReadInt(); var hash = socket.readInt(); var len = socket.ReadInt(); var schemaId = socket.ReadInt(); var schemaOffset = socket.ReadInt(); // Read field data into array, everything between header and schema var fieldData = socket.readByteArray(schemaOffset - 24); // Read schema var fieldCount = (len - schemaOffset) / 8; var fieldIds = new int[fieldCount]; var fieldOffsets = new int[fieldCount]; for (int i = 0; i < fieldCount; i++) { fieldIds[i] = socket.readInt(); fieldOffsets[i] = socket.readInt(); } // Let's suppose that user wants a value of the field named "myfield" var fieldName = "myfield"; var fieldId = getJavaHash(fieldName); // 1515208398 var fieldIdx = fieldIds.indexOf(fieldId); // Can be missing, handle accordingly var fieldOffset = fieldOffsets[fieldsIdx]; // We got the field offset, now read binary object from fieldData var reader = new ArrayReader(fieldData); reader.seek(fieldOffset - 24); var fieldType = reader.readByte(); if (fieldType = 3) // int { var fieldVal = reader.readInt(); } else if (fieldVal = 103) { // Nested binary object ... } else ...
Similar protocols from other vendors: