0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-25 23:14:13 +01:00

Refactor scache.

This commit is contained in:
Jason Volk 2016-08-24 03:11:01 -07:00
parent fdf396862b
commit 5f218cdbb2
20 changed files with 294 additions and 278 deletions

View file

@ -62,6 +62,42 @@ namespace help
void load();
}
namespace serv
{
using client::client; //TODO: move up for motd::send_user/send_oper
enum flag
{
HIDDEN = 0x01,
ONLINE = 0x02,
};
struct entry;
const std::string &name(const entry &entry);
const flag &flags(const entry &entry);
void split(entry &entry);
void split(std::shared_ptr<entry> &entry); // safe if null
void send_flattened_links(client &source);
void send_missing(client &source);
size_t count_servers();
size_t count_bytes();
void clear();
// flag |= ONLINE whether or not passed in the argument
std::shared_ptr<entry>
connect(const std::string &name,
const std::string &info,
const flag &flag);
std::shared_ptr<entry>
connect(const std::string &name,
const std::string &info,
const bool &hidden = false);
}
void init();
} // namespace cache

View file

@ -619,16 +619,24 @@ use_id(const client *const &client)
}
bool is_server(const client &client);
inline char *get_id(const client *const &source, const client *const &target)
{
return const_cast<char *>(is_server(*target->from) && has_id(target->from) ? use_id(source) : (source)->name);
}
inline auto get_id(const client &source, const client &target)
inline auto
get_id(const client &source, const client &target)
{
return get_id(&source, &target);
}
inline auto
id(const client &source, const client &target)
{
return is_server(*target.from) && has_id(*target.from)? use_id(source) : source.name;
}
/* flags for local clients, this needs stuff moved from above to here at some point */

View file

@ -43,7 +43,9 @@ namespace serv
int &caps(serv &);
std::string &fullcaps(serv &);
struct scache_entry *&nameinfo(serv &);
using entry = cache::serv::entry;
const std::shared_ptr<entry> &nameinfo(const serv &);
std::shared_ptr<entry> &nameinfo(serv &);
}
} // namespace client
} // namespace ircd

View file

@ -28,7 +28,6 @@
#ifdef __cplusplus
namespace ircd {
struct User;
struct oper_conf;
extern time_t LastUsedWallops;

View file

@ -1,42 +0,0 @@
/*
* ircd-ratbox: A slightly useful ircd.
* scache.h: A header for the servername cache functions.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2004 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#pragma once
#define HAVE_IRCD_SCACHE_H
#ifdef __cplusplus
namespace ircd {
struct scache_entry;
extern void clear_scache_hash_table(void);
extern struct scache_entry *scache_connect(const char *name, const char *info, int hidden);
extern void scache_split(struct scache_entry *ptr);
extern const char *scache_get_name(struct scache_entry *ptr);
extern void scache_send_flattened_links(client::client *source_p);
extern void scache_send_missing(client::client *source_p);
extern void count_scache(size_t *, size_t *);
} // namespace ircd
#endif // __cplusplus

View file

@ -60,7 +60,6 @@ namespace ircd
struct _ssl_ctl;
struct ev_ctl;
struct ws_ctl;
struct scache_entry;
struct server_conf;
}
@ -71,12 +70,11 @@ namespace ircd
#include "messages.h"
#include "rfc1459.h"
#include "err.h"
#include "fs.h"
#include "s_assert.h"
#include "match.h"
#include "cache.h"
#include "tgchange.h"
#include "msgbuf.h"
#include "msg.h"
@ -87,7 +85,6 @@ namespace ircd
#include "authproc.h"
#include "bandbi.h"
#include "cache.h"
#include "capability.h"
#include "certfp.h"
#include "class.h"
@ -112,7 +109,6 @@ namespace ircd
#include "ratelimit.h"
#include "reject.h"
#include "restart.h"
#include "scache.h"
#include "s_conf.h"
#include "send.h"
#include "s_newconf.h"

View file

@ -48,7 +48,7 @@ struct Whowas
char realname[REALLEN + 1];
char suser[NICKLEN + 1];
unsigned char flags;
const char *servername;
std::shared_ptr<cache::serv::entry> scache;
time_t logoff;
client::client *online; /* Pointer to new nickname for chasing or NULL */
};

