bool
batch_exists_cb(const as_batch_read* results, uint32_t n, void* udata)
{
    TSRMLS_FETCH();
    as_status                   status = AEROSPIKE_OK;
    foreach_callback_udata*     udata_ptr = (foreach_callback_udata*)udata;
    uint32_t                    i = 0;
    zval*                       record_metadata_p = NULL;
    bool                        null_flag = false;

    for (i = 0; i < n; i++) {
        if (results[i].result == AEROSPIKE_OK) {
            MAKE_STD_ZVAL(record_metadata_p);
            array_init(record_metadata_p);
            if (0 != add_assoc_long(record_metadata_p, PHP_AS_RECORD_DEFINE_FOR_GENERATION,
                        results[i].record.gen)) {
                DEBUG_PHP_EXT_DEBUG("Unable to get generation of a record");
                status = AEROSPIKE_ERR;
                goto exit;
            }

            if (0 != add_assoc_long(record_metadata_p, PHP_AS_RECORD_DEFINE_FOR_TTL,
                    results[i].record.ttl)) {
                DEBUG_PHP_EXT_DEBUG("Unable to get ttl of a record");
                status = AEROSPIKE_ERR;
                goto exit;
            }
        } else if (results[i].result == AEROSPIKE_ERR_RECORD_NOT_FOUND) {
            null_flag = true;
        } else {
            return false;
        }

        populate_result_for_get_exists_many((as_key *) results[i].key,
                udata_ptr->udata_p, record_metadata_p, udata_ptr->error_p,
                null_flag TSRMLS_CC);
        if (AEROSPIKE_OK != udata_ptr->error_p->code) {
            DEBUG_PHP_EXT_DEBUG("%s", udata_ptr->error_p->message);
            goto cleanup;
        } else {
            continue;
        }

        if (null_flag) {
            goto cleanup;
        }
cleanup:
        if (record_metadata_p && AEROSPIKE_OK != udata_ptr->error_p->code) {
            zval_ptr_dtor(&record_metadata_p);
        }
        goto exit;
    }

exit:
    if (udata_ptr->error_p->code != AEROSPIKE_OK) {
        return false;
    }
    return true;
}
/*
 ******************************************************************************************************
 Applies a UDF to a record at the Aerospike DB.
 *
 * @param aerospike_obj_p           The C client's aerospike object.
 * @param as_key_p                  The C client's as_key that identifies the
 *                                  record on which UDF will be applied.
 * @param error_p                   The C client's as_error to be set to the encountered error.
 * @param module_p                  The name of the UDF module registered
 *                                  against the Aerospike DB.
 * @param function_p                The name of the function to be applied to
 *                                  the record.
 * @param args_pp                   An array of arguments for the UDF.
 * @param return_value_p            It will contain result value of calling the
 *                                  UDF.
 * @param options_p                 The optional policy.
 *
 * @return AEROSPIKE_OK if success. Otherwise AEROSPIKE_x.
 ******************************************************************************************************
 */
