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 )