View file

@ -39,6 +39,7 @@ libircd_la_SOURCES = \
authproc.cc \
bandbi.cc \
cache.cc \
cache_serv.cc \
capability.cc \
channel.cc \
chmode.cc \
@ -76,7 +77,6 @@ libircd_la_SOURCES = \
s_newconf.cc \
s_serv.cc \
s_user.cc \
scache.cc \
send.cc \
snomask.cc \
sslproc.cc \

219
ircd/cache_serv.cc Normal file
View file

@ -0,0 +1,219 @@
/*
* charybdis
* scache.c: Server names cache.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
* Copyright (C) 2005-2016 Charybdis Development Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
/*
* ircd used to store full servernames in anUser as well as in the
* whowas info. there can be some 40k such structures alive at any
* given time, while the number of unique server names a server sees
* in its lifetime is at most a few hundred. by tokenizing server
* names internally, the server can easily save 2 or 3 megs of RAM.
* -orabidoo
*
* reworked to serve for flattening/delaying /links also
* -- jilles
*
* reworked to make use of rb_radixtree.
* -- kaniini
*
* reworked to use standard template container.
* -- jzk
*/
using ircd::client::client;
using ircd::cache::serv::entry;
using namespace ircd;
struct cache::serv::entry
{
std::string name;
std::string info;
time_t known_since;
time_t last_connect;
time_t last_split;
enum flag flag;
entry(const std::string &name, const std::string &info, const enum flag &flag);
};
cache::serv::entry::entry(const std::string &name,
const std::string &info,
const enum flag &flag)
:name{name}
,info{info}
,known_since{rb_current_time()}
,last_connect{0}
,last_split{0}
,flag{flag | ONLINE}
{
}
std::map<const std::string *, std::shared_ptr<entry>, rfc1459::less> ents;
std::shared_ptr<entry>
cache::serv::connect(const std::string &name,
const std::string &info,
const bool &hidden)
{
return connect(name, info, flag(hidden));
}
std::shared_ptr<entry>
cache::serv::connect(const std::string &name,
const std::string &info,
const flag &flag)
{
auto it(ents.lower_bound(&name));
if(it == end(ents) || *it->first != name)
{
auto entry(std::make_shared<struct entry>(name, info, flag));
const auto *const name_p(&entry->name);
it = ents.emplace_hint(it, name_p, std::move(entry));
return it->second;
}
auto &entry(it->second);
entry->last_connect = rb_current_time();
return entry;
}
void
cache::serv::clear()
{
ents.clear();
}
/*
* count_scache
* inputs - pointer to where to leave number of servers cached
* - pointer to where to leave total memory usage
* side effects -
*/
size_t
cache::serv::count_bytes()
{
return ents.size() * sizeof(entry);
}
size_t
cache::serv::count_servers()
{
return ents.size();
}
/* scache_send_flattened_links()
*
* inputs - client to send to
* outputs - the cached links, us, and RPL_ENDOFLINKS
* side effects -
*/
void
cache::serv::send_flattened_links(client &source)
{
for(const auto &pair : ents)
{
const auto &entry(*pair.second);
if(irccmp(name(entry), me.name) == 0)
continue;
if(flags(entry) & HIDDEN && !ConfigServerHide.disable_hidden)
continue;
if(flags(entry) & ONLINE && entry.known_since >= rb_current_time() - ConfigServerHide.links_delay)
continue;
if(~flags(entry) & ONLINE && entry.last_split <= rb_current_time() - ConfigServerHide.links_delay)
continue;
if(~flags(entry) & ONLINE && entry.last_split - entry.known_since <= ConfigServerHide.links_delay)
continue;
sendto_one_numeric(&source, RPL_LINKS, form_str(RPL_LINKS),
name(entry).c_str(),
me.name,
1,
entry.info.c_str());
}
sendto_one_numeric(&source, RPL_LINKS, form_str(RPL_LINKS),
me.name,
me.name,
0,
me.info);
sendto_one_numeric(&source, RPL_ENDOFLINKS, form_str(RPL_ENDOFLINKS),
"*");
}
/* scache_send_missing()
*
* inputs - client to send to
* outputs - recently split servers
* side effects -
*/
void
cache::serv::send_missing(client &source)
{
static const auto MISSING_TIMEOUT = 60 * 60 * 24;
for(const auto &pair : ents)
{
const auto &entry(*pair.second);
if(flags(entry) & ONLINE)
continue;
if(entry.last_split <= rb_current_time() - MISSING_TIMEOUT)
continue;
sendto_one_numeric(&source, RPL_MAP, "** %s (recently split)",
name(entry).c_str());
}
}
void
cache::serv::split(std::shared_ptr<entry> &entry)
{
if(entry)
split(*entry);
}
void
cache::serv::split(entry &entry)
{
entry.flag &= ~ONLINE;
entry.last_split = rb_current_time();
}
const cache::serv::flag &
cache::serv::flags(const entry &entry)
{
return entry.flag;
}
const std::string &
cache::serv::name(const entry &entry)
{
return entry.name;
}

