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 +--------------------------------------------------------------------+
16 #include "libmemcached/common.h"
18 static memcached_return_t
ascii_touch(memcached_instance_st
*instance
, const char *key
,
19 size_t key_length
, time_t expiration
) {
20 char expiration_buffer
[MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH
+ 1];
21 int expiration_buffer_length
= snprintf(expiration_buffer
, sizeof(expiration_buffer
), " %llu",
22 (unsigned long long) expiration
);
23 if (size_t(expiration_buffer_length
) >= sizeof(expiration_buffer
) + 1
24 or expiration_buffer_length
< 0)
26 return memcached_set_error(
27 *instance
, MEMCACHED_MEMORY_ALLOCATION_FAILURE
, MEMCACHED_AT
,
28 memcached_literal_param("snprintf(MEMCACHED_MAXIMUM_INTEGER_DISPLAY_LENGTH)"));
31 libmemcached_io_vector_st vector
[] = {{NULL
, 0},
32 {memcached_literal_param("touch ")},
33 {memcached_array_string(instance
->root
->_namespace
),
34 memcached_array_size(instance
->root
->_namespace
)},
36 {expiration_buffer
, size_t(expiration_buffer_length
)},
37 {memcached_literal_param("\r\n")}};
39 memcached_return_t rc
;
40 if (memcached_failed(rc
= memcached_vdo(instance
, vector
, 6, true))) {
41 return memcached_set_error(*instance
, MEMCACHED_WRITE_FAILURE
, MEMCACHED_AT
);
47 static memcached_return_t
binary_touch(memcached_instance_st
*instance
, const char *key
,
48 size_t key_length
, time_t expiration
) {
49 protocol_binary_request_touch request
= {}; //{.bytes= {0}};
51 initialize_binary_request(instance
, request
.message
.header
);
53 request
.message
.header
.request
.opcode
= PROTOCOL_BINARY_CMD_TOUCH
;
54 request
.message
.header
.request
.extlen
= 4;
55 request
.message
.header
.request
.keylen
=
56 htons((uint16_t)(key_length
+ memcached_array_size(instance
->root
->_namespace
)));
57 request
.message
.header
.request
.datatype
= PROTOCOL_BINARY_RAW_BYTES
;
58 request
.message
.header
.request
.bodylen
=
59 htonl((uint32_t)(key_length
+ memcached_array_size(instance
->root
->_namespace
)
60 + request
.message
.header
.request
.extlen
));
61 request
.message
.body
.expiration
= htonl((uint32_t) expiration
);
63 libmemcached_io_vector_st vector
[] = {{NULL
, 0},
64 {request
.bytes
, sizeof(request
.bytes
)},
65 {memcached_array_string(instance
->root
->_namespace
),
66 memcached_array_size(instance
->root
->_namespace
)},
69 memcached_return_t rc
;
70 if (memcached_failed(rc
= memcached_vdo(instance
, vector
, 4, true))) {
71 return memcached_set_error(*instance
, MEMCACHED_WRITE_FAILURE
, MEMCACHED_AT
);
77 memcached_return_t
memcached_touch(memcached_st
*ptr
, const char *key
, size_t key_length
,
79 return memcached_touch_by_key(ptr
, key
, key_length
, key
, key_length
, expiration
);
82 memcached_return_t
memcached_touch_by_key(memcached_st
*shell
, const char *group_key
,
83 size_t group_key_length
, const char *key
,
84 size_t key_length
, time_t expiration
) {
85 Memcached
*ptr
= memcached2Memcached(shell
);
86 LIBMEMCACHED_MEMCACHED_TOUCH_START();
88 memcached_return_t rc
;
89 if (memcached_failed(rc
= initialize_query(ptr
, true))) {
93 if (memcached_failed(rc
= memcached_key_test(*ptr
, (const char **) &key
, &key_length
, 1))) {
94 return memcached_set_error(*ptr
, rc
, MEMCACHED_AT
);
98 memcached_generate_hash_with_redistribution(ptr
, group_key
, group_key_length
);
99 memcached_instance_st
*instance
= memcached_instance_fetch(ptr
, server_key
);
101 if (ptr
->flags
.binary_protocol
) {
102 rc
= binary_touch(instance
, key
, key_length
, expiration
);
104 rc
= ascii_touch(instance
, key
, key_length
, expiration
);
107 if (memcached_failed(rc
)) {
108 return memcached_set_error(
109 *instance
, rc
, MEMCACHED_AT
,
110 memcached_literal_param("Error occcured while writing touch command to server"));
113 char buffer
[MEMCACHED_DEFAULT_COMMAND_SIZE
];
114 rc
= memcached_response(instance
, buffer
, sizeof(buffer
), NULL
);
116 if (rc
== MEMCACHED_SUCCESS
or rc
== MEMCACHED_NOTFOUND
) {
120 return memcached_set_error(*instance
, rc
, MEMCACHED_AT
,
121 memcached_literal_param("Error occcured while reading response"));