1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-07 07:43:13 +02:00

Move channel history sending from one layer to the other.

This so for example history_backend_mem() does not do any sending.
Less efficient but needed for later when things get more complex.
This commit is contained in:
Bram Matthys
2021-04-07 09:42:18 +02:00
parent 4dc999d2b6
commit e596b730af
7 changed files with 151 additions and 65 deletions
+4 -1
View File
@@ -944,8 +944,11 @@ extern void free_message_tags(MessageTag *m);
extern time_t server_time_to_unix_time(const char *tbuf);
extern int history_set_limit(char *object, int max_lines, long max_t);
extern int history_add(char *object, MessageTag *mtags, char *line);
extern int history_request(Client *acptr, char *object, HistoryFilter *filter);
extern HistoryResult *history_request(char *object, HistoryFilter *filter);
extern int history_destroy(char *object);
extern int can_receive_history(Client *client);
extern void history_send_result(Client *client, HistoryResult *r);
extern void free_history_result(HistoryResult *r);
extern void special_delayed_unloading(void);
extern int write_int64(FILE *fd, uint64_t t);
extern int write_int32(FILE *fd, uint32_t t);
+18 -2
View File
@@ -493,6 +493,22 @@ struct HistoryFilter {
int last_seconds;
};
/** History log lines, used by HistoryResult among others */
typedef struct HistoryLogLine HistoryLogLine;
struct HistoryLogLine {
HistoryLogLine *prev, *next;
time_t t;
MessageTag *mtags;
char line[1];
};
typedef struct HistoryResult HistoryResult;
struct HistoryResult {
char *object; /**< Name of the history object, eg '#test' */
HistoryLogLine *log; /**< The resulting log lines */
HistoryLogLine *log_tail; /**< Last entry in the log lines */
};
/** History Backend */
typedef struct HistoryBackend HistoryBackend;
struct HistoryBackend {
@@ -500,7 +516,7 @@ struct HistoryBackend {
char *name; /**< The name of the history backend (eg: "mem") */
int (*history_set_limit)(char *object, int max_lines, long max_time); /**< Impose a limit on a history object */
int (*history_add)(char *object, MessageTag *mtags, char *line); /**< Add to history */
int (*history_request)(Client *acptr, char *object, HistoryFilter *filter); /**< Request history */
HistoryResult *(*history_request)(char *object, HistoryFilter *filter); /**< Request history */
int (*history_destroy)(char *object); /**< Destroy history of this object completely */
Module *owner; /**< Module introducing this */
char unloaded; /**< Internal flag to indicate module is being unloaded */
@@ -513,7 +529,7 @@ typedef struct {
char *name;
int (*history_set_limit)(char *object, int max_lines, long max_time);
int (*history_add)(char *object, MessageTag *mtags, char *line);
int (*history_request)(Client *acptr, char *object, HistoryFilter *filter);
HistoryResult *(*history_request)(char *object, HistoryFilter *filter);
int (*history_destroy)(char *object);
} HistoryBackendInfo;
+83 -5
View File
@@ -166,14 +166,21 @@ int history_add(char *object, MessageTag *mtags, char *line)
return 1;
}
int history_request(Client *client, char *object, HistoryFilter *filter)
HistoryResult *history_request(char *object, HistoryFilter *filter)
{
HistoryBackend *hb;
HistoryBackend *hb = historybackends;
HistoryResult *r;
HistoryLogLine *l;
for (hb = historybackends; hb; hb=hb->next)
hb->history_request(client, object, filter);
if (!hb)
return 0; /* no history backend loaded */
return 1;
/* Right now we return whenever the first backend has a result. */
for (hb = historybackends; hb; hb = hb->next)
if ((r = hb->history_request(object, filter)))
return r;
return NULL;
}
int history_destroy(char *object)
@@ -195,3 +202,74 @@ int history_set_limit(char *object, int max_lines, long max_t)
return 1;
}
/** Free a HistoryResult object that was returned from request_result() earlier */
void free_history_result(HistoryResult *r)
{
HistoryLogLine *l, *l_next;
for (l = r->log; l; l = l_next)
{
l_next = l->next;
free_message_tags(l->mtags);
safe_free(l);
}
safe_free(r->object);
safe_free(r);
}
/** Returns 1 if the client can receive channel history, 0 if not.
* @param client The client to check.
* @note It is recommend to call this function BEFORE trying to
* retrieve channel history via history_request(),
* as to not waste useless resources.
*/
int can_receive_history(Client *client)
{
if (HasCapability(client, "server-time"))
return 1;
return 0;
}
static void history_send_result_line(Client *client, HistoryLogLine *l, char *batchid)
{
if (BadPtr(batchid))
{
sendto_one(client, l->mtags, "%s", l->line);
} else {
MessageTag *m = safe_alloc(sizeof(MessageTag));
m->name = "batch";
m->value = batchid;
AddListItem(m, l->mtags);
sendto_one(client, l->mtags, "%s", l->line);
DelListItem(m, l->mtags);
safe_free(m);
}
}
/** Send the result of a history_request() to the client.
* @param client The client to send to.
* @param r The history result retrieved via history_request().
*/
void history_send_result(Client *client, HistoryResult *r)
{
char batch[BATCHLEN+1];
HistoryLogLine *l;
if (!can_receive_history(client))
return;
batch[0] = '\0';
if (HasCapability(client, "batch"))
{
/* Start a new batch */
generate_batch_id(batch);
sendto_one(client, NULL, ":%s BATCH +%s chathistory %s", me.name, batch, r->object);
}
for (l = r->log; l; l = l->next)
history_send_result_line(client, l, batch);
/* End of batch */
if (*batch)
sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
}
+8 -2
View File
@@ -534,13 +534,19 @@ int history_join(Client *client, Channel *channel, MessageTag *mtags, char *parv
if (!HistoryEnabled(channel))
return 0;
if (MyUser(client))
if (MyUser(client) && can_receive_history(client))
{
HistoryFilter filter;
HistoryResult *r;
memset(&filter, 0, sizeof(filter));
filter.last_lines = cfg.playback_on_join.lines;
filter.last_seconds = cfg.playback_on_join.time;
history_request(client, channel->chname, &filter);
r = history_request(channel->chname, &filter);
if (r)
{
history_send_result(client, r);
free_history_result(r);
}
}
return 0;
+7 -1
View File
@@ -72,6 +72,7 @@ void history_usage(Client *client)
CMD_FUNC(cmd_history)
{
HistoryFilter filter;
HistoryResult *r;
Channel *channel;
int lines = HISTORY_LINES_DEFAULT;
@@ -122,5 +123,10 @@ CMD_FUNC(cmd_history)
memset(&filter, 0, sizeof(filter));
filter.last_lines = lines;
history_request(client, channel->chname, &filter);
if ((r = history_request(channel->chname, &filter)))
{
history_send_result(client, r);
free_history_result(r);
}
}
+28 -51
View File
@@ -41,14 +41,6 @@ ModuleHeader MOD_HEADER
#define HISTORY_TIMER_EVERY (HISTORY_MAX_OFF_SECS/HISTORY_SPREAD)
/* Definitions (structs, etc.) */
typedef struct HistoryLogLine HistoryLogLine;
struct HistoryLogLine {
HistoryLogLine *prev, *next;
time_t t;
MessageTag *mtags;
char line[1];
};
typedef struct HistoryLogObject HistoryLogObject;
struct HistoryLogObject {
HistoryLogObject *prev, *next;
@@ -68,7 +60,7 @@ HistoryLogObject *history_hash_table[HISTORY_BACKEND_MEM_HASH_TABLE_SIZE];
/* Forward declarations */
int hbm_history_add(char *object, MessageTag *mtags, char *line);
int hbm_history_cleanup(HistoryLogObject *h);
int hbm_history_request(Client *client, char *object, HistoryFilter *filter);
HistoryResult *hbm_history_request(char *object, HistoryFilter *filter);
int hbm_history_destroy(char *object);
int hbm_history_set_limit(char *object, int max_lines, long max_time);
EVENT(history_mem_clean);
@@ -263,53 +255,27 @@ int hbm_history_add(char *object, MessageTag *mtags, char *line)
return 0;
}
int can_receive_history(Client *client)
HistoryLogLine *duplicate_log_line(HistoryLogLine *l)
{
if (HasCapability(client, "server-time"))
return 1;
return 0;
HistoryLogLine *n = safe_alloc(sizeof(HistoryLogLine) + strlen(l->line));
strcpy(n->line, l->line); /* safe, see memory allocation above ^ */
hbm_duplicate_mtags(n, l->mtags);
return n;
}
void hbm_send_line(Client *client, HistoryLogLine *l, char *batchid)
{
if (can_receive_history(client))
{
if (BadPtr(batchid))
{
sendto_one(client, l->mtags, "%s", l->line);
} else {
MessageTag *m = safe_alloc(sizeof(MessageTag));
m->name = "batch";
m->value = batchid;
AddListItem(m, l->mtags);
sendto_one(client, l->mtags, "%s", l->line);
DelListItem(m, l->mtags);
safe_free(m);
}
} else {
/* without server-time, log playback is a bit annoying, so skip it? */
}
}
int hbm_history_request(Client *client, char *object, HistoryFilter *filter)
HistoryResult *hbm_history_request(char *object, HistoryFilter *filter)
{
HistoryResult *r;
HistoryLogObject *h = hbm_find_object(object);
HistoryLogLine *l;
char batch[BATCHLEN+1];
long redline; /* Imaginary timestamp. Before the red line, history is too old. */
int lines_sendable = 0, lines_to_skip = 0, cnt = 0;
if (!h || !can_receive_history(client))
return 0;
if (!h)
return NULL; /* nothing found */
batch[0] = '\0';
if (HasCapability(client, "batch"))
{
/* Start a new batch */
generate_batch_id(batch);
sendto_one(client, NULL, ":%s BATCH +%s chathistory %s", me.name, batch, object);
}
r = safe_alloc(sizeof(HistoryResult));
safe_strdup(r->object, object);
/* Decide on red line, under this the history is too old.
* Filter can be more strict than history object (but not the other way around):
@@ -336,13 +302,24 @@ int hbm_history_request(Client *client, char *object, HistoryFilter *filter)
* taken into account in hbm_history_add.
*/
if (l->t >= redline && (++cnt > lines_to_skip))
hbm_send_line(client, l, batch);
{
/* Add to result */
HistoryLogLine *n = duplicate_log_line(l);
if (!r->log)
{
/* First item */
r->log = r->log_tail = n;
} else
{
/* Quick append to tail */
r->log_tail->next = n;
n->prev = r->log_tail;
r->log_tail = n; /* we are the new tail */
}
}
}
/* End of batch */
if (*batch)
sendto_one(client, NULL, ":%s BATCH -%s", me.name, batch);
return 1;
return r;
}
/** Clean up expired entries */
+3 -3
View File
@@ -22,7 +22,7 @@ ModuleHeader MOD_HEADER
/* Forward declarations */
int hbn_history_set_limit(char *object, int max_lines, long max_time);
int hbn_history_add(char *object, MessageTag *mtags, char *line);
int hbn_history_request(Client *client, char *object, HistoryFilter *filter);
HistoryResult *hbn_history_request(char *object, HistoryFilter *filter);
int hbn_history_destroy(char *object);
MOD_INIT()
@@ -59,9 +59,9 @@ int hbn_history_add(char *object, MessageTag *mtags, char *line)
return 1;
}
int hbn_history_request(Client *client, char *object, HistoryFilter *filter)
HistoryResult *hbn_history_request(char *object, HistoryFilter *filter)
{
return 0;
return NULL;
}
int hbn_history_set_limit(char *object, int max_lines, long max_time)