degesch: finish implementation of rehashing

I can only hope it works.
This commit is contained in:
Přemysl Eric Janouch 2015-06-23 23:13:15 +02:00
parent e39bb976cb
commit fafe1fde90
1 changed files with 64 additions and 35 deletions

View File

@ -2925,6 +2925,58 @@ irc_left_channel (struct channel *channel)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
static void
remove_conflicting_buffer (struct server *s, struct buffer *buffer)
{
buffer_send_status (s->ctx, NULL,
"Removed buffer %s because of casemapping conflict", buffer->name);
if (s->ctx->current_buffer == buffer)
buffer_activate (s->ctx, s->buffer);
buffer_remove (s->ctx, buffer);
}
static void
irc_try_readd_user (struct server *s,
struct user *user, struct buffer *buffer)
{
if (str_map_find (&s->irc_users, user->nickname))
{
// Remove user from all channels and destroy any PM buffer
user_ref (user);
LIST_FOR_EACH (struct user_channel, iter, user->channels)
irc_remove_user_from_channel (user, iter->channel);
if (buffer)
remove_conflicting_buffer (s, buffer);
user_unref (user);
}
else
{
str_map_set (&s->irc_users, user->nickname, user);
str_map_set (&s->irc_buffer_map, user->nickname, buffer);
}
}
static void
irc_try_readd_channel (struct server *s,
struct channel *channel, struct buffer *buffer)
{
if (str_map_find (&s->irc_channels, channel->name))
{
// Remove all users from channel and destroy any channel buffer
channel_ref (channel);
LIST_FOR_EACH (struct channel_user, iter, channel->users)
irc_channel_unlink_user (channel, iter);
if (buffer)
remove_conflicting_buffer (s, buffer);
channel_unref (channel);
}
else
{
str_map_set (&s->irc_channels, channel->name, channel);
str_map_set (&s->irc_buffer_map, channel->name, buffer);
}
}
static void
irc_rehash_and_fix_conflicts (struct server *s)
{
@ -2937,10 +2989,6 @@ irc_rehash_and_fix_conflicts (struct server *s)
str_map_init (&s->irc_channels);
str_map_init (&s->irc_buffer_map);
s->irc_users .free = old_users .free;
s->irc_channels .free = old_channels .free;
s->irc_buffer_map.free = old_buffer_map.free;
s->irc_users .key_xfrm = s->irc_strxfrm;
s->irc_channels .key_xfrm = s->irc_strxfrm;
s->irc_buffer_map.key_xfrm = s->irc_strxfrm;
@ -2949,46 +2997,27 @@ irc_rehash_and_fix_conflicts (struct server *s)
// from server maps upon removing the last reference to them
s->rehashing = true;
// TODO: "Removed similarly named buffer %s because of casemapping conflict"
// XXX: to be perfectly sure, we should also check
// whether any users collide with channels and vice versa
// Our own user always takes priority, add him first
if (s->irc_user)
irc_try_readd_user (s, s->irc_user,
str_map_find (&old_buffer_map, s->irc_user->nickname));
struct str_map_iter iter;
str_map_iter_init (&iter, &old_users);
struct user *user;
struct channel *channel;
str_map_iter_init (&iter, &old_users);
while ((user = str_map_iter_next (&iter)))
{
// FIXME: don't remove ourselves!
if (str_map_find (&s->irc_users, user->nickname))
{
// TODO: move or merge any PM buffer and remove
// the user from channels and altogether
}
else
{
str_map_set (&s->irc_users, user->nickname, user);
str_map_set (&s->irc_buffer_map, user->nickname,
str_map_find (&old_buffer_map, user->nickname));
}
}
irc_try_readd_user (s, user,
str_map_find (&old_buffer_map, user->nickname));
str_map_iter_init (&iter, &old_channels);
struct channel *channel;
while ((channel = str_map_iter_next (&iter)))
{
if (str_map_find (&s->irc_channels, channel->name))
{
// TODO: remove all users from the buffer
// and probably issue NAMES if registered and on the channel,
// and of course remove the colliding channel
}
else
{
str_map_set (&s->irc_channels, channel->name, user);
str_map_set (&s->irc_buffer_map, user->nickname,
str_map_find (&old_buffer_map, user->nickname));
}
}
irc_try_readd_channel (s, channel,
str_map_find (&old_buffer_map, channel->name));
// Hopefully we've either moved or destroyed all the old content
s->rehashing = false;