View file

@ -1447,7 +1447,7 @@ client::exit_remote_server(client *client_p, client *source_p, client *from,
del_from_client_hash(source_p->name, source_p);
remove_client_from_list(source_p);
scache_split(source_p->serv->nameinfo);
split(nameinfo(*source_p->serv));
set_dead(*source_p);
#ifdef DEBUG_EXITED_CLIENTS
@ -1474,7 +1474,7 @@ client::qs_server(client *client_p, client *source_p, client *from,
del_from_client_hash(source_p->name, source_p);
remove_client_from_list(source_p);
scache_split(source_p->serv->nameinfo);
split(nameinfo(*source_p->serv));
set_dead(*source_p);
rb_dlinkAddAlloc(source_p, &dead_list);
@ -1541,7 +1541,7 @@ client::exit_local_server(client *client_p, client *source_p, client *from,
del_from_client_hash(source_p->name, source_p);
remove_client_from_list(source_p);
scache_split(source_p->serv->nameinfo);
split(nameinfo(*source_p->serv));
set_dead(*source_p);
rb_dlinkAddAlloc(source_p, &dead_list);

View file

@ -34,7 +34,7 @@ struct serv
int caps; /* capabilities bit-field */
std::string fullcaps;
struct scache_entry *nameinfo;
std::shared_ptr<cache::serv::entry> nameinfo;
serv();
~serv() noexcept;
@ -85,12 +85,18 @@ servers(serv &serv)
return serv.servers;
}
struct scache_entry *&
std::shared_ptr<cache::serv::entry> &
nameinfo(serv &serv)
{
return serv.nameinfo;
}
const std::shared_ptr<cache::serv::entry> &
nameinfo(const serv &serv)
{
return serv.nameinfo;
}
} // namespace serv
} // namespace client
} // namespace ircd

View file

@ -625,7 +625,6 @@ charybdis_main(int argc, char * const argv[])
init_s_conf();
init_s_newconf();
init_hash();
clear_scache_hash_table(); /* server cache name table */
init_host_hash();
client::init();
init_hook();
@ -709,7 +708,7 @@ charybdis_main(int argc, char * const argv[])
make_serv(me);
add_to_client_hash(me.name, &me);
add_to_id_hash(me.id, &me);
nameinfo(serv(me)) = scache_connect(me.name, me.info, 0);
nameinfo(serv(me)) = cache::serv::connect(me.name, me.info);
rb_dlinkAddAlloc(&me, &global_serv_list);

View file

@ -844,7 +844,7 @@ server_estab(client::client *client_p)
client_p->localClient->fullcaps = NULL;
}
nameinfo(serv(*client_p)) = scache_connect(client_p->name, client_p->info, is_hidden(*client_p));
nameinfo(serv(*client_p)) = cache::serv::connect(client_p->name, client_p->info, is_hidden(*client_p));
client_p->localClient->firsttime = rb_current_time();
/* fixing eob timings.. -gnp */

View file