extern as_status
aerospike_udf_apply(Aerospike_object* aerospike_obj_p,
        as_key* as_key_p, as_error* error_p, char* module_p, char* function_p,
        zval** args_pp, zval* return_value_p, zval* options_p)
{
    as_arraylist                args_list;
    as_arraylist*               args_list_p = NULL;
    as_static_pool              udf_pool = {0};
    as_val*                     udf_result_p = NULL;
    foreach_callback_udata      udf_result_callback_udata;
    uint32_t                    serializer_policy = -1;
    as_policy_apply             apply_policy;
    TSRMLS_FETCH_FROM_CTX(aerospike_obj_p->ts);

    set_policy_udf_apply(&aerospike_obj_p->as_ref_p->as_p->config, &apply_policy, &serializer_policy,
            options_p, error_p TSRMLS_CC);

    if (AEROSPIKE_OK != (error_p->code)) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    if ((*args_pp)) {
        as_arraylist_inita(&args_list,
                zend_hash_num_elements(Z_ARRVAL_PP(args_pp)));
        args_list_p = &args_list;
        AS_LIST_PUT(NULL, args_pp, args_list_p, &udf_pool, serializer_policy, error_p TSRMLS_CC);
    }

    if (AEROSPIKE_OK != (aerospike_key_apply(aerospike_obj_p->as_ref_p->as_p,
                    error_p, &apply_policy, as_key_p, module_p, function_p,
                    (as_list *) args_list_p, &udf_result_p))) {
        DEBUG_PHP_EXT_DEBUG("%s", error_p->message);
        goto exit;
    }

    if (return_value_p) {
        udf_result_callback_udata.udata_p = return_value_p;
        udf_result_callback_udata.error_p = error_p;
        AS_DEFAULT_GET(NULL, udf_result_p, &udf_result_callback_udata);
    }
     
exit:
    if (udf_result_p) {
        as_val_destroy(udf_result_p);
    }
    
    if (args_list_p) {
        as_arraylist_destroy(args_list_p);
    }

    /* clean up the as_* objects that were initialised */
    aerospike_helper_free_static_pool(&udf_pool);

    return error_p->code;
}
/*
 ******************************************************************************************************
 Get the code of registered UDF module.
 *
 * @param aerospike_obj_p           The C client's aerospike object.
 * @param error_p                   The C client's as_error to be set to the encountered error.
 * @param module_p                  The name of the UDF module to get from the
 *                                  server.
 * @param module_len                Length of UDF module name.
 * @param udf_code_p                Code of the UDF to be populated by this
 *                                  function.
 * @param language                  The Aerospike::UDF_TYPE_* constant.
 * @param options_p                 The optional policy.
 *
 * @return AEROSPIKE_OK if success. Otherwise AEROSPIKE_x.
 ******************************************************************************************************
 */
extern as_status
aerospike_get_registered_udf_module_code(Aerospike_object* aerospike_obj_p,
        as_error* error_p, char* module_p, zval* udf_code_p,
        long language, zval* options_p)
{
    uint32_t                init_udf_file = 0;
    as_udf_file             udf_file;
    as_policy_info          info_policy;
    TSRMLS_FETCH_FROM_CTX(aerospike_obj_p->ts);

    set_policy(&aerospike_obj_p->as_ref_p->as_p->config, NULL, NULL,
            NULL, NULL, &info_policy, NULL, NULL, NULL, options_p,
            error_p TSRMLS_CC);
    if (AEROSPIKE_OK != (error_p->code)) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    as_udf_file_init(&udf_file);
    init_udf_file = 1;
    
    if (AEROSPIKE_OK != aerospike_udf_get(aerospike_obj_p->as_ref_p->as_p,
                error_p, &info_policy, module_p, language, &udf_file)) {
        DEBUG_PHP_EXT_ERROR("%s", error_p->message);
        goto exit;
    }

    ZVAL_STRINGL(udf_code_p, (char*) udf_file.content.bytes, udf_file.content.size, 1);
exit:
    if (init_udf_file) {
        as_udf_file_destroy(&udf_file);
    }
    return error_p->code;
}
/*
 *******************************************************************************************************
 * Wrapper function to perform an aerospike_key_remove within the C client.
 *
 * @param as_object_p           The C client's aerospike object.
 * @param as_key_p              The C client's as_key that identifies the record.
 * @param error_p               The as_error to be populated by the function
 *                              with the encountered error if any.
 * @param options_p             The user's optional policy options to be used if set, else defaults.
 *
 *******************************************************************************************************
 */
