1. VGX Operation Stream
Operations performed on a VGX graph via its API may be captured and transferred to a destination graph where the same operations are applied. A destination graph is a remote replica maintained incrementally via the stream of VGX transactions.
A VGX source instance may attach to any number of VGX destination instances. A VGX source produces a transaction stream derived from graph API operations executed in the source instance. A VGX destination consumes the transaction stream to mirror exactly the graphs in the source. We sometimes refer to the VGX source as provider and the VGX destination as subscriber.
A subscriber may only have a single provider, but it may itself be a provider for a set of sub-subscribers. Such a subscription tree always has a single root provider. Since all subscriber replicas are built from the stream originating in the root provider eventual consistency among all VGX instances is achieved. Durability is achieved when at least one subscriber has transaction logs enabled.
Eventual consistency is automatic. Temporary disconnects between a subscriber and a provider are handled without loss of data. As long as a provider-subscriber relationship is maintained and the VGX instances are alive the protocol guarantees consistency between the two.
Durability is handled by a combination of automatic transaction logs (incrementally written to disk) and externally triggered graph snapshots, typically managed by application specific plugins that persist data according to rules appropriate for the application. This scheme ensures automatic durable writes.
A VGX instance configured with durability is referred to as durable. Restoring a durable VGX instance from disk is automatic. A VGX instance configured without durability is referred to as volatile. Restoring a volatile VGX instance is achieved via externally controlled procedures, which may be automated by a higher level orchestration layer (outside the scope of VGX itself) or through manual operational steps.
1.1. Attach operation stream to subscriber
VGX may be configured to generate transaction output at system initialization or by calling op.Attach() at a later point. It is usually best to attach at initialization to ensure all operations are emitted.
1.1.1. URI Format
A VGX provider can attach to its subscribers using any of the three supported URI schemes.
1.1.1.1. URI scheme vgx://
The vgx:// scheme is used for streaming VGX transactions over a network to a subscriber VGX instance. When using this scheme the VGX provider will establish a socket connection to the subscriber at <host>:<port>.
vgx://<host>:<port>
1.1.1.2. URI scheme file://
The file:// scheme writes the VGX transaction stream to a local file. In this case the subscriber is the local file system. This is useful for debugging or for storing a set of transactions that can be used later to initialize another VGX instance.
file://<path>
1.1.1.3. URI scheme null://
The null:// scheme acts as a no-op sink with infinite capacity (like Unix /dev/null.) This is primarily useful for debugging and verification of internal components in the provider’s producer logic.
null://<path>
1.1.2. Attach at initialization
In normal operation a VGX provider instance should attach to its subscribers immediately on startup. This ensures all operations are captured and transmitted.
Specify destination URI in the attach= parameter of system.Initialize().
import pyvgx
# Attach to subscriber service on localhost port 8099
pyvgx.system.Initialize( attach="vgx://127.0.0.1:8099" )
# All subsequent API operations are sent to the subscriber
g = pyvgx.Graph( "test" )
g.CreateVertex( "A" )
1.1.3. Explicit attach after initialization
It is possible to attach subscribers after VGX has been initialized using op.Attach(). Any operations performed before the subscriber is attached will not be transmitted.
import pyvgx
# Local operations only
g = pyvgx.Graph( "test" )
A = g.NewVertex( "A" )
# Attach to subscriber service on localhost port 8099
pyvgx.op.Attach( "vgx://127.0.0.1:8099" )
# All subsequent API operations are sent to the subscriber
B = g.NewVertex( "B" ) # Create B with
B['x'] = 123 # property x=3
g.CloseVertex( B ) # and output transaction.
# However, changes to the vertex A opened before
# subscriber was attached will NOT be emitted.
A['x'] = 456 # Local only.
g.CloseVertex( A ) #
It is possible to attach multiple subscribers. A list of URI strings may be passed instead of a single URI string to attach multiple subscribers at once.
from pyvgx import *
system.Initialize( attach=[ "vgx://vgx.service.one:8099",
"vgx://vgx.service.two:8099",
"file:///./opcodes" ]
)
# API operations are sent to all attached subscribers
g = pyvgx.Graph( "test" )
g.CreateVertex( "A" )
from pyvgx import *
op.Attach( ["vgx://vgx.service.one:8099",
"vgx://vgx.service.two:8099",
"file:///./opcodes" ]
)
# API operations are sent to all attached subscribers
g = pyvgx.Graph( "test" )
g.CreateVertex( "A" )
1.1.4. Detach
A VGX instance may detach from any attached subscribers. Operations performed after detaching subscribers will not be transmitted to those subscribers.
from pyvgx import *
# Attach to three subscribers
system.Initialize( attach=[ "vgx://vgx.service.one:8099",
"vgx://vgx.service.two:8099",
"file:///./opcodes" ]
)
# Operations are transmitted to attached subscribers
g = pyvgx.Graph( "test" )
g.CreateVertex( "A" )
# Detach specific subscriber
op.Detach( "file:///./opcodes" )
# Operations are no longer written to detached file
g.CreateVertex( "B" )
# Detach all remaining subscribers
op.Detach()
# Local operation only
g.CreateVertex( "C" )
1.2. Consume VGX transaction data
A destination VGX instance may be populated by consuming transaction data generated by a VGX provider. This data may come from a previously written file, or from an external orchestration framework.
A destination VGX instance populated this way is not considered a VGX subscriber.
Transaction data is manually submitted to a VGX destination using op.Consume(). It is recommended to globally disable event processing before calling this function because the TTL processor may interfere with the processing of transactions. To globally disable event processing the system must be initialized with parameter events=False.
from pyvgx import *
# Globally disable asynchronous event processing
system.Initialize( events=False )
# Assume a function exist capable of returning a chunk
# of operation data generated by some source VGX instance.
data = get_transaction_data()
# Submit chunk of operation data. This will modify one
# or more graphs in the local VGX instance.
op.Consume( data )
1.2.1. Operation Filter
Some applications may want to prevent certain operations from being executed. Operation filters can be configured via op.Deny(), op.Allow() and op.Profile(). Operation filters are applied by supplying operator opcodes, operator groups, or operator profiles as arguments to these functions.
For instance, it may be desirable to prevent a VGX instance from executing graph truncation and graph persist:
op.Deny( op.OP_grt )
op.Deny( op.OP_grp )
Pre-defined profiles can be applied for instances with certain roles in a larger setup:
op.Profile( op.OP_PROFILE_consumer )
1.3. VGX Transaction Service
To prepare a VGX instance for becoming a subscriber it must have the VGX Transaction service running. The VGX Transaction service may be started at initialization using the bind= parameter, or after initialization using op.Bind().
1.3.1. Bind at initialization
from pyvgx import *
# Start VGX Transaction service at initialization
system.Initialize( bind=8099, events=False )
# A VGX provider may now attach to this instance at port 8099
1.3.2. Bind after initialization
from pyvgx import *
# Initialize with events globally disabled
system.Initialize( events=False )
# Start VGX Transaction service
op.Bind( 8099 )
# A VGX provider may now attach to this instance at port 8099
1.3.3. Unbind
The VGX Transaction service can be shut down by calling op.Unbind(). Any attached provider will remain attached to a subscriber that shuts down its VGX Transaction service in this manner. This means the provider will automatically reconnect to the subscriber once its VGX Transaction service is restarted.
# Stop VGX Transaction service
op.Unbind()
# If a provider was attached when Unbind was called
# the provider will try to reconnect while queuing up
# transaction data.
# Start VGX Transaction service
op.Bind( 8099 )
# No transaction data lost from provider
2. VGX Transaction Stream Format Overview
Communication between provider and subscriber uses a simple ASCII text format - the VGX Transaction Stream Protocol - consisting of tokens separated by whitespace.
The request stream from provider to subscriber represents a series of commands with arguments that, when executed by a destination VGX instance via pyvgx.op.Consume() or VGX Transaction service, re-creates a perfect copy of all graph(s) in the originating VGX instance.
The response stream from subscriber back to provider represents a series of acknowledgements that data has been processed or other responses that ask the provider to modify its behavior in some way.
2.1. Request
The major building blocks of the operation stream from provider to subscriber are:
-
transaction
-
A set of one or more operation blocks that must be presented to the destination as a complete unit. A transaction starts with the
TRANSACTIONstatement and ends with theCOMMITstatement.
-
-
operation block
-
A block of one or more operators pertaining to a specific VGX object such as graph or vertex. An operation block starts with the
OPstatement and ends with theENDOPstatement.
-
-
operator
-
A single "instruction" affecting the operation block's object in some way, such as creating a vertex (in a graph), or creating an arc or setting a property (on a vertex.)
-
TRANSACTION <transid> <serial> OP <optype> [<graph> [<objectid>]] <opname> <opcode> [<arg1> [<arg2> [...]]] ... ENDOP [<opid> <tms>] <crc32c> ... COMMIT <transid> <tms> <crc32c> \n
2.2. Response
Responses from subscriber to provider are single-line messages (terminated by \n) containing a status keyword followed by zero or more arguments.
In typical operation the subscriber responds with the ACCEPTED message for every transaction block processed.
ACCEPTED <transid> <crc32c> \n
3. VGX Transaction Stream Format Specification
The VGX Transaction Stream Protocol format is represented in plain ASCII text. This section contains the complete specification for data exchange between VGX providers and subscribers.
Once attached, a provider starts sending data to its subscriber(s) according to the Request Format and will listen for subscriber responses according to Response Format.
A provider may have multiple subscribers. Transaction exchange is asynchronous and managed independently, in parallel for each subscriber.
3.1. Request Format
The building blocks of the VGX Transaction Stream Protocol are summarized in the table below.
| Element | EBNF | Description |
|---|---|---|
Token |
|
A token is a sequence of one or more alphanumeric characters, or the |
Space |
|
Tokens are separated by one or more space characters. Consecutive occurrences of space characters are treated as a single space. |
Keyword |
|
|
Stream |
|
Operation transfer occurs as a continuous stream of transaction blocks that must be delivered as unbroken units to the destination site. |
Transaction |
|
A transaction block embeds a set of operation blocks between the keywords |
Transaction ID |
|
A transid is a unique transaction identifier appearing at the start and end of a transaction. |
Stream Resync |
|
A resync request is sent after a rollback event occurs, typically triggered by a preceding |
Rollback Bytes |
|
The number of bytes previously streamed that should be discarded as part of a rollback event. |
Attach |
|
A provider initiates a new connection by sending |
Detach |
|
A subscriber may request to terminate attachment by sending |
Idle |
|
The subscriber should expect regular |
Fingerprint |
|
A fingerprint represents a digest of the current data in a VGX instance. Providers and subscribers can communicate their current state via fingerprints to verify data consistency. |
Operation Block |
|
An operation block is a group of one or more operator statements pertaining to the object instance (such as a vertex) specified by objectid, or the graph instance specified by opgraph if objectid is not included, or the system graph if neither opgraph nor objectid is included. The affected object depends on optype. |
Operation Type |
|
The type of operation block is indicated by optype and determines what kind of operators may appear within the block. A block type having graph-wide effect specifies the graph with opgraph and does not have the objectid field. A block type affecting a specific object within the graph (such as a vertex) specifies the objectid in addition to opgraph containing the object. |
Operation Graph |
|
The opgraph field specifies the graph affected by the operators in the operation block. |
Object Identifier |
|
The objectid field is present for operation types affecting a specific object within a graph. |
Operation Identifier |
|
The set of one or more operators within an operation block modify the selected object as a unit identified by the unique identifier opid. |
Timestamp |
|
The modification time (at the source VGX instance) is given by tms in milliseconds since 1970. |
CRC32C checksum |
|
The operation data crc32c checksum ( |
Operator |
|
The operator is a single "instruction" affecting the operation block’s object in some way, such as creating a vertex in a graph, or creating and arc or setting a property on a vertex. |
Operator name |
|
Operators are three-character mnemonics, such as |
Opcode |
|
The opcode is the numeric equivalent of the opname mnemonic. |
Argument |
|
Operators may have arguments. The number, types and order of arguments is defined for each operator. |
Hex digit |
|
Hexadecimal digit |
BYTE |
|
A numeric 8-bit value, such as |
WORD |
|
A numeric 16-bit value, such as |
DWORD |
|
A numeric 32-bit value, such as |
QWORD |
|
A numeric 64-bit value, such as |
m128 |
|
A numeric 128-bit value used for representing object identifiers and digests. |
Variable string |
|
Variable string data such as names, properties and other non-numeric information is encoded in a base-16 format and includes internal meta information (strmetas), number of bytes in the original data string (strsize), number of data elements (nstrqwords) followed by the one or more specified number of data elements (strdata) |
Comment |
|
Text appearing after an occurrence of |
If an intermediary streaming service is used to convey transaction data from a provider to a subscriber (i.e. by not using the VGX Transaction service), the streaming service must guarantee that once the beginning of a transaction has been submitted to a destination VGX instance via pyvgx.op.Consume() the entire transaction will eventually be submitted.
|
3.2. Response Format
Provider and subscriber communicate asynchronously. A subscriber sends messages back to the provider in the form of single status lines, as summarized in the Response Message Specification table below.
3.2.1. Transaction Responses
A subscriber is required to send a response for every transaction it has received from the provider. The transaction response messages are:
Transactions are identified by a unique <transid> label and ordered by a <serial> number. A subscriber applies transactions only when serial numbers increase monotonically. Out-of-order transactions or repeated transactions are ignored.
It is not necessary to send transaction responses synchronously. The provider will continue to stream new transactions even if previous transactions have not yet been responded to. However, responses must eventually be sent and they must be ordered according to the transaction <serial> number.
If the backlog of unconfirmed transactions grows too large the provider will adjust production to a slower rate.
If an out of order response is received by the provider it will consider the chain of transactions broken at the earliest unconfirmed transaction. The provider will attempt to heal the broken chain by re-transmitting all unconfirmed transactions starting with the earliest unconfirmed transaction. Re-transmitted transactions retain their original <transid> transaction identifiers and <serial> numbers.
If a response is received for a transaction that is unknown to the provider (i.e. not present in the unconfirmed backlog) the response is ignored and the transaction stream continues normally.
3.2.2. State Change Responses
Non-transactional messages may be sent from subscriber to provider at any time, requesting certain behavior or actions to be performed by the provider.
-
SUSPENDindicates the subscriber is unable to keep up with processing at this time and provider should stop streaming new transactions -
RESUMEindicates the subscriber is ready to process data and the provider may start streaming new transactions -
DETACHindicates the subscriber want to terminate attachment and the provider should flush pending transactions, then detach.
| Response | Syntax | Description |
|---|---|---|
Transaction Accepted |
|
Subscriber has processed the transaction identified by transid. If the subscriber is a VGX Transaction service it means the transaction has been successfully applied. If the subscriber is a non-VGX intermediary streaming service it means the service now has accepted responsibility for propagating the transaction to all its destinations. The crc32c checksum encompasses all bytes starting with the first "T" of the |
Retry Transaction |
|
The transaction identified by transid could not be processed, and the transaction to be re-tried. The provider will rewind its backlog and re-transmit all transactions starting with the identified transaction. The reason code carries flow-control information. |
Transaction Stream Rejected |
|
The subscriber refused to process the transaction identified by transid and asks VGX provider to stop the transmission of new transactions. The reason code is currently ignored. The provider should regard this message as a request to permanently cease the production of new transactions. |
Suspend |
|
The subscriber asks the provider to temporarily stop producing new transactions. The provider must transition to a suspended state where no additional transactions are sent to the subscriber for the duration of the suspended state. The requested suspend duration is provided in reason. |
Resume |
|
The subscriber requests VGX provider to resume the production of new transactions. If the provider is currently in a suspended state caused by a previous suspend it will now exit the suspended state and begin producing new transactions. A non-suspended VGX provider ignores this request. |
Hex digit |
|
Hexadecimal digit |
Reason Code |
|
A reason code in a response contains flow control hints that the provider should respect. When the upper digits |
3.2.3. ACCEPTED
The subscriber sends the ACCEPTED response for each transaction processed in the same order they were received from the provider.
ACCEPTED <transid> <crc32c> \n
When the subscriber accepts transaction transid by sending the ACCEPTED response it assumes responsibility for the durability of all data in this transaction. If the subscriber is a VGX Transaction service it means transaction data has been successfully processed into the destination graph. If the subscriber is a non-VGX streaming service it is now responsible for propagating the transaction to its destination(s).
Data integrity is verified by crc32c checksum. The subscriber computes the crc32c checksum for each transaction and matches the computed checksum against the checksum provided in the transaction’s COMMIT statement. The same checksum is returned in the ACCEPTED response.
ACCEPTED 5aa90824415dd8c0475141f186ec51d5 4456A9AD \n
It is not necessary to send a response immediately after processing a transaction. The provider will continue to stream new transactions as they are being produced. However, the provider will begin to throttle its production once a threshold of pending transactions is reached.
Provider --> ... t4 t3 t2 t1 --> Subscriber
|
ACCEPTED |
<-- t1 t2 t3 t4 ... <--'
If an out-of-order response is detected by the provider it will assume something went wrong with transmission and/or processing at the subscriber side. The provider automatically triggers a rollback and internally issues a RETRY response to itself with the transaction identifier of its earliest unconfirmed transaction. I.e., an out-of-order response is equivalent to a RETRY for the earliest transaction that has not yet been accepted.
A transaction identifier not known to the provider is not considered out-of-order. An ACCEPTED response containing an unknown transaction identifier is simply ignored. Already accepted transactions are erased from the providers’s memory and are therefore unknown. Duplicate accepted messages are thus ignored.
3.2.4. RETRY
A temporary failure to receive or process a transaction is communicated by the RETRY response. The provider rewinds its output queue to the start of the earliest unconfirmed transaction, i.e. the next transaction in the stream following the last accepted transaction.
RETRY <transid> <reason> \n
The transid is echoed by the provider in the subsequent RESYNC request which indicates the point in the stream where the subscriber should resume processing. (This transid should match the earliest unconfirmed transaction but will not affect the provider’s rollback action. The provider always rewinds to the start of the earliest unconfirmed transaction.)
A reason code carries an optional request to temporarily suspend data output for a brief period.
RETRY ff1e94aa0c72f459a268933eedeb2b71 00000001 \n
When the provider acts upon a retry response it will re-transmit the earliest unconfirmed transaction and then wait for it to be accepted by the subscriber before continuing. Transaction handshakes are thus temporarily synchronous until a reliable stream has been re-established. No further data will be sent by the provider until the subscriber sends a response for the re-tried transaction. If the response is ACCEPTED normal operation is resumed. If the response is again RETRY the process of retrying is repeated. It is up to the subscriber to decide if and when to terminate a cycle of repeated unsuccessful attempts, either by closing the connection or sending a REJECTED response.
A RESYNC message is injected into the stream immediately before the earliest unconfirmed transaction is re-transmitted. This allows the subscriber to discard all remaining data queued on the socket until it encounters RESYNC.
\n RESYNC ff1e94aa0c72f459a268933eedeb2b71 000000000001E240 \n \n
The first argument (transid) is the transaction identifier of the earliest unconfirmed transaction. The second argument (nrollback) is the amount of data (in bytes) known by the provider to have been streamed to the socket at the time it received the RETRY response, and is therefore the amount of data that should have been discarded by the subscriber at the time it receives the RESYNC request.
======== ==========
PROVIDER SUBSCRIBER
======== ==========
(produce) --> ... t3 t2 t1 \
| (find t1 has problem)
| (discard all incoming until t1)
(rewind to t1) RETRY "t1" <-- '
|
`--> RESYNC "t1" \
`--> t1 |
(sync wait) | (t1 now ok)
|
(resume stream) ACCEPTED "t1" <-- '
|
`--> ... t3 t2 \
| (normal async flow)
ACCEPTED "t2" <-- '
ACCEPTED "t3" <-- '
After responding with a RETRY for transaction t1 the subscriber discards all incoming data on the socket until RESYNC … appears, immediately followed by re-transmission of transaction t1. Any data queued up before RESYNC is invalid and must be read from the socket and discarded by the subscriber. Once the subscriber encounters RESYNC it can expect a re-transmission of t1 to immediately follow. When t1 is successfully processed and accepted by the subscriber, the provider will resume asynchronous streaming starting with re-transmission of t2.
Note that the RESYNC request itself has no associated response. The provider expects a response to the first transaction immediately following RESYNC before transmitting any more data. If the response is ACCEPTED the provider resumes asynchronous streaming. If the response is RETRY the resync operation is repeated. If no response is received after 60 seconds the provider will close the socket, then re-connect and re-attempt the resync operation.
======== ==========
PROVIDER SUBSCRIBER
======== ==========
|________________________________________|
| Resulting transaction stream |
| ... t5 t4 t3 t2 t1 t4* t3 t2 t1 t0 -> |
| ~~~~~~~~~~~~ |
| (discarded) |
| (t4* possibly truncated) |
|________________________________________|
send t0 | |
send t1 | <- ACCEPTED "t0" | process t0
send t2 | | t1 error!
send t2 | <- RETRY "t1" | RETRY t1
send t3 | |
send t4* | | (discard all
recv RETRY | | incoming
(rewind t1) | | until RESYNC)
send RESYNC | RESYNC "t1" -> |
(re)send t1 | |
(sync wait) | <- ACCEPTED "t1" | process t1
(re)send t2 | |
(re)send t3 | <- ACCEPTED "t2" | process t2
(re)send t4 | |
send t5 | <- ACCEPTED "t3" | process t3
send ... | <- ACCEPTED "t4" | process t4
| |
| <- ACCEPTED "t5" | process t5
| <- ACCEPTED ... | process ...
3.2.5. REJECTED
A permanent failure to receive or process transactions is communicated by the REJECTED response. The transaction identifier indicates the transaction which triggered the rejection of the stream. The provider should regard this message as a request to permanently cease the production of new transactions.
REJECTED <transid> <reason> \n
A reason code indicates the nature of the rejected message. (This code is currently ignored by the provider.)
REJECTED ff1e94aa0c72f459a268933eedeb2b71 00000000 \n
3.2.6. SUSPEND
The subscriber may send a SUSPEND response to temporarily halt production of new transactions in the VGX provider.
Although the provider will stop producing new transactions as soon as it receives the SUSPEND response, data already streamed to the socket by the provider will still be inflight and eventually arrive at the subscriber.
|
SUSPEND <reason> \n
The reason encodes how long the provider should suspend production of new transactions. When reason ≤ 0xffff the value is interpreted as a number of milliseconds to suspend before automatically resuming. When reason ≥ 0x10000 the provider will suspend indefinitely.
SUSPEND 00001388 \n
This response asks the provider to suspend for 5 seconds (0x1388 = 5000 ms) and then automatically resume without the need for an explicit RESUME.
3.2.7. RESUME
The subscriber may send a RESUME response when it is ready to receive new transactions from the VGX provider.
If the provider is in a suspended state when it receives the RESUME response it will immediately exit the suspended state.
The provider ignores the RESUME response if it is not currently suspended.
RESUME \n
4. VGX Transaction Stream Building Blocks
4.1. Transaction
TRANSACTION <transid> <serial> <operation> ... COMMIT <transid> <tms> <crc32c> \n
A transaction represents a set of operations that must be processed by a destination VGX instance as a complete unit before any of the operations can be executed. A subscriber must guarantee that processing of a partial transaction is never attempted. However, it is acceptable for a non-VGX streaming service to submit partial transaction data to pyvgx.op.Consume() as long as the streaming service can guarantee that the remainder of the transaction data also exists at the destination site and can be submitted in quick succession with further calls to pyvgx.op.Consume() until complete.
4.1.1. Zero intra-transaction submission delay
Transactions embed a sequence of operations that must be processed by a destination VGX instance such that the speed of processing is determined only by the VGX instance. This has practical meaning only for a non-VGX streaming services acting as an intermediary between VGX instances. (A subscriber running the VGX Transaction service handles these requirements automatically.)
A non-VGX streaming service either has to submit the entire transaction via one call to pyvgx.op.Consume(), or split the transaction data over multiple calls to pyvgx.op.Consume() with zero delay between calls.
A transaction may operate on multiple objects that require atomic locking, where locks are acquired early in the transaction and released late in the transaction. For this reason it is not acceptable for the a non-VGX streaming service to begin applying a transaction at the destination until all transaction data has arrived at the destination site. Doing so would introduce the risk of leaving VGX objects in a locked state for an undetermined length of time.
4.1.2. Transaction identifier and serial number
Transactions carry unique transaction identifiers transid and serial numbers. The transid is a label used for keeping track of individual transactions and must be included in responses from subscriber to provider. The serial numbers are monotonically increasing integers ensuring that transactions are applied in the correct order at destinations.
4.1.3. Transaction confirmation
Successful processing of a transaction by the a subscriber must be followed by the ACCEPTED message back to the VGX provider. The transaction identifier transid and a crc32c checksum are included in this response.
A non-VGX streaming service is not required to compute the crc32c checksum itself. It may echo back the crc32c included in the COMMIT statement of the transaction. However, to increase reliability of the overall system the service should compute its own checksum and verify against the transaction request’s checksum. A REJECTED or RETRY response is appropriate after a checksum mismatch.
4.1.4. Compute transaction CRC32-C checksum
The CRC32-C algorithm is used to compute the checksum. The first byte to be processed is the leading "T" of the TRANSACTION keyword. The last byte to be processed is the byte immediately preceding the "C" of the transaction’s COMMIT keyword. All bytes in between are processed including spaces, newlines and comments.
For example, computing the CRC32-C of the transaction shown below starts with "T", followed by "R", "A", "N", …, "C", "0", "A", "\n". The resulting checksum is 0x45021C31. This is the same value included in the COMMIT statement. The streaming service can match checksums to verify data was received correctly.
TRANSACTION 71ae6c324062bed56a925c74311ab3ce 0000017725809E90
OP 2001 a5b3aedf778003cd15dc8178017db09b 7fc56270e7a70fa81a5935b72eacbe29
arc 1020011C 00052B660000000A 9d5ed678fe57bcca610140957afab571
ENDOP 002386F26FC10012 0000017725EB59CA 8A26C4B9
OP 2001 a5b3aedf778003cd15dc8178017db09b 9d5ed678fe57bcca610140957afab571
vps 1010161C C4FAA57A858CFC79 02 0000000000000000 0000000000000014
ENDOP 002386F26FC10014 0000017725EB59CA 9BA3EC0A
COMMIT 71ae6c324062bed56a925c74311ab3ce 0000017725EB5B12 45021C31 \n
A correctly processed transaction should be followed by an ACCEPTED response.
ACCEPTED 71ae6c324062bed56a925c74311ab3ce 45021C31 \n
4.1.5. Transaction Example
This example opens three existing vertices atomically before creating connections and setting properties, then finally releases the vertices triggering a new transaction.
def func():
A, B, C = g.OpenVertices( ["A","B","C"] )
g.Connect( A, ("to",M_INT,10), B )
A['x'] = 10
g.Connect( B, ("to",M_INT,10), C )
B['x'] = 20
g.CloseVertices( [A, B, C] )
# Execute
func()
The VGX provider instance generates the following transaction data which is sent to the streaming service.
TRANSACTION 71ae6c324062bed56a925c74311ab3ce 0000017725809E90
OP 200A a5b3aedf778003cd15dc8178017db09b
lxw 10A011F5 00000003 7fc56270e7a70fa81a5935b72eacbe29 9d5ed678fe57bcca610140957afab571 0d61f8370cad1d412f80b84d143e1257
ENDOP D08213E7
OP 1001 a5b3aedf778003cd15dc8178017db09b
rea 10E0021C 659DFC2ACDBEACD9 0000000000000AD9 000000010000000200000000000000010000000000006F74
ENDOP 002386F26FC10010 0000017725EB59CA 66ABBDB6
OP 1001 a5b3aedf778003cd15dc8178017db09b
kea 10E0041C C4FAA57A858CFC79 C4FAA57A858CFC79 000100010000000100000000000000010000000000000078
ENDOP 002386F26FC10011 0000017725EB59CA 40BABBDD
OP 2001 a5b3aedf778003cd15dc8178017db09b 7fc56270e7a70fa81a5935b72eacbe29
arc 1020011C 00052B660000000A 9d5ed678fe57bcca610140957afab571
vps 1010161C C4FAA57A858CFC79 02 0000000000000000 000000000000000A
ENDOP 002386F26FC10012 0000017725EB59CA E616976A
OP 2001 a5b3aedf778003cd15dc8178017db09b 9d5ed678fe57bcca610140957afab571
arc 1020011C 00052B660000000A 0d61f8370cad1d412f80b84d143e1257
vps 1010161C C4FAA57A858CFC79 02 0000000000000000 0000000000000014
ENDOP 002386F26FC10014 0000017725EB59CA 0FB98268
OP 200B a5b3aedf778003cd15dc8178017db09b
ulv 00A013F5 00000003 7fc56270e7a70fa81a5935b72eacbe29 9d5ed678fe57bcca610140957afab571 0d61f8370cad1d412f80b84d143e1257
ENDOP 02BD8995
COMMIT 71ae6c324062bed56a925c74311ab3ce 0000017725EB5B12 68F7E2C0 \n
The subscriber sends a response to the provider indicating the transaction was received and processed successfully.
ACCEPTED 71ae6c324062bed56a925c74311ab3ce 68F7E2C0 \n
If the subscriber is a VGX instance running the VGX Transaction service the graph has now been updated with all data in the accepted transaction.
If the subscriber is a non-VGX streaming service, it now forwards the transaction to a destination VGX instance where it will be applied.
# Events must be globally disabled at initialization
pyvgx.system.Initialize( attach=None, events=False )
# Suppose this function returns the complete transaction data
data = get_stream_data()
# This will modify the destination graph having the same effect
# as func() had in the source VGX instance
pyvgx.op.Consume( data )
4.2. Resync
RESYNC <transid> <nrollback>
The resync message identifies the point in the message stream where the subscriber should resume processing new transactions following a temporary interruption.
If the temporary interruption was triggered by a previous RETRY response from the subscriber the appearance of RESYNC prompts the subscriber to continue processing at the next transaction. In this case the subscriber should expect the RESYNC transid to match the transaction id of its most recent RETRY response.
It is also possible for RESYNC to appear if the provider has performed an internal rollback triggered by circumstances unknown to the subscriber. In this case the subscriber should simply expect a new transaction to follow.
4.3. Operation Block
OP <optype> [ <opgraph> [ <objectid> ] ] <operator> ... ENDOP [ <opid> <tms> ] <crc32c>
The operation block embeds one or more operators that modify a graph in some way. An operation block starts with the OP keyword and has a type specified by optype which determines the kind of operators that may appear in the block.
Operation blocks have different scope depending on optype.
-
System Operations
-
Graph Operations
-
Vertex Operations
-
Locking Operations
4.3.1. System Operations
Operation blocks with system-wide effect apply operators relative to the system graph. The OP statement includes optype only, and the ENDOP statement includes crc32c only.
OP <optype> <operator> ... ENDOP <crc32c>
Examples of operators appearing in a system operation block include create graph and < <grd, delete graph>>.
4.3.2. Graph Operations
Operation blocks with graph-wide effect apply operators relative to a specific graph instance. The OP statement includes optype and opgraph fields. The ENDOP statement includes opid, tms and crc32c for graph instance operation blocks, and crc32c only for graph state operation blocks.
OP <optype> <opgraph> <operator> ... ENDOP <opid> <tms> <crc32c>
Examples of operators appearing in a graph instance operation block include creating a new vertex, defining a new relationship type and defining a new property key.
OP <optype> <opgraph> <operator> ... ENDOP <crc23c>
Examples of operators appearing in a graph state operation block include the synchronous execute events instruction, setting graph to readonly mode and performing time synchronization.
4.3.3. Vertex Operations
Operation blocks that modify vertices apply operators relative to a specific object instance within a specific graph instance. The OP statement includes optype, opgraph and objectid. The ENDOP statement includes opid, tms and crc32c.
OP <optype> <opgraph> <objectid> <operator> ... ENDOP <opid> <tms> <crc32c>
Examples of operators appearing in a vertex instance operation block include setting properties, assigning rank coefficients, and connecting or disconnecting arcs.
4.3.4. Locking Operations
Operation blocks acquiring or releasing locks for one or more vertices at the same time apply atomic locking operators relative to a specific graph instance. The OP statement includes optype and opgraph fields. The ENDOP statement includes crc32c only.
OP <optype> <opgraph> <operator> ... ENDOP <crc32c>
Operators appearing in lock acquisition operation blocks include acquire exclusive write locks. Operators appearing in lock release operation blocks include unlock vertices.
4.3.5. Compute operation block CRC32-C checksum
All operation blocks include a crc32c checksum in the ENDOP statement, allowing the destination VGX instance to validate the integrity of the operation data.
The checksum is computed over all tokens in the operation block starting with OP and ending with the token up to but not including the crc32c field itself. Only tokens are included in the computation. Spaces, newlines and comments are all excluded.
4.3.5.1. CRC32-C Example
The two operation blocks below are equivalent since they contain the exact same tokens, and therefore have the same CRC32-C checksum C9A3FDBB.
OP 2001 31e259a88d0d4db53a4dbb629ded46ff 7fc56270e7a70fa81a5935b72eacbe29 vps 1010161C C4FAA57A858CFC79 02 0000000000000000 00000000000003E8 ENDOP 002386F26FC10BE3 00000178B24EB030 C9A3FDBB
OP 2001 # vertex instance optype
31e259a88d0d4db53a4dbb629ded46ff # graph id
7fc56270e7a70fa81a5935b72eacbe29 # vertex id
# Set vertex property
# x = 1000
vps 1010161C # operator: "vertex property set"
C4FAA57A858CFC79 # key: "x"
02 # type: integer
0000000000000000 # (n/a)
00000000000003E8 # value: 1000
ENDOP 002386F26FC10BE3 # opid
00000178B24EB030 # tms
C9A3FDBB # checksum
4.3.6. Operation Block Example
This example shows five operation blocks performing the following actions:
-
Acquire two existing vertices
-
Define a new relationship type
-
Define a new property key
-
Connect the vertices and set a vertex property
-
Release two vertices
4.3.6.1. Atomically acquire vertices "A" and "B"
A, B = graph.OpenVertices( ["A", "B"] )
This is a graph-wide operation of type 200A specifying opgraph as the target for the lxw operator which acquires exclusive write locks on the specified vertices. This operation does not modify the vertices and therefore only includes the crc32c field at the end.
OP 200A eef63fb0fe9de6d719821ad5ff64b3ea
lxw 10A011F5 00000002 7fc56270e7a70fa81a5935b72eacbe29 9d5ed678fe57bcca610140957afab571
ENDOP 12AC3A3C
4.3.6.2. Define new relationship "to"
g.Connect( A, ("to",M_INT,10), B )
This is a graph-wide operation of type 1001 specifying opgraph as the target for the rea operator which adds a new relationship enumeration to the graph. This operation modifies the graph data by affecting the relationship enumerator and therefore includes a new opid and tms for the graph, in addition to the crc32c field at the end.
OP 1001 eef63fb0fe9de6d719821ad5ff64b3ea
rea 10E0021C 659DFC2ACDBEACD9 0000000000000AD9 000000010000000200000000000000010000000000006F74
ENDOP 002386F26FC1000D 000001772639B8D6 5BC210F7
4.3.6.3. Define new property key "x"
A['x'] = 10
This is a graph-wide operation of type 1001 specifying opgraph as the target for the kea operator which adds a new property key enumeration to the graph. This operation modifies the graph data by affecting the property key enumerator and therefore includes a new opid and tms for the graph, in addition to the crc32c field at the end.
OP 1001 eef63fb0fe9de6d719821ad5ff64b3ea
kea 10E0041C C4FAA57A858CFC79 C4FAA57A858CFC79 000100010000000100000000000000010000000000000078
ENDOP 002386F26FC1000E 000001772639B8D6 7DD3169C
4.3.6.4. Connect vertices and set property
g.Connect( A, ("to",M_INT,10), B )
A['x'] = 10
This is a vertex operation of type 2001 specifying objectid (for vertex "A") as the the target vertex in graph opgraph. The operation consists of two operators arc and vps that modify vertex "A" by first creating the "to" arc to vertex "B" and then assigning the value 10 to a property named "x". This operation modifies vertex "A" and therefore includes a new opid nad tms for the vertex, in addition to the crc32c field at the end.
OP 2001 eef63fb0fe9de6d719821ad5ff64b3ea 7fc56270e7a70fa81a5935b72eacbe29
arc 1020011C 00052B660000000A 9d5ed678fe57bcca610140957afab571
vps 1010161C C4FAA57A858CFC79 02 0000000000000000 000000000000000A
ENDOP 002386F26FC1000F 000001772639B8D6 10E0741C
4.3.6.5. Atomically release both vertices
g.CloseVertices( [A, B] )
This is a graph-wide operation of type 200B specifying opgraph as the target for the ulv operator which unlocks the specified vertices. This operation does not modify the vertices and therefore only includes the crc32c field at the end.
OP 200B eef63fb0fe9de6d719821ad5ff64b3ea
ulv 00A013F5 00000002 7fc56270e7a70fa81a5935b72eacbe29 9d5ed678fe57bcca610140957afab571
ENDOP 0CF7036D
4.4. Operator
<opname> <opcode> [ <arg1> [ <arg2> ... ] ]
Operators are the "instructions" that actually perform work. Every type of action that can be performed via the VGX programming API has a corresponding operator or set of operators. Operators are sequenced and bundled into one ore more operation blocks according to an algorithm that ensures semantic equivalence between the original source code and the operation stream output product.
Operators without references to objects outside the scope of the enclosing operation block are guaranteed to complete immediately once executed. This is because all resource acquisition is managed on the operation block level.
Some operators may reference objects whose acquisition is not managed by the enclosing operation block. Such operators (of which arc is a prominent example) are not guaranteed to complete immediately upon execution. If a required resource is busy at the time of the operator’s execution the operator will block until the resource becomes available. For example, the arc operator has to acquire the terminal in order to execute.
4.4.1. Operator Example
This example shows two operators executing the following actions:
-
Create a new arc
-
Set a vertex property
4.4.1.1. Connect two vertices with arc
The arc opname mnemonic and 1020011C opcode fields carry equivalent meaning and are both included to support human readability and parsing convenience at the same time.
The third field 00052B660000000A encodes the arc data, which in this case happens to reference the "to" relationship type with modifier M_INT and value 10.
The fourth field 9d5ed678fe57bcca610140957afab571 references the terminal vertex which needs to be acquired at the time of execution. The initial vertex has already been acquired by the enclosing operation block. Because the terminal must be acquired this operation may block.
arc 1020011C 00052B660000000A 9d5ed678fe57bcca610140957afab571
4.4.1.2. Set vertex integer property with vps
The vps opname mnemonic and 1010161C opcode fields carry equivalent meaning and are both included to support human readability and parsing convenience at the same time.
The third field C4FAA57A858CFC79 encodes the property key, which in this case happens to reference the "x" property key enumeration.
The fourth field 02 encodes the property value type, which means integer.
The fifth field 0000000000000000 is ignored for integer properties (but would be part of a reference to a string value enumeration if this were a string property.)
The sixth field 000000000000000A encodes the integer value 10.
vps 1010161C C4FAA57A858CFC79 02 0000000000000000 000000000000000A
5. Transaction Reference
5.1. Transaction start TRANSACTION
# transid serial TRANSACTION hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh HHHHHHHHHHHHHHHH
Transactions open with a TRANSACTION statement. The transid and serial field values are unique per transaction.
The transid field is a label representing the transaction.
The serial field is a monotonically increasing integer ensuring transactions are processed in order. Out-of-order transactions applied at the destination will result in an unrecoverable error.
| Field | Type | Format | Description |
|---|---|---|---|
transid |
m128 |
|
Unique transaction identifier |
serial |
QWORD |
|
Monotonically increasing serial number |
5.2. Transaction end COMMIT
# transid tms crc32c COMMIT hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh HHHHHHHHHHHHHHHH HHHHHHHH \n
Transactions end with a COMMIT statement.
The transid field in COMMIT has the same value as transid in TRANSACTION.
The tms field is a transaction timestamp, in milliseconds since 1970.
The crc32c field is a 32-bit integer checksum over all data in the transaction.
| Field | Type | Format | Description |
|---|---|---|---|
transid |
m128 |
|
Unique transaction identifier |
tms |
QWORD |
|
Transaction timestamp in milliseconds since 1970 |
crc32c |
DWORD |
|
Transaction checksum |
6. Operation Block Reference
6.1. Operation Type
| Type | Operation scope | Description |
|---|---|---|
System |
Operators within this block type have system-wide effect, such as creating graphs and managing the registry. |
|
Graph instance |
Operators within this block type create or destroy objects in the graph, such as vertices and enumerations. |
|
Graph state |
Operators within this block type alter the graph state, such as enabling or disabling event execution and switching between readonly and writable mode. |
|
Vertex instance |
Operators within this block type manipulate individual vertex objects, such as setting properties and crating connections. |
|
Vertex group lock |
Operators within this block type acquire vertex locks. |
|
Vertex group unlock |
Operators within this block type release vertex locks. |
6.2. Operation block start OP
# optype [opgraph [objectid ]] OP HHHH [hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh [hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh]]
All operation blocks include the operation type optype field. Operations affecting a specific (existing) graph also include the opgraph field. Operations targeting specific objects within a graph also include the object instance reference objectid.
| Field | Type | Format | Description |
|---|---|---|---|
optype |
WORD |
|
Determines the target object of the operation and the operators that may appear in the block. |
opgraph |
m128 |
|
Graph instance that will be affected by the operation. |
objectid |
m128 |
|
Object within graph that will be affected by the operation. |
6.3. Operation block end ENDOP
# [opid tms ] crc32c ENDOP [HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH] HHHHHHHH
The operation block terminates with the ENDOP statement. For operation types that apply permanent modifications to object instances, the affected object is updated with the operation identifier opid and timestamp tms after all operators in the operation block have been executed.
A crc32c checksum is included for each operation block to help detect unintended modification or data corruption.
| Field | Type | Format | Description |
|---|---|---|---|
opid |
QWORD |
|
Unique operation identifier |
tms |
QWORD |
|
Graph tick in milliseconds since 1970 |
crc32c |
DWORD |
|
CRC32-C checksum computed over all tokens in the operation block starting with |
7. Operator Reference
7.1. General Operator Format
# opname opcode [<p1> [<p2> [...]]]
ccc HHHHHHHH [... [... [...]]]
Operators appear as separate lines within operation blocks. All operators within a block are relative to the object instance in the operation header as determined by the operation type. Operators are applied in the order they appear.
An operator starts with a three-character mnemonic opname followed by its numeric opcode. Zero or more operator parameters p1 … pn follow next.
| Field | Type | Format | Description |
|---|---|---|---|
opname |
STRING |
|
Operator mnemonic |
opcode |
DWORD |
|
Numeric opcode |
pi |
|
|
Operator parameter |
7.2. System Operators
These operators may appear in operations of type 0001, which have system-wide effect.
OP 0001
sya 103011F5 <tms> <uri> <src> <ver> <stat>
syd 003012F5 <tms> <src> <ver> <stat>
rcl 003021FD
scf 1030311C <nsg> <nsi> <vsz> <vmi> <cm> <jm> <cx> <jx> <ham> <sim>
grn 1040511C <vblk> <t0> <opcnt> <id> <path> <name>
grd 0040521D <id>
dat 1030DA1E <nparts> <pn> <datapart> <sz> <obid>
ENDOP crc32c
| Opname | Opcode | Description | Comment |
|---|---|---|---|
103011F5 |
Attach source VGX instance to destination |
||
003012F5 |
Detach source VGX instance |
||
003021FD |
Clear system registry |
||
1030311C |
Define vector similarity parameters for graph |
||
1040511C |
Create a new graph instance |
||
0040521D |
Remove graph instance from memory |
||
1030DA1E |
Raw data package |
7.2.1. System Attach
# op opcode tms uri src ver stat sya 103011F5 HHHHHHHHHHHHHHHH ... ... ... 00000001
| Field | Type | Format | Description |
|---|---|---|---|
sya |
STRING |
|
"SYstem Attach" |
103011F5 |
DWORD |
|
sya opcode |
<tms> |
QWORD |
|
Source graph timestamp in milliseconds since 1970 |
<uri> |
VARSTR |
|
URI of streaming service handling data transport from source to destination |
<src> |
VARSTR |
|
Hostname of source VGX instance |
<ver> |
VARSTR |
|
Source VGX instance version |
<stat> |
DWORD |
|
Status code = 1 |
7.2.2. System Detach
# op opcode tms src ver stat syd 003012F5 HHHHHHHHHHHHHHHH ... ... 00000000
| Field | Type | Format | Description |
|---|---|---|---|
syd |
STRING |
|
"SYstem Detach" |
003012F5 |
DWORD |
|
syd opcode |
<tms> |
QWORD |
|
Source graph timestamp in milliseconds since 1970 |
<src> |
VARSTR |
|
Hostname of source VGX instance |
<ver> |
VARSTR |
|
Source VGX instance version |
<stat> |
DWORD |
|
Status code = 0 |
7.2.3. Clear Registry
# op opcode rcl 003021FD
| Field | Type | Format | Description |
|---|---|---|---|
rcl |
STRING |
|
"Registry CLear" |
003021FD |
DWORD |
|
rcl opcode |
7.2.4. Similarity config
# op opcode nsg nsi vsz vmi cm
jm cx jx ham sim
scf 1030311C HHHHHHHH HHHHHHHH HHHHHHHH HHHHHHHH HHHHHHHH
HHHHHHHH HHHHHHHH HHHHHHHH HHHHHHHH HHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
scf |
STRING |
|
"Similarity ConFiguration" |
1030311C |
DWORD |
|
scf opcode |
<nsg> |
DWORD |
|
Permutation table segments |
<nsi> |
DWORD |
|
Permutation table significant regions |
<vsz> |
DWORD |
|
Maximum vector size |
<vmi> |
DWORD |
|
Minimum vector intersection |
<cm> |
DWORD |
|
Minimum cosine |
<jm> |
DWORD |
|
Minimum jaccard |
<cx> |
DWORD |
|
Cosine exponent |
<jx> |
DWORD |
|
Jaccard exponent |
<ham> |
DWORD |
|
Hamming threshold |
<sim> |
DWORD |
|
Similarity threshold |
7.2.5. Create new graph
# op opcode vblk t0 opcnt
# id path name
grn 1040511C HHHHHHHH HHHHHHHH HHHHHHHHHHHHHHHH
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh ... ...
| Field | Type | Format | Description |
|---|---|---|---|
grn |
STRING |
|
"GRaph New" |
1040511C |
DWORD |
|
grn opcode |
<vblk> |
DWORD |
|
Vertex block order |
<t0> |
DWORD |
|
Inception time |
<opcnt> |
QWORD |
|
Operation count |
<id> |
m128 |
|
Graph objectid |
<path> |
VARSTR |
|
Graph path |
<name> |
VARSTR |
|
Graph name |
7.2.6. Delete graph from memory
# op opcode id grd 0040521D hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
| Field | Type | Format | Description |
|---|---|---|---|
grd |
STRING |
|
"GRaph Delete" |
0040521D |
DWORD |
|
grd opcode |
<id> |
m128 |
|
Objectid of graph to remove from memory |
7.2.7. Transmit Raw Data
# op opcode nparts pn datapart
# sz obid
dat 1030DA1E HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH ...
HHHHHHHHHHHHHHHH hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
| Field | Type | Format | Description |
|---|---|---|---|
dat |
STRING |
|
"DATa" |
1030DA1E |
DWORD |
|
dat opcode |
<nparts> |
QWORD |
|
Number of dataparts (separate dat operators) used to transfer the object |
<pn> |
QWORD |
|
Current datapart for this object transfer |
<datapart> |
VARSTR |
|
Data payload |
<sz> |
QWORD |
|
Number of bytes in payload |
<obid> |
m128 |
|
Object identifier |
7.3. Graph Instance Operators
These operators may appear in operations of type 1001, which modify graph instances.
OP 1001 <opgraph>
grt 0040531D <vtyp> <ntrunc>
grp 1040551E <ord> <sz> <nk> <ns> <np> <nv> <nd> <nr> <nt> <flg>
grs 1040561E <ord> <sz> <nk> <ns> <np> <nv> <nd> <nr> <nt> <flg>
vea 10E0011C <hash> <enum> <typestr>
ved 00E0011D <hash> <enum>
rea 10E0021C <hash> <enum> <relstr>
red 00E0021D <hash> <enum>
dea 10E0031C <hash> <enum> <dimstr>
ded 00E0031D <hash> <enum>
kea 10E0041C <hash> <enum> <keystr>
ked 00E0041D <hash> <enum>
sea 10E0051C <str> <obid>
sed 00E0051D <obid>
vxn 1010111C <obid> <tp> <tmc> <tmx> <tmx.arc> <rank> <id>
vxd 0010111D <obid> <ex>
ENDOP <opid> <tms> <crc32c>
| Op | Opcode | Description | Comment |
|---|---|---|---|
0040531D |
Remove all or some vertices from graph |
||
1040551E |
Persist graph to local storage |
||
1040561E |
Assert graph state in terms of object counters |
||
10E0011C |
Define a unique numeric code to represent a vertex type string |
||
00E0011D |
Remove numeric code mapping for vertex type |
||
10E0021C |
Define a unique numeric code to represent a relationship type string |
||
00E0021D |
Remove numeric code mapping for relationship type |
||
10E0031C |
Define a unique numeric code to represent a vector dimension string |
||
00E0031D |
Remove numeric code mapping for vector dimension |
||
10E0041C |
Define a unique numeric code to represent a property key string |
||
00E0041D |
Remove numeric code mapping for property key |
||
10E0051C |
Define a unique numeric code to represent an arbitrary string value |
||
00E0051D |
Remove numeric code mapping for string value |
||
1010111C |
Create new vertex |
||
0010111D |
Delete vertex |
7.3.1. Truncate graph
# op opcode tp ndiscarded grt 0040531D HH HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
grt |
STRING |
|
"GRaph Truncate" |
0040531D |
DWORD |
|
grt opcode |
<tp> |
BYTE |
|
Remove all vertices with specified type enumeration code, or remove all vertices when |
<ndiscarded> |
QWORD |
|
Number or vertices discarded from graph (for validation) |
7.3.2. Persist graph to local storage
# op opcode ord sz nk
# ns np nv
# nd nr nt flg
grp 1040551E HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
HHHHHHHH HHHH HH HH
| Field | Type | Format | Description |
|---|---|---|---|
grp |
STRING |
|
"GRaph Persist" |
1040551E |
DWORD |
|
grp opcode |
<ord> |
QWORD |
|
Graph order (number of vertices) |
<sz> |
QWORD |
|
Graph size (number of arcs) |
<nk> |
QWORD |
|
Number of unique property keys |
<ns> |
QWORD |
|
Number of unique property string values |
<np> |
QWORD |
|
Total number of vertex properties |
<nv> |
QWORD |
|
Number of vector instances |
<nd> |
QWORD |
|
Number of unique vector dimensions |
<nr> |
QWORD |
|
Number of relationship type enumerations |
<nt> |
QWORD |
|
Number of vertex type enumerations |
<flg> |
QWORD |
|
Internal flags |
7.3.3. Assert graph state
# op opcode ord sz nk
# ns np nv
# nd nr nt flg
grs 1040561E HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
HHHHHHHH HHHH HH HH
| Field | Type | Format | Description |
|---|---|---|---|
grs |
STRING |
|
"GRaph State" |
1040561E |
DWORD |
|
grs opcode |
<ord> |
QWORD |
|
Graph order (number of vertices) |
<sz> |
QWORD |
|
Graph size (number of arcs) |
<nk> |
QWORD |
|
Number of unique property keys |
<ns> |
QWORD |
|
Number of unique property string values |
<np> |
QWORD |
|
Total number of vertex properties |
<nv> |
QWORD |
|
Number of vector instances |
<nd> |
QWORD |
|
Number of unique vector dimensions |
<nr> |
QWORD |
|
Number of relationship type enumerations |
<nt> |
QWORD |
|
Number of vertex type enumerations |
<flg> |
QWORD |
|
Internal flags |
7.3.4. Add vertex type enumeration
# op opcode hash enum typestr vea 10E0011C HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH ...
| Field | Type | Format | Description |
|---|---|---|---|
vea |
STRING |
|
"Vertex Enumeration Add" |
10E0011C |
DWORD |
|
vea opcode |
<hash> |
QWORD |
|
Hash of <type> string |
<enum> |
QWORD |
|
Vertex type enumeration code representing string <typestr> |
<typestr> |
VARSTR |
|
Vertex type string enumerated as <enum> |
7.3.5. Delete vertex type enumeration
# op opcode hash enum ved 00E0011D HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
ved |
STRING |
|
"Vertex Enumeration Delete" |
00E0011D |
DWORD |
|
ved opcode |
<hash> |
QWORD |
|
Hash of enumerated vertex type string to delete |
<enumtype> |
QWORD |
|
Vertex type enumeration code |
7.3.6. Add relationship type enumeration
# op opcode hash enum relstr rea 10E0021C HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH ...
| Field | Type | Format | Description |
|---|---|---|---|
rea |
STRING |
|
"Relationship Enumeration Add" |
10E0021C |
DWORD |
|
rea opcode |
<hash> |
QWORD |
|
Hash of <relstr> |
<enum> |
QWORD |
|
Relationship type enumeration code representing string <relstr> |
<relstr> |
VARSTR |
|
Relationship type string enumerated as <enum> |
7.3.7. Delete relationship type enumeration
# op opcode hash enum red 00E0021D HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
red |
STRING |
|
"Relationship Enumeration Delete" |
00E0021D |
DWORD |
|
red opcode |
<hash> |
QWORD |
|
Hash of enumerated string relationship string to delete |
<enum> |
QWORD |
|
Relationship type enumeration code |
7.3.8. Add dimension enumeration
# op opcode hash enum dimstr dea 10E0031C HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH ...
| Field | Type | Format | Description |
|---|---|---|---|
dea |
STRING |
|
"Dimension Enumeration Add" |
10E0031C |
DWORD |
|
dea opcode |
<hash> |
QWORD |
|
Hash of <dimstr> |
<enum> |
QWORD |
|
Dimension enumeration code representing string <dimstr> |
<dimstr> |
VARSTR |
|
Dimension string enumerated as <enum> |
7.3.9. Delete dimension enumeration
# op opcode hash enum ded 00E0031D HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
ded |
STRING |
|
"Dimension Enumeration Delete" |
00E0031D |
DWORD |
|
ded opcode |
<hash> |
QWORD |
|
Hash of enumerated dimension string to delete |
<enum> |
QWORD |
|
Dimension string enumeration code |
7.3.10. Add key enumeration
# op opcode hash enum keystr kea 10E0041C HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH ...
| Field | Type | Format | Description |
|---|---|---|---|
kea |
STRING |
|
"Key Enumeration Add" |
10E0041C |
DWORD |
|
kea opcode |
<hash> |
QWORD |
|
Hash of <keystr> |
<enum> |
QWORD |
|
Key enumeration code representing string <keystr> |
<keystr> |
VARSTR |
|
Key string enumerated as <enum> |
7.3.11. Delete key enumeration
# op opcode hash enum ked 00E0041D HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
ked |
STRING |
|
"Key Enumeration Delete" |
00E0041D |
DWORD |
|
ked opcode |
<hash> |
QWORD |
|
Hash of enumerated key string to delete |
<enum> |
QWORD |
|
Key string enumeration code |
7.3.12. Add string value enumeration
# op opcode str obid sea 10E0051C ... hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
| Field | Type | Format | Description |
|---|---|---|---|
sea |
STRING |
|
"String Enumeration Add" |
10E0051C |
DWORD |
|
sea opcode |
<str> |
VARSTR |
|
String value enumerated as <obid> |
<obid> |
m128 |
|
String enumeration code representing string <str> |
7.3.13. Delete string value enumeration
# op opcode obid sed 00E0051D hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
| Field | Type | Format | Description |
|---|---|---|---|
sed |
STRING |
|
"String Enumeration Delete" |
00E0051D |
DWORD |
|
sed opcode |
<obid> |
m128 |
|
Enumeration code for string to delete |
7.3.14. Create new vertex
# op opcode obid tp tmc
tmx tmx.arc rank id
vxn 1010111C hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh HH HHHHHHHH
HHHHHHHH HHHHHHHH HHHHHHHHHHHHHHHH ...
| Field | Type | Format | Description |
|---|---|---|---|
vxn |
STRING |
|
"VerteX New" |
1000111C |
DWORD |
|
vxn opcode |
<obid> |
m128 |
|
Vertex internalid |
<tp> |
BYTE |
|
Vertex type enumeration code, as defined by a preceding vea operator |
<tmc> |
DWORD |
|
Vertex creation time, in seconds since 1970 |
<tmx> |
DWORD |
|
Vertex expiration time, in seconds since 1970, or |
<tmx.arc> |
DWORD |
|
Earliest arc expiration time for vertex outarc, in seconds since 1970, or |
<rank> |
QWORD |
|
Two single-precision floats packed as qword, representing vertex.c0 and vertex.c1. |
<id> |
VARSTR |
|
Vertex identifier |
7.3.15. Delete vertex
# op opcode obid ex vxd 0010111D hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh HH
| Field | Type | Format | Description |
|---|---|---|---|
vxd |
STRING |
|
"VerteX Delete" |
0010111D |
DWORD |
|
vxd opcode |
<obid> |
m128 |
|
Vertex internalid |
<ex> |
BYTE |
|
Nonzero if TTL triggered deletion, otherwise zero |
7.4. Graph State Operators
These operators may appear in operations of type 100A, which alter the overall state of graphs.
OP 100A <opgraph>
grr 00500115
grw 10500215
gre 10600315
gri 00600415
tic 1070051E <tms>
evx 1080061E <ts> <tmx>
ENDOP <crc32c>
| Op | Opcode | Description | Comment |
|---|---|---|---|
00500115 |
Make graph readonly |
||
10500215 |
Make graph writable |
||
10600315 |
Enable graph events |
||
00600415 |
Disable graph events |
||
1070051E |
Send a synchronization timestamp |
||
1080061E |
Execute events |
7.4.1. Readonly graph
# op opcode grr 00500115
| Fields | Type | Format | Description |
|---|---|---|---|
grr |
STRING |
|
"GRaph Readonly" |
00500115 |
DWORD |
|
grr opcode |
7.4.2. Readwrite graph
# op opcode grw 10500215
| Fields | Type | Format | Description |
|---|---|---|---|
grw |
STRING |
|
"GRaph Writable" |
10500215 |
DWORD |
|
grw opcode |
7.4.3. Enable graph events
# op opcode gre 10600315
| Fields | Type | Format | Description |
|---|---|---|---|
gre |
STRING |
|
"GRaph Events" |
10600315 |
DWORD |
|
gre opcode |
7.4.4. Disable graph events
# op opcode gri 00600415
| Fields | Type | Format | Description |
|---|---|---|---|
gri |
STRING |
|
"GRaph Idle" |
00600415 |
DWORD |
|
gri opcode |
7.4.5. Resync graph time
# op opcode tms tic 1070051E HHHHHHHHHHHHHHHH
| Fields | Type | Format | Description |
|---|---|---|---|
tic |
STRING |
|
"TICk" |
1070051E |
DWORD |
|
tic opcode |
<tms> |
QWORD |
|
Milliseconds since 1970 |
7.4.6. Execute events
# op opcode ts tmx evx 1080061E HHHHHHHH HHHHHHHH
| Fields | Type | Format | Description |
|---|---|---|---|
evx |
STRING |
|
"EVents eXecute" |
1080061E |
DWORD |
|
evx opcode |
<ts> |
DWORD |
|
Reference current time (in seconds since 1970) |
<tmx> |
DWORD |
|
Execute events with expiration no later than <tmx> |
7.5. Vertex Instance Operators
These operators may appear in operations of type 2001, which modify vertex instances.
OP 2001 <graph> <vertex>
vxr 1010121A <rank>
vxt 1010131A <tp>
vxx 1010141A <tmx>
vxc 1010151A <man>
vps 1010161C <key> <tp> <high> <low>
vpd 0010161D <key>
vpc 001016FD
vvs 1010171C <vector>
vvd 0010171D
vod 001018FD <ndel>
vid 001019FD <ndel>
vrl 00101C15
arc 1020011C <pred> <head>
ard 002002FD <ex> <ndel> <pred> <head>
ENDOP <opid> <tms> <crc32c>
| Op | Opcode | Description | Comment |
|---|---|---|---|
1010121A |
Set vertex rank |
||
1010131A |
Set vertex type |
||
1010141A |
Set vertex expiration |
||
1010151A |
Convert vertex manifestation |
||
1010161C |
Set vertex property |
||
0010161D |
Delete vertex property |
||
001016FD |
Clear all vertex properties |
||
1010171C |
Set vertex vector |
||
0010171D |
Remove vertex vector |
||
001018FD |
Delete vertex outarcs |
||
001019FD |
Delete vertex inarcs |
||
00101C15 |
Release vertex lock |
||
1020011C |
Create arc |
||
002002FD |
Delete arc |
7.5.1. Set vertex rank
# op opcode rank vxr 1010121A HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
vxr |
STRING |
|
"VerteX Rank" |
1010121A |
DWORD |
|
vxr opcode |
<rank> |
QWORD |
|
Two single-precision floats packed as qword, representing vertex.c0 and vertex.c1. |
7.5.1.1. Rank qword encoding
Then qword expressed with 16 hex digits HHHHHHHHHHHHHHHH packs two single-precision float (32 bit) values. The upper 32 bits represent vertex.c0 and the lower 32 bits represent vertex.c1. The packed value can be re-interpreted as two floats using the following Python code:
import struct
rankqword = "000000003F800000" # example qword
c1, c0 = struct.unpack( "ff", struct.pack( "Q", long(rankqword, 16) ) )
7.5.2. Set vertex type
# op opcode tp vxt 1010131A HH
| Field | Type | Format | Description |
|---|---|---|---|
vxt |
STRING |
|
"VerteX Type" |
1010131A |
DWORD |
|
vxt opcode |
<tp> |
BYTE |
|
Vertex type enumeration code, as defined by preceding vea operator |
7.5.3. Set vertex expiration
# op opode tmx vxx 1010141A HHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
vxx |
STRING |
|
"VerteX eXpiration" |
1010141A |
DWORD |
|
vxx opcode |
<tmx> |
DWORD |
|
Vertex expiration time, in seconds since 1970, or |
7.5.4. Convert vertex manifestation
# op opcode man vxc 1010151A HH
| Field | Type | Format | Description |
|---|---|---|---|
vxc |
STRING |
|
"VerteX Convert" |
1010151A |
DWORD |
|
vxc opcode |
<man> |
BYTE |
|
|
7.5.5. Set vertex property
# op opcode key tp high low vps 1010161C HHHHHHHHHHHHHHHH HH HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
vps |
STRING |
|
"Vertex Property Set" |
1010161C |
DWORD |
|
vps opcode |
<key> |
QWORD |
|
Key enumeration code, as defined by a preceding kea operator |
<tp> |
BYTE |
|
|
<high> |
QWORD |
|
Encodes the upper 64 bits of a string enumeration, or always |
<low> |
QWORD |
|
Encodes numeric values, or the lower 64 bits of a string enumeration. |
7.5.5.1. Property value types
| Code | Type | Comment |
|---|---|---|
|
boolean |
<low> will be |
|
integer |
<low> will be in the range |
|
real |
<low> packs a double precision float value as a raw qword, which can be re-interpreted as float value using the following Python code |
|
string |
<high> encodes the upper 64 bits and <low> encodes the lower 64 bits of a 128-bit string enumeration defined by a preceding sea operator. |
|
string |
Same as |
7.5.6. Delete vertex property
# op opcode key vpd 0010161D HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
vpd |
STRING |
|
"Vertex Property Delete" |
0010161D |
DWORD |
|
vpd opcode |
<key> |
QWORD |
|
Key enumeration code, as defined by a preceding kea operator |
7.5.7. Clear all vertex properties
# op opcode vpc 001016FD
| Field | Type | Format | Description |
|---|---|---|---|
vpc |
STRING |
|
"Vertex Properties Clear" |
001016FD |
DWORD |
|
Opcode |
7.5.8. Set vertex vector
# op opcode vector vvs 1010171C ...
| Field | Type | Format | Description |
|---|---|---|---|
vvs |
STRING |
|
"Vertex Vector Set" |
1010171C |
DWORD |
|
vvs opcode |
<vector> |
VARSTR |
|
Vector data string |
7.5.9. Delete vertex vector
# op opcode vvd 0010171D
| Field | Type | Format | Description |
|---|---|---|---|
vvd |
STRING |
|
"Vertex Vector Delete" |
0010171D |
DWORD |
|
vvd opcode |
7.5.10. Remove vertex outarcs
# op opcode ndel vod 001018FD HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
vod |
STRING |
|
"Vertex Outarcs Delete" |
001018FD |
DWORD |
|
vod opcode |
<ndel> |
QWORD |
|
Number of outarcs removed by the operator (for validation) |
7.5.11. Remove vertex inarcs
# op opcode ndel vid 001019FD HHHHHHHHHHHHHHHH
| Field | Type | Format | Description |
|---|---|---|---|
vid |
STRING |
|
"Vertex Inarcs Delete" |
001019FD |
DWORD |
|
vid opcode |
<ndel> |
QWORD |
|
Number of inarcs removed by the operator (for validation) |
7.5.12. Release vertex lock
# op opcode vrl 00101C15
| Field | Type | Format | Description |
|---|---|---|---|
vrl |
STRING |
|
"Vertex Release Lock" |
00101C15 |
DWORD |
|
vrl opcode |
7.5.13. Connect arc
# op opcode pred head arc 1020011C HHHHHHHHHHHHHHHH hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
| Field | Type | Format | Description |
|---|---|---|---|
arc |
STRING |
|
"ARc Connect" |
1020011C |
DWORD |
|
arc opcode |
<pred> |
QWORD |
|
Predicator |
<head> |
m128 |
|
Internalid of head vertex |
7.5.14. Disconnect arc
# op opcode ex ndel pred
# head
ard 002002FD HH HHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHH
hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
| Field | Type | Format | Description |
|---|---|---|---|
ard |
STRING |
|
"ARc Disconnect" |
002002FD |
DWORD |
|
ard opcode |
<ex> |
BYTE |
|
Nonzero if TTL triggered arc deletion, otherwise zero |
<ndel> |
QWORD |
|
Number of (multiple)arcs removed (for validation) |
<pred> |
QWORD |
|
Probe predicator |
<head> |
m128 |
|
Internalid of head vertex |
7.6. Vertex Lock Operators
These operators may appear in operations of type 200A, which atomically acquire a set of vertices.
OP 200A <opgraph>
lxw 10A011F5 <cnt> <vertex1> <vertex2> ... <vertexN>
ENDOP <crc32c>
| Op | Opcode | Description | Comment |
|---|---|---|---|
10A011F5 |
Acquire exclusive write lock(s) on specified vertex instance(s) |
7.6.1. Acquire exclusive write locks
# op opcode cnt vertex1 ... lxw 10A011F5 HHHHHHH hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh ...
| Fields | Type | Format | Description |
|---|---|---|---|
lxw |
STRING |
|
"Lock eXclusive Writable vertices" |
10A011F5 |
DWORD |
|
lxw opcode |
<cnt> |
DWORD |
|
Number of writable vertices to acquire |
<vertexN> |
m128 |
|
Internalid of vertexN to acquire writeable |
7.7. Vertex Unlock Operators
These operators may appear in operations of type 200B, which atomically release a set of previously acquired vertices.
OP 200B <opgraph>
ulv 00A013F5 <cnt> <vertex1> <vertex2> ... <vertexN>
ENDOP <crc32c>
| Op | Opcode | Description | Comment |
|---|---|---|---|
00A013F5 |
Unlock previously acquired lock(s) on the specified vertex instance(s) |
7.7.1. Unlock vertices
# op opcode cnt vertexN ... ulv 00A013F5 HHHHHHHH hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh ...
| Fields | Type | Format | Description |
|---|---|---|---|
ulv |
STRING |
|
"UnLock Vertices" |
00A013F5 |
DWORD |
|
ulv opcode |
<cnt> |
DWORD |
|
Number of vertices to unlock |
<vertexN> |
m128 |
|
Internalid of vertexN to unlock |
