diff options
author | Přemysl Janouch <p.janouch@gmail.com> | 2015-06-23 22:10:16 +0200 |
---|---|---|
committer | Přemysl Janouch <p.janouch@gmail.com> | 2015-06-23 22:10:16 +0200 |
commit | e39bb976cbd81952ae00d0a56c09486ac3f6ab0f (patch) | |
tree | 977767ec839c00c53735d7b8e4077bbd56df8584 /degesch.c | |
parent | 63a65f9f7cf255934558902a57d969eba87b160b (diff) | |
download | xK-e39bb976cbd81952ae00d0a56c09486ac3f6ab0f.tar.gz xK-e39bb976cbd81952ae00d0a56c09486ac3f6ab0f.tar.xz xK-e39bb976cbd81952ae00d0a56c09486ac3f6ab0f.zip |
degesch: partially implement rehashing
Diffstat (limited to 'degesch.c')
-rw-r--r-- | degesch.c | 77 |
1 files changed, 74 insertions, 3 deletions
@@ -1059,6 +1059,8 @@ struct server // TODO: an output queue to prevent excess floods (this will be needed // especially for away status polling) + bool rehashing; ///< Rehashing IRC identifiers + struct str_map irc_users; ///< IRC user data struct str_map irc_channels; ///< IRC channel data struct str_map irc_buffer_map; ///< Maps IRC identifiers to buffers @@ -2791,7 +2793,8 @@ irc_user_on_destroy (void *object, void *user_data) { struct user *user = object; struct server *s = user_data; - str_map_set (&s->irc_users, user->nickname, NULL); + if (!s->rehashing) + str_map_set (&s->irc_users, user->nickname, NULL); } static struct user * @@ -2877,7 +2880,8 @@ irc_channel_on_destroy (void *object, void *user_data) struct server *s = user_data; LIST_FOR_EACH (struct channel_user, iter, channel->users) irc_channel_unlink_user (channel, iter); - str_map_set (&s->irc_channels, channel->name, NULL); + if (!s->rehashing) + str_map_set (&s->irc_channels, channel->name, NULL); } static struct channel * @@ -2924,7 +2928,74 @@ irc_left_channel (struct channel *channel) static void irc_rehash_and_fix_conflicts (struct server *s) { - // TODO + // Save the old maps and initialize new ones + struct str_map old_users = s->irc_users; + struct str_map old_channels = s->irc_channels; + struct str_map old_buffer_map = s->irc_buffer_map; + + str_map_init (&s->irc_users); + 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; + + // Prevent channels and users from unsetting themselves + // 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 + + struct str_map_iter iter; + str_map_iter_init (&iter, &old_users); + struct user *user; + 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)); + } + } + + 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)); + } + } + + // Hopefully we've either moved or destroyed all the old content + s->rehashing = false; + + str_map_free (&old_users); + str_map_free (&old_channels); + str_map_free (&old_buffer_map); } static void |