extern as_status 
aerospike_record_operations_remove(aerospike* as_object_p,
                                   as_key* as_key_p,
                                   as_error *error_p,
                                   zval* options_p)
{
    as_status                   status = AEROSPIKE_OK;
    as_policy_remove            remove_policy;

    if ( (!as_key_p) || (!error_p) ||
         (!as_object_p)) {
        status = AEROSPIKE_ERR;
        goto exit;
    }

    set_policy(NULL, NULL, NULL, &remove_policy, NULL, NULL, options_p, error_p);
    if (AEROSPIKE_OK != (status = (error_p->code))) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    if (AEROSPIKE_OK != (status = aerospike_key_remove(as_object_p, error_p,
                    &remove_policy, as_key_p))) {
        goto exit;
    }
exit: 
    return(status);
}
/*
 ******************************************************************************************************
 Lists the UDF modules registered with the server.
 *
 * @param aerospike_obj_p           The C client's aerospike object.
 * @param error_p                   The C client's as_error to be set to the encountered error.
 * @param array_of_modules_p        An array of registered UDF modules
 *                                  against the Aerospike DB to be populated by
 *                                  this function.
 * @param language                  Optionally filters a subset of modules
 *                                  matching the given type.
 * @options_p                       The optional parameters to the
 *                                  Aerospike::listRegistered().
 *
 * @return AEROSPIKE_OK if success. Otherwise AEROSPIKE_x.
 ******************************************************************************************************
 */
extern as_status
aerospike_list_registered_udf_modules(Aerospike_object* aerospike_obj_p,
        as_error* error_p, zval* array_of_modules_p, long language,
        zval* options_p)
{
    as_udf_files            udf_files;
    uint32_t                init_udf_files = 0; 
    uint32_t                i=0;
    as_policy_info          info_policy;

    if ((language != -1) && ((language & AS_UDF_TYPE) != AS_UDF_TYPE)) {
            PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR_PARAM,
                    "Invalid Value for language");
            DEBUG_PHP_EXT_ERROR("Invalid value for language");
            goto exit;
    }

    set_policy(NULL, NULL, NULL, NULL, &info_policy, NULL, options_p, error_p);
    if (AEROSPIKE_OK != (error_p->code)) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    as_udf_files_init(&udf_files, 0);
    init_udf_files = 1;
    if (AEROSPIKE_OK != aerospike_udf_list(aerospike_obj_p->as_ref_p->as_p,
                error_p, &info_policy, &udf_files)) {
        DEBUG_PHP_EXT_ERROR(error_p->message);
        goto exit;
    }

    for (i = 0; i < udf_files.size; i++) {
        if ((language != -1) && ((udf_files.entries[i].type) != 
                    (language - AS_UDF_TYPE))) {
                continue;
        }
        zval* module_p = NULL;
        MAKE_STD_ZVAL(module_p);
        array_init(module_p);
        add_assoc_stringl(module_p, UDF_MODULE_NAME, udf_files.entries[i].name,
                strlen(udf_files.entries[i].name), 1);
        add_assoc_long(module_p, UDF_MODULE_TYPE,
                (udf_files.entries[i].type + AS_UDF_TYPE));
        add_next_index_zval(array_of_modules_p, module_p);
    }

exit:
    if (init_udf_files) {
        as_udf_files_destroy(&udf_files);
    }
    return error_p->code;
}
/*
 *******************************************************************************************************
 * Wrapper function to remove bin(s) from a record.
 *
 * @param as_object_p           The C client's aerospike object.
 * @param as_key_p              The C client's as_key that identifies the record.
 * @param bins_p                The PHP array of bins to be removed from the record.
 * @param error_p               The as_error to be populated by the function
 *                              with the encountered error if any.
 * @param options_p             The user's optional policy options to be used if set, else defaults.
 *
 *******************************************************************************************************
 */