@ -1,207 +0,0 @@
/*
* charybdis
* scache.c: Server names cache.
*
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
namespace ircd {
/*
* ircd used to store full servernames in anUser as well as in the
* whowas info. there can be some 40k such structures alive at any
* given time, while the number of unique server names a server sees
* in its lifetime is at most a few hundred. by tokenizing server
* names internally, the server can easily save 2 or 3 megs of RAM.
* -orabidoo
*
* reworked to serve for flattening/delaying /links also
* -- jilles
*
* reworked to make use of rb_radixtree.
* -- kaniini
*/
#define SC_ONLINE 1
#define SC_HIDDEN 2
struct scache_entry
{
char name[HOSTLEN + 1];
char info[REALLEN + 1];
int flags;
time_t known_since;
time_t last_connect;
time_t last_split;
};
static rb_radixtree *scache_tree = NULL;
void
clear_scache_hash_table(void)
{
scache_tree = rb_radixtree_create("server names cache", irccasecanon);
}
static struct scache_entry *
find_or_add(const char *name)
{
struct scache_entry *ptr;
ptr = (scache_entry *)rb_radixtree_retrieve(scache_tree, name);
if (ptr != NULL)
return ptr;
ptr = (struct scache_entry *) rb_malloc(sizeof(struct scache_entry));
s_assert(0 != ptr);
rb_strlcpy(ptr->name, name, sizeof(ptr->name));
ptr->info[0] = '\0';
ptr->flags = 0;
ptr->known_since = rb_current_time();
ptr->last_connect = 0;
ptr->last_split = 0;
rb_radixtree_add(scache_tree, ptr->name, ptr);
return ptr;
}
struct scache_entry *
scache_connect(const char *name, const char *info, int hidden)
{
struct scache_entry *ptr;
ptr = find_or_add(name);
rb_strlcpy(ptr->info, info, sizeof(ptr->info));
ptr->flags |= SC_ONLINE;
if (hidden)
ptr->flags |= SC_HIDDEN;
else
ptr->flags &= ~SC_HIDDEN;
ptr->last_connect = rb_current_time();
return ptr;
}
void
scache_split(struct scache_entry *ptr)
{
if (ptr == NULL)
return;
ptr->flags &= ~SC_ONLINE;
ptr->last_split = rb_current_time();
}
const char *scache_get_name(struct scache_entry *ptr)
{
return ptr->name;
}
/* scache_send_flattened_links()
*
* inputs - client to send to
* outputs - the cached links, us, and RPL_ENDOFLINKS
* side effects -
*/
void
scache_send_flattened_links(client::client *source_p)
{
struct scache_entry *scache_ptr;
rb_radixtree_iteration_state iter;
int show;
void *elem;
RB_RADIXTREE_FOREACH(elem, &iter, scache_tree)
{
scache_ptr = (scache_entry *)elem;
if (!irccmp(scache_ptr->name, me.name))
show = FALSE;
else if (scache_ptr->flags & SC_HIDDEN &&
!ConfigServerHide.disable_hidden)
show = FALSE;
else if (scache_ptr->flags & SC_ONLINE)
show = scache_ptr->known_since < rb_current_time() - ConfigServerHide.links_delay;
else
show = scache_ptr->last_split > rb_current_time() - ConfigServerHide.links_delay && scache_ptr->last_split - scache_ptr->known_since > ConfigServerHide.links_delay;
if (show)
sendto_one_numeric(source_p, RPL_LINKS, form_str(RPL_LINKS),
scache_ptr->name, me.name, 1, scache_ptr->info);
}
sendto_one_numeric(source_p, RPL_LINKS, form_str(RPL_LINKS),
me.name, me.name, 0, me.info);
sendto_one_numeric(source_p, RPL_ENDOFLINKS, form_str(RPL_ENDOFLINKS), "*");
}
#define MISSING_TIMEOUT 86400
/* scache_send_missing()
*
* inputs - client to send to
* outputs - recently split servers
* side effects -
*/
void
scache_send_missing(client::client *source_p)
{
struct scache_entry *scache_ptr;
rb_radixtree_iteration_state iter;
void *elem;
RB_RADIXTREE_FOREACH(elem, &iter, scache_tree)
{
scache_ptr = (scache_entry *)elem;
if (!(scache_ptr->flags & SC_ONLINE) && scache_ptr->last_split > rb_current_time() - MISSING_TIMEOUT)
sendto_one_numeric(source_p, RPL_MAP, "** %s (recently split)",
scache_ptr->name);
}
}
/*
* count_scache
* inputs - pointer to where to leave number of servers cached
* - pointer to where to leave total memory usage
* output - NONE
* side effects -
*/
void
count_scache(size_t * number_servers_cached, size_t * mem_servers_cached)
{
struct scache_entry *scache_ptr;
rb_radixtree_iteration_state iter;
*number_servers_cached = 0;
*mem_servers_cached = 0;
void *elem;
RB_RADIXTREE_FOREACH(elem, &iter, scache_tree)
{
scache_ptr = (scache_entry *)elem;
*number_servers_cached = *number_servers_cached + 1;
*mem_servers_cached = *mem_servers_cached +
sizeof(struct scache_entry);
}
}
} // namespace ircd

View file

@ -101,8 +101,7 @@ whowas_add_history(client::client *client_p, int online)
who->flags = (is_ip_spoof(*client_p) ? WHOWAS_IP_SPOOFING : 0) |
(is_dyn_spoof(*client_p) ? WHOWAS_DYNSPOOF : 0);
/* this is safe do to with the servername cache */
who->servername = scache_get_name(nameinfo(serv(*client_p)));
who->scache = nameinfo(serv(*client_p));
if(online)
{

View file

@ -476,7 +476,7 @@ ms_server(struct MsgBuf *msgbuf_p, client::client &client, client::client &sourc
add_to_client_hash(target_p->name, target_p);
target_p->lnode = servers(serv(*target_p)).emplace(end(servers(serv(*target_p))), target_p);
nameinfo(serv(*target_p)) = scache_connect(target_p->name, target_p->info, is_hidden(*target_p));
nameinfo(serv(*target_p)) = cache::serv::connect(target_p->name, target_p->info, is_hidden(*target_p));
sendto_server(&client, NULL, NOCAPS, NOCAPS,
":%s SERVER %s %d :%s%s",
@ -633,7 +633,7 @@ ms_sid(struct MsgBuf *msgbuf_p, client::client &client, client::client &source,
add_to_id_hash(target_p->id, target_p);
target_p->lnode = servers(serv(*target_p)).emplace(end(servers(serv(*target_p))), target_p);
nameinfo(serv(*target_p)) = scache_connect(target_p->name, target_p->info, is_hidden(*target_p));
nameinfo(serv(*target_p)) = cache::serv::connect(target_p->name, target_p->info, is_hidden(*target_p));
sendto_server(&client, NULL, CAP_TS6, NOCAPS,
":%s SID %s %d %s :%s%s",

View file

@ -57,7 +57,7 @@ static void
m_links(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char *parv[])
{
if(ConfigServerHide.flatten_links && !is_exempt_shide(source))
scache_send_flattened_links(&source);
cache::serv::send_flattened_links(source);
else
mo_links(msgbuf_p, client, source, parc, parv);
}

View file

@ -67,7 +67,7 @@ static void
mo_map(struct MsgBuf *msgbuf_p, client::client &client, client::client &source, int parc, const char *parv[])
{
dump_map(client, &me, buf);
scache_send_missing(&client);
cache::serv::send_missing(client);
sendto_one_numeric(&client, RPL_MAPEND, form_str(RPL_MAPEND));
}

View file

@ -1437,7 +1437,8 @@ stats_memory (client::client &source)
"z :linebuf %ld(%ld)",
(long)linebuf_count, (long)linebuf_memory_used);
count_scache(&number_servers_cached, &mem_servers_cached);
number_servers_cached = cache::serv::count_servers();
mem_servers_cached = cache::serv::count_bytes();
sendto_one_numeric(&source, RPL_STATSDEBUG,
"z :scache %ld(%ld)",

View file

@ -123,10 +123,10 @@ m_whowas(struct MsgBuf *msgbuf_p, client::client &client, client::client &source
"%s %s :was logged in as",
temp->name, temp->suser);
sendto_one_numeric(&source, RPL_WHOISSERVER,
form_str(RPL_WHOISSERVER),
temp->name, temp->servername,
rb_ctime(temp->logoff, tbuf, sizeof(tbuf)));
sendto_one_numeric(&source, RPL_WHOISSERVER, form_str(RPL_WHOISSERVER),
temp->name,
temp->scache? name(*temp->scache).c_str() : "*",
rb_ctime(temp->logoff, tbuf, sizeof(tbuf)));
cur++;
if(max > 0 && cur >= max)