//------------------------------------------------ // Register a UDF function in the database. // bool example_register_udf(aerospike* p_as, const char* udf_file_path) { FILE* file = fopen(udf_file_path, "r"); if (! file) { // If we get here it's likely that we're not running the example from // the right directory - the specific example directory. LOG("cannot open script file %s : %s", udf_file_path, strerror(errno)); return false; } // Read the file's content into a local buffer. uint8_t* content = (uint8_t*)malloc(1024 * 1024); if (! content) { LOG("script content allocation failed"); return false; } uint8_t* p_write = content; int read = (int)fread(p_write, 1, 512, file); int size = 0; while (read) { size += read; p_write += read; read = (int)fread(p_write, 1, 512, file); } fclose(file); // Wrap the local buffer as an as_bytes object. as_bytes udf_content; as_bytes_init_wrap(&udf_content, content, size, true); as_error err; as_string base_string; const char * base = as_basename(&base_string, udf_file_path); // Register the UDF file in the database cluster. if (aerospike_udf_put(p_as, &err, NULL, base, AS_UDF_TYPE_LUA, &udf_content) == AEROSPIKE_OK) { // Wait for the system metadata to spread to all nodes. aerospike_udf_put_wait(p_as, &err, NULL, base, 100); } else { LOG("aerospike_udf_put() returned %d - %s", err.code, err.message); } as_string_destroy(&base_string); // This frees the local buffer. as_bytes_destroy(&udf_content); return err.code == AEROSPIKE_OK; }
bool udf_put(const char * filename) { FILE * file = fopen(filename,"r"); if ( !file ) { error("cannot open script file %s : %s", filename, strerror(errno)); return -1; } uint8_t * content = (uint8_t *) malloc(SCRIPT_LEN_MAX); if ( content == NULL ) { error("malloc failed"); return -1; } int size = 0; uint8_t * buff = content; int read = (int)fread(buff, 1, 512, file); while ( read ) { size += read; buff += read; read = (int)fread(buff, 1, 512, file); } fclose(file); as_bytes udf_content; as_bytes_init_wrap(&udf_content, content, size, true); as_error err; as_error_reset(&err); as_string filename_string; const char * base = as_basename(&filename_string, filename); if ( aerospike_udf_put(as, &err, NULL, base, AS_UDF_TYPE_LUA, &udf_content) == AEROSPIKE_OK ) { aerospike_udf_put_wait(as, &err, NULL, base, 100); } else { error("error caused by aerospike_udf_put(): (%d) %s @ %s[%s:%d]", err.code, err.message, err.func, err.file, err.line); } as_string_destroy(&filename_string); as_val_destroy(&udf_content); return err.code == AEROSPIKE_OK; }
bool udf_remove(const char * filename) { as_error err; as_error_reset(&err); as_string filename_string; const char * base = as_basename(&filename_string, filename); if ( aerospike_udf_remove(as, &err, NULL, base) != AEROSPIKE_OK ) { error("error caused by aerospike_udf_remove(): (%d) %s @ %s[%s:%d]", err.code, err.message, err.func, err.file, err.line); } as_string_destroy(&filename_string); WAIT_MS(100); return err.code == AEROSPIKE_OK; }
/** * @return AEROSPIKE_OK if successful. Otherwise an error occurred. */ as_status aerospike_udf_put( aerospike * as, as_error * err, const as_policy_info * policy, const char * filename, as_udf_type type, as_bytes * content) { if (type != AS_UDF_TYPE_LUA) { return as_error_update(err, AEROSPIKE_ERR_PARAM, "Invalid udf type: %d", type); } as_error_reset(err); if (! policy) { policy = &as->config.policies.info; } char* command = NULL; as_string filename_string; const char* filebase = as_basename(&filename_string, filename); uint32_t encoded_len = cf_b64_encoded_len(content->size); char* content_base64 = malloc(encoded_len + 1); cf_b64_encode(content->value, content->size, content_base64); content_base64[encoded_len] = 0; if (! asprintf(&command, "udf-put:filename=%s;content=%s;content-len=%d;udf-type=%s;", filebase, content_base64, encoded_len, as_udf_type_str[type])) { as_string_destroy(&filename_string); free(content_base64); return as_error_set_message(err, AEROSPIKE_ERR_CLIENT, "Udf put asprintf failed"); } as_string_destroy(&filename_string); char* response = 0; as_status status = aerospike_info_any(as, err, policy, command, &response); free(command); free(content_base64); if (status) { return status; } free(response); return AEROSPIKE_OK; }
//------------------------------------------------ // Remove a UDF function from the database. // bool example_remove_udf(aerospike* p_as, const char* udf_file_path) { as_error err; as_string path_string; const char * base = as_basename(&path_string, udf_file_path); if (aerospike_udf_remove(p_as, &err, NULL, base) != AEROSPIKE_OK) { LOG("aerospike_udf_remove() returned %d - %s", err.code, err.message); return false; } as_string_destroy(&path_string); // Wait for the system metadata to spread to all nodes. usleep(100 * 1000); return true; }
bool udf_exists(const char * filename) { as_error err; as_error_reset(&err); as_udf_file file; as_udf_file_init(&file); as_string filename_string; const char * base = as_basename(&filename_string, filename); if ( aerospike_udf_get(as, &err, NULL, base, AS_UDF_TYPE_LUA, &file) != AEROSPIKE_OK ) { error("error caused by aerospike_udf_get: (%d) %s @ %s[%s:%d]", err.code, err.message, err.func, err.file, err.line); } as_string_destroy(&filename_string); as_udf_file_destroy(&file); return err.code == AEROSPIKE_OK; }
/****************************************************************************** * TEST CASES *****************************************************************************/ TEST( key_apply2_file_exists , "apply2: key_apply2 exists" ) { as_error err; as_error_reset(&err); const char * filename = LUA_FILE; as_udf_file file; as_udf_file_init(&file); as_string filename_string; const char * base = as_basename(&filename_string, filename); as_key key; as_key_init(&key, "test", "test", "foo"); if ( aerospike_udf_get(as, &err, NULL, base, AS_UDF_TYPE_LUA, &file) != AEROSPIKE_OK ) { error("error caused by aerospike_udf_get(%s): (%d) %s @ %s[%s:%d]", err.code, err.message, err.func, err.file, err.line); } as_string_destroy(&filename_string); as_udf_file_destroy(&file); } // TEST( key_apply2_getboolean , "apply2: (test,test,foo) <!> key_apply2.getboolean() => 1" ) {
/** ******************************************************************************************************* * Registers a UDF module with the Aerospike DB. * @param self AerospikeClient object * @param args The args is a tuple object containing an argument * list passed from Python to a C function * @param kwds Dictionary of keywords * * Returns an integer status. 0(Zero) is success value. * In case of error,appropriate exceptions will be raised. ******************************************************************************************************* */ PyObject * AerospikeClient_UDF_Put(AerospikeClient * self, PyObject *args, PyObject * kwds) { // Initialize error as_error err; as_error_init(&err); // Python Function Arguments PyObject * py_filename = NULL; long language = 0; PyObject * py_udf_type = NULL; PyObject * py_policy = NULL; PyObject * py_ustr = NULL; uint8_t * bytes = NULL; as_policy_info info_policy; as_policy_info *info_policy_p = NULL; // Python Function Keyword Arguments static char * kwlist[] = {"filename", "udf_type", "policy", NULL}; // Python Function Argument Parsing if ( PyArg_ParseTupleAndKeywords(args, kwds, "O|lO:udf_put", kwlist, &py_filename, &language, &py_policy) == false ) { return NULL; } if(language != AS_UDF_TYPE_LUA) { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "Invalid UDF language"); goto CLEANUP; } py_udf_type = PyLong_FromLong(language); if (!self || !self->as) { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid aerospike object"); goto CLEANUP; } if (!self->is_conn_16) { as_error_update(&err, AEROSPIKE_ERR_CLUSTER, "No connection to aerospike cluster"); goto CLEANUP; } // Convert PyObject into a filename string char *filename = NULL; if (PyUnicode_Check(py_filename)) { py_ustr = PyUnicode_AsUTF8String(py_filename); filename = PyString_AsString(py_ustr); } else if (PyString_Check(py_filename)) { filename = PyString_AsString(py_filename); } else { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Filename should be a string"); goto CLEANUP; } // Convert python object to policy_info pyobject_to_policy_info( &err, py_policy, &info_policy, &info_policy_p, &self->as->config.policies.info); if ( err.code != AEROSPIKE_OK ) { goto CLEANUP; } as_udf_type udf_type = (as_udf_type)PyInt_AsLong(py_udf_type); // Convert lua file to content as_bytes content; FILE * file_p = fopen(filename,"r"); FILE * copy_file_p = NULL; char copy_filepath[AS_CONFIG_PATH_MAX_LEN] = {0}; uint32_t user_path_len = strlen(self->as->config.lua.user_path); memcpy( copy_filepath, self->as->config.lua.user_path, user_path_len); if ( self->as->config.lua.user_path[user_path_len-1] != '/' ) { memcpy( copy_filepath + user_path_len, "/", 1); user_path_len = user_path_len + 1; } char* extracted_filename = strrchr(filename, '/'); if (extracted_filename) { memcpy( copy_filepath + user_path_len, extracted_filename + 1, strlen(extracted_filename) - 1); copy_filepath[user_path_len + strlen(extracted_filename) - 1] = '\0'; } else { memcpy( copy_filepath + user_path_len, filename, strlen(filename)); copy_filepath[user_path_len + strlen(filename)] = '\0'; } if ( !file_p ) { as_error_update(&err, AEROSPIKE_ERR_LUA_FILE_NOT_FOUND, "cannot open script file"); goto CLEANUP; } bytes = (uint8_t *) malloc(SCRIPT_LEN_MAX); if ( bytes == NULL ) { as_error_update(&err, errno, "malloc failed"); goto CLEANUP; } int size = 0; uint8_t * buff = bytes; if (access(self->as->config.lua.user_path, W_OK) == 0) { copy_file_p = fopen(copy_filepath, "r"); if (!copy_file_p) { copy_file_p = fopen(copy_filepath, "w+"); int read = (int)fread(buff, 1, LUA_FILE_BUFFER_FRAME, file_p); if (read && fwrite(buff, 1, read, copy_file_p)) { while (read) { size += read; buff += read; read = (int)fread(buff, 1, LUA_FILE_BUFFER_FRAME, file_p); if (!fwrite(buff, 1, read, copy_file_p)) { break; } } } else { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "Write of lua file to user path failed"); goto CLEANUP; } } else { int read = (int)fread(buff, 1, LUA_FILE_BUFFER_FRAME, file_p); while (read) { size += read; buff += read; read = (int)fread(buff, 1, LUA_FILE_BUFFER_FRAME, file_p); } } } else { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "No permissions to write lua file to user path"); goto CLEANUP; } if (file_p) { fclose(file_p); } if (copy_file_p) { fclose(copy_file_p); } as_bytes_init_wrap(&content, bytes, size, true); // Invoke operation Py_BEGIN_ALLOW_THREADS aerospike_udf_put(self->as, &err, info_policy_p, filename, udf_type, &content); Py_END_ALLOW_THREADS if( err.code != AEROSPIKE_OK ) { as_error_update(&err, err.code, NULL); goto CLEANUP; } else { aerospike_udf_put_wait(self->as, &err, info_policy_p, as_basename(NULL, filename), 2000); } CLEANUP: if(bytes) { free(bytes); } if (py_ustr) { Py_DECREF(py_ustr); } if ( err.code != AEROSPIKE_OK ) { PyObject * py_err = NULL; error_to_pyobject(&err, &py_err); PyObject *exception_type = raise_exception(&err); if(PyObject_HasAttrString(exception_type, "module")) { PyObject_SetAttrString(exception_type, "module", Py_None); } if(PyObject_HasAttrString(exception_type, "func")) { PyObject_SetAttrString(exception_type, "func", Py_None); } PyErr_SetObject(exception_type, py_err); Py_DECREF(py_err); return NULL; } return PyLong_FromLong(0); }