src/libmemcached: apply clang-format
[m6w6/libmemcached] / src / libmemcached / delete.cc
1 /*
2 +--------------------------------------------------------------------+
3 | libmemcached - C/C++ Client Library for memcached |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted under the terms of the BSD license. |
7 | You should have received a copy of the license in a bundled file |
8 | named LICENSE; in case you did not receive a copy you can review |
9 | the terms online at: https://opensource.org/licenses/BSD-3-Clause |
10 +--------------------------------------------------------------------+
11 | Copyright (c) 2006-2014 Brian Aker https://datadifferential.com/ |
12 | Copyright (c) 2020 Michael Wallner <mike@php.net> |
13 +--------------------------------------------------------------------+
14 */
15
16 #include "libmemcached/common.h"
17
18 memcached_return_t memcached_delete(memcached_st *shell, const char *key, size_t key_length,
19 time_t expiration) {
20 return memcached_delete_by_key(shell, key, key_length, key, key_length, expiration);
21 }
22
23 static inline memcached_return_t ascii_delete(memcached_instance_st *instance, uint32_t,
24 const char *key, const size_t key_length,
25 const bool reply, const bool is_buffering) {
26 libmemcached_io_vector_st vector[] = {
27 {NULL, 0},
28 {memcached_literal_param("delete ")},
29 {memcached_array_string(instance->root->_namespace),
30 memcached_array_size(instance->root->_namespace)},
31 {key, key_length},
32 {" noreply", reply ? 0 : memcached_literal_param_size(" noreply")},
33 {memcached_literal_param("\r\n")}};
34
35 /* Send command header, only flush if we are NOT buffering */
36 return memcached_vdo(instance, vector, 6, is_buffering ? false : true);
37 }
38
39 static inline memcached_return_t binary_delete(memcached_instance_st *instance, uint32_t server_key,
40 const char *key, const size_t key_length,
41 const bool reply, const bool is_buffering) {
42 protocol_binary_request_delete request = {};
43
44 bool should_flush = is_buffering ? false : true;
45
46 initialize_binary_request(instance, request.message.header);
47
48 if (reply) {
49 request.message.header.request.opcode = PROTOCOL_BINARY_CMD_DELETE;
50 } else {
51 request.message.header.request.opcode = PROTOCOL_BINARY_CMD_DELETEQ;
52 }
53 request.message.header.request.keylen =
54 htons(uint16_t(key_length + memcached_array_size(instance->root->_namespace)));
55 request.message.header.request.datatype = PROTOCOL_BINARY_RAW_BYTES;
56 request.message.header.request.bodylen =
57 htonl(uint32_t(key_length + memcached_array_size(instance->root->_namespace)));
58
59 libmemcached_io_vector_st vector[] = {{NULL, 0},
60 {request.bytes, sizeof(request.bytes)},
61 {memcached_array_string(instance->root->_namespace),
62 memcached_array_size(instance->root->_namespace)},
63 {key, key_length}};
64
65 memcached_return_t rc = memcached_vdo(instance, vector, 4, should_flush);
66
67 if (memcached_has_replicas(instance)) {
68 request.message.header.request.opcode = PROTOCOL_BINARY_CMD_DELETEQ;
69
70 for (uint32_t x = 0; x < memcached_has_replicas(instance); ++x) {
71 ++server_key;
72
73 if (server_key == memcached_server_count(instance->root)) {
74 server_key = 0;
75 }
76
77 memcached_instance_st *replica = memcached_instance_fetch(instance->root, server_key);
78
79 if (memcached_success(memcached_vdo(replica, vector, 4, should_flush))) {
80 memcached_server_response_decrement(replica);
81 }
82 }
83 }
84
85 return rc;
86 }
87
88 memcached_return_t memcached_delete_by_key(memcached_st *shell, const char *group_key,
89 size_t group_key_length, const char *key,
90 size_t key_length, time_t expiration) {
91 Memcached *memc = memcached2Memcached(shell);
92 LIBMEMCACHED_MEMCACHED_DELETE_START();
93
94 memcached_return_t rc;
95 if (memcached_fatal(rc = initialize_query(memc, true))) {
96 return rc;
97 }
98
99 if (memcached_fatal(rc = memcached_key_test(*memc, (const char **) &key, &key_length, 1))) {
100 return memcached_last_error(memc);
101 }
102
103 if (expiration) {
104 return memcached_set_error(
105 *memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
106 memcached_literal_param(
107 "Memcached server version does not allow expiration of deleted items"));
108 }
109
110 uint32_t server_key =
111 memcached_generate_hash_with_redistribution(memc, group_key, group_key_length);
112 memcached_instance_st *instance = memcached_instance_fetch(memc, server_key);
113
114 bool is_buffering = memcached_is_buffering(instance->root);
115 bool is_replying = memcached_is_replying(instance->root);
116
117 // If a delete trigger exists, we need a response, so no buffering/noreply
118 if (memc->delete_trigger) {
119 if (is_buffering) {
120 return memcached_set_error(
121 *memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
122 memcached_literal_param("Delete triggers cannot be used if buffering is enabled"));
123 }
124
125 if (is_replying == false) {
126 return memcached_set_error(
127 *memc, MEMCACHED_INVALID_ARGUMENTS, MEMCACHED_AT,
128 memcached_literal_param(
129 "Delete triggers cannot be used if MEMCACHED_BEHAVIOR_NOREPLY is set"));
130 }
131 }
132
133 if (memcached_is_binary(memc)) {
134 rc = binary_delete(instance, server_key, key, key_length, is_replying, is_buffering);
135 } else {
136 rc = ascii_delete(instance, server_key, key, key_length, is_replying, is_buffering);
137 }
138
139 if (rc == MEMCACHED_SUCCESS) {
140 if (is_buffering == true) {
141 rc = MEMCACHED_BUFFERED;
142 } else if (is_replying == false) {
143 rc = MEMCACHED_SUCCESS;
144 } else {
145 char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE];
146 rc = memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL);
147 if (rc == MEMCACHED_DELETED) {
148 rc = MEMCACHED_SUCCESS;
149 if (memc->delete_trigger) {
150 memc->delete_trigger(memc, key, key_length);
151 }
152 }
153 }
154 }
155
156 LIBMEMCACHED_MEMCACHED_DELETE_END();
157 return rc;
158 }