Skip to content
Snippets Groups Projects
Commit 6b4382b8 authored by Vladimír Čunát's avatar Vladimír Čunát
Browse files

Merge !194: kresc: misc improvements

parents 46d87c85 e7a7a084
Branches
Tags
2 merge requests!254Knot Resolver 1.2.5,!194kresc: misc improvements
Pipeline #1627 passed with stages
in 1 minute and 39 seconds
......@@ -711,30 +711,44 @@ The daemon provides an interface for dynamic loading of :ref:`daemon modules <mo
Cache configuration
^^^^^^^^^^^^^^^^^^^
The cache in Knot DNS Resolver is persistent with LMDB backend, this means that the daemon doesn't lose
The default cache in Knot DNS Resolver is persistent with LMDB backend, this means that the daemon doesn't lose
the cached data on restart or crash to avoid cold-starts. The cache may be reused between cache
daemons or manipulated from other processes, making for example synchronised load-balanced recursors possible.
.. envvar:: cache.size (number)
Get/set the cache maximum size in bytes. Note that this is only a hint to the backend,
Set the cache maximum size in bytes. Note that this is only a hint to the backend,
which may or may not respect it. See :func:`cache.open()`.
.. code-block:: lua
print(cache.size)
cache.size = 100 * MB -- equivalent to `cache.open(100 * MB)`
.. envvar:: cache.current_size (number)
Get the maximum size in bytes.
.. code-block:: lua
print(cache.current_size)
.. envvar:: cache.storage (string)
Get or change the cache storage backend configuration, see :func:`cache.backends()` for
Set the cache storage backend configuration, see :func:`cache.backends()` for
more information. If the new storage configuration is invalid, it is not set.
.. code-block:: lua
print(cache.storage)
cache.storage = 'lmdb://.'
.. envvar:: cache.current_storage (string)
Get the storage backend configuration.
.. code-block:: lua
print(cache.storage)
.. function:: cache.backends()
:return: map of backends
......
......@@ -28,6 +28,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#define HISTORY_FILE "kresc_history"
#define PROGRAM_NAME "kresc"
......@@ -79,6 +80,7 @@ const char *get_type_name(const char *value)
if (starts_with(type, "[")) {
//Return "nil" on non-valid name.
free(type);
return "nil";
} else {
type[(strlen(type)) - 1] = '\0';
......@@ -86,6 +88,152 @@ const char *get_type_name(const char *value)
}
}
static void complete_function(EditLine * el)
{
//Add left parenthesis to function name.
el_insertstr(el, "(");
}
static void complete_members(EditLine * el, const char *str,
const char *str_type, int str_len, char *dot)
{
char *table = strdup(str);
if (!table) {
perror("While tab-completing");
return;
}
//Get only the table name (without partial member name).
if (dot) {
*(table + (dot - str)) = '\0';
}
//Insert a dot after the table name.
if (!strncmp(str_type, "table", 5)) {
el_insertstr(el, ".");
str_len++;
}
//Check if the substring before dot is a valid table name.
const char *t_type = get_type_name(table);
if (t_type && !strncmp("table", t_type, 5)) {
//Get string of members of the table.
char *cmd =
afmt
("do local s=\"\"; for i in pairs(%s) do s=s..i..\"\\n\" end return(s) end",
table);
if (!cmd) {
perror("While tab-completing.");
goto complete_members_exit;
}
size_t members_len;
char *members = run_cmd(cmd, &members_len);
free(cmd);
if (!members) {
perror("While communication with daemon");
goto complete_members_exit;
}
//Split members by newline.
char *members_tok = strdup(members);
free(members);
if (!members_tok) {
goto complete_members_exit;
}
char *token = strtok(members_tok, "\n");
int matches = 0;
char *lastmatch = NULL;
if (!dot || dot - str + 1 == strlen(str)) {
//Prints all members.
while (token) {
char *member = afmt("%s.%s", table, token);
const char *member_type = get_type_name(member);
if (member && member_type) {
printf("\n%s (%s)", member, member_type);
free(member);
free((void *)member_type);
} else if (member) {
printf("\n%s", member);
free(member);
}
token = strtok(NULL, "\n");
matches++;
}
} else {
//Print members matching the current line.
while (token) {
if (str && starts_with(token, dot + 1)) {
const char *member_type =
get_type_name(afmt
("%s.%s", table,
token));
if (member_type) {
printf("\n%s.%s (%s)", table,
token, member_type);
free((void *)member_type);
} else {
printf("\n%s.%s", table, token);
}
lastmatch = token;
matches++;
}
token = strtok(NULL, "\n");
}
//Complete matching member.
if (matches == 1) {
el_deletestr(el, str_len);
el_insertstr(el, table);
el_insertstr(el, ".");
el_insertstr(el, lastmatch);
}
}
if (matches > 1) {
printf("\n");
}
free(members_tok);
}
complete_members_exit:
free(table);
if(t_type) {
free((void*)t_type);
}
}
static void complete_globals(EditLine * el, const char *str, int str_len)
{
//Parse Lua globals.
size_t globals_len;
char *globals = run_cmd("_G.__orig_name_list", &globals_len);
if (!globals) {
perror("While tab-completing");
return;
}
//Show possible globals.
char *globals_tok = strdup(globals);
free(globals);
if (!globals_tok) {
return;
}
char *token = strtok(globals_tok, "\n");
int matches = 0;
char *lastmatch = NULL;
while (token) {
if (str && starts_with(token, str)) {
printf("\n%s (%s)", token, get_type_name(token));
lastmatch = token;
matches++;
}
token = strtok(NULL, "\n");
}
if (matches > 1) {
printf("\n");
}
//Complete matching global.
if (matches == 1) {
el_deletestr(el, str_len);
el_insertstr(el, lastmatch);
}
free(globals_tok);
}
static unsigned char complete(EditLine * el, int ch)
{
int argc, pos;
......@@ -125,136 +273,19 @@ static unsigned char complete(EditLine * el, int ch)
//Get position of last dot in current line (useful for parsing table).
char *dot = strrchr(argv[0], '.');
//Line is not a name of some table and there is no dot in it.
if (strncmp(type, "table", 5) && !dot) {
//Parse Lua globals.
size_t globals_len;
char *globals = run_cmd("_G.__orig_name_list", &globals_len);
if (!globals) {
perror("While tab-completing");
goto complete_exit;
}
//Show possible globals.
char *globals_tok = strdup(globals);
free(globals);
if (!globals_tok) {
goto complete_exit;
}
char *token = strtok(globals_tok, "\n");
int matches = 0;
char *lastmatch;
while (token) {
if (argv[0] && starts_with(token, argv[0])) {
printf("\n%s (%s)", token,
get_type_name(token));
fflush(stdout);
lastmatch = token;
matches++;
}
token = strtok(NULL, "\n");
}
if (matches > 1) {
printf("\n");
}
//Complete matching global.
if (matches == 1) {
el_deletestr(el, pos);
el_insertstr(el, lastmatch);
pos = strlen(lastmatch);
}
free(globals_tok);
//Current line (or part of it) is a name of some table.
//Line is not a name of some table and there is no dot in it.
complete_globals(el, argv[0], pos);
} else if ((dot && !strncmp(type, "nil", 3))
|| !strncmp(type, "table", 5)) {
char *table = strdup(argv[0]);
if (!table) {
perror("While tab-completing");
goto complete_exit;
}
//Get only the table name (without partial member name).
if (dot) {
*(table + (dot - argv[0])) = '\0';
}
//Insert a dot after the table name.
if (!strncmp(type, "table", 5)) {
el_insertstr(el, ".");
pos++;
}
//Check if the substring before dot is a valid table name.
const char *t_type = get_type_name(table);
if (t_type && !strncmp("table", t_type, 5)) {
//Get string of members of the table.
char *cmd =
afmt
("do local s=\"\"; for i in pairs(%s) do s=s..i..\"\\n\" end return(s) end",
table);
if (!cmd) {
perror("While tab-completing.");
goto complete_exit;
}
size_t members_len;
char *members = run_cmd(cmd, &members_len);
free(cmd);
if (!members) {
perror("While communication with daemon");
}
//Split members by newline.
char *members_tok = strdup(members);
free(members);
if (!members_tok) {
goto complete_exit;
}
char *token = strtok(members_tok, "\n");
int matches = 0;
char *lastmatch;
if (!dot || dot - argv[0] + 1 == strlen(argv[0])) {
//Prints all members.
while (token) {
char *member =
afmt("%s.%s", table, token);
printf("\n%s (%s)", member,
get_type_name(member));
token = strtok(NULL, "\n");
matches++;
}
} else {
//Print members matching the current line.
while (token) {
if (argv[0]
&& starts_with(token, dot + 1)) {
printf("\n%s.%s (%s)", table,
token,
get_type_name(afmt
("%s.%s",
table,
token)));
lastmatch = token;
matches++;
}
token = strtok(NULL, "\n");
}
//Complete matching member.
if (matches == 1) {
el_deletestr(el, pos);
el_insertstr(el, table);
el_insertstr(el, ".");
el_insertstr(el, lastmatch);
pos =
strlen(lastmatch) + strlen(table) +
1;
}
}
if (matches > 1) {
printf("\n");
}
free(members_tok);
}
//Current line (or part of it) is a name of some table.
complete_members(el, argv[0], type, pos, dot);
} else if (!strncmp(type, "function", 8)) {
//Add left parenthesis to function name.
el_insertstr(el, "(");
pos++;
//Current line is a function.
complete_function(el);
}
if (type) {
free((void *)type);
}
complete_exit:
......@@ -275,23 +306,28 @@ static int init_tty(const char *path)
size_t plen = strlen(path);
if (plen + 1 > sizeof(addr.sun_path)) {
fprintf(stderr, "Path too long\n");
close(fd);
return 1;
}
memcpy(addr.sun_path, path, plen + 1);
if (connect(fd, (const struct sockaddr *)&addr, sizeof(addr))) {
perror("While connecting to daemon");
close(fd);
return 1;
}
g_tty = fdopen(fd, "r+");
if (!g_tty) {
perror("While opening TTY");
close(fd);
return 1;
}
// Switch to binary mode and consume the text "> ".
if (fprintf(g_tty, "__binary\n") < 0 || !fread(&addr, 2, 1, g_tty)
|| fflush(g_tty)) {
perror("While initializing TTY");
fclose(g_tty);
g_tty = NULL;
return 1;
}
......
......@@ -106,30 +106,26 @@ setmetatable(modules, {
})
-- Syntactic sugar for cache
-- `#cache -> cache.count()`
-- `cache[x] -> cache.get(x)`
-- `cache.{size|storage} = value`
setmetatable(cache, {
__len = function (t)
return t.count()
end,
__index = function (t, k)
if type(k) == 'number' then
return rawget(t, k) or (rawget(t, 'current_size') and t.get(k))
end
local res = rawget(t, k)
if res and not rawget(t, 'current_size') then return res end
-- Beware: t.get returns empty table on failure to find.
-- That would be confusing here (breaking kresc), so return nil instead.
res = t.get(k)
if res and next(res) ~= nil then return res else return nil end
end,
__newindex = function (t,k,v)
-- Defaults
if type(k) == number then
local storage = rawget(t, 'current_storage')
if not storage then storage = 'lmdb://' end
local size = rawget(t, 'current_size')
if not size then size = 10*MB end
end
local storage = rawget(t, 'current_storage')
if not storage then storage = 'lmdb://' end
local size = rawget(t, 'current_size')
if not size then size = 10*MB end
-- Declarative interface for cache
if k == 'size' then t.open(v, storage)
elseif k == 'storage' then t.open(size, v)
else rawset(t, k, v) end
elseif k == 'storage' then t.open(size, v) end
end
})
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment