Prior to 1.4.x, see blogs and use trees:

Mosquitos Source Code Analysis (III) – Subscription Tree 1

Mosquitos Source Code Analysis (IV) – Subscription Tree 2

 

Mosquito has changed the data structure for theme subscriptions starting with version 1.5.x. Use hash tables for storage. Each layer has a hash table to store it.

/src/database.c

There are two themes initialized, one is the business theme “”, which is empty; The other is the system theme “$SYS”

The sub__add_hier_entry function is important for creating new hash key-values.

int db__open(struct mosquitto__config *config, struct mosquitto_db *db) { struct mosquitto__subhier *subhier; if(! config || ! db) return MOSQ_ERR_INVAL; db->last_db_id = 0; db->contexts_by_id = NULL; db->contexts_by_sock = NULL; db->contexts_for_free = NULL; #ifdef WITH_BRIDGE db->bridges = NULL; db->bridge_count = 0; #endif // Initialize the hashtable db->clientid_index_hash = NULL; db->subs = NULL; subhier = sub__add_hier_entry(NULL, &db->subs, "", strlen("")); // Business child root if(! subhier) return MOSQ_ERR_NOMEM; subhier = sub__add_hier_entry(NULL, &db->subs, "$SYS", strlen("$SYS")); // System subroot node if(! subhier) return MOSQ_ERR_NOMEM;Copy the code

Subs.c will create memory

child = mosquitto__malloc(sizeof(struct mosquitto__subhier));

struct mosquitto__subhier *sub__add_hier_entry(struct mosquitto__subhier *parent, struct mosquitto__subhier **sibling, const char *topic, size_t len) { struct mosquitto__subhier *child; assert(sibling); child = mosquitto__malloc(sizeof(struct mosquitto__subhier)); if(! child){ log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return NULL; } child->parent = parent; child->topic_len = len; if(UHPA_ALLOC_TOPIC(child) == 0){ child->topic_len = 0; mosquitto__free(child); log__printf(NULL, MOSQ_LOG_ERR, "Error: Out of memory."); return NULL; }else{ strncpy(UHPA_ACCESS_TOPIC(child), topic, child->topic_len+1); } child->subs = NULL; child->children = NULL; child->retained = NULL; if(child->topic_len+1 > sizeof(child->topic.array)){ if(child->topic.ptr){ HASH_ADD_KEYPTR(hh, *sibling, child->topic.ptr, child->topic_len, child); }else{ mosquitto__free(child); return NULL; } }else{ HASH_ADD(hh, *sibling, topic.array, child->topic_len, child); } return child; }Copy the code

Screenshot 1

 

Each layer has a hash table to store it.

For example, the subject of a system message is represented as:

$SYS/broker/version

$SYS/broker/uptime

$SYS/broker/clients/total

$SYS/broker/clients/inactive

$SYS/broker/clients/disconnected

I sketched the hash table structure as shown in Screenshot 2

Screenshot 2

The core is the static int sub__add_recurse() function of the subs.c source file, which adds hash elements.

For a subscription to a business topic (non-system topic), the process is as follows. Please see the bottom part of Screenshot 3 for the detailed function jump process:

Screenshot 3

The ultimate goal of a subscription is to execute the statement HASH_ADD(hh, *sibling, top. array, child->topic_len, child); Add elements to the hash table!