static struct hashable_client *table;
/** Read/write lock, which protects @table and its inhabitants. */
static pthread_rwlock_t lock;
+/** Serial number from which deltas must be stored */
+uint32_t min_serial;
int
clients_db_init(void)
error = pthread_rwlock_init(&lock, NULL);
if (error)
return pr_errno(error, "pthread_rwlock_init() errored");
-
+ min_serial = 0;
return 0;
}
return error;
}
+void
+clients_update_serial(int fd, uint32_t serial)
+{
+ struct hashable_client *cur_client;
+
+ rwlock_write_lock(&lock);
+ HASH_FIND_INT(table, &fd, cur_client);
+ if (cur_client == NULL)
+ goto unlock;
+
+ cur_client->meat.serial_number = serial;
+
+unlock:
+ rwlock_unlock(&lock);
+}
+
+uint32_t
+clients_get_min_serial(void)
+{
+ struct hashable_client *current, *ptr;
+ uint32_t result;
+
+ rwlock_write_lock(&lock);
+ if (HASH_COUNT(table) == 0)
+ goto unlock;
+
+ HASH_ITER(hh, table, current, ptr) {
+ if (current == table) {
+ min_serial = current->meat.serial_number;
+ continue;
+ }
+ if (current->meat.serial_number < min_serial)
+ min_serial = current->meat.serial_number;
+ }
+
+unlock:
+ result = min_serial;
+ rwlock_unlock(&lock);
+
+ return result;
+}
+
void
clients_forget(int fd)
{
};
in_port_t sin_port;
uint8_t rtr_version;
+ uint32_t serial_number;
};
int clients_db_init(void);
int clients_add(int, struct sockaddr_storage *, uint8_t);
+void clients_update_serial(int, uint32_t);
void clients_forget(int);
typedef int (*clients_foreach_cb)(struct client const *, void *);
int clients_foreach(clients_foreach_cb, void *);
+uint32_t clients_get_min_serial(void);
void clients_db_destroy(void);
#include <pthread.h>
#include <stdbool.h>
#include <string.h>
+#include "clients.h"
#include "common.h"
#include "data_structure/array_list.h"
return error;
}
+/**
+ * Reallocate the array of @db starting at @start, the length and capacity are
+ * calculated according to the new start.
+ */
+static void
+resize_deltas_db(struct deltas_db *db, struct delta *start)
+{
+ struct delta *tmp;
+
+ db->len -= (start - db->array);
+ while (db->len < db->capacity / 2)
+ db->capacity /= 2;
+ tmp = malloc(sizeof(struct delta) * db->capacity);
+ if (tmp == NULL) {
+ pr_enomem();
+ return;
+ }
+ memcpy(tmp, start, db->len * sizeof(struct delta));
+ free(db->array);
+ db->array = tmp;
+}
+
+void
+vrps_purge(void)
+{
+ struct delta *d;
+ uint32_t min_serial;
+ int error;
+
+ min_serial = clients_get_min_serial();
+ error = rwlock_read_lock(&lock);
+ if (error) {
+ pr_err("Couldn't lock deltas DB to purge it");
+ return;
+ }
+
+ /** Assume is ordered by serial, so get the new initial pointer */
+ ARRAYLIST_FOREACH(&state.deltas, d)
+ if (d->serial >= min_serial)
+ break;
+
+ /** Is the first element or reached end, nothing to purge */
+ if (d == state.deltas.array ||
+ (d - state.deltas.array) == state.deltas.len)
+ goto rlock_succeed;
+
+ resize_deltas_db(&state.deltas, d);
+
+rlock_succeed:
+ rwlock_unlock(&lock);
+}
+
int
get_last_serial_number(uint32_t *result)
{
int vrps_foreach_base_roa(vrp_foreach_cb, void *);
int vrps_foreach_delta_roa(uint32_t, uint32_t, vrp_foreach_cb, void *);
+void vrps_purge(void);
int get_last_serial_number(uint32_t *);
uint16_t get_current_session_id(uint8_t);
#include <unistd.h>
#include <sys/queue.h>
+#include "clients.h"
#include "config.h"
#include "log.h"
#include "rtr/pdu_serializer.h"
struct end_of_data_pdu pdu;
unsigned char data[BUFFER_SIZE];
size_t len;
+ int error;
set_header_values(&pdu.header, common->version, PDU_TYPE_END_OF_DATA,
*common->session_id);
len = serialize_end_of_data_pdu(&pdu, data);
- return send_response(common->fd, data, len);
+ error = send_response(common->fd, data, len);
+ if (error)
+ return error;
+
+ clients_update_serial(common->fd, pdu.serial_number);
+ return error;
}
int
}
old_roas = validation_handler.arg;
+
+ /** Remove unnecessary deltas */
+ vrps_purge();
+
error = notify_clients();
if (error)
pr_debug("Could not notify clients of the new VRPs. (Error code %d.) Sleeping...",