extern as_status 
aerospike_record_operations_remove_bin(aerospike* as_object_p,
                                       as_key* as_key_p,
                                       zval* bins_p,
                                       as_error* error_p,
                                       zval* options_p)
{
    as_status           status = AEROSPIKE_OK;
    as_record           rec;
    HashTable           *bins_array_p = Z_ARRVAL_P(bins_p);
    HashPosition        pointer;
    zval                **bin_names;
    as_policy_write     write_policy;

    as_record_inita(&rec, zend_hash_num_elements(bins_array_p));
    
    if ((!as_object_p) || (!error_p) || (!as_key_p) || (!bins_array_p)) {
        status = AEROSPIKE_ERR;
        goto exit;
    }

    set_policy(NULL, &write_policy, NULL, NULL, NULL, NULL, options_p, error_p);
    if (AEROSPIKE_OK != (status = (error_p->code))) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }


    foreach_hashtable(bins_array_p, pointer, bin_names) {
        if (IS_STRING == Z_TYPE_PP(bin_names)) {
            if (!(as_record_set_nil(&rec, Z_STRVAL_PP(bin_names)))) {
                status = AEROSPIKE_ERR;
                goto exit;
            }
        } else {
             status = AEROSPIKE_ERR;
             goto exit;
        }
    }         

    if (AEROSPIKE_OK != (status = aerospike_key_put(as_object_p, error_p,
                    NULL, as_key_p, &rec))) {
         goto exit;
    }

exit:
    as_record_destroy(&rec);
    return(status);
}
static void
populate_result_for_get_exists_many(as_key *key_p, zval *outer_container_p,
        zval *inner_container_p, as_error *error_p, bool null_flag TSRMLS_DC)
{
    if (!(as_val*)(key_p->valuep)) {
        if (!null_flag) {
            if (0 != add_assoc_zval(outer_container_p, (char *) key_p->digest.value, inner_container_p)) {
                PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR,
                        "Unable to get key of a record");
                DEBUG_PHP_EXT_DEBUG("Unable to get key of a record");
            }
        } else {
            if (0 != add_assoc_null(outer_container_p, (char *) key_p->digest.value)) {
                PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR,
                        "Unable to get key of a record");
                DEBUG_PHP_EXT_DEBUG("Unable to get key of a record");
            }
        }
    } else {
        switch (((as_val*)(key_p->valuep))->type) {
            case AS_STRING:
                if (!null_flag) {
                    if (0 != add_assoc_zval(outer_container_p, key_p->value.string.value, inner_container_p)) {
                        PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR,
                                "Unable to get key of a record");
                        DEBUG_PHP_EXT_DEBUG("Unable to get key of a record");
                    }
                } else {
                    if (0 != add_assoc_null(outer_container_p, key_p->value.string.value)) {
                        PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR,
                                "Unable to get key of a record");
                        DEBUG_PHP_EXT_DEBUG("Unable to get key of a record");
                    }
                }
                break;
            case AS_INTEGER:
                if (!null_flag) {
                    if (FAILURE == add_index_zval(outer_container_p, key_p->value.integer.value,
                                inner_container_p)) {
                        PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR,
                                "Unable to get key of a record");
                        DEBUG_PHP_EXT_DEBUG("Unable to get key of a record");
                    }
                } else {
                    if (0 != add_index_null(outer_container_p, key_p->value.integer.value)) {
                        PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR,
                                "Unable to get key of a record");
                        DEBUG_PHP_EXT_DEBUG("Unable to get key of a record");
                    }
                }
                break;
            default:
                break;
        }
    }
}
/*
 ******************************************************************************************************
 Remove a UDF module from the aerospike DB.
 *
 * @param aerospike_obj_p           The C client's aerospike object.
 * @param error_p                   The C client's as_error to be set to the encountered error.
 * @param module_p                  The name of the UDF module to remove from the Aerospike DB.
 * @param module_len                The module name length.
 * @param options_p                 The optional policy.
 *
 * @return AEROSPIKE_OK if success. Otherwise AEROSPIKE_x.
 ******************************************************************************************************
 */
