Skip to content

Commit d6e8119

Browse files
0x501DLeonidVas
authored andcommitted
expire: fix expire fiber termination in ro mode
The instance can return from read-only mode, so the fiber cannot be terminated. Closes #119
1 parent bf155b5 commit d6e8119

File tree

6 files changed

+83
-4
lines changed

6 files changed

+83
-4
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
66
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
77

8+
## [Unreleased]
9+
10+
### Fixed
11+
12+
- Don't terminate the memcached expire fiber in read-only mode.
13+
814
## [1.1.0] - 2022-12-07
915

1016
### Added

memcached/internal/expiration.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "memcached_layer.h"
1111

1212
#include "error.h"
13+
#include "utils.h"
1314

1415
int
1516
memcached_expire_process(struct memcached_service *p, box_iterator_t **iterp)
@@ -58,16 +59,31 @@ memcached_expire_process(struct memcached_service *p, box_iterator_t **iterp)
5859
int
5960
memcached_expire_loop(va_list ap)
6061
{
62+
static int box_ro;
6163
struct memcached_service *p = va_arg(ap, struct memcached_service *);
6264
char key[2], *key_end = mp_encode_array(key, 0);
6365
box_iterator_t *iter = NULL;
6466
int rv = 0;
6567
say_info("Memcached expire fiber started");
66-
restart:
67-
if (iter == NULL) {
68-
iter = box_index_iterator(p->space_id, 0, ITER_ALL, key, key_end);
68+
restart: ;
69+
int old_state = box_ro;
70+
71+
if (memcached_box_is_ro(&box_ro) != true) {
72+
say_error("Cannot get box.info.ro value");
73+
goto finish;
74+
}
75+
76+
if (box_ro) {
77+
if (old_state != box_ro) {
78+
say_info("Expire: the instance has been moved to a read-only mode");
79+
}
80+
goto delay;
6981
}
82+
7083
if (rv == -1 || iter == NULL) {
84+
iter = box_index_iterator(p->space_id, 0, ITER_ALL, key, key_end);
85+
}
86+
if (iter == NULL) {
7187
const box_error_t *err = box_error_last();
7288
say_error("Unexpected error %u: %s",
7389
box_error_code(err),
@@ -82,7 +98,7 @@ memcached_expire_loop(va_list ap)
8298
box_error_message(err));
8399
goto finish;
84100
}
85-
101+
delay: ;
86102
/* This part is where we rest after all deletes */
87103
double delay = ((double )p->expire_count * p->expire_time) /
88104
(box_index_len(p->space_id, 0) + 1);

memcached/internal/utils.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <string.h>
66
#include <inttypes.h>
77

8+
#include <tarantool/lua.h>
89
#include <tarantool/module.h>
910
#include <msgpuck.h>
1011

@@ -101,3 +102,30 @@ strindex(const char **haystack, const char *needle, uint32_t hmax)
101102
return index;
102103
return hmax;
103104
}
105+
106+
/** Get box.info.ro value.
107+
*
108+
* @param result pointer to where the value will be stored.
109+
* @return true if the value was retrieved successfully.
110+
*/
111+
bool
112+
memcached_box_is_ro(int *result)
113+
{
114+
lua_State *L = luaT_state();
115+
int top = lua_gettop(L);
116+
int ro;
117+
118+
lua_getfield(L, LUA_GLOBALSINDEX, "box");
119+
lua_getfield(L, -1, "info");
120+
lua_getfield(L, -1, "ro");
121+
122+
if (!lua_isboolean(L, -1)) {
123+
return false;
124+
}
125+
126+
ro = lua_toboolean(L, -1);
127+
lua_settop(L, top);
128+
*result = ro;
129+
130+
return true;
131+
}

memcached/internal/utils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ safe_strtoull(const char *begin, const char *end, uint64_t *out);
1818
void
1919
memcached_binary_header_dump(struct memcached_hdr *hdr);
2020

21+
bool
22+
memcached_box_is_ro(int *result);
23+
2124
/* Macros to define enum and corresponding strings. */
2225
#define ENUM0_MEMBER(s, ...) s,
2326
#define ENUM_MEMBER(s, v, ...) s = v,

test/text/expirations.result

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,18 @@ add add 0 1 7
6464
addval2
6565
>>--------------------------------------------------
6666
STORED
67+
# return from RO - key should be removed
68+
<<--------------------------------------------------
69+
add key 0 1 3
70+
foo
71+
>>--------------------------------------------------
72+
STORED
73+
# set RO
74+
# set RW
75+
box.space.__mc_memcached:len()
76+
---
77+
- 0
78+
...
6779
<<--------------------------------------------------
6880
flush_all
6981
>>--------------------------------------------------

test/text/expirations.test.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@
9898
print("""# readd add - shoud be success""")
9999
mc_client("add add 0 1 7\r\naddval2\r\n")
100100

101+
server.wait_lsn(master_id, lsn + 3)
102+
print("""# return from RO - key should be removed""")
103+
mc_client("add key 0 1 3\r\nfoo\r\n")
104+
print("""# set RO""")
105+
server.admin("box.cfg({read_only = true})", silent=True)
106+
log = server.get_log()
107+
while log.seek_once("Expire: the instance has been moved to a read-only mode") < 0:
108+
time.sleep(0.01)
109+
time.sleep(1)
110+
print("""# set RW""")
111+
server.admin("box.cfg({read_only = false})", silent=True)
112+
server.wait_lsn(master_id, lsn + 6)
113+
server.admin("box.space.__mc_memcached:len()", silent=False)
114+
101115
mc_client("flush_all\r\n")
102116

103117
sys.path = saved_path

0 commit comments

Comments
 (0)