+int Mmsg(POOLMEM *&pool_buf, const char *fmt, ...)
+{
+ va_list arg_ptr;
+ int len, maxlen;
+
+ for (;;) {
+ maxlen = sizeof_pool_memory(pool_buf) - 1;
+ va_start(arg_ptr, fmt);
+ len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
+ va_end(arg_ptr);
+ if (len < 0 || len >= (maxlen-5)) {
+ pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
+ continue;
+ }
+ break;
+ }
+ return len;
+}
+
+int Mmsg(POOL_MEM &pool_buf, const char *fmt, ...)
+{
+ va_list arg_ptr;
+ int len, maxlen;
+
+ for (;;) {
+ maxlen = pool_buf.max_size() - 1;
+ va_start(arg_ptr, fmt);
+ len = bvsnprintf(pool_buf.c_str(), maxlen, fmt, arg_ptr);
+ va_end(arg_ptr);
+ if (len < 0 || len >= (maxlen-5)) {
+ pool_buf.realloc_pm(maxlen + maxlen/2);
+ continue;
+ }
+ break;
+ }
+ return len;
+}
+
+
+static pthread_mutex_t msg_queue_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*
+ * We queue messages rather than print them directly. This
+ * is generally used in low level routines (msg handler, bnet)
+ * to prevent recursion (i.e. if you are in the middle of
+ * sending a message, it is a bit messy to recursively call
+ * yourself when the bnet packet is not reentrant).
+ */
+void Qmsg(JCR *jcr, int type, time_t mtime, const char *fmt,...)
+{
+ va_list arg_ptr;
+ int len, maxlen;
+ POOLMEM *pool_buf;
+ MQUEUE_ITEM *item;
+
+ pool_buf = get_pool_memory(PM_EMSG);
+
+ for (;;) {
+ maxlen = sizeof_pool_memory(pool_buf) - 1;
+ va_start(arg_ptr, fmt);
+ len = bvsnprintf(pool_buf, maxlen, fmt, arg_ptr);
+ va_end(arg_ptr);
+ if (len < 0 || len >= (maxlen-5)) {
+ pool_buf = realloc_pool_memory(pool_buf, maxlen + maxlen/2);
+ continue;
+ }
+ break;
+ }
+ item = (MQUEUE_ITEM *)malloc(sizeof(MQUEUE_ITEM) + strlen(pool_buf) + 1);
+ item->type = type;
+ item->mtime = time(NULL);
+ strcpy(item->msg, pool_buf);
+ if (!jcr) {
+ jcr = get_jcr_from_tsd();
+ }
+ /* If no jcr or dequeuing send to daemon to avoid recursion */
+ if ((jcr && !jcr->msg_queue) || !jcr || jcr->dequeuing) {
+ /* jcr==NULL => daemon message, safe to send now */
+ Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
+ free(item);
+ } else {
+ /* Queue message for later sending */
+ P(msg_queue_mutex);
+ jcr->msg_queue->append(item);
+ V(msg_queue_mutex);
+ }
+ free_memory(pool_buf);
+}
+
+/*
+ * Dequeue messages
+ */
+void dequeue_messages(JCR *jcr)
+{
+ MQUEUE_ITEM *item;
+ P(msg_queue_mutex);
+ if (!jcr->msg_queue) {
+ goto bail_out;
+ }
+ jcr->dequeuing = true;
+ foreach_dlist(item, jcr->msg_queue) {
+ Jmsg(jcr, item->type, item->mtime, "%s", item->msg);
+ }
+ jcr->msg_queue->destroy();
+ jcr->dequeuing = false;
+
+bail_out:
+ V(msg_queue_mutex);
+}
+