extern as_status
aerospike_udf_deregister(Aerospike_object* aerospike_obj_p,
        as_error* error_p, char* module_p, zval* options_p)
{
    as_policy_info          info_policy;
    
    set_policy(NULL, NULL, NULL, NULL, &info_policy, NULL, options_p, error_p);
    if (AEROSPIKE_OK != (error_p->code)) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    if (AEROSPIKE_OK != aerospike_udf_remove(aerospike_obj_p->as_ref_p->as_p,
                error_p, NULL, module_p)) {
        DEBUG_PHP_EXT_ERROR(error_p->message);
        goto exit;
    }
exit:
    return error_p->code;
}
/*
 ******************************************************************************************************
 Get the code of registered UDF module.
 *
 * @param aerospike_obj_p           The C client's aerospike object.
 * @param error_p                   The C client's as_error to be set to the encountered error.
 * @param module_p                  The name of the UDF module to get from the
 *                                  server.
 * @param module_len                Length of UDF module name.
 * @param udf_code_p                Code of the UDF to be populated by this
 *                                  function.
 * @param language                  The Aerospike::UDF_TYPE_* constant.
 * @param options_p                 The optional policy.
 *
 * @return AEROSPIKE_OK if success. Otherwise AEROSPIKE_x.
 ******************************************************************************************************
 */
extern as_status
aerospike_get_registered_udf_module_code(Aerospike_object* aerospike_obj_p,
        as_error* error_p, char* module_p, zval* udf_code_p,
        long language, zval* options_p)
{
    uint32_t                init_udf_file = 0;
    as_udf_file             udf_file;
    as_policy_info          info_policy;

    if ((language & AS_UDF_TYPE) != AS_UDF_TYPE) {
            PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR_PARAM,
                    "Invalid Value for language");
            DEBUG_PHP_EXT_ERROR("Invalid value for language");
            goto exit;
    }

    set_policy(NULL, NULL, NULL, NULL, &info_policy, NULL, options_p, error_p);
    if (AEROSPIKE_OK != (error_p->code)) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    as_udf_file_init(&udf_file);
    init_udf_file = 1;
    
    if (AEROSPIKE_OK != aerospike_udf_get(aerospike_obj_p->as_ref_p->as_p,
                error_p, &info_policy, module_p, (language - AS_UDF_TYPE),
                &udf_file)) {
        DEBUG_PHP_EXT_ERROR(error_p->message);
        goto exit;
    }

    ZVAL_STRINGL(udf_code_p, udf_file.content.bytes, udf_file.content.size, 1);
exit:
    if (init_udf_file) {
        as_udf_file_destroy(&udf_file);
    }
    return error_p->code;
}
/*
 *******************************************************************************************************
 * Wrapper function to perform an aerospike_key_exists within the C client.
 *
 * @param as_object_p           The C client's aerospike object.
 * @param as_key_p              The C client's as_key that identifies the record.
 * @param error_p               The as_error to be populated by the function
 *                              with the encountered error if any.
 * @param metadata_p            The return metadata for the exists/getMetadata API to be 
 *                              populated by this function.
 * @param options_p             The user's optional policy options to be used if set, else defaults.
 *
 *******************************************************************************************************
 */
extern as_status aerospike_record_operations_exists(aerospike* as_object_p,
                                                    as_key* as_key_p,
                                                    as_error *error_p,
                                                    zval* metadata_p,
                                                    zval* options_p)
{
    as_status                   status = AEROSPIKE_OK;
    as_policy_read              read_policy;
    as_record*                  record_p = NULL;

    if ( (!as_key_p) || (!error_p) ||
         (!as_object_p) || (!metadata_p)) {
        status = AEROSPIKE_ERR;
        goto exit;
    }

    set_policy(&read_policy, NULL, NULL, NULL, NULL, NULL, options_p, error_p);
    if (AEROSPIKE_OK != (status = (error_p->code))) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }
  
    if (AEROSPIKE_OK != (status = aerospike_key_exists(as_object_p, error_p,
                    &read_policy, as_key_p, &record_p))) {
        goto exit;
    }

    add_assoc_long(metadata_p, "generation", record_p->gen);
    add_assoc_long(metadata_p, "ttl", record_p->ttl);

