Many messages generated by an IRC server are sent to multiple recipients. Previous versions of ircd used DBuf to store these messages until they could actually be sent. The problem with using a DBuf for this, though, is that there are multiple copies of the same message hanging around. Another problem is that there is at least one strcpy() or equivalent call for each destination the message is sent to. A simple solution to this problem is to use messages queues. This file documents the MsgQ interface for ircd. The MsgQ interface is loosely based on the API for DBuf. Although the structures are vastly different, most calls, including several of the macros, are similar to certain pieces of the DBuf API. This made retrofitting ircd with MsgQ support much simpler. struct MsgCounts { int alloc; int used; }; The MsgCounts structure may be used for determining how much memory is in use by the MsgQ system. The _alloc_ element is a count of the total number of structures (of whatever type) that have been allocated; the _used_ element is a count of how many are actually in use. MsgQ never releases any of its allocated memory; instead, it places unused structures onto a free list. struct MsgBuf; The MsgBuf structure contains the actual message, along with a reference count and the message's length. None of its fields are directly accessible by the application. struct MsgQ; The MsgQ structure is a structure allocated by the application that is used by the MsgQ system to describe an entire message queue, including both normal and priority queues. None of its fields are directly accessible by the application. struct MsgCounts msgBufCounts; /* resource count for struct MsgBuf */ This global variable counts the number of MsgBuf structures that have been allocated. This may be used to determine how much memory is in use by the MsgQ system. struct MsgCounts msgCounts; /* resource count for struct Msg */ This global variable counts the number of Msg structures that have been allocated. The Msg structure describes the link between a queue and a message. It is not accessible to the application, and so not further documented here. unsigned int MsgQLength(struct MsgQ* mq); This macro returns the number of bytes in a particular user's message queue. unsigned int MsgQCount(struct MsgQ* mq); This macro returns the number of messages in a particular user's message queue. void MsgQClear(struct MsgQ* mq); This macro simply clears the content of a particular message queue. NOTE: This macro evaluates its argument twice. void msgq_init(struct MsgQ *mq); This function initializes a caller-allocated message queue to be empty. Calling this function on a message queue with messages in it WILL RESULT IN A MEMORY LEAK. void msgq_delete(struct MsgQ *mq, unsigned int length); This function removes the given number of bytes from the message queue. If entire messages have been sent, they will be unlinked from the queue. The _length_ parameter does not need to correspond to a given message's length; the MsgQ system is able to deal with messages that have only partially been sent. int msgq_mapiov(const struct MsgQ *mq, struct iovec *iov, int count, unsigned int *len); The msgq_mapiov() function takes a struct MsgQ (specified by the _mq_ parameter) and a caller allocated struct iovec array (specified by the _iov_ parameter) and maps the contents of the message into the struct iovec array. The _count_ parameter must indicate the total number of elements available for msgq_mapiov() to use. The _len_ parameter must be a pointer to an unsigned int, and upon return from the function will contain the total number of bytes that have been mapped into the struct iovec array. This function returns the number of struct iovec elements that have been filled. For more information about the purpose of struct iovec, see your system's man page for the writev() function. struct MsgBuf *msgq_make(struct Client *dest, const char *format, ...); This function allocates a struct MsgBuf and calls ircd_vsnprintf() with the _dest_ and _format_ parameters to fill it in. Most callers should use the send_buffer() function (declared in send.h) to attach the struct MsgBuf to a client's message queue. struct MsgBuf *msgq_vmake(struct Client *dest, const char *format, va_list vl); This function is identical to msgq_make() except that it takes a va_list (given by the _vl_ parameter) and calls ircd_vsnprintf() to format the message. void msgq_append(struct Client *dest, struct MsgBuf *mb, const char *format, ...); Occasionally a caller is not able to completely compute a message before calling msgq_make(). When this happens, the msgq_append() function may be called to append more text onto the struct MsgBuf specified by the _mb_ parameter. As with msgq_make(), the _dest_ and _format_ parameters are passed to ircd_vsnprintf(), along with the additional arguments. void msgq_clean(struct MsgBuf *mb); As mentioned above, struct MsgBuf includes a reference count. When that reference count reaches zero, the structure is released. The reference count is set to 1 by msgq_make() and msgq_vmake(). Once a given message has been attached to all the queues it needs to be, the caller should call the msgq_clean() function to decrement this reference count. This function will place the struct MsgBuf back onto the free list if it did not get attached to any message queues. The msgq_delete() function calls msgq_clean() internally, so the application need not call msgq_clean() explicitly afterwards. void msgq_add(struct MsgQ *mq, struct MsgBuf *mb, int prio); This function is used to attach a given struct MsgBuf, as specified by the _mb_ parameter, to a given message queue. The _prio_ parameter, if non-zero, specifies that the message should be placed on the priority queue. This function is called by send_buffer(), defined in send.h; most applications should call that function, rather than this one. void msgq_count_memory(size_t *msg_alloc, size_t *msg_used, size_t *msgbuf_alloc, size_t *msgbuf_used); This function simply takes the counts kept in msgBufCounts and msgCounts and multiplies them by the appropriate structure sizes, storing the resulting sizes into its parameters. unsigned int msgq_bufleft(struct MsgBuf *mb); This function is for use in conjunction with msgq_append(). It returns the total number of bytes of free storage in the given _mb_. Kev [2001-6-15 Kev] Initial documentation for the MsgQ functions.