- msgid table
msgid tableはmsgidごとに実際のパケットを 以下の形式で保存する。
#{msgid => #{packet => packet, ref_count => integer}}
ここで、ref countは参照カウンタであり、各clientにPUBLISHするたびに1増やし、QoS1ではPUBACK、QoS2ではPUBCOMPで完了するたびに1を減らす。これが0になった場合には削除しても良い。(残しておいても良い。)
- clientid table
以下のようにclientidごとにmsgidのqueueを持つ。
#{clientid => #{msg_queue => [msgid, msgid...]}
clientはこのqueueに溜まっているmsgidのmsgについて送信したりする。
msgidは単なるidのstringではなく、mosquittoのclient_msgのように、msgのstateを管理する情報をも持たせたほうがいい。
- retain
ここで問題となるのがretain。retainはQoS0でもあるので、msgidがない場合もある。 そのため、retainはmsgid tableとは別個に、topicの部分にpacketを持っておくといいのでは。
- mosquittoの場合
src/mosquitto_broker.hでこう定義されている。
struct mosquitto_msg_store{
struct mosquitto_msg_store *next;
dbid_t db_id;
int ref_count;
char *source_id;
char **dest_ids;
int dest_id_count;
uint16_t source_mid;
struct mosquitto_message msg;
};
struct mosquitto_client_msg{
struct mosquitto_client_msg *next;
struct mosquitto_msg_store *store;
uint16_t mid;
int qos;
bool retain;
time_t timestamp;
enum mosquitto_msg_direction direction;
enum mosquitto_msg_state state;
bool dup;
};
mosquitto_msg_storeでは、dest_idのリストとref_countを持ち、db_idというdb格納用のidを持っている。
また、mosquitto_client_msgはmosquitto_msg_storeへのポインタを持っている。
mosquitto_client_msgはclient単位で持っているmsgの情報。 つまり、各msgの状態はclientごとに違うので、それを管理する部分 (mosquitto_msg_state) が必要なので、それを持っているということ