diff --git a/src/include/policy.h b/src/include/policy.h index 1a82671647..4359691a89 100644 --- a/src/include/policy.h +++ b/src/include/policy.h @@ -30,6 +30,8 @@ #include #include +#include "types.h" + enum Aerospike_serializer_values { SERIALIZER_NONE, /* default handler for serializer type */ SERIALIZER_PYTHON, @@ -269,8 +271,7 @@ as_status pyobject_to_policy_admin(AerospikeClient *self, as_error *err, as_status pyobject_to_policy_apply(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_apply *policy, as_policy_apply **policy_p, - as_policy_apply *config_apply_policy, - as_exp **exp_list_p); + as_policy_apply *config_apply_policy); typedef enum { SECOND_AS_POLICY_WRITE, @@ -288,49 +289,32 @@ pyobject_to_policy_info(as_error *err, PyObject *py_policy, as_status pyobject_to_policy_query(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_query *policy, as_policy_query **policy_p, - as_policy_query *config_query_policy, - as_exp **exp_list_p); - -as_status pyobject_to_policy_read(AerospikeClient *self, as_error *err, - PyObject *py_policy, as_policy_read *policy, - as_policy_read **policy_p, - as_policy_read *config_read_policy, - as_exp **exp_list_p); + as_policy_query *config_query_policy); as_status pyobject_to_policy_remove(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_remove *policy, as_policy_remove **policy_p, - as_policy_remove *config_remove_policy, - as_exp **exp_list_p); + as_policy_remove *config_remove_policy); // py_policy_also_supports_info_policy_fields only applies if self->validate_keys is true as_status pyobject_to_policy_scan(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_scan *policy, as_policy_scan **policy_p, - as_policy_scan *config_scan_policy, as_exp **exp_list_p, + as_policy_scan *config_scan_policy, bool py_policy_also_supports_info_policy_fields); -// py_policy_also_supports_info_policy_fields only applies if self->validate_keys is true -as_status pyobject_to_policy_write( - AerospikeClient *self, as_error *err, PyObject *py_policy, - as_policy_write *policy, as_policy_write **policy_p, - as_policy_write *config_write_policy, as_exp **exp_list_p, - bool py_policy_also_supports_info_policy_fields); - as_status pyobject_to_policy_operate(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_operate *policy, as_policy_operate **policy_p, - as_policy_operate *config_operate_policy, - as_exp **exp_list_p); + as_policy_operate *config_operate_policy); as_status pyobject_to_policy_batch(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch *policy, as_policy_batch **policy_p, - as_policy_batch *config_batch_policy, - as_exp **exp_list_p); + as_policy_batch *config_batch_policy); as_status pyobject_to_map_policy(as_error *err, PyObject *py_policy, as_map_policy *policy, bool validate_keys); @@ -352,27 +336,82 @@ as_status pyobject_to_hll_policy(as_error *err, PyObject *py_policy, as_status pyobject_to_batch_write_policy(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch_write *policy, - as_policy_batch_write **policy_p, - as_exp **exp_list_p); + as_policy_batch_write **policy_p); as_status pyobject_to_batch_read_policy(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch_read *policy, - as_policy_batch_read **policy_p, - as_exp **exp_list_p); + as_policy_batch_read **policy_p); as_status pyobject_to_batch_apply_policy(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch_apply *policy, - as_policy_batch_apply **policy_p, - as_exp **exp_list_p); + as_policy_batch_apply **policy_p); as_status pyobject_to_batch_remove_policy(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch_remove *policy, - as_policy_batch_remove **policy_p, - as_exp **exp_list_p); - + as_policy_batch_remove **policy_p); + +// These methods are used for setting config-level policies and are re-used for the helper methods +// that set transaction-level policies. +// +// Overrides an as_policy_* *policy* fields using entries from a Python object *py_policy*. +// +// *policy* must point to a valid as_policy_* instance. +// +// If py_policy is NULL, do nothing. Else if it is not a Python dictionary, an error will be raised. +// (We check if it's a dictionary here because *py_policy*'s type is not validated when parsing API arguments) +// +// We only need the AerospikeClient *self* for parsing Python client expressions and to tell whether to validate keys. +// +// *is_this_txn_policy* is required because there are fields that should only be set in *policy* for txn-level +// policies. +// +// Returns AEROSPIKE_OK on success or another status code on error. On error, the err argument is populated. + +as_status as_policy_read_set_from_pyobject(AerospikeClient *self, as_error *err, + PyObject *py_policy, + as_policy_read *policy, + bool is_policy_txn_level); + +as_status as_policy_write_set_from_pyobject(AerospikeClient *self, + as_error *err, PyObject *py_policy, + as_policy_write *policy, + bool is_policy_txn_level); + +as_status as_policy_apply_set_from_pyobject(AerospikeClient *self, + as_error *err, PyObject *py_policy, + as_policy_apply *policy, + bool is_policy_txn_level); + +// These methods are used for setting transaction level policies +// 1. Copies an config-level as_policy_* *src* to a txn-level *dst* policy +// 2. Sets an as_policy_* *dst* from a Python object *py_policy*. to override the defaults from *src* +// *py_policy* must be a Python dictionary, and *src* and *dst* must point to valid as_policy_* instances. +// We only need the AerospikeClient *self* for parsing Python client expressions and to tell whether to validate keys. +// +// Returns AEROSPIKE_OK on success or another status code on error. On error, the err argument is populated. + +as_status as_policy_write_copy_and_set_from_pyobject(AerospikeClient *self, + as_error *err, + PyObject *py_policy, + as_policy_write *dst, + as_policy_write *src); + +as_status as_policy_read_copy_and_set_from_pyobject(AerospikeClient *self, + as_error *err, + PyObject *py_policy, + as_policy_read *dst, + as_policy_read *src); + +as_status as_policy_apply_copy_and_set_from_pyobject(AerospikeClient *self, + as_error *err, + PyObject *py_policy, + as_policy_apply *dst, + as_policy_apply *src); + +// TODO: make consistent // metrics_policy must be declared already // py_metrics_policy must be non-NULL // Returns non-zero integer value on error. diff --git a/src/include/policy_config.h b/src/include/policy_config.h index 1e8c59c927..a788cd5299 100644 --- a/src/include/policy_config.h +++ b/src/include/policy_config.h @@ -19,6 +19,7 @@ #include #include "macros.h" +#include "types.h" as_status set_optional_uint32_property(uint32_t *target_ptr, PyObject *policy_dict, const char *name); @@ -39,10 +40,15 @@ as_status set_optional_gen(as_policy_gen *target_ptr, PyObject *py_policy, as_status set_optional_exists(as_policy_exists *target_ptr, PyObject *py_policy, const char *name); +// Although set_subpolicies is called by AerospikeClient's init method, and it takes in AerospikeClient as a param, +// it should be safe to use because set_subpolicies only reads from self->validate_keys in this case +// We know that self->validate_keys is initialized by the time we call this. +// TODO: refactor set_subpolicies to not depend on AerospikeClient +// // This only sets the err object if an invalid dictionary key is passed // On error, return an error code -as_status set_subpolicies(as_error *err, as_config *config, - PyObject *py_policies, int validate_keys); +as_status set_subpolicies(AerospikeClient *self, as_error *err, + as_config *config, PyObject *py_policies); as_status set_read_policy(as_error *err, as_policy_read *read_policy, PyObject *py_policy, int validate_keys); as_status set_write_policy(as_error *err, as_policy_write *write_policy, diff --git a/src/main/client/apply.c b/src/main/client/apply.c index ed727d6670..8f0a8f3344 100644 --- a/src/main/client/apply.c +++ b/src/main/client/apply.c @@ -63,9 +63,6 @@ PyObject *AerospikeClient_Apply_Invoke(AerospikeClient *self, PyObject *py_key, PyObject *py_umodule = NULL; PyObject *py_ufunction = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - as_static_pool static_pool; memset(&static_pool, 0, sizeof(static_pool)); // Initialisation flags @@ -108,11 +105,21 @@ PyObject *AerospikeClient_Apply_Invoke(AerospikeClient *self, PyObject *py_key, } // Convert python policy object to as_policy_apply - pyobject_to_policy_apply(self, &err, py_policy, &apply_policy, - &apply_policy_p, &self->as->config.policies.apply, - &exp_list_p); - if (err.code != AEROSPIKE_OK) { - goto CLEANUP; + // This is a double check if py_policy is NULL where as_policy_apply_set_from_pyobject + // also checks the same thing before setting the apply policy. + // But this is because for the client config dictionary, as_policy_apply_set_from_pyobject is the only + // place where we check if py_policy is NULL before setting apply policy. + // + // Also, I didn't want to set the pointer to the apply policy in this helper function as well to make + // the latter more simple + if (py_policy) { + as_policy_apply_copy_and_set_from_pyobject( + self, &err, py_policy, &apply_policy, + &self->as->config.policies.apply); + if (err.code != AEROSPIKE_OK) { + goto CLEANUP; + } + apply_policy_p = &apply_policy; } if (PyUnicode_Check(py_module)) { @@ -147,8 +154,8 @@ PyObject *AerospikeClient_Apply_Invoke(AerospikeClient *self, PyObject *py_key, } CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (apply_policy_p) { + as_exp_destroy(apply_policy_p->base.filter_exp); } if (py_umodule) { @@ -209,6 +216,10 @@ PyObject *AerospikeClient_Apply(AerospikeClient *self, PyObject *args, return NULL; } + if (py_policy == Py_None) { + py_policy = NULL; + } + // Invoke Operation return AerospikeClient_Apply_Invoke(self, py_key, py_module, py_function, py_arglist, py_policy); diff --git a/src/main/client/batch_apply.c b/src/main/client/batch_apply.c index 9b8368fc14..81126f510d 100644 --- a/src/main/client/batch_apply.c +++ b/src/main/client/batch_apply.c @@ -124,8 +124,6 @@ static PyObject *AerospikeClient_Batch_Apply_Invoke( as_batch_init(&batch, 0); // For expressions conversion. - as_exp *batch_exp_list_p = NULL; - as_exp *batch_apply_exp_list_p = NULL; PyObject *br_instance = NULL; @@ -177,10 +175,9 @@ static PyObject *AerospikeClient_Batch_Apply_Invoke( sizeof(as_key) * processed_key_count); if (py_policy_batch) { - if (pyobject_to_policy_batch(self, err, py_policy_batch, &policy_batch, - &policy_batch_p, - &self->as->config.policies.batch, - &batch_exp_list_p) != AEROSPIKE_OK) { + if (pyobject_to_policy_batch( + self, err, py_policy_batch, &policy_batch, &policy_batch_p, + &self->as->config.policies.batch) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -188,8 +185,7 @@ static PyObject *AerospikeClient_Batch_Apply_Invoke( if (py_policy_batch_apply) { if (pyobject_to_batch_apply_policy( self, err, py_policy_batch_apply, &policy_batch_apply, - &policy_batch_apply_p, - &batch_apply_exp_list_p) != AEROSPIKE_OK) { + &policy_batch_apply_p) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -270,12 +266,12 @@ static PyObject *AerospikeClient_Batch_Apply_Invoke( as_list_destroy(arglist); } - if (batch_exp_list_p) { - as_exp_destroy(batch_exp_list_p); + if (policy_batch_p) { + as_exp_destroy(policy_batch_p->base.filter_exp); } - if (batch_apply_exp_list_p) { - as_exp_destroy(batch_apply_exp_list_p); + if (policy_batch_apply_p) { + as_exp_destroy(policy_batch_apply_p->filter_exp); } as_batch_destroy(&batch); diff --git a/src/main/client/batch_operate.c b/src/main/client/batch_operate.c index d2e0c53043..d726adeebd 100644 --- a/src/main/client/batch_operate.c +++ b/src/main/client/batch_operate.c @@ -130,11 +130,6 @@ static PyObject *AerospikeClient_Batch_Operate_Invoke( as_batch batch; as_batch_init(&batch, 0); - // For expressions conversion. - as_exp *batch_exp_list_p = NULL; - - as_exp *batch_write_exp_list_p = NULL; - as_vector *unicodeStrVector = as_vector_create(sizeof(char *), 128); as_static_pool static_pool; @@ -207,10 +202,9 @@ static PyObject *AerospikeClient_Batch_Operate_Invoke( sizeof(as_key) * processed_key_count); if (py_policy_batch) { - if (pyobject_to_policy_batch(self, err, py_policy_batch, &policy_batch, - &policy_batch_p, - &self->as->config.policies.batch, - &batch_exp_list_p) != AEROSPIKE_OK) { + if (pyobject_to_policy_batch( + self, err, py_policy_batch, &policy_batch, &policy_batch_p, + &self->as->config.policies.batch) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -218,8 +212,7 @@ static PyObject *AerospikeClient_Batch_Operate_Invoke( if (py_policy_batch_write) { if (pyobject_to_batch_write_policy( self, err, py_policy_batch_write, &policy_batch_write, - &policy_batch_write_p, - &batch_write_exp_list_p) != AEROSPIKE_OK) { + &policy_batch_write_p) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -300,12 +293,12 @@ static PyObject *AerospikeClient_Batch_Operate_Invoke( free(as_vector_get_ptr(unicodeStrVector, i)); } - if (batch_exp_list_p) { - as_exp_destroy(batch_exp_list_p); + if (policy_batch_p) { + as_exp_destroy(policy_batch_p->base.filter_exp); } - if (batch_write_exp_list_p) { - as_exp_destroy(batch_write_exp_list_p); + if (policy_batch_write_p) { + as_exp_destroy(policy_batch_write_p->filter_exp); } as_vector_destroy(unicodeStrVector); diff --git a/src/main/client/batch_read.c b/src/main/client/batch_read.c index 0185062b90..fc384ae7ea 100644 --- a/src/main/client/batch_read.c +++ b/src/main/client/batch_read.c @@ -153,14 +153,10 @@ PyObject *AerospikeClient_BatchRead(AerospikeClient *self, PyObject *args, as_policy_batch policy_batch; as_policy_batch *policy_batch_p = NULL; - // For expressions conversion. - as_exp *batch_exp_list_p = NULL; - if (py_policy_batch) { - if (pyobject_to_policy_batch(self, &err, py_policy_batch, &policy_batch, - &policy_batch_p, - &self->as->config.policies.batch, - &batch_exp_list_p) != AEROSPIKE_OK) { + if (pyobject_to_policy_batch( + self, &err, py_policy_batch, &policy_batch, &policy_batch_p, + &self->as->config.policies.batch) != AEROSPIKE_OK) { goto CLEANUP3; } } @@ -287,8 +283,8 @@ PyObject *AerospikeClient_BatchRead(AerospikeClient *self, PyObject *args, as_batch_destroy(&batch); - if (batch_exp_list_p) { - as_exp_destroy(batch_exp_list_p); + if (policy_batch_p) { + as_exp_destroy(policy_batch_p->base.filter_exp); } CLEANUP2: diff --git a/src/main/client/batch_remove.c b/src/main/client/batch_remove.c index 2cb1e77008..cb721a9ee3 100644 --- a/src/main/client/batch_remove.c +++ b/src/main/client/batch_remove.c @@ -122,11 +122,6 @@ static PyObject *AerospikeClient_Batch_Remove_Invoke( as_batch batch; as_batch_init(&batch, 0); - // For expressions conversion. - as_exp *batch_exp_list_p = NULL; - - as_exp *batch_remove_exp_list_p = NULL; - PyObject *br_instance = NULL; Py_ssize_t keys_size = PyList_Size(py_keys); @@ -172,10 +167,9 @@ static PyObject *AerospikeClient_Batch_Remove_Invoke( sizeof(as_key) * processed_key_count); if (py_policy_batch) { - if (pyobject_to_policy_batch(self, err, py_policy_batch, &policy_batch, - &policy_batch_p, - &self->as->config.policies.batch, - &batch_exp_list_p) != AEROSPIKE_OK) { + if (pyobject_to_policy_batch( + self, err, py_policy_batch, &policy_batch, &policy_batch_p, + &self->as->config.policies.batch) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -183,8 +177,7 @@ static PyObject *AerospikeClient_Batch_Remove_Invoke( if (py_policy_batch_remove) { if (pyobject_to_batch_remove_policy( self, err, py_policy_batch_remove, &policy_batch_remove, - &policy_batch_remove_p, - &batch_remove_exp_list_p) != AEROSPIKE_OK) { + &policy_batch_remove_p) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -252,12 +245,12 @@ static PyObject *AerospikeClient_Batch_Remove_Invoke( as_error_reset(err); CLEANUP: - if (batch_exp_list_p) { - as_exp_destroy(batch_exp_list_p); + if (policy_batch_p) { + as_exp_destroy(policy_batch_p->base.filter_exp); } - if (batch_remove_exp_list_p) { - as_exp_destroy(batch_remove_exp_list_p); + if (policy_batch_remove_p) { + as_exp_destroy(policy_batch_remove_p->filter_exp); } as_batch_destroy(&batch); diff --git a/src/main/client/batch_write.c b/src/main/client/batch_write.c index 46154e56a6..90e430f868 100644 --- a/src/main/client/batch_write.c +++ b/src/main/client/batch_write.c @@ -44,12 +44,11 @@ PyObject *py___policy = \ PyObject_GetAttrString(py_batch_record, FIELD_NAME_BATCH_POLICY); \ if (py___policy != Py_None) { \ - as_exp *expr_p = NULL; \ if (py___policy != NULL) { \ __policy = (__policy_type *)malloc(sizeof(__policy_type)); \ garb->policy_to_free = __policy; \ if (__conversion_func(self, err, py___policy, __policy, \ - &__policy, &expr_p) != AEROSPIKE_OK) { \ + &__policy) != AEROSPIKE_OK) { \ /* Don't call strstr unless we have to. It is a linear time operation */ \ /* Also, not bothering to use POSIX regex library in this case */ \ if (!(self->validate_keys && \ @@ -64,7 +63,7 @@ Py_DECREF(py___policy); \ goto CLEANUP_ON_ERROR; \ } \ - garb->expressions_to_free = expr_p; \ + garb->expressions_to_free = __policy->filter_exp; \ } \ else { \ as_error_update(err, AEROSPIKE_ERR_PARAM, \ @@ -133,7 +132,6 @@ static PyObject *AerospikeClient_BatchWriteInvoke(AerospikeClient *self, as_policy_batch batch_policy; as_policy_batch *batch_policy_p = NULL; - as_exp *exp_list_p = NULL; PyObject *py_batch_type = NULL; PyObject *py_key = NULL; @@ -165,10 +163,9 @@ static PyObject *AerospikeClient_BatchWriteInvoke(AerospikeClient *self, } if (py_policy != NULL) { - if (pyobject_to_policy_batch(self, err, py_policy, &batch_policy, - &batch_policy_p, - &self->as->config.policies.batch, - &exp_list_p) != AEROSPIKE_OK) { + if (pyobject_to_policy_batch( + self, err, py_policy, &batch_policy, &batch_policy_p, + &self->as->config.policies.batch) != AEROSPIKE_OK) { goto CLEANUP4; } } @@ -553,8 +550,8 @@ static PyObject *AerospikeClient_BatchWriteInvoke(AerospikeClient *self, as_vector_destroy(unicodeStrVector); - if (exp_list_p != NULL) { - as_exp_destroy(exp_list_p); + if (batch_policy_p != NULL) { + as_exp_destroy(batch_policy_p->base.filter_exp); } if (err->code != AEROSPIKE_OK) { diff --git a/src/main/client/exists.c b/src/main/client/exists.c index e3d262c7a9..6ba9e316c0 100644 --- a/src/main/client/exists.c +++ b/src/main/client/exists.c @@ -52,9 +52,6 @@ extern PyObject *AerospikeClient_Exists_Invoke(AerospikeClient *self, as_key key; as_record *rec = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - // Initialisation flags bool key_initialised = false; @@ -80,11 +77,14 @@ extern PyObject *AerospikeClient_Exists_Invoke(AerospikeClient *self, // key is initialised successfully key_initialised = true; - // Convert python policy object to as_policy_exists - pyobject_to_policy_read(self, &err, py_policy, &read_policy, &read_policy_p, - &self->as->config.policies.read, &exp_list_p); - if (err.code != AEROSPIKE_OK) { - goto CLEANUP; + if (py_policy) { + as_policy_read_copy_and_set_from_pyobject( + self, &err, py_policy, &read_policy, + &self->as->config.policies.read); + if (err.code != AEROSPIKE_OK) { + goto CLEANUP; + } + read_policy_p = &read_policy; } // Invoke operation @@ -120,8 +120,8 @@ extern PyObject *AerospikeClient_Exists_Invoke(AerospikeClient *self, CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (read_policy_p) { + as_exp_destroy(read_policy_p->base.filter_exp); } if (key_initialised == true) { @@ -169,6 +169,10 @@ PyObject *AerospikeClient_Exists(AerospikeClient *self, PyObject *args, return NULL; } + if (py_policy == Py_None) { + py_policy = NULL; + } + // Invoke Operation return AerospikeClient_Exists_Invoke(self, py_key, py_policy); } diff --git a/src/main/client/get.c b/src/main/client/get.c index be38f515d3..f6b87e79a2 100644 --- a/src/main/client/get.c +++ b/src/main/client/get.c @@ -53,9 +53,6 @@ PyObject *AerospikeClient_Get_Invoke(AerospikeClient *self, PyObject *py_key, as_key key; as_record *rec = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - // Initialised flags bool key_initialised = false; bool record_initialised = false; @@ -82,11 +79,14 @@ PyObject *AerospikeClient_Get_Invoke(AerospikeClient *self, PyObject *py_key, // Key is successfully initialised. key_initialised = true; - // Convert python policy object to as_policy_exists - pyobject_to_policy_read(self, &err, py_policy, &read_policy, &read_policy_p, - &self->as->config.policies.read, &exp_list_p); - if (err.code != AEROSPIKE_OK) { - goto CLEANUP; + if (py_policy) { + as_policy_read_copy_and_set_from_pyobject( + self, &err, py_policy, &read_policy, + &self->as->config.policies.read); + if (err.code != AEROSPIKE_OK) { + goto CLEANUP; + } + read_policy_p = &read_policy; } // Invoke operation @@ -100,7 +100,8 @@ PyObject *AerospikeClient_Get_Invoke(AerospikeClient *self, PyObject *py_key, AEROSPIKE_OK) { goto CLEANUP; } - if (!read_policy_p || + if ((!read_policy_p && + self->as->config.policies.read.key == AS_POLICY_KEY_DIGEST) || (read_policy_p && read_policy_p->key == AS_POLICY_KEY_DIGEST)) { // This is a special case. // C-client returns NULL key, so to the user @@ -115,9 +116,8 @@ PyObject *AerospikeClient_Get_Invoke(AerospikeClient *self, PyObject *py_key, CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); - ; + if (read_policy_p) { + as_exp_destroy(read_policy_p->base.filter_exp); } if (key_initialised == true) { @@ -167,6 +167,10 @@ PyObject *AerospikeClient_Get(AerospikeClient *self, PyObject *args, return NULL; } + if (py_policy == Py_None) { + py_policy = NULL; + } + // Invoke Operation return AerospikeClient_Get_Invoke(self, py_key, py_policy); } diff --git a/src/main/client/operate.c b/src/main/client/operate.c index b85bd6619e..436039b4fc 100644 --- a/src/main/client/operate.c +++ b/src/main/client/operate.c @@ -927,9 +927,6 @@ static PyObject *AerospikeClient_Operate_Invoke(AerospikeClient *self, as_policy_operate operate_policy; as_policy_operate *operate_policy_p = NULL; - // For expressions conversion. - as_exp *exp_list_p = NULL; - as_vector *unicodeStrVector = as_vector_create(sizeof(char *), 128); as_operations ops; @@ -937,10 +934,9 @@ static PyObject *AerospikeClient_Operate_Invoke(AerospikeClient *self, as_operations_inita(&ops, size); if (py_policy) { - if (pyobject_to_policy_operate(self, err, py_policy, &operate_policy, - &operate_policy_p, - &self->as->config.policies.operate, - &exp_list_p) != AEROSPIKE_OK) { + if (pyobject_to_policy_operate( + self, err, py_policy, &operate_policy, &operate_policy_p, + &self->as->config.policies.operate) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -988,8 +984,8 @@ static PyObject *AerospikeClient_Operate_Invoke(AerospikeClient *self, free(as_vector_get_ptr(unicodeStrVector, i)); } - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (operate_policy_p) { + as_exp_destroy(operate_policy_p->base.filter_exp); } as_vector_destroy(unicodeStrVector); @@ -1101,9 +1097,6 @@ AerospikeClient_OperateOrdered_Invoke(AerospikeClient *self, as_error *err, Py_ssize_t ops_list_size = PyList_Size(py_list); as_operations_inita(&ops, ops_list_size); - // For expressions conversion. - as_exp *exp_list_p = NULL; - /* These are the values which will be returned in a 3 element list */ PyObject *py_return_key = NULL; PyObject *py_return_meta = NULL; @@ -1112,10 +1105,9 @@ AerospikeClient_OperateOrdered_Invoke(AerospikeClient *self, as_error *err, CHECK_CONNECTED(err); if (py_policy) { - if (pyobject_to_policy_operate(self, err, py_policy, &operate_policy, - &operate_policy_p, - &self->as->config.policies.operate, - &exp_list_p) != AEROSPIKE_OK) { + if (pyobject_to_policy_operate( + self, err, py_policy, &operate_policy, &operate_policy_p, + &self->as->config.policies.operate) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -1201,8 +1193,8 @@ AerospikeClient_OperateOrdered_Invoke(AerospikeClient *self, as_error *err, as_vector_destroy(unicodeStrVector); - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (operate_policy_p) { + as_exp_destroy(operate_policy_p->base.filter_exp); } if (rec && operation_succeeded) { diff --git a/src/main/client/put.c b/src/main/client/put.c index 69296433b5..a233000cfe 100644 --- a/src/main/client/put.c +++ b/src/main/client/put.c @@ -49,14 +49,9 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, { // Aerospike Client Arguments as_error err; - as_policy_write write_policy; - as_policy_write *write_policy_p = NULL; as_key key; as_record rec; - // For converting expressions. - as_exp *exp_list_p = NULL; - // Initialisation flags bool key_initialised = false; bool record_initialised = false; @@ -67,6 +62,9 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, // Initialize error as_error_init(&err); + as_policy_write write_policy; + as_policy_write *write_policy_p = NULL; + if (!self || !self->as) { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid aerospike object"); goto CLEANUP; @@ -96,12 +94,14 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, record_initialised = true; // Convert python policy object to as_policy_write - pyobject_to_policy_write(self, &err, py_policy, &write_policy, - &write_policy_p, &self->as->config.policies.write, - &exp_list_p, false); - - if (err.code != AEROSPIKE_OK) { - goto CLEANUP; + if (py_policy) { + as_policy_write_copy_and_set_from_pyobject( + self, &err, py_policy, &write_policy, + &self->as->config.policies.write); + if (err.code != AEROSPIKE_OK) { + goto CLEANUP; + } + write_policy_p = &write_policy; } // Invoke operation @@ -112,8 +112,8 @@ PyObject *AerospikeClient_Put_Invoke(AerospikeClient *self, PyObject *py_key, CLEANUP: POOL_DESTROY(&static_pool); - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (write_policy_p) { + as_exp_destroy(write_policy_p->base.filter_exp); } if (key_initialised == true) { @@ -167,6 +167,10 @@ PyObject *AerospikeClient_Put(AerospikeClient *self, PyObject *args, return NULL; } + if (py_policy == Py_None) { + py_policy = NULL; + } + if (py_serializer_option) { if (PyLong_Check(py_serializer_option)) { self->is_client_put_serializer = true; diff --git a/src/main/client/query.c b/src/main/client/query.c index 5f7f7c88eb..f309f8c4db 100644 --- a/src/main/client/query.c +++ b/src/main/client/query.c @@ -290,9 +290,6 @@ static PyObject *AerospikeClient_QueryApply_Invoke( PyObject *py_ustr2 = NULL; PyObject *py_ustr3 = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - as_static_pool static_pool; memset(&static_pool, 0, sizeof(static_pool)); @@ -340,13 +337,13 @@ static PyObject *AerospikeClient_QueryApply_Invoke( is_query_init = true; if (py_policy) { - pyobject_to_policy_write( - self, &err, py_policy, &write_policy, &write_policy_p, - &self->as->config.policies.write, &exp_list_p, true); - + as_policy_write_copy_and_set_from_pyobject( + self, &err, py_policy, &write_policy, + &self->as->config.policies.write); if (err.code != AEROSPIKE_OK) { goto CLEANUP; } + write_policy_p = &write_policy; } char *module_p = NULL; @@ -473,8 +470,8 @@ static PyObject *AerospikeClient_QueryApply_Invoke( } CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (write_policy_p) { + as_exp_destroy(write_policy_p->base.filter_exp); } if (py_ustr1) { @@ -541,6 +538,10 @@ PyObject *AerospikeClient_QueryApply(AerospikeClient *self, PyObject *args, return NULL; } + if (py_policy == Py_None) { + py_policy = NULL; + } + // Invoke Operation return AerospikeClient_QueryApply_Invoke( self, namespace, py_set, py_predicate, py_module, py_function, py_args, diff --git a/src/main/client/remove.c b/src/main/client/remove.c index 345d3702a3..1631e3fd22 100644 --- a/src/main/client/remove.c +++ b/src/main/client/remove.c @@ -50,9 +50,6 @@ PyObject *AerospikeClient_Remove_Invoke(AerospikeClient *self, PyObject *py_key, as_policy_remove *remove_policy_p = NULL; as_key key; - // For converting expressions. - as_exp *exp_list_p = NULL; - // Initialisation flags bool key_initialised = false; @@ -80,9 +77,9 @@ PyObject *AerospikeClient_Remove_Invoke(AerospikeClient *self, PyObject *py_key, // Convert python policy object to as_policy_exists if (py_policy) { - pyobject_to_policy_remove( - self, &err, py_policy, &remove_policy, &remove_policy_p, - &self->as->config.policies.remove, &exp_list_p); + pyobject_to_policy_remove(self, &err, py_policy, &remove_policy, + &remove_policy_p, + &self->as->config.policies.remove); if (err.code != AEROSPIKE_OK) { goto CLEANUP; } @@ -122,8 +119,8 @@ PyObject *AerospikeClient_Remove_Invoke(AerospikeClient *self, PyObject *py_key, CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (remove_policy_p) { + as_exp_destroy(remove_policy_p->base.filter_exp); } if (key_initialised == true) { diff --git a/src/main/client/remove_bin.c b/src/main/client/remove_bin.c index e0d7fc50ac..0d6179ec92 100644 --- a/src/main/client/remove_bin.c +++ b/src/main/client/remove_bin.c @@ -57,9 +57,6 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, int count = 0; PyObject *py_ustr = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - // Get the bin list size; Py_ssize_t size = PyList_Size(py_binList); // Initialize record @@ -73,12 +70,16 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, key_initialized = true; // Convert python policy object to as_policy_write - pyobject_to_policy_write(self, err, py_policy, &write_policy, - &write_policy_p, &self->as->config.policies.write, - &exp_list_p, false); - if (err->code != AEROSPIKE_OK) { - as_error_update(err, AEROSPIKE_ERR_CLIENT, "Incorrect policy"); - goto CLEANUP; + if (py_policy != NULL) { + as_policy_write_copy_and_set_from_pyobject( + self, err, py_policy, &write_policy, + &self->as->config.policies.write); + + if (err->code != AEROSPIKE_OK) { + as_error_update(err, AEROSPIKE_ERR_CLIENT, "Incorrect policy"); + goto CLEANUP; + } + write_policy_p = &write_policy; } // Invoke operation @@ -116,8 +117,8 @@ AerospikeClient_RemoveBin_Invoke(AerospikeClient *self, PyObject *py_key, as_record_destroy(&rec); - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (write_policy_p) { + as_exp_destroy(write_policy_p->base.filter_exp); } if (key_initialized) { @@ -167,6 +168,10 @@ PyObject *AerospikeClient_RemoveBin(AerospikeClient *self, PyObject *args, return NULL; } + if (py_policy == Py_None) { + py_policy = NULL; + } + if (!self || !self->as) { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid aerospike object"); goto CLEANUP; diff --git a/src/main/client/scan.c b/src/main/client/scan.c index 2062113d25..afc0dbb59f 100644 --- a/src/main/client/scan.c +++ b/src/main/client/scan.c @@ -93,9 +93,6 @@ static PyObject *AerospikeClient_ScanApply_Invoke( PyObject *py_ustr2 = NULL; PyObject *py_ustr3 = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - as_static_pool static_pool; memset(&static_pool, 0, sizeof(static_pool)); @@ -144,7 +141,7 @@ static PyObject *AerospikeClient_ScanApply_Invoke( if (py_policy) { pyobject_to_policy_scan(self, &err, py_policy, &scan_policy, &scan_policy_p, &self->as->config.policies.scan, - &exp_list_p, true); + true); if (err.code != AEROSPIKE_OK) { goto CLEANUP; @@ -223,9 +220,8 @@ static PyObject *AerospikeClient_ScanApply_Invoke( CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); - ; + if (scan_policy_p) { + as_exp_destroy(scan_policy_p->base.filter_exp); } if (py_ustr1) { diff --git a/src/main/client/select.c b/src/main/client/select.c index fefae2fa80..f78c63e1d7 100644 --- a/src/main/client/select.c +++ b/src/main/client/select.c @@ -56,9 +56,6 @@ PyObject *AerospikeClient_Select_Invoke(AerospikeClient *self, PyObject *py_key, bool select_succeeded = false; char **bins = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - // Initialisation flags bool key_initialised = false; @@ -143,10 +140,14 @@ PyObject *AerospikeClient_Select_Invoke(AerospikeClient *self, PyObject *py_key, } // Convert python policy object to as_policy_exists - pyobject_to_policy_read(self, &err, py_policy, &read_policy, &read_policy_p, - &self->as->config.policies.read, &exp_list_p); - if (err.code != AEROSPIKE_OK) { - goto CLEANUP; + if (py_policy) { + as_policy_read_copy_and_set_from_pyobject( + self, &err, py_policy, &read_policy, + &self->as->config.policies.read); + if (err.code != AEROSPIKE_OK) { + goto CLEANUP; + } + read_policy_p = &read_policy; } // Invoke operation @@ -161,9 +162,8 @@ PyObject *AerospikeClient_Select_Invoke(AerospikeClient *self, PyObject *py_key, } CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); - ; + if (read_policy_p) { + as_exp_destroy(read_policy_p->base.filter_exp); } if (py_ustr) { @@ -217,6 +217,10 @@ PyObject *AerospikeClient_Select(AerospikeClient *self, PyObject *args, return NULL; } + if (py_policy == Py_None) { + py_policy = NULL; + } + // Invoke Operation return AerospikeClient_Select_Invoke(self, py_key, py_bins, py_policy); } diff --git a/src/main/client/type.c b/src/main/client/type.c index 39c68f8ea0..8bf1335e4e 100644 --- a/src/main/client/type.c +++ b/src/main/client/type.c @@ -1050,8 +1050,8 @@ static int AerospikeClient_Type_Init(AerospikeClient *self, PyObject *args, * Set the individual policy groups new in 3.0 * */ - if (set_subpolicies(&constructor_err, &config, py_policies, - validate_keys) != AEROSPIKE_OK) { + if (set_subpolicies(self, &constructor_err, &config, py_policies) != + AEROSPIKE_OK) { if (constructor_err.code != AEROSPIKE_OK) { // This would only be set if an invalid key was passed to a policy. // Don't override the error caused by validating the dictionary keys diff --git a/src/main/policy.c b/src/main/policy.c index 231cca2890..1f88d26b55 100644 --- a/src/main/policy.c +++ b/src/main/policy.c @@ -17,6 +17,8 @@ #include #include +#include "pythoncapi_compat.h" + #include #include #include @@ -39,18 +41,23 @@ #define MAP_WRITE_FLAGS_KEY "map_write_flags" #define BIT_WRITE_FLAGS_KEY "bit_write_flags" -#define POLICY_INIT(__policy) \ - as_error_reset(err); \ - if (!py_policy || py_policy == Py_None) { \ - return err->code; \ +#define POLICY_UPDATE() *policy_p = policy; + +// Don't make an inline function because +// we want to return early if the policy is NULL or Py_None. +// If we make this an inline function, we have to check again outside the inline function +// +// For transaction level policies, before calling this, we convert policy = None to NULL and this never gets called. +// But for config-level policies, we do not check whether py_policy is NULL or None. +// Either way, we want as_policy_*_set_from_pyobject to be a no-op. +#define RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() \ + if (py_policy == NULL || py_policy == Py_None) { \ + return AEROSPIKE_OK; \ } \ - if (!PyDict_Check(py_policy)) { \ + else if (!PyDict_Check(py_policy)) { \ return as_error_update(err, AEROSPIKE_ERR_PARAM, \ "policy must be a dict"); \ - } \ - __policy##_init(policy); - -#define POLICY_UPDATE() *policy_p = policy; + } // TODO: Python exceptions should be propagated up instead of being cleared // but the policy helper functions don't handle this case and they only populate @@ -61,26 +68,18 @@ // exception that was thrown #define POLICY_SET_FIELD(__field, __type) \ { \ - PyObject *py_field_name = PyUnicode_FromString(#__field); \ - if (py_field_name == NULL) { \ + PyObject *py_field = NULL; \ + int retval = PyDict_GetItemStringRef(py_policy, #__field, &py_field); \ + if (retval == -1) { \ PyErr_Clear(); \ - return as_error_update(err, AEROSPIKE_ERR_CLIENT, \ - "Unable to create Python unicode object"); \ - } \ - PyObject *py_field = \ - PyDict_GetItemWithError(py_policy, py_field_name); \ - if (py_field == NULL && PyErr_Occurred()) { \ - PyErr_Clear(); \ - Py_DECREF(py_field_name); \ return as_error_update( \ err, AEROSPIKE_ERR_CLIENT, \ "Unable to fetch field from policy dictionary"); \ } \ - Py_DECREF(py_field_name); \ - \ if (py_field) { \ if (PyLong_Check(py_field)) { \ long field_val = PyLong_AsLong(py_field); \ + Py_DECREF(py_field); \ if (field_val == -1 && PyErr_Occurred()) { \ PyErr_Clear(); \ return as_error_update( \ @@ -90,6 +89,7 @@ policy->__field = (__type)field_val; \ } \ else { \ + Py_DECREF(py_field); \ return as_error_update(err, AEROSPIKE_ERR_PARAM, \ "%s is invalid", #__field); \ } \ @@ -98,26 +98,22 @@ #define POLICY_SET_EXPRESSIONS_FIELD() \ { \ - PyObject *py_field_name = PyUnicode_FromString("expressions"); \ - if (py_field_name == NULL) { \ - PyErr_Clear(); \ - return as_error_update(err, AEROSPIKE_ERR_CLIENT, \ - "Unable to create Python unicode object"); \ - } \ - PyObject *py_exp_list = \ - PyDict_GetItemWithError(py_policy, py_field_name); \ - if (py_exp_list == NULL && PyErr_Occurred()) { \ + PyObject *py_exp_list = NULL; \ + int retval = \ + PyDict_GetItemStringRef(py_policy, "expressions", &py_exp_list); \ + if (retval == -1) { \ PyErr_Clear(); \ - Py_DECREF(py_field_name); \ return as_error_update(err, AEROSPIKE_ERR_CLIENT, \ "Unable to fetch expressions field " \ "from policy dictionary"); \ } \ - Py_DECREF(py_field_name); \ - if (py_exp_list) { \ - if (as_exp_new_from_pyobject(self, py_exp_list, exp_list_p, err, \ - false) == AEROSPIKE_OK) { \ - policy->filter_exp = *exp_list_p; \ + else if (py_exp_list) { \ + as_exp *exp_list = NULL; \ + retval = as_exp_new_from_pyobject(self, py_exp_list, &exp_list, \ + err, false); \ + Py_DECREF(py_exp_list); \ + if (retval == AEROSPIKE_OK) { \ + policy->filter_exp = exp_list; \ } \ else { \ return err->code; \ @@ -241,10 +237,8 @@ as_status pyobject_to_policy_admin(AerospikeClient *self, as_error *err, as_policy_admin *config_admin_policy) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_admin); - } + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL(); + //Initialize policy with global defaults as_policy_admin_copy(config_admin_policy, policy); @@ -263,7 +257,6 @@ as_status pyobject_to_policy_admin(AerospikeClient *self, as_error *err, } } - // Set policy fields POLICY_SET_FIELD(timeout, uint32_t); } // Update the policy @@ -309,11 +302,11 @@ static inline void check_and_set_txn_field(as_error *err, policy_base->txn = py_txn->txn; } -static inline as_status pyobject_to_policy_base(AerospikeClient *self, - as_error *err, - PyObject *py_policy, - as_policy_base *policy, - as_exp **exp_list_p) +// py_policy must be a Python dictionary +static inline as_status +as_policy_base_set_from_pyobject(AerospikeClient *self, as_error *err, + PyObject *py_policy, as_policy_base *policy, + bool is_this_txn_policy) { POLICY_SET_FIELD(total_timeout, uint32_t); POLICY_SET_FIELD(socket_timeout, uint32_t); @@ -324,14 +317,16 @@ static inline as_status pyobject_to_policy_base(AerospikeClient *self, POLICY_SET_FIELD(connect_timeout, uint32_t); POLICY_SET_FIELD(error_detail_verbosity, uint8_t); - // Setting txn field to a non-NULL value in a query or scan policy is a no-op, - // so this is safe to call for a scan/query policy's base policy - check_and_set_txn_field(err, policy, py_policy); - if (err->code != AEROSPIKE_OK) { - return err->code; - } + if (is_this_txn_policy) { + // Setting txn field to a non-NULL value in a query or scan policy is a no-op, + // so this is safe to call for a scan/query policy's base policy + check_and_set_txn_field(err, policy, py_policy); + if (err->code != AEROSPIKE_OK) { + return err->code; + } - POLICY_SET_EXPRESSIONS_FIELD(); + POLICY_SET_EXPRESSIONS_FIELD(); + } return AEROSPIKE_OK; } @@ -341,52 +336,40 @@ static inline as_status pyobject_to_policy_base(AerospikeClient *self, * We assume that the error object and the policy object are already allocated * and initialized (although, we do reset the error object here). */ -as_status pyobject_to_policy_apply(AerospikeClient *self, as_error *err, - PyObject *py_policy, as_policy_apply *policy, - as_policy_apply **policy_p, - as_policy_apply *config_apply_policy, - as_exp **exp_list_p) +as_status as_policy_apply_set_from_pyobject(AerospikeClient *self, + as_error *err, PyObject *py_policy, + as_policy_apply *policy, + bool is_this_txn_policy) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_apply); - } - //Initialize policy with global defaults - as_policy_apply_copy(config_apply_policy, policy); + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL(); - if (py_policy && py_policy != Py_None) { - if (self->validate_keys) { - as_status retval = does_py_dict_contain_valid_keys( - err, py_policy, py_apply_policy_valid_keys, - POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); - if (retval == -1) { - // This shouldn't happen, but if it did... - return as_error_update(err, AEROSPIKE_ERR, - ERR_MSG_FAILED_TO_VALIDATE_POLICY_KEYS); - } - else if (retval == 0) { - return err->code; - } + if (self->validate_keys) { + as_status retval = does_py_dict_contain_valid_keys( + err, py_policy, py_apply_policy_valid_keys, + POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); + if (retval == -1) { + return as_error_update(err, AEROSPIKE_ERR, + ERR_MSG_FAILED_TO_VALIDATE_POLICY_KEYS); } - - // Set policy fields - as_status retval = pyobject_to_policy_base(self, err, py_policy, - &policy->base, exp_list_p); - if (retval != AEROSPIKE_OK) { - return retval; + else if (retval == 0) { + return err->code; } + } - POLICY_SET_FIELD(key, as_policy_key); - POLICY_SET_FIELD(replica, as_policy_replica); - //POLICY_SET_FIELD(gen, as_policy_gen); removed - POLICY_SET_FIELD(commit_level, as_policy_commit_level); - POLICY_SET_FIELD(durable_delete, bool); - POLICY_SET_FIELD(ttl, uint32_t); - POLICY_SET_FIELD(on_locking_only, bool); + // Set policy fields + as_status retval = as_policy_base_set_from_pyobject( + self, err, py_policy, &policy->base, is_this_txn_policy); + if (retval != AEROSPIKE_OK) { + return retval; } - // Update the policy - POLICY_UPDATE(); + POLICY_SET_FIELD(key, as_policy_key); + POLICY_SET_FIELD(replica, as_policy_replica); + //POLICY_SET_FIELD(gen, as_policy_gen); removed + POLICY_SET_FIELD(commit_level, as_policy_commit_level); + POLICY_SET_FIELD(durable_delete, bool); + POLICY_SET_FIELD(ttl, uint32_t); + POLICY_SET_FIELD(on_locking_only, bool); return err->code; } @@ -403,10 +386,8 @@ pyobject_to_policy_info(as_error *err, PyObject *py_policy, as_policy_info *config_info_policy, bool validate_keys, as_policy_with_extra_keys_allowed other_policy) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_info); - } + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL(); + //Initialize policy with global defaults as_policy_info_copy(config_info_policy, policy); @@ -460,13 +441,10 @@ pyobject_to_policy_info(as_error *err, PyObject *py_policy, as_status pyobject_to_policy_query(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_query *policy, as_policy_query **policy_p, - as_policy_query *config_query_policy, - as_exp **exp_list_p) + as_policy_query *config_query_policy) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_query); - } + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL(); + //Initialize policy with global defaults as_policy_query_copy(config_query_policy, policy); @@ -485,8 +463,8 @@ as_status pyobject_to_policy_query(AerospikeClient *self, as_error *err, } } - as_status retval = pyobject_to_policy_base(self, err, py_policy, - &policy->base, exp_list_p); + as_status retval = as_policy_base_set_from_pyobject( + self, err, py_policy, &policy->base, true); if (retval != AEROSPIKE_OK) { return retval; } @@ -505,60 +483,61 @@ as_status pyobject_to_policy_query(AerospikeClient *self, as_error *err, return err->code; } -/** - * Converts a PyObject into an as_policy_read object. - * Returns AEROSPIKE_OK on success. On error, the err argument is populated. - * We assume that the error object and the policy object are already allocated - * and initialized (although, we do reset the error object here). - */ -as_status pyobject_to_policy_read(AerospikeClient *self, as_error *err, - PyObject *py_policy, as_policy_read *policy, - as_policy_read **policy_p, - as_policy_read *config_read_policy, - as_exp **exp_list_p) +as_status as_policy_apply_copy_and_set_from_pyobject(AerospikeClient *self, + as_error *err, + PyObject *py_policy, + as_policy_apply *dst, + as_policy_apply *src) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_read); - } + as_policy_apply_copy(src, dst); + return as_policy_apply_set_from_pyobject(self, err, py_policy, dst, true); +} - //Initialize policy with global defaults - as_policy_read_copy(config_read_policy, policy); +as_status as_policy_read_copy_and_set_from_pyobject(AerospikeClient *self, + as_error *err, + PyObject *py_policy, + as_policy_read *dst, + as_policy_read *src) +{ + as_policy_read_copy(src, dst); + return as_policy_read_set_from_pyobject(self, err, py_policy, dst, true); +} - if (py_policy && py_policy != Py_None) { - if (self->validate_keys) { - as_status retval = does_py_dict_contain_valid_keys( - err, py_policy, py_read_policy_valid_keys, - POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); - if (retval == -1) { - // This shouldn't happen, but if it did... - return as_error_update(err, AEROSPIKE_ERR, - ERR_MSG_FAILED_TO_VALIDATE_POLICY_KEYS); - } - else if (retval == 0) { - return err->code; - } - } +as_status as_policy_read_set_from_pyobject(AerospikeClient *self, as_error *err, + PyObject *py_policy, + as_policy_read *policy, + bool is_policy_txn_level) +{ + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL(); - // Set policy fields - as_status retval = pyobject_to_policy_base(self, err, py_policy, - &policy->base, exp_list_p); - if (retval != AEROSPIKE_OK) { - return retval; + if (self->validate_keys) { + as_status retval = does_py_dict_contain_valid_keys( + err, py_policy, py_read_policy_valid_keys, + POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); + if (retval == -1) { + return as_error_update(err, AEROSPIKE_ERR, + ERR_MSG_FAILED_TO_VALIDATE_POLICY_KEYS); } + else if (retval == 0) { + return err->code; + } + } - POLICY_SET_FIELD(key, as_policy_key); - POLICY_SET_FIELD(replica, as_policy_replica); - POLICY_SET_FIELD(deserialize, bool); - POLICY_SET_FIELD(read_touch_ttl_percent, int); - - // 4.0.0 new policies - POLICY_SET_FIELD(read_mode_ap, as_policy_read_mode_ap); - POLICY_SET_FIELD(read_mode_sc, as_policy_read_mode_sc); + // Set policy fields + as_status retval = as_policy_base_set_from_pyobject( + self, err, py_policy, &policy->base, is_policy_txn_level); + if (retval != AEROSPIKE_OK) { + return retval; } - // Update the policy - POLICY_UPDATE(); + POLICY_SET_FIELD(key, as_policy_key); + POLICY_SET_FIELD(replica, as_policy_replica); + POLICY_SET_FIELD(deserialize, bool); + POLICY_SET_FIELD(read_touch_ttl_percent, int); + + // 4.0.0 new policies + POLICY_SET_FIELD(read_mode_ap, as_policy_read_mode_ap); + POLICY_SET_FIELD(read_mode_sc, as_policy_read_mode_sc); return err->code; } @@ -573,13 +552,9 @@ as_status pyobject_to_policy_remove(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_remove *policy, as_policy_remove **policy_p, - as_policy_remove *config_remove_policy, - as_exp **exp_list_p) + as_policy_remove *config_remove_policy) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_remove); - } + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL(); //Initialize policy with global defaults as_policy_remove_copy(config_remove_policy, policy); @@ -599,8 +574,8 @@ as_status pyobject_to_policy_remove(AerospikeClient *self, as_error *err, } // Set policy fields - as_status retval = pyobject_to_policy_base(self, err, py_policy, - &policy->base, exp_list_p); + as_status retval = as_policy_base_set_from_pyobject( + self, err, py_policy, &policy->base, true); if (retval != AEROSPIKE_OK) { return retval; } @@ -630,13 +605,11 @@ as_status pyobject_to_policy_scan(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_scan *policy, as_policy_scan **policy_p, - as_policy_scan *config_scan_policy, as_exp **exp_list_p, + as_policy_scan *config_scan_policy, bool py_policy_also_supports_info_policy_fields) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_scan); - } + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL(); + //Initialize policy with global defaults as_policy_scan_copy(config_scan_policy, policy); @@ -663,8 +636,8 @@ pyobject_to_policy_scan(AerospikeClient *self, as_error *err, } // Set policy fields - as_status retval = pyobject_to_policy_base(self, err, py_policy, - &policy->base, exp_list_p); + as_status retval = as_policy_base_set_from_pyobject( + self, err, py_policy, &policy->base, true); if (retval != AEROSPIKE_OK) { return retval; } @@ -682,68 +655,57 @@ pyobject_to_policy_scan(AerospikeClient *self, as_error *err, return err->code; } -/** - * Converts a PyObject into an as_policy_write object. - * Returns AEROSPIKE_OK on success. On error, the err argument is populated. - * We assume that the error object and the policy object are already allocated - * and initialized (although, we do reset the error object here). - */ -as_status pyobject_to_policy_write( - AerospikeClient *self, as_error *err, PyObject *py_policy, - as_policy_write *policy, as_policy_write **policy_p, - as_policy_write *config_write_policy, as_exp **exp_list_p, - bool py_policy_also_supports_info_policy_fields) +as_status as_policy_write_copy_and_set_from_pyobject(AerospikeClient *self, + as_error *err, + PyObject *py_policy, + as_policy_write *dst, + as_policy_write *src) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_write); - } - //Initialize policy with global defaults - as_policy_write_copy(config_write_policy, policy); + as_policy_write_copy(src, dst); + return as_policy_write_set_from_pyobject(self, err, py_policy, dst, true); +} - if (py_policy && py_policy != Py_None) { - if (self->validate_keys) { - PyObject *py_policy_valid_keys = NULL; - if (py_policy_also_supports_info_policy_fields) { - py_policy_valid_keys = py_info_and_write_policy_valid_keys; - } - else { - py_policy_valid_keys = py_write_policy_valid_keys; - } +as_status as_policy_write_set_from_pyobject(AerospikeClient *self, + as_error *err, PyObject *py_policy, + as_policy_write *policy, + bool is_policy_txn_level) +{ + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() - as_status retval = does_py_dict_contain_valid_keys( - err, py_policy, py_policy_valid_keys, - POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); - if (retval == -1) { - return as_error_update(err, AEROSPIKE_ERR, - ERR_MSG_FAILED_TO_VALIDATE_POLICY_KEYS); - } - else if (retval == 0) { - return err->code; - } + if (self->validate_keys) { + as_status retval = does_py_dict_contain_valid_keys( + err, py_policy, py_write_policy_valid_keys, + POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); + if (retval == -1) { + return as_error_update(err, AEROSPIKE_ERR, + ERR_MSG_FAILED_TO_VALIDATE_POLICY_KEYS); } - - // Set policy fields - as_status retval = pyobject_to_policy_base(self, err, py_policy, - &policy->base, exp_list_p); - if (retval != AEROSPIKE_OK) { - return retval; + else if (retval == 0) { + return err->code; } + } - POLICY_SET_FIELD(key, as_policy_key); - POLICY_SET_FIELD(gen, as_policy_gen); - POLICY_SET_FIELD(exists, as_policy_exists); - POLICY_SET_FIELD(commit_level, as_policy_commit_level); - POLICY_SET_FIELD(durable_delete, bool); - POLICY_SET_FIELD(replica, as_policy_replica); - POLICY_SET_FIELD(ttl, uint32_t); - POLICY_SET_FIELD(compression_threshold, uint32_t); - POLICY_SET_FIELD(on_locking_only, bool); + as_status retval = as_policy_base_set_from_pyobject( + self, err, py_policy, &policy->base, is_policy_txn_level); + if (retval != AEROSPIKE_OK) { + goto exit; } - // Update the policy - POLICY_UPDATE(); + POLICY_SET_FIELD(key, as_policy_key); + POLICY_SET_FIELD(gen, as_policy_gen); + POLICY_SET_FIELD(exists, as_policy_exists); + POLICY_SET_FIELD(commit_level, as_policy_commit_level); + POLICY_SET_FIELD(durable_delete, bool); + POLICY_SET_FIELD(replica, as_policy_replica); + POLICY_SET_FIELD(compression_threshold, uint32_t); + POLICY_SET_FIELD(on_locking_only, bool); + + if (is_policy_txn_level == false) { + // Only for config level policy + POLICY_SET_FIELD(ttl, uint32_t); + } +exit: return err->code; } @@ -757,13 +719,10 @@ as_status pyobject_to_policy_operate(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_operate *policy, as_policy_operate **policy_p, - as_policy_operate *config_operate_policy, - as_exp **exp_list_p) + as_policy_operate *config_operate_policy) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_operate); - } + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL(); + //Initialize policy with global defaults as_policy_operate_copy(config_operate_policy, policy); @@ -782,8 +741,8 @@ as_status pyobject_to_policy_operate(AerospikeClient *self, as_error *err, } // Set policy fields - as_status retval = pyobject_to_policy_base(self, err, py_policy, - &policy->base, exp_list_p); + as_status retval = as_policy_base_set_from_pyobject( + self, err, py_policy, &policy->base, true); if (retval != AEROSPIKE_OK) { return retval; } @@ -819,13 +778,10 @@ as_status pyobject_to_policy_operate(AerospikeClient *self, as_error *err, as_status pyobject_to_policy_batch(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch *policy, as_policy_batch **policy_p, - as_policy_batch *config_batch_policy, - as_exp **exp_list_p) + as_policy_batch *config_batch_policy) { - if (py_policy && py_policy != Py_None) { - // Initialize Policy - POLICY_INIT(as_policy_batch); - } + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() + //Initialize policy with global defaults as_policy_batch_copy(config_batch_policy, policy); @@ -844,8 +800,8 @@ as_status pyobject_to_policy_batch(AerospikeClient *self, as_error *err, } // Set policy fields - as_status retval = pyobject_to_policy_base(self, err, py_policy, - &policy->base, exp_list_p); + as_status retval = as_policy_base_set_from_pyobject( + self, err, py_policy, &policy->base, true); if (retval != AEROSPIKE_OK) { return retval; } @@ -875,10 +831,10 @@ as_status pyobject_to_policy_batch(AerospikeClient *self, as_error *err, as_status pyobject_to_batch_write_policy(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch_write *policy, - as_policy_batch_write **policy_p, - as_exp **exp_list_p) + as_policy_batch_write **policy_p) { - POLICY_INIT(as_policy_batch_write); + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() + as_policy_batch_write_init(policy); if (self->validate_keys) { as_status retval = does_py_dict_contain_valid_keys( @@ -916,10 +872,10 @@ as_status pyobject_to_batch_write_policy(AerospikeClient *self, as_error *err, as_status pyobject_to_batch_read_policy(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch_read *policy, - as_policy_batch_read **policy_p, - as_exp **exp_list_p) + as_policy_batch_read **policy_p) { - POLICY_INIT(as_policy_batch_read); + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() + as_policy_batch_read_init(policy); if (self->validate_keys) { as_status retval = does_py_dict_contain_valid_keys( @@ -952,10 +908,10 @@ as_status pyobject_to_batch_read_policy(AerospikeClient *self, as_error *err, as_status pyobject_to_batch_apply_policy(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch_apply *policy, - as_policy_batch_apply **policy_p, - as_exp **exp_list_p) + as_policy_batch_apply **policy_p) { - POLICY_INIT(as_policy_batch_apply); + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() + as_policy_batch_apply_init(policy); if (self->validate_keys) { as_status retval = does_py_dict_contain_valid_keys( @@ -990,10 +946,10 @@ as_status pyobject_to_batch_apply_policy(AerospikeClient *self, as_error *err, as_status pyobject_to_batch_remove_policy(AerospikeClient *self, as_error *err, PyObject *py_policy, as_policy_batch_remove *policy, - as_policy_batch_remove **policy_p, - as_exp **exp_list_p) + as_policy_batch_remove **policy_p) { - POLICY_INIT(as_policy_batch_remove); + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() + as_policy_batch_remove_init(policy); if (self->validate_keys) { as_status retval = does_py_dict_contain_valid_keys( @@ -1028,7 +984,7 @@ as_status pyobject_to_bit_policy(as_error *err, PyObject *py_policy, as_bit_policy *policy, bool validate_keys) { as_bit_policy_init(policy); - POLICY_INIT(as_bit_policy); + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() if (validate_keys) { as_status retval = does_py_dict_contain_valid_keys( @@ -1065,7 +1021,8 @@ as_status pyobject_to_map_policy(as_error *err, PyObject *py_policy, as_map_policy *policy, bool validate_keys) { // Initialize Policy - POLICY_INIT(as_map_policy); + RETURN_IF_PY_POLICY_IS_INVALID_OR_NONE_OR_NULL() + as_map_policy_init(policy); if (validate_keys) { as_status retval = does_py_dict_contain_valid_keys( diff --git a/src/main/policy_config.c b/src/main/policy_config.c index c9cfba056a..499340e0e0 100644 --- a/src/main/policy_config.c +++ b/src/main/policy_config.c @@ -17,6 +17,7 @@ #include "policy_config.h" #include "types.h" + #include "policy.h" #include "conversions.h" @@ -41,96 +42,97 @@ as_status set_optional_int_property(int *property_ptr, PyObject *py_policy, /* * py_policies must exist, and be a dictionary */ -as_status set_subpolicies(as_error *err, as_config *config, - PyObject *py_policies, int validate_keys) +as_status set_subpolicies(AerospikeClient *self, as_error *err, + as_config *config, PyObject *py_policies_dict) { - as_status set_policy_status = AEROSPIKE_OK; - - PyObject *read_policy = PyDict_GetItemString(py_policies, "read"); - set_policy_status = set_read_policy(err, &config->policies.read, - read_policy, validate_keys); + PyObject *py_read_policy = PyDict_GetItemString(py_policies_dict, "read"); + set_policy_status = as_policy_read_set_from_pyobject( + self, err, py_read_policy, &config->policies.read, false); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } - PyObject *write_policy = PyDict_GetItemString(py_policies, "write"); - set_policy_status = set_write_policy(err, &config->policies.write, - write_policy, validate_keys); + PyObject *py_write_policy = PyDict_GetItemString(py_policies_dict, "write"); + set_policy_status = as_policy_write_set_from_pyobject( + self, err, py_write_policy, &config->policies.write, false); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } - PyObject *apply_policy = PyDict_GetItemString(py_policies, "apply"); - set_policy_status = set_apply_policy(err, &config->policies.apply, - apply_policy, validate_keys); + PyObject *py_apply_policy = PyDict_GetItemString(py_policies_dict, "apply"); + set_policy_status = as_policy_apply_set_from_pyobject( + self, err, py_apply_policy, &config->policies.apply, false); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } - PyObject *remove_policy = PyDict_GetItemString(py_policies, "remove"); + PyObject *remove_policy = PyDict_GetItemString(py_policies_dict, "remove"); set_policy_status = set_remove_policy(err, &config->policies.remove, - remove_policy, validate_keys); + remove_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } - PyObject *query_policy = PyDict_GetItemString(py_policies, "query"); + PyObject *query_policy = PyDict_GetItemString(py_policies_dict, "query"); set_policy_status = set_query_policy(err, &config->policies.query, - query_policy, validate_keys); + query_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } - PyObject *scan_policy = PyDict_GetItemString(py_policies, "scan"); + PyObject *scan_policy = PyDict_GetItemString(py_policies_dict, "scan"); set_policy_status = set_scan_policy(err, &config->policies.scan, - scan_policy, validate_keys); + scan_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } - PyObject *operate_policy = PyDict_GetItemString(py_policies, "operate"); + PyObject *operate_policy = + PyDict_GetItemString(py_policies_dict, "operate"); set_policy_status = set_operate_policy(err, &config->policies.operate, - operate_policy, validate_keys); + operate_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } - PyObject *info_policy = PyDict_GetItemString(py_policies, "info"); + PyObject *info_policy = PyDict_GetItemString(py_policies_dict, "info"); set_policy_status = set_info_policy(err, &config->policies.info, - info_policy, validate_keys); + info_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } - PyObject *admin_policy = PyDict_GetItemString(py_policies, "admin"); + PyObject *admin_policy = PyDict_GetItemString(py_policies_dict, "admin"); set_policy_status = set_admin_policy(err, &config->policies.admin, - admin_policy, validate_keys); + admin_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } PyObject *batch_apply_policy = - PyDict_GetItemString(py_policies, "batch_apply"); - set_policy_status = set_batch_apply_policy( - err, &config->policies.batch_apply, batch_apply_policy, validate_keys); + PyDict_GetItemString(py_policies_dict, "batch_apply"); + set_policy_status = + set_batch_apply_policy(err, &config->policies.batch_apply, + batch_apply_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } PyObject *batch_remove_policy = - PyDict_GetItemString(py_policies, "batch_remove"); + PyDict_GetItemString(py_policies_dict, "batch_remove"); set_policy_status = set_batch_remove_policy(err, &config->policies.batch_remove, - batch_remove_policy, validate_keys); + batch_remove_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } PyObject *batch_write_policy = - PyDict_GetItemString(py_policies, "batch_write"); - set_policy_status = set_batch_write_policy( - err, &config->policies.batch_write, batch_write_policy, validate_keys); + PyDict_GetItemString(py_policies_dict, "batch_write"); + set_policy_status = + set_batch_write_policy(err, &config->policies.batch_write, + batch_write_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } @@ -138,14 +140,17 @@ as_status set_subpolicies(as_error *err, as_config *config, const char *batch_policy_names[] = {"batch", "batch_parent_write", "txn_verify", "txn_roll"}; as_policy_batch *batch_policies[] = { - &config->policies.batch, &config->policies.batch_parent_write, - &config->policies.txn_verify, &config->policies.txn_roll}; + &config->policies.batch, + &config->policies.batch_parent_write, + &config->policies.txn_verify, + &config->policies.txn_roll, + }; for (unsigned long i = 0; i < sizeof(batch_policy_names) / sizeof(batch_policy_names[0]); i++) { PyObject *py_batch_policy = - PyDict_GetItemString(py_policies, batch_policy_names[i]); - set_policy_status = set_batch_policy(err, batch_policies[i], - py_batch_policy, validate_keys); + PyDict_GetItemString(py_policies_dict, batch_policy_names[i]); + set_policy_status = set_batch_policy( + err, batch_policies[i], py_batch_policy, self->validate_keys); if (set_policy_status != AEROSPIKE_OK) { return set_policy_status; } @@ -156,203 +161,6 @@ as_status set_subpolicies(as_error *err, as_config *config, return AEROSPIKE_OK; } -as_status set_read_policy(as_error *err, as_policy_read *read_policy, - PyObject *py_policy, int validate_keys) -{ - - as_status status = AEROSPIKE_OK; - if (!py_policy) { - return AEROSPIKE_OK; - } - - if (!PyDict_Check(py_policy)) { - return AEROSPIKE_ERR_PARAM; - } - - if (validate_keys) { - int retval = does_py_dict_contain_valid_keys( - err, py_policy, py_read_policy_valid_keys, - POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); - if (retval != 1) { - return AEROSPIKE_ERR_PARAM; - } - } - - status = set_base_policy(&read_policy->base, py_policy); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_key(&read_policy->key, py_policy, "key"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_replica(&read_policy->replica, py_policy, "replica"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_bool_property(&read_policy->deserialize, py_policy, - "deserialize"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_ap_read_mode(&read_policy->read_mode_ap, py_policy, - "read_mode_ap"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_sc_read_mode(&read_policy->read_mode_sc, py_policy, - "read_mode_sc"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_int_property(&read_policy->read_touch_ttl_percent, - py_policy, "read_touch_ttl_percent"); - if (status != AEROSPIKE_OK) { - return status; - } - - return AEROSPIKE_OK; -} - -as_status set_write_policy(as_error *err, as_policy_write *write_policy, - PyObject *py_policy, int validate_keys) -{ - - as_status status = AEROSPIKE_OK; - - if (!py_policy) { - return AEROSPIKE_OK; - } - - if (!PyDict_Check(py_policy)) { - return AEROSPIKE_ERR_PARAM; - } - - if (validate_keys) { - int retval = does_py_dict_contain_valid_keys( - err, py_policy, py_write_policy_valid_keys, - POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); - if (retval != 1) { - return AEROSPIKE_ERR_PARAM; - } - } - - status = set_base_policy(&write_policy->base, py_policy); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_key(&write_policy->key, py_policy, "key"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_replica(&write_policy->replica, py_policy, "replica"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_commit_level(&write_policy->commit_level, py_policy, - "commit_level"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_gen(&write_policy->gen, py_policy, "gen"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_exists(&write_policy->exists, py_policy, "exists"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_uint32_property(&write_policy->ttl, py_policy, "ttl"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_uint32_property( - (uint32_t *)&write_policy->compression_threshold, py_policy, - "compression_threshold"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_bool_property(&write_policy->durable_delete, - py_policy, "durable_delete"); - if (status != AEROSPIKE_OK) { - return status; - } - - return AEROSPIKE_OK; -} - -as_status set_apply_policy(as_error *err, as_policy_apply *apply_policy, - PyObject *py_policy, int validate_keys) -{ - - as_status status = AEROSPIKE_OK; - - if (!py_policy) { - return AEROSPIKE_OK; - } - - if (!PyDict_Check(py_policy)) { - return AEROSPIKE_ERR_PARAM; - } - - if (validate_keys) { - int retval = does_py_dict_contain_valid_keys( - err, py_policy, py_apply_policy_valid_keys, - POLICY_DICTIONARY_ADJECTIVE_FOR_ERROR_MESSAGE); - if (retval != 1) { - return AEROSPIKE_ERR_PARAM; - } - } - - status = set_base_policy(&apply_policy->base, py_policy); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_key(&apply_policy->key, py_policy, "key"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_replica(&apply_policy->replica, py_policy, "replica"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_uint32_property(&apply_policy->ttl, py_policy, "ttl"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_commit_level(&apply_policy->commit_level, py_policy, - "commit_level"); - if (status != AEROSPIKE_OK) { - return status; - } - - status = set_optional_bool_property(&apply_policy->durable_delete, - py_policy, "durable_delete"); - if (status != AEROSPIKE_OK) { - return status; - } - - return AEROSPIKE_OK; -} - as_status set_remove_policy(as_error *err, as_policy_remove *remove_policy, PyObject *py_policy, int validate_keys) { diff --git a/src/main/query/execute_background.c b/src/main/query/execute_background.c index 5657c37038..5827871c99 100644 --- a/src/main/query/execute_background.c +++ b/src/main/query/execute_background.c @@ -40,14 +40,15 @@ PyObject *AerospikeQuery_ExecuteBackground(AerospikeQuery *self, PyObject *args, static char *kwlist[] = {"policy", NULL}; - // For converting expressions. - as_exp *exp_list_p = NULL; - if (PyArg_ParseTupleAndKeywords(args, kwds, "|O:execute_background", kwlist, &py_policy) == false) { return NULL; } + if (py_policy == Py_None) { + py_policy = NULL; + } + as_error err; as_error_init(&err); @@ -61,11 +62,14 @@ PyObject *AerospikeQuery_ExecuteBackground(AerospikeQuery *self, PyObject *args, goto CLEANUP; } - if (pyobject_to_policy_write(self->client, &err, py_policy, &write_policy, - &write_policy_p, - &self->client->as->config.policies.write, - &exp_list_p, false) != AEROSPIKE_OK) { - goto CLEANUP; + if (py_policy) { + as_policy_write_copy_and_set_from_pyobject( + self->client, &err, py_policy, &write_policy, + &self->client->as->config.policies.write); + if (err.code != AEROSPIKE_OK) { + goto CLEANUP; + } + write_policy_p = &write_policy; } Py_BEGIN_ALLOW_THREADS @@ -75,8 +79,8 @@ PyObject *AerospikeQuery_ExecuteBackground(AerospikeQuery *self, PyObject *args, CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (write_policy_p) { + as_exp_destroy(write_policy_p->base.filter_exp); ; } diff --git a/src/main/query/foreach.c b/src/main/query/foreach.c index e4ee85de19..373fd0a0e6 100644 --- a/src/main/query/foreach.c +++ b/src/main/query/foreach.c @@ -164,9 +164,6 @@ PyObject *AerospikeQuery_Foreach(AerospikeQuery *self, PyObject *args, as_policy_query query_policy; as_policy_query *query_policy_p = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - as_partition_filter partition_filter = {0}; as_partition_filter *partition_filter_p = NULL; as_partitions_status *ps = NULL; @@ -185,9 +182,9 @@ PyObject *AerospikeQuery_Foreach(AerospikeQuery *self, PyObject *args, } // Convert python policy object to as_policy_exists - pyobject_to_policy_query( - self->client, &err, py_policy, &query_policy, &query_policy_p, - &self->client->as->config.policies.query, &exp_list_p); + pyobject_to_policy_query(self->client, &err, py_policy, &query_policy, + &query_policy_p, + &self->client->as->config.policies.query); if (err.code != AEROSPIKE_OK) { goto CLEANUP; } @@ -243,8 +240,8 @@ PyObject *AerospikeQuery_Foreach(AerospikeQuery *self, PyObject *args, } CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (query_policy_p) { + as_exp_destroy(query_policy_p->base.filter_exp); } if (self->query.apply.arglist) { diff --git a/src/main/query/results.c b/src/main/query/results.c index e09fc3db0d..0b4241a9bc 100644 --- a/src/main/query/results.c +++ b/src/main/query/results.c @@ -87,9 +87,6 @@ PyObject *AerospikeQuery_Results(AerospikeQuery *self, PyObject *args, as_policy_query query_policy; as_policy_query *query_policy_p = NULL; - // For converting expressions. - as_exp *exp_list_p = NULL; - as_partition_filter partition_filter = {0}; as_partition_filter *partition_filter_p = NULL; as_partitions_status *ps = NULL; @@ -106,9 +103,9 @@ PyObject *AerospikeQuery_Results(AerospikeQuery *self, PyObject *args, } // Convert python policy object to as_policy_query - pyobject_to_policy_query( - self->client, &err, py_policy, &query_policy, &query_policy_p, - &self->client->as->config.policies.query, &exp_list_p); + pyobject_to_policy_query(self->client, &err, py_policy, &query_policy, + &query_policy_p, + &self->client->as->config.policies.query); if (err.code != AEROSPIKE_OK) { goto CLEANUP; } @@ -159,8 +156,8 @@ PyObject *AerospikeQuery_Results(AerospikeQuery *self, PyObject *args, Py_END_ALLOW_THREADS CLEANUP: /*??trace()*/ - if (exp_list_p) { - as_exp_destroy(exp_list_p); + if (query_policy_p) { + as_exp_destroy(query_policy_p->base.filter_exp); } if (err.code != AEROSPIKE_OK) { diff --git a/src/main/scan/execute_background.c b/src/main/scan/execute_background.c index a1159c8e4e..d5dcc4703b 100644 --- a/src/main/scan/execute_background.c +++ b/src/main/scan/execute_background.c @@ -38,9 +38,6 @@ PyObject *AerospikeScan_ExecuteBackground(AerospikeScan *self, PyObject *args, uint64_t scan_id = 0; static char *kwlist[] = {"policy", NULL}; - // For converting expressions. - as_exp *exp_list_p = NULL; - if (PyArg_ParseTupleAndKeywords(args, kwds, "|O:execute_background", kwlist, &py_policy) == false) { return NULL; @@ -63,7 +60,7 @@ PyObject *AerospikeScan_ExecuteBackground(AerospikeScan *self, PyObject *args, if (pyobject_to_policy_scan(self->client, &err, py_policy, &scan_policy, &scan_policy_p, &self->client->as->config.policies.scan, - &exp_list_p, false) != AEROSPIKE_OK) { + false) != AEROSPIKE_OK) { goto CLEANUP; } } @@ -75,9 +72,8 @@ PyObject *AerospikeScan_ExecuteBackground(AerospikeScan *self, PyObject *args, CLEANUP: - if (exp_list_p) { - as_exp_destroy(exp_list_p); - ; + if (scan_policy_p) { + as_exp_destroy(scan_policy_p->base.filter_exp); } if (err.code != AEROSPIKE_OK) { diff --git a/src/main/scan/foreach.c b/src/main/scan/foreach.c index 2d82eab761..2c1b384d08 100644 --- a/src/main/scan/foreach.c +++ b/src/main/scan/foreach.c @@ -172,9 +172,9 @@ PyObject *AerospikeScan_Foreach(AerospikeScan *self, PyObject *args, } // Convert python policy object to as_policy_exists - pyobject_to_policy_scan( - self->client, &data.error, py_policy, &scan_policy, &scan_policy_p, - &self->client->as->config.policies.scan, &exp_list_p, false); + pyobject_to_policy_scan(self->client, &data.error, py_policy, &scan_policy, + &scan_policy_p, + &self->client->as->config.policies.scan, false); if (data.error.code != AEROSPIKE_OK) { goto CLEANUP; diff --git a/src/main/scan/results.c b/src/main/scan/results.c index 9113621559..8a9bf8cc78 100644 --- a/src/main/scan/results.c +++ b/src/main/scan/results.c @@ -109,9 +109,9 @@ PyObject *AerospikeScan_Results(AerospikeScan *self, PyObject *args, } // Convert python policy object to as_policy_scan - pyobject_to_policy_scan( - self->client, &err, py_policy, &scan_policy, &scan_policy_p, - &self->client->as->config.policies.scan, &exp_list_p, false); + pyobject_to_policy_scan(self->client, &err, py_policy, &scan_policy, + &scan_policy_p, + &self->client->as->config.policies.scan, false); if (err.code != AEROSPIKE_OK) { as_error_update(&err, err.code, NULL); goto CLEANUP; diff --git a/test/new_tests/test_client_config_level_options.py b/test/new_tests/test_client_config_level_options.py index ab269fb5b3..fe7df6e146 100644 --- a/test/new_tests/test_client_config_level_options.py +++ b/test/new_tests/test_client_config_level_options.py @@ -538,9 +538,8 @@ def test_query_client_default_ttl(self, config_ttl_setup): def test_invalid_read_touch_ttl_percent(self, policy_name: str): config = copy.deepcopy(gconfig) config["policies"][policy_name]["read_touch_ttl_percent"] = "fail" - with pytest.raises(e.ParamError) as excinfo: + with pytest.raises(e.ParamError): aerospike.client(config) - assert excinfo.value.msg == "Invalid Policy setting value" @pytest.mark.parametrize( "config, context", diff --git a/test/new_tests/test_get_put.py b/test/new_tests/test_get_put.py index 795b81d259..e8a54f4425 100644 --- a/test/new_tests/test_get_put.py +++ b/test/new_tests/test_get_put.py @@ -126,23 +126,6 @@ def test_pos_get_initkey_with_client_policy_send(self, put_data): """ Invoke get() for a record having string data. """ - - key = ("test", "demo", 1) - - rec = {"name": "john", "age": 1} - - put_data(self.as_connection, key, rec) - - key, _, bins = self.as_connection.get(key) - - assert bins == {"name": "john", "age": 1} - assert key == ( - "test", - "demo", - None, - bytearray(b"\xb7\xf4\xb88\x89\xe2\xdag\xdeh>\x1d\xf6\x91\x9a\x1e\xac\xc4F\xc8"), - ) - config = self.connection_config.copy() config["policies"] = {"key": aerospike.POLICY_KEY_SEND} diff --git a/test/new_tests/test_validate_keys.py b/test/new_tests/test_validate_keys.py index c7b56e10fc..4022b75ee3 100644 --- a/test/new_tests/test_validate_keys.py +++ b/test/new_tests/test_validate_keys.py @@ -62,7 +62,7 @@ def setup(self, as_connection): [ (aerospike.Client.operate, {"key": KEY, "list": OPS_LIST, "policy": INVALID_POLICY}, nullcontext()), # User doesn't exist - (aerospike.Client.admin_query_user_info, {"user": "asdf", "policy": INVALID_POLICY}, pytest.raises((e.InvalidUser, e.SecurityNotSupported))), + (aerospike.Client.admin_query_user_info, {"user": "asdf", "policy": INVALID_POLICY}, pytest.raises((e.InvalidUser, e.SecurityNotSupported, e.SecurityNotEnabled))), (aerospike.Client.info_all, {"command": "status", "policy": INVALID_POLICY}, nullcontext()), # UDF doesn't exist on server (aerospike.Client.apply, {"key": KEY, "module": "module", "function": "function", "args": [], "policy": INVALID_POLICY}, pytest.raises(e.UDFError)),