exit:
    if (record_p) {
        as_record_destroy(record_p);
    }

    return(status);   
}
/*
 ******************************************************************************************************
 Registers a UDF module.
 *
 * @param aerospike_obj_p           The C client's aerospike object.
 * @param error_p                   The C client's as_error to be set to the encountered error.
 * @param path_p                    The path to the module on the client side
 * @param language                  The Aerospike::UDF_TYPE_* constant.
 * @param options_p                 The optional policy.
 *
 * @return AEROSPIKE_OK if success. Otherwise AEROSPIKE_x.
 ******************************************************************************************************
 */
extern as_status
aerospike_udf_register(Aerospike_object* aerospike_obj_p, as_error* error_p,
        char* path_p, char* module_p, long language, zval* options_p)
{
    FILE*                   file_p = NULL;
    uint32_t                size = 0;
    uint32_t                content_size;
    uint8_t*                bytes_p = NULL;
    uint8_t*                buff_p = NULL;
    uint32_t                read;
    as_bytes                udf_content;
    as_bytes*               udf_content_p = NULL;
    as_policy_info          info_policy;
    TSRMLS_FETCH_FROM_CTX(aerospike_obj_p->ts);

    set_policy(&aerospike_obj_p->as_ref_p->as_p->config, NULL,
            NULL, NULL, NULL, &info_policy, NULL, NULL, NULL,
            options_p, error_p TSRMLS_CC);
    if (AEROSPIKE_OK != (error_p->code)) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    file_p = fopen(path_p, "r");

    if (!file_p) {
        PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR_UDF_NOT_FOUND,
                "Cannot open script file");
        DEBUG_PHP_EXT_DEBUG("Cannot open script file");
        goto exit;
    }

    fseek(file_p, 0L, SEEK_END);
    content_size = ftell(file_p);
    fseek(file_p, 0L, SEEK_SET);

    /*
     * Using emalloc here to maintain consistency of PHP extension.
     * malloc can also be used for C-SDK.
     * if emalloc is used, pass parameter 4 of function as_bytes_init_wrap as
     * "false" and handle the freeing up of the same here.
     */
    if (NULL == (bytes_p = (uint8_t *) emalloc(content_size + 1))) {
        PHP_EXT_SET_AS_ERR(error_p, AEROSPIKE_ERR,
                "Memory allocation failed for contents of UDF");
        DEBUG_PHP_EXT_DEBUG("Memory allocation failed for contents of UDF");
        goto exit;
    }

    buff_p = bytes_p;
    read = (int) fread(buff_p, 1, LUA_FILE_BUFFER_FRAME, file_p);
    while (read) {
        size += read;
        buff_p += read;
        read = (int) fread(buff_p, 1, LUA_FILE_BUFFER_FRAME, file_p);
    }

    as_bytes_init_wrap(&udf_content, bytes_p, size, false);
    udf_content_p = &udf_content;
    /*
     * Register the UDF file in the database cluster.
     */
    if (AEROSPIKE_OK != aerospike_udf_put(aerospike_obj_p->as_ref_p->as_p,
                error_p, &info_policy, module_p, language,
                      udf_content_p)) {
        DEBUG_PHP_EXT_DEBUG("%s", error_p->message);
        goto exit;
    } else if (AEROSPIKE_OK !=
            aerospike_udf_put_wait(aerospike_obj_p->as_ref_p->as_p,
                error_p, &info_policy, module_p, 0)) {
        DEBUG_PHP_EXT_DEBUG("%s", error_p->message);
        goto exit;
    }

