Neo4j-Client
view release on metacpan or search on metacpan
build/lib/src/transaction.c view on Meta::CPAN
/* vi:set ts=4 sw=4 expandtab:
*
* Copyright 2016, Chris Leishman (http://github.com/cleishm)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "../../config.h"
#include "transaction.h"
#include "connection.h"
#include "neo4j-client.h"
#include "memory.h"
#include "result_stream.h"
#include "util.h"
#include "values.h"
#include "atomic.h"
#include <assert.h>
#include <string.h>
#include <stddef.h>
#include <unistd.h>
#include <stdio.h>
neo4j_transaction_t *new_transaction(neo4j_config_t *config, neo4j_connection_t *connection, int timeout, const char *mode, const char *dbname);
int begin_callback(void *cdata, neo4j_message_type_t type, const neo4j_value_t *argv, uint16_t argc);
int commit_callback(void *cdata, neo4j_message_type_t type, const neo4j_value_t *argv, uint16_t argc);
int rollback_callback(void *cdata, neo4j_message_type_t type, const neo4j_value_t *argv, uint16_t argc);
int tx_failure(neo4j_transaction_t *tx);
bool tx_defunct(neo4j_transaction_t *tx);
int tx_commit(neo4j_transaction_t *tx);
int tx_rollback(neo4j_transaction_t *tx);
neo4j_result_stream_t *tx_run(neo4j_transaction_t *tx, const char *statement, neo4j_value_t params, int send);
// rough out the transaction based calls
// there will be bookkeeping to do - handling errors when server state
// is mismatch with the request:
// - when server is READY but run_in_tx is exec'd
// - when server is STREAMING but run is exec'd <- may be handled by the results->starting,
// results->streaming flags
// - when server is TX_READY but run or send is exec'd
// - when server is TX_STREAMING but run or send is exec'd
// erroring when negotiated protocol is not 3+
// Note, BEGIN, COMMIT, ROLLBACK responses don't belong on a results stream. So maybe
// should have a transaction structure, analogous to the results structure, that
// stores info like success responses, failure responses, bookmarks.
// begin_tx - specify timeout and mode, but ignore bookmarks and metadata ATM
// must check neo4j_tx_failure(tx)
neo4j_transaction_t *neo4j_begin_tx(neo4j_connection_t *connection,
int tx_timeout, const char *tx_mode, const char *dbname)
{
REQUIRE(connection != NULL, NULL);
neo4j_config_t *config = connection->config;
if (connection->version < 3)
{
errno = NEO4J_FEATURE_UNAVAILABLE;
char ebuf[256];
neo4j_log_error(connection->logger,
"Cannot create transaction on %p: %s\n", (void *)connection,
neo4j_strerror(errno, ebuf, sizeof(ebuf)));
return NULL;
}
neo4j_transaction_t *tx = new_transaction(config, connection, tx_timeout, tx_mode, dbname);
if (neo4j_session_transact(connection, "BEGIN", begin_callback, tx))
{
neo4j_log_error_errno(tx->logger, "tx begin failed");
tx->failed = 1;
tx->failure = errno;
}
return tx;
}
int begin_callback(void *cdata, neo4j_message_type_t type, const neo4j_value_t *argv, uint16_t argc)
{
assert(cdata != NULL);
assert(argc == 0 || argv != NULL);
neo4j_transaction_t *tx = (neo4j_transaction_t *) cdata;
#ifndef NEOCLIENT_BUILD
if (type == NEO4J_FAILURE_MESSAGE)
#else
if ( MESSAGE_TYPE_IS(type,FAILURE) )
#endif
{
// get FAILURE argv and set tx failure info here
tx->failed = 1;
tx->failure = NEO4J_TRANSACTION_FAILED;
tx->failure_code = neo4j_map_get(argv[0],"code");
tx->failure_message = neo4j_map_get(argv[0],"message");
errno = tx->failure;
neo4j_log_error_errno(tx->logger, "tx begin failed");
return -1;
}
#ifndef NEOCLIENT_BUILD
if (type == NEO4J_IGNORED_MESSAGE)
( run in 0.831 second using v1.01-cache-2.11-cpan-39bf76dae61 )