diff --git a/src/box/index.h b/src/box/index.h index 475889cf8fc7e919e8c7995dc24f4f49131e8bcf..69a544f9f48d8127f8e54280fbf139533b41dd9e 100644 --- a/src/box/index.h +++ b/src/box/index.h @@ -122,6 +122,12 @@ struct index_traits bool allows_partial_key; }; +enum replace_flags { + REPLACE_INSERT = 0, + THROW_INSERT = 0x02, + REPLACE_THROW = 0x04 +}; + @interface Index: tnt_Object { /* Index features. */ struct index_traits *traits; @@ -174,7 +180,7 @@ struct index_traits - (struct tuple *) findByTuple: (struct tuple *) tuple; - (struct tuple *) replace: (struct tuple *) old_tuple : (struct tuple *) new_tuple - : (u32) flags; + : (enum replace_flags) flags; /** * Create a structure to represent an iterator. Must be * initialized separately. diff --git a/src/box/index.m b/src/box/index.m index 69bdefd64baaa64ed55f35515c04d64cc9ca86c1..a065da9387dcd3328af9d7ae4d158b1c63f10920 100644 --- a/src/box/index.m +++ b/src/box/index.m @@ -32,7 +32,6 @@ #include "tuple.h" #include "pickle.h" #include "exception.h" -#include "request.h" /* for BOX_ADD, BOX_REPLACE */ #include "space.h" #include "assoc.h" @@ -214,7 +213,7 @@ check_key_parts(struct key_def *key_def, - (struct tuple *) replace: (struct tuple *) old_tuple : (struct tuple *) new_tuple - : (u32) flags + : (enum replace_flags) flags { (void) old_tuple; (void) new_tuple; @@ -380,7 +379,7 @@ hash_iterator_lstr_eq(struct iterator *it) - (void) buildNext: (struct tuple *)tuple { - [self replace: NULL: tuple: BOX_ADD]; + [self replace: NULL: tuple: THROW_INSERT]; } - (void) endBuild @@ -404,7 +403,7 @@ hash_iterator_lstr_eq(struct iterator *it) [pk initIterator: it :ITER_ALL :NULL :0]; while ((tuple = it->next(it))) - [self replace: NULL: tuple: BOX_ADD]; + [self replace: NULL: tuple: THROW_INSERT]; } - (void) free @@ -452,7 +451,7 @@ hash_iterator_lstr_eq(struct iterator *it) - (struct tuple *) replace: (struct tuple *) old_tuple : (struct tuple *) new_tuple - : (u32) flags + : (enum replace_flags) flags { /* Mostly like tree::replace */ @@ -470,16 +469,16 @@ hash_iterator_lstr_eq(struct iterator *it) /* Try to optimistically replace the new_tuple in the space */ [self replaceNode: hash: new_node: &replaced_node]; - if (unlikely(key_def->is_unique && (flags & BOX_ADD) + if (unlikely(key_def->is_unique && (flags & THROW_INSERT) && replaced_node != NULL)) { - /* BOX_ADD, a tuple with the same key is found */ + /* THROW_INSERT, a tuple with the same key is found */ [self replaceNode: hash: replaced_node: NULL]; tnt_raise(ClientError, :ER_TUPLE_FOUND); } - if (unlikely(key_def->is_unique && (flags & BOX_REPLACE) + if (unlikely(key_def->is_unique && (flags & REPLACE_THROW) && replaced_node == NULL)) { - /* BOX_REPLACE,a tuple with the same key is not found */ + /* REPLACE_THROW, a tuple with the same key is not found*/ [self deleteNode: hash: new_node: NULL]; tnt_raise(ClientError, :ER_TUPLE_NOT_FOUND); } @@ -501,7 +500,7 @@ hash_iterator_lstr_eq(struct iterator *it) } else /* (old_tuple != NULL && new_tuple != NULL) */ { /* Case #3: remove(old_tuple); insert(new_tuple) */ - assert(!key_def->is_unique || (flags & BOX_ADD)); + assert(!key_def->is_unique || (flags & THROW_INSERT)); void *new_node = node1; void *replaced_node = node2; diff --git a/src/box/request.m b/src/box/request.m index 59f68989772947dff59eee1ffb08355b315eebce..8227889fa248b5a48f1b175efaef54459f632779 100644 --- a/src/box/request.m +++ b/src/box/request.m @@ -86,9 +86,13 @@ execute_replace(struct request *request, struct txn *txn) new_tuple->field_count = field_count; memcpy(new_tuple->data, data->data, data->size); + assert(BOX_ADD == THROW_INSERT); + assert(BOX_REPLACE == REPLACE_THROW); + const enum replace_flags flags = (enum replace_flags) request->flags; + @try { space_validate_tuple(sp, new_tuple); - txn_replace(txn, sp, NULL, new_tuple, request->flags); + txn_replace(txn, sp, NULL, new_tuple, flags); } @catch (tnt_Exception *e) { tuple_ref(new_tuple, -1); @throw; @@ -713,7 +717,7 @@ execute_update(struct request *request, struct txn *txn) do_update_ops(rope, new_tuple); space_validate_tuple(sp, new_tuple); - txn_replace(txn, sp, old_tuple, new_tuple, BOX_ADD); + txn_replace(txn, sp, old_tuple, new_tuple, THROW_INSERT); } @catch(tnt_Exception *e) { tuple_ref(new_tuple, -1); @throw; @@ -793,7 +797,7 @@ execute_delete(struct request *request, struct txn *txn) if (unlikely(old_tuple == NULL)) return; - txn_replace(txn, sp, old_tuple, NULL, request->flags); + txn_replace(txn, sp, old_tuple, NULL, REPLACE_INSERT); } /** To collects stats, we need a valid request type. diff --git a/src/box/space.h b/src/box/space.h index bc2b0dbacd623fe847b7c28b0917431acc038068..06c54602d905b58c4366abeec7d40075cf644d79 100644 --- a/src/box/space.h +++ b/src/box/space.h @@ -93,11 +93,11 @@ static inline i32 space_n(struct space *sp) { return sp->no; } * 1. old_tuple = NULL, new_tuple != NULL * Inserts or replaces the @a new_tuple in the @a space. If no flags are set * and an old tuple in the @a sp has the same primary key as @a new_tuple, - * the old tuple is removed before new tuple is inserted. If BOX_ADD flag is set - * and old tuple with same primary key is found, TupleFound exception is thrown. - * If BOX_REPLACE flags is set and old tple is not found, TupleNotFound - * exception is thrown. The return value is an tuple that was actually removed. - * This case is usually used for box.replace. + * the old tuple is removed before new tuple is inserted. If THROW_INSERT flag + * is set and old tuple with same primary key is found, TupleFound exception + * is thrown. If REPLACE_THROW flags is set and old tple is not found, + * TupleNotFound exception is thrown. The return value is an tuple that was + * actually removed. This case is usually used for box.replace. * * 2. old_tuple != NULL, new_tuple == NULL * Removes @a old_tuple from the @a space. Please note, that @a old_tuple @@ -108,8 +108,8 @@ static inline i32 space_n(struct space *sp) { return sp->no; } * 3. old_tuple != NULL, new_tuple != NULL * Perform atomically an operation that equivalent to * replace(sp, old_tuple, NULL, flags) + replace(sp, NULL, new_tuple, flags). - * BOX_ADD flag must be always set, because only one tuple can be removed per - * one call. This case is usually used for box.update. + * THROW_INSERT flag must be always set, because only one tuple can be removed + * per one call. This case is usually used for box.update. * * The method is **atomic** in all cases. Changes are either applied to all * indexes, or nothing applied at all. @@ -134,17 +134,17 @@ static inline i32 space_n(struct space *sp) { return sp->no; } * | XX | XX | NULL | NULL | 1 | 0 | i(new) | NULL | * +------+------+------+------+---+---+----------------------+---------------+ * oldf = findByTuple(old), newf = findByTuple(new), i = insert, r = remove, - * A - BOX_ADD, R = BOX_REPLACE (in @a flags parameter). + * A - THROW_INSERT, R = REPLACE_THROW (in @a flags parameter). * * @param sp space * @param old_tuple the tuple that should be removed (can be NULL) * @param new_tuple the tuple that should be inserted (can be NULL) - * @param flags BOX_ADD and BOX_REPLACE flags, as defined in @a request.h + * @param flags THROW_INSERT and REPLACE_THROW flags * @return tuple that actually has been removed from the space */ struct tuple * space_replace(struct space *space, struct tuple *old_tuple, - struct tuple *new_tuple, u32 flags); + struct tuple *new_tuple, enum replace_flags flags); void space_validate_tuple(struct space *sp, struct tuple *new_tuple); diff --git a/src/box/space.m b/src/box/space.m index 3b8f82e655d5c3e9db39d5d58b92f97d1af63022..e5162ac2dc56886f601670af19e3ff2fe3481865 100644 --- a/src/box/space.m +++ b/src/box/space.m @@ -33,7 +33,6 @@ #include <cfg/warning.h> #include <tarantool.h> #include <exception.h> -#include "request.h" /* for BOX_ADD, BOX_REPLACE */ #include "tuple.h" #include <pickle.h> #include <palloc.h> @@ -123,7 +122,7 @@ key_free(struct key_def *key_def) struct tuple * space_replace(struct space *sp, struct tuple *old_tuple, - struct tuple *new_tuple, u32 flags) + struct tuple *new_tuple, enum replace_flags flags) { struct tuple *removed_tuple = NULL; @@ -147,7 +146,7 @@ space_replace(struct space *sp, struct tuple *old_tuple, /* Update secondary keys */ for (; i < n; i++) { Index *index = sp->index[i]; - [index replace: removed_tuple: new_tuple: BOX_ADD]; + [index replace: removed_tuple: new_tuple: THROW_INSERT]; } return removed_tuple; @@ -156,7 +155,7 @@ space_replace(struct space *sp, struct tuple *old_tuple, /* Rollback all changes */ for (; i >= 0; i--) { Index *index = sp->index[i]; - [index replace: new_tuple: removed_tuple: BOX_ADD]; + [index replace: new_tuple: removed_tuple: THROW_INSERT]; } @throw; diff --git a/src/box/tree.m b/src/box/tree.m index a17eb0156cd84a422706559db324f031b0ecc81e..ef7529b24f1c869d1d6e790458a8f20e79b40ccf 100644 --- a/src/box/tree.m +++ b/src/box/tree.m @@ -30,7 +30,7 @@ #include "tuple.h" #include "space.h" #include "exception.h" -#include "request.h" /* for BOX_ADD, BOX_REPLACE */ +#include "index.h" #include <pickle.h> /* {{{ Utilities. *************************************************/ @@ -946,7 +946,7 @@ tree_iterator_gt(struct iterator *iterator) - (struct tuple *) replace: (struct tuple *) old_tuple : (struct tuple *) new_tuple - : (u32) flags + : (enum replace_flags) flags { assert (old_tuple != NULL || new_tuple != NULL); void *node1 = alloca([self node_size]); @@ -962,14 +962,14 @@ tree_iterator_gt(struct iterator *iterator) /* Try to optimistically replace the new_tuple in the space */ sptree_index_replace(&tree, new_node, &replaced_node); - if (unlikely(key_def->is_unique && (flags & BOX_ADD) + if (unlikely(key_def->is_unique && (flags & THROW_INSERT) && replaced_node != NULL)) { /* BOX_ADD, a tuple with the same key is found */ sptree_index_replace(&tree, replaced_node, NULL); tnt_raise(ClientError, :ER_TUPLE_FOUND); } - if (unlikely(key_def->is_unique && (flags & BOX_REPLACE) + if (unlikely(key_def->is_unique && (flags & REPLACE_THROW) && replaced_node == NULL)) { /* BOX_REPLACE,a tuple with the same key is not found */ sptree_index_delete(&tree, new_node, NULL); @@ -993,7 +993,7 @@ tree_iterator_gt(struct iterator *iterator) } else /* (old_tuple != NULL && new_tuple != NULL) */ { /* Case #3: remove(old_tuple); insert(new_tuple) */ - assert(!key_def->is_unique || (flags & BOX_ADD)); + assert(!key_def->is_unique || (flags & THROW_INSERT)); void *new_node = node1; void *replaced_node = node2;