exit:
    if (file_p) {
        fclose(file_p);
    }

    if (bytes_p) {
        efree(bytes_p);
    }

    if (udf_content_p) {
        as_bytes_destroy(udf_content_p);
    }

    return error_p->code;
}
/*
 *******************************************************************************************************
 * Wrapper function to perform an aerospike_key_oeprate within the C client.
 *
 * @param as_object_p           The C client's aerospike object.
 * @param as_key_p              The C client's as_key that identifies the record.
 * @param options_p             The user's optional policy options to be used if set, else defaults.
 * @param error_p               The as_error to be populated by the function
 *                              with the encountered error if any.
 * @param bin_name_p            The bin name to perform operation upon.
 * @param str                   The string to be appended in case of operation: append.
 * @param offset                The offset to be incremented by in case of operation: increment.
 * @param initial_value         The initial value to be set if record is absent
 *                              in case of operation: increment.
 * @param time_to_live          The ttl for the record in case of operation: touch.
 * @param operation             The operation type.
 *
 *******************************************************************************************************
 */
extern as_status
aerospike_record_operations_ops(aerospike* as_object_p,
                                as_key* as_key_p,
                                zval* options_p,
                                as_error* error_p,
                                int8_t* bin_name_p,
                                int8_t* str,
                                u_int64_t offset,
                                u_int64_t initial_value,
                                u_int64_t time_to_live,
                                u_int64_t operation)
{
    as_status           status = AEROSPIKE_OK;
    as_policy_operate   operate_policy;
    uint32_t            serializer_policy;
    as_record*          get_rec = NULL;
    as_operations       ops;
    as_val*             value_p = NULL;
    as_integer          initial_int_val;
    int16_t             initialize_int = 0;
    const char *select[] = {bin_name_p, NULL};

    as_operations_inita(&ops, 1);
    as_policy_operate_init(&operate_policy);

    if ((!as_object_p) || (!error_p) || (!as_key_p)) {
        status = AEROSPIKE_ERR;
        goto exit;
    }

    set_policy(NULL, NULL, &operate_policy, NULL, NULL, &serializer_policy,
            options_p, error_p);
    if (AEROSPIKE_OK != (status = (error_p->code))) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    switch(operation) {
        case AS_OPERATOR_APPEND:
            as_operations_add_append_str(&ops, bin_name_p, str);
            break;
        case AS_OPERATOR_PREPEND:
            as_operations_add_prepend_str(&ops, bin_name_p, str);
            break;
        case AS_OPERATOR_INCR:
            if (AEROSPIKE_OK != (status = aerospike_key_select(as_object_p,
                            error_p, NULL, as_key_p, select, &get_rec))) {
                goto exit;
            } else {
                if (NULL != (value_p = (as_val *) as_record_get (get_rec, bin_name_p))) {
                   if (AS_NIL == value_p->type) {
                       as_integer_init(&initial_int_val, initial_value);
                       initialize_int = 1;
                       if (!as_operations_add_write(&ops, bin_name_p,
                                   (as_bin_value*) &initial_int_val)) {
                           status = AEROSPIKE_ERR;
                           goto exit;
                       }
                   } else {
                       as_operations_add_incr(&ops, bin_name_p, offset);
                   }
                } else {
                    status = AEROSPIKE_ERR;
                    goto exit;
                }
            }
            break;
        case AS_OPERATOR_TOUCH:
            ops.ttl = time_to_live;
            as_operations_add_touch(&ops);
            break;
        default:
            status = AEROSPIKE_ERR;
            goto exit;
            break;
    }

    if (AEROSPIKE_OK != (status = aerospike_key_operate(as_object_p, error_p,
                    &operate_policy, as_key_p, &ops, &get_rec))) {
        goto exit;
    }

exit:
     as_operations_destroy(&ops);
     if (get_rec) {
         as_record_destroy(get_rec);
     }
     if (initialize_int) { 
         as_integer_destroy(&initial_int_val);
     }
     return status;
}