More memory efficient message store than with hashes.
Also frees messages from the message store after removing...
This commit is contained in:
parent
d30d711c3b
commit
1e64bb171a
@ -121,10 +121,66 @@ static void subhier_clean(struct _mosquitto_subhier *subhier)
|
|||||||
int mqtt3_db_close(struct mosquitto_db *db)
|
int mqtt3_db_close(struct mosquitto_db *db)
|
||||||
{
|
{
|
||||||
subhier_clean(db->subs.children);
|
subhier_clean(db->subs.children);
|
||||||
|
mosquitto__db_msg_store_clean(db);
|
||||||
|
|
||||||
return MOSQ_ERR_SUCCESS;
|
return MOSQ_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mosquitto__db_msg_store_add(struct mosquitto_db *db, struct mosquitto_msg_store *store)
|
||||||
|
{
|
||||||
|
store->next = db->msg_store;
|
||||||
|
store->prev = NULL;
|
||||||
|
if(db->msg_store){
|
||||||
|
db->msg_store->prev = store;
|
||||||
|
}
|
||||||
|
db->msg_store = store;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mosquitto__db_msg_store_remove(struct mosquitto_db *db, struct mosquitto_msg_store *store)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if(store->prev){
|
||||||
|
store->prev->next = store->next;
|
||||||
|
if(store->next){
|
||||||
|
store->next->prev = store->prev;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
db->msg_store = store->next;
|
||||||
|
if(store->next){
|
||||||
|
store->next->prev = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
db->msg_store_count--;
|
||||||
|
|
||||||
|
if(store->source_id) _mosquitto_free(store->source_id);
|
||||||
|
if(store->dest_ids){
|
||||||
|
for(i=0; i<store->dest_id_count; i++){
|
||||||
|
if(store->dest_ids[i]) _mosquitto_free(store->dest_ids[i]);
|
||||||
|
}
|
||||||
|
_mosquitto_free(store->dest_ids);
|
||||||
|
}
|
||||||
|
if(store->topic) _mosquitto_free(store->topic);
|
||||||
|
if(store->payload) _mosquitto_free(store->payload);
|
||||||
|
_mosquitto_free(store);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void mosquitto__db_msg_store_clean(struct mosquitto_db *db)
|
||||||
|
{
|
||||||
|
struct mosquitto_msg_store *store, *next;;
|
||||||
|
|
||||||
|
store = db->msg_store;
|
||||||
|
while(store){
|
||||||
|
next = store->next;
|
||||||
|
mosquitto__db_msg_store_remove(db, store);
|
||||||
|
store = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _message_remove(struct mosquitto_db *db, struct mosquitto *context, struct mosquitto_client_msg **msg, struct mosquitto_client_msg *last)
|
static void _message_remove(struct mosquitto_db *db, struct mosquitto *context, struct mosquitto_client_msg **msg, struct mosquitto_client_msg *last)
|
||||||
{
|
{
|
||||||
if(!context || !msg || !(*msg)){
|
if(!context || !msg || !(*msg)){
|
||||||
@ -133,8 +189,7 @@ static void _message_remove(struct mosquitto_db *db, struct mosquitto *context,
|
|||||||
|
|
||||||
(*msg)->store->ref_count--;
|
(*msg)->store->ref_count--;
|
||||||
if((*msg)->store->ref_count == 0){
|
if((*msg)->store->ref_count == 0){
|
||||||
HASH_DELETE(hh, db->msg_store, (*msg)->store);
|
mosquitto__db_msg_store_remove(db, (*msg)->store);
|
||||||
db->msg_store_count--;
|
|
||||||
}
|
}
|
||||||
if(last){
|
if(last){
|
||||||
last->next = (*msg)->next;
|
last->next = (*msg)->next;
|
||||||
@ -399,8 +454,7 @@ int mqtt3_db_messages_delete(struct mosquitto_db *db, struct mosquitto *context)
|
|||||||
while(tail){
|
while(tail){
|
||||||
tail->store->ref_count--;
|
tail->store->ref_count--;
|
||||||
if(tail->store->ref_count == 0){
|
if(tail->store->ref_count == 0){
|
||||||
HASH_DELETE(hh, db->msg_store, tail->store);
|
mosquitto__db_msg_store_remove(db, tail->store);
|
||||||
db->msg_store_count--;
|
|
||||||
}
|
}
|
||||||
next = tail->next;
|
next = tail->next;
|
||||||
_mosquitto_free(tail);
|
_mosquitto_free(tail);
|
||||||
@ -502,7 +556,7 @@ int mqtt3_db_message_store(struct mosquitto_db *db, const char *source, uint16_t
|
|||||||
temp->db_id = store_id;
|
temp->db_id = store_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
HASH_ADD(hh, db->msg_store, db_id, sizeof(dbid_t), temp);
|
mosquitto__db_msg_store_add(db, temp);
|
||||||
|
|
||||||
return MOSQ_ERR_SUCCESS;
|
return MOSQ_ERR_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -141,9 +141,16 @@ struct _mosquitto_subhier {
|
|||||||
struct mosquitto_msg_store *retained;
|
struct mosquitto_msg_store *retained;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mosquitto_msg_store{
|
struct mosquitto_msg_store_load{
|
||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
dbid_t db_id;
|
dbid_t db_id;
|
||||||
|
struct mosquitto_msg_store *store;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mosquitto_msg_store{
|
||||||
|
struct mosquitto_msg_store *next;
|
||||||
|
struct mosquitto_msg_store *prev;
|
||||||
|
dbid_t db_id;
|
||||||
char *source_id;
|
char *source_id;
|
||||||
char **dest_ids;
|
char **dest_ids;
|
||||||
int dest_id_count;
|
int dest_id_count;
|
||||||
@ -220,6 +227,7 @@ struct mosquitto_db{
|
|||||||
struct mosquitto *contexts_bridge;
|
struct mosquitto *contexts_bridge;
|
||||||
struct _clientid_index_hash *clientid_index_hash;
|
struct _clientid_index_hash *clientid_index_hash;
|
||||||
struct mosquitto_msg_store *msg_store;
|
struct mosquitto_msg_store *msg_store;
|
||||||
|
struct mosquitto_msg_store_load *msg_store_load;
|
||||||
int msg_store_count;
|
int msg_store_count;
|
||||||
struct mqtt3_config *config;
|
struct mqtt3_config *config;
|
||||||
int persistence_changes;
|
int persistence_changes;
|
||||||
@ -380,6 +388,9 @@ int mqtt3_db_messages_easy_queue(struct mosquitto_db *db, struct mosquitto *cont
|
|||||||
int mqtt3_db_messages_queue(struct mosquitto_db *db, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store *stored);
|
int mqtt3_db_messages_queue(struct mosquitto_db *db, const char *source_id, const char *topic, int qos, int retain, struct mosquitto_msg_store *stored);
|
||||||
int mqtt3_db_message_store(struct mosquitto_db *db, const char *source, uint16_t source_mid, const char *topic, int qos, uint32_t payloadlen, const void *payload, int retain, struct mosquitto_msg_store **stored, dbid_t store_id);
|
int mqtt3_db_message_store(struct mosquitto_db *db, const char *source, uint16_t source_mid, const char *topic, int qos, uint32_t payloadlen, const void *payload, int retain, struct mosquitto_msg_store **stored, dbid_t store_id);
|
||||||
int mqtt3_db_message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto_msg_store **stored);
|
int mqtt3_db_message_store_find(struct mosquitto *context, uint16_t mid, struct mosquitto_msg_store **stored);
|
||||||
|
void mosquitto__db_msg_store_add(struct mosquitto_db *db, struct mosquitto_msg_store *store);
|
||||||
|
void mosquitto__db_msg_store_remove(struct mosquitto_db *db, struct mosquitto_msg_store *store);
|
||||||
|
void mosquitto__db_msg_store_clean(struct mosquitto_db *db);
|
||||||
/* Check all messages waiting on a client reply and resend if timeout has been exceeded. */
|
/* Check all messages waiting on a client reply and resend if timeout has been exceeded. */
|
||||||
int mqtt3_db_message_timeout_check(struct mosquitto_db *db, unsigned int timeout);
|
int mqtt3_db_message_timeout_check(struct mosquitto_db *db, unsigned int timeout);
|
||||||
int mqtt3_db_message_reconnect_reset(struct mosquitto_db *db, struct mosquitto *context);
|
int mqtt3_db_message_reconnect_reset(struct mosquitto_db *db, struct mosquitto *context);
|
||||||
|
@ -131,13 +131,14 @@ static int mqtt3_db_message_store_write(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
uint32_t i32temp;
|
uint32_t i32temp;
|
||||||
uint16_t i16temp, slen;
|
uint16_t i16temp, slen;
|
||||||
uint8_t i8temp;
|
uint8_t i8temp;
|
||||||
struct mosquitto_msg_store *stored, *stored_tmp;
|
struct mosquitto_msg_store *stored;
|
||||||
bool force_no_retain;
|
bool force_no_retain;
|
||||||
|
|
||||||
assert(db);
|
assert(db);
|
||||||
assert(db_fptr);
|
assert(db_fptr);
|
||||||
|
|
||||||
HASH_ITER(hh, db->msg_store, stored, stored_tmp){
|
stored = db->msg_store;
|
||||||
|
while(stored){
|
||||||
if(!strncmp(stored->topic, "$SYS", 4)){
|
if(!strncmp(stored->topic, "$SYS", 4)){
|
||||||
/* Don't save $SYS messages as retained otherwise they can give
|
/* Don't save $SYS messages as retained otherwise they can give
|
||||||
* misleading information when reloaded. They should still be saved
|
* misleading information when reloaded. They should still be saved
|
||||||
@ -192,6 +193,7 @@ static int mqtt3_db_message_store_write(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
if(stored->payloadlen){
|
if(stored->payloadlen){
|
||||||
write_e(db_fptr, stored->payload, (unsigned int)stored->payloadlen);
|
write_e(db_fptr, stored->payload, (unsigned int)stored->payloadlen);
|
||||||
}
|
}
|
||||||
|
stored = stored->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MOSQ_ERR_SUCCESS;
|
return MOSQ_ERR_SUCCESS;
|
||||||
@ -403,7 +405,7 @@ error:
|
|||||||
static int _db_client_msg_restore(struct mosquitto_db *db, const char *client_id, uint16_t mid, uint8_t qos, uint8_t retain, uint8_t direction, uint8_t state, uint8_t dup, uint64_t store_id)
|
static int _db_client_msg_restore(struct mosquitto_db *db, const char *client_id, uint16_t mid, uint8_t qos, uint8_t retain, uint8_t direction, uint8_t state, uint8_t dup, uint64_t store_id)
|
||||||
{
|
{
|
||||||
struct mosquitto_client_msg *cmsg;
|
struct mosquitto_client_msg *cmsg;
|
||||||
struct mosquitto_msg_store *store;
|
struct mosquitto_msg_store_load *load;
|
||||||
struct mosquitto *context;
|
struct mosquitto *context;
|
||||||
|
|
||||||
cmsg = _mosquitto_malloc(sizeof(struct mosquitto_client_msg));
|
cmsg = _mosquitto_malloc(sizeof(struct mosquitto_client_msg));
|
||||||
@ -422,13 +424,13 @@ static int _db_client_msg_restore(struct mosquitto_db *db, const char *client_id
|
|||||||
cmsg->state = state;
|
cmsg->state = state;
|
||||||
cmsg->dup = dup;
|
cmsg->dup = dup;
|
||||||
|
|
||||||
HASH_FIND(hh, db->msg_store, &store_id, sizeof(dbid_t), store);
|
HASH_FIND(hh, db->msg_store_load, &store_id, sizeof(dbid_t), load);
|
||||||
if(!store){
|
if(!load){
|
||||||
_mosquitto_free(cmsg);
|
_mosquitto_free(cmsg);
|
||||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error restoring persistent database, message store corrupt.");
|
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error restoring persistent database, message store corrupt.");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
cmsg->store = store;
|
cmsg->store = load->store;
|
||||||
|
|
||||||
context = _db_find_or_add_context(db, client_id, 0);
|
context = _db_find_or_add_context(db, client_id, 0);
|
||||||
if(!context){
|
if(!context){
|
||||||
@ -555,8 +557,16 @@ static int _db_msg_store_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
char *topic = NULL;
|
char *topic = NULL;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct mosquitto_msg_store *stored = NULL;
|
struct mosquitto_msg_store *stored = NULL;
|
||||||
|
struct mosquitto_msg_store_load *load;
|
||||||
char err[256];
|
char err[256];
|
||||||
|
|
||||||
|
load = _mosquitto_malloc(sizeof(struct mosquitto_msg_store_load));
|
||||||
|
if(!load){
|
||||||
|
fclose(db_fptr);
|
||||||
|
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||||
|
return MOSQ_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
read_e(db_fptr, &i64temp, sizeof(dbid_t));
|
read_e(db_fptr, &i64temp, sizeof(dbid_t));
|
||||||
store_id = i64temp;
|
store_id = i64temp;
|
||||||
|
|
||||||
@ -565,6 +575,7 @@ static int _db_msg_store_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
if(slen){
|
if(slen){
|
||||||
source_id = _mosquitto_malloc(slen+1);
|
source_id = _mosquitto_malloc(slen+1);
|
||||||
if(!source_id){
|
if(!source_id){
|
||||||
|
_mosquitto_free(load);
|
||||||
fclose(db_fptr);
|
fclose(db_fptr);
|
||||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||||
return MOSQ_ERR_NOMEM;
|
return MOSQ_ERR_NOMEM;
|
||||||
@ -583,6 +594,7 @@ static int _db_msg_store_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
if(slen){
|
if(slen){
|
||||||
topic = _mosquitto_malloc(slen+1);
|
topic = _mosquitto_malloc(slen+1);
|
||||||
if(!topic){
|
if(!topic){
|
||||||
|
_mosquitto_free(load);
|
||||||
fclose(db_fptr);
|
fclose(db_fptr);
|
||||||
if(source_id) _mosquitto_free(source_id);
|
if(source_id) _mosquitto_free(source_id);
|
||||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory.");
|
||||||
@ -591,6 +603,7 @@ static int _db_msg_store_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
read_e(db_fptr, topic, slen);
|
read_e(db_fptr, topic, slen);
|
||||||
topic[slen] = '\0';
|
topic[slen] = '\0';
|
||||||
}else{
|
}else{
|
||||||
|
_mosquitto_free(load);
|
||||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid msg_store chunk when restoring persistent database.");
|
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Invalid msg_store chunk when restoring persistent database.");
|
||||||
fclose(db_fptr);
|
fclose(db_fptr);
|
||||||
if(source_id) _mosquitto_free(source_id);
|
if(source_id) _mosquitto_free(source_id);
|
||||||
@ -605,6 +618,7 @@ static int _db_msg_store_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
if(payloadlen){
|
if(payloadlen){
|
||||||
payload = _mosquitto_malloc(payloadlen);
|
payload = _mosquitto_malloc(payloadlen);
|
||||||
if(!payload){
|
if(!payload){
|
||||||
|
_mosquitto_free(load);
|
||||||
fclose(db_fptr);
|
fclose(db_fptr);
|
||||||
if(source_id) _mosquitto_free(source_id);
|
if(source_id) _mosquitto_free(source_id);
|
||||||
_mosquitto_free(topic);
|
_mosquitto_free(topic);
|
||||||
@ -615,6 +629,12 @@ static int _db_msg_store_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = mqtt3_db_message_store(db, source_id, source_mid, topic, qos, payloadlen, payload, retain, &stored, store_id);
|
rc = mqtt3_db_message_store(db, source_id, source_mid, topic, qos, payloadlen, payload, retain, &stored, store_id);
|
||||||
|
|
||||||
|
load->db_id = stored->db_id;
|
||||||
|
load->store = stored;
|
||||||
|
|
||||||
|
HASH_ADD(hh, db->msg_store_load, db_id, sizeof(dbid_t), load);
|
||||||
|
|
||||||
if(source_id) _mosquitto_free(source_id);
|
if(source_id) _mosquitto_free(source_id);
|
||||||
_mosquitto_free(topic);
|
_mosquitto_free(topic);
|
||||||
_mosquitto_free(payload);
|
_mosquitto_free(payload);
|
||||||
@ -633,7 +653,7 @@ error:
|
|||||||
static int _db_retain_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
static int _db_retain_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
||||||
{
|
{
|
||||||
dbid_t i64temp, store_id;
|
dbid_t i64temp, store_id;
|
||||||
struct mosquitto_msg_store *store;
|
struct mosquitto_msg_store_load *load;
|
||||||
char err[256];
|
char err[256];
|
||||||
|
|
||||||
if(fread(&i64temp, sizeof(dbid_t), 1, db_fptr) != 1){
|
if(fread(&i64temp, sizeof(dbid_t), 1, db_fptr) != 1){
|
||||||
@ -643,9 +663,9 @@ static int _db_retain_chunk_restore(struct mosquitto_db *db, FILE *db_fptr)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
store_id = i64temp;
|
store_id = i64temp;
|
||||||
HASH_FIND(hh, db->msg_store, &store_id, sizeof(dbid_t), store);
|
HASH_FIND(hh, db->msg_store_load, &store_id, sizeof(dbid_t), load);
|
||||||
if(store){
|
if(load){
|
||||||
mqtt3_db_messages_queue(db, NULL, store->topic, store->qos, store->retain, store);
|
mqtt3_db_messages_queue(db, NULL, load->store->topic, load->store->qos, load->store->retain, load->store);
|
||||||
}else{
|
}else{
|
||||||
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Corrupt database whilst restoring a retained message.");
|
_mosquitto_log_printf(NULL, MOSQ_LOG_ERR, "Error: Corrupt database whilst restoring a retained message.");
|
||||||
return MOSQ_ERR_INVAL;
|
return MOSQ_ERR_INVAL;
|
||||||
@ -712,11 +732,14 @@ int mqtt3_db_restore(struct mosquitto_db *db)
|
|||||||
uint8_t i8temp;
|
uint8_t i8temp;
|
||||||
ssize_t rlen;
|
ssize_t rlen;
|
||||||
char err[256];
|
char err[256];
|
||||||
|
struct mosquitto_msg_store_load *load, *load_tmp;
|
||||||
|
|
||||||
assert(db);
|
assert(db);
|
||||||
assert(db->config);
|
assert(db->config);
|
||||||
assert(db->config->persistence_filepath);
|
assert(db->config->persistence_filepath);
|
||||||
|
|
||||||
|
db->msg_store_load = NULL;
|
||||||
|
|
||||||
fptr = _mosquitto_fopen(db->config->persistence_filepath, "rb");
|
fptr = _mosquitto_fopen(db->config->persistence_filepath, "rb");
|
||||||
if(fptr == NULL) return MOSQ_ERR_SUCCESS;
|
if(fptr == NULL) return MOSQ_ERR_SUCCESS;
|
||||||
read_e(fptr, &header, 15);
|
read_e(fptr, &header, 15);
|
||||||
@ -790,6 +813,10 @@ int mqtt3_db_restore(struct mosquitto_db *db)
|
|||||||
|
|
||||||
fclose(fptr);
|
fclose(fptr);
|
||||||
|
|
||||||
|
HASH_ITER(hh, db->msg_store_load, load, load_tmp){
|
||||||
|
HASH_DELETE(hh, db->msg_store_load, load);
|
||||||
|
_mosquitto_free(load);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
error:
|
error:
|
||||||
strerror_r(errno, err, 256);
|
strerror_r(errno, err, 256);
|
||||||
|
@ -82,8 +82,7 @@ static int _subs_process(struct mosquitto_db *db, struct _mosquitto_subhier *hie
|
|||||||
if(hier->retained){
|
if(hier->retained){
|
||||||
hier->retained->ref_count--;
|
hier->retained->ref_count--;
|
||||||
if(hier->retained->ref_count == 0){
|
if(hier->retained->ref_count == 0){
|
||||||
HASH_DELETE(hh, db->msg_store, hier->retained);
|
mosquitto__db_msg_store_remove(db, hier->retained);
|
||||||
db->msg_store_count--;
|
|
||||||
}
|
}
|
||||||
#ifdef WITH_SYS_TREE
|
#ifdef WITH_SYS_TREE
|
||||||
db->retained_count--;
|
db->retained_count--;
|
||||||
|
Loading…
Reference in New Issue
Block a user