Code

Add write_mongodb.patch to make the plugin compatible with Debian.
authorSebastian Harl <sh@tokkee.org>
Sat, 21 Oct 2017 15:04:37 +0000 (17:04 +0200)
committerSebastian Harl <sh@tokkee.org>
Sat, 21 Oct 2017 15:04:37 +0000 (17:04 +0200)
This updates the plugin to the most recent upstream version to bring it up to
date with Debian's libmongoc and fix some other issues.

debian/changelog
debian/patches/series
debian/patches/write_mongodb.patch [new file with mode: 0644]

index 2e32122f116d1b7c5c14553b3bbc9ef1273f344f..deae6c02f70fde9cd5147b55e43decedd2ba3cd2 100644 (file)
@@ -12,6 +12,9 @@ collectd (5.7.2-2) trusty; urgency=medium
     thanks to Adrian Bunk for reporting this (Closes: #878348).
   * Enable the write_mongodb plugin, libmongoc is now available. Thanks to
     Saikrishna Arcot for reporting this (Closes: #858315).
+    - Add write_mongodb.patch to update the plugin to the most recent upstream
+      version to bring it up to date with Debian's libmongoc and fix some
+      other issues.
   * Update to standards-version 4.1.1:
     - Build depend on debhelper (>= 9.20160709~) instead of dh-systemd.
     - Use priority "optional" instead of deprecated priority "extra".
index 5630e9983dccf70592418ac5340c488342fb23dc..bf0b745e8eb118893785fd6211d5265dc918e742 100644 (file)
@@ -5,3 +5,4 @@ nagios-debian-paths.patch
 libcollectdclient_error_buffer.patch
 local-msr-index-h.patch
 dpdk-pkg-config.patch
+write_mongodb.patch
diff --git a/debian/patches/write_mongodb.patch b/debian/patches/write_mongodb.patch
new file mode 100644 (file)
index 0000000..ff5a0cb
--- /dev/null
@@ -0,0 +1,630 @@
+Description: Update mongodb write code to use latest API and other fixes.
+ This makes the plugin compile with libmongoc in Debian and includes all fixes
+ to the write_mongodb plugin since 5.7.2 (plus related changes to other
+ files):
+ .
+ % git log --oneline collectd-5.7.2.. -- src/write_mongodb.c
+ 7f38ca96 Merge branch 'ssnprintf-cleanup'
+ bea5daae write_mongodb: fix a couple of build warnings
+ f81a5a84 write_mongodb: fix build warning
+ be126043 Treewide: replace ssnprintf with snprintf
+ a93cc681 write_mongodb: use ssnprintf_alloc to create dsn
+ 2c597543 write_mongodb: fix potential NULL dereference
+ 7f9c8e70 write_mongodb.c: clang-format
+ ca1ed50e Use bson_destroy instead of bson_free, and fix memleak issue.
+ 307c875e Remove parentheses around return arguments
+ 4d3d0c97 Tree-wide: remove last remnants of sizeof(char)
+ 1811b98c Update mongodb write code to use latest API (Fixes: #492) (#2236)
+ c7c89cc9 Treewide: remove vim modelines from C code files
+ 865f2eb3 More autoconf work
+ eec0cd9c Merge pull request #2041 from mfournier/contrib-docker
+diff a/configure.ac b/configure.ac
+--- a/configure.ac
++++ b/configure.ac
+@@ -3319,66 +3319,71 @@
+ # }}}
+ # --with-libmongoc {{{
+-AC_ARG_WITH(libmongoc, [AS_HELP_STRING([--with-libmongoc@<:@=PREFIX@:>@], [Path to libmongoc.])],
+-[
+- if test "x$withval" = "xyes"
+- then
+-       with_libmongoc="yes"
+- else if test "x$withval" = "xno"
+- then
+-       with_libmongoc="no"
+- else
+-       with_libmongoc="yes"
+-       LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS -I$withval/include"
+-       LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS -L$withval/lib"
+- fi; fi
+-],
+-[with_libmongoc="yes"])
+-
+-SAVE_CPPFLAGS="$CPPFLAGS"
+-SAVE_LDFLAGS="$LDFLAGS"
+-
+-CPPFLAGS="$CPPFLAGS $LIBMONGOC_CPPFLAGS"
+-LDFLAGS="$LDFLAGS $LIBMONGOC_LDFLAGS"
+-
+-if test "x$with_libmongoc" = "xyes"
+-then
+-      if test "x$LIBMONGOC_CPPFLAGS" != "x"
+-      then
+-              AC_MSG_NOTICE([libmongoc CPPFLAGS: $LIBMONGOC_CPPFLAGS])
+-      fi
+-      AC_CHECK_HEADERS(mongo.h,
+-      [with_libmongoc="yes"],
+-      [with_libmongoc="no ('mongo.h' not found)"],
+-[#if HAVE_STDINT_H
+-# define MONGO_HAVE_STDINT 1
+-#else
+-# define MONGO_USE_LONG_LONG_INT 1
+-#endif
+-])
++AC_ARG_WITH([libmongoc],
++  [AS_HELP_STRING([--with-libmongoc@<:@=PREFIX@:>@], [Path to libmongoc.])],
++  [
++    if test "x$withval" = "xyes"; then
++      with_libmongoc="yes"
++    else if test "x$withval" = "xno"; then
++      with_libmongoc="no"
++    else
++      with_libmongoc="no"
++    fi; fi
++  ],
++  [with_libmongoc="yes"]
++)
++
++if test "x$with_libmongoc" = "xyes"; then
++  PKG_CHECK_MODULES([LIBMONGOC], [libmongoc-1.0],
++    [with_libmongoc="yes"],
++    [with_libmongoc="no (pkg-config could not find libmongoc)"]
++  )
+ fi
+-if test "x$with_libmongoc" = "xyes"
+-then
+-      if test "x$LIBMONGOC_LDFLAGS" != "x"
+-      then
+-              AC_MSG_NOTICE([libmongoc LDFLAGS: $LIBMONGOC_LDFLAGS])
+-      fi
+-      AC_CHECK_LIB(mongoc, mongo_run_command,
+-      [with_libmongoc="yes"],
+-      [with_libmongoc="no (symbol 'mongo_run_command' not found)"])
++
++if test "x$with_libmongoc" = "xyes"; then
++  SAVE_CPPFLAGS="$CPPFLAGS"
++
++  CPPFLAGS="$CPPFLAGS $LIBMONGOC_CFLAGS"
++
++  if test "x$CPPFLAGS" != "x"; then
++    AC_MSG_NOTICE([libmongoc CPPFLAGS: $LIBMONGOC_CFLAGS])
++  fi
++
++  AC_CHECK_HEADERS([mongoc.h],
++    [with_libmongoc="yes"],
++    [with_libmongoc="no ('mongoc.h' not found)"]
++  )
++
++  CPPFLAGS="$SAVE_CPPFLAGS"
+ fi
+-CPPFLAGS="$SAVE_CPPFLAGS"
+-LDFLAGS="$SAVE_LDFLAGS"
++if test "x$with_libmongoc" = "xyes"; then
++  SAVE_CPPFLAGS="$CPPFLAGS"
++  SAVE_LDFLAGS="$LDFLAGS"
++
++  CPPFLAGS="$CPPFLAGS $LIBMONGOC_CFLAGS"
++  LDFLAGS="$LDFLAGS $LIBMONGOC_LDFLAGS"
++
++  if test "x$LIBMONGOC_LDFLAGS" != "x"; then
++    AC_MSG_NOTICE([libmongoc LDFLAGS: $LIBMONGOC_LDFLAGS])
++  fi
++
++  AC_CHECK_LIB([mongoc-1.0], [mongoc_init],
++    [with_libmongoc="yes"],
++    [with_libmongoc="no (symbol 'mongoc_init' not found)"]
++  )
++
++  CPPFLAGS="$SAVE_CPPFLAGS"
++  LDFLAGS="$SAVE_LDFLAGS"
++fi
+-if test "x$with_libmongoc" = "xyes"
+-then
+-      BUILD_WITH_LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS"
+-      BUILD_WITH_LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS"
+-      AC_SUBST(BUILD_WITH_LIBMONGOC_CPPFLAGS)
+-      AC_SUBST(BUILD_WITH_LIBMONGOC_LDFLAGS)
++if test "x$with_libmongoc" = "xyes"; then
++  BUILD_WITH_LIBMONGOC_CFLAGS="$LIBMONGOC_CFLAGS"
++  BUILD_WITH_LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS"
+ fi
+-AM_CONDITIONAL(BUILD_WITH_LIBMONGOC, test "x$with_libmongoc" = "xyes")
++
++AC_SUBST([BUILD_WITH_LIBMONGOC_CFLAGS])
++AC_SUBST([BUILD_WITH_LIBMONGOC_LDFLAGS])
+ # }}}
+ # --with-libmosquitto {{{
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -1329,9 +1329,8 @@
+ if BUILD_PLUGIN_WRITE_MONGODB
+ pkglib_LTLIBRARIES += write_mongodb.la
+ write_mongodb_la_SOURCES = write_mongodb.c
+-write_mongodb_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMONGOC_CPPFLAGS)
++write_mongodb_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMONGOC_CFLAGS)
+ write_mongodb_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMONGOC_LDFLAGS)
+-write_mongodb_la_LIBADD = -lmongoc
+ endif
+ if BUILD_PLUGIN_WRITE_PROMETHEUS
+--- a/src/write_mongodb.c
++++ b/src/write_mongodb.c
+@@ -3,6 +3,7 @@
+  * Copyright (C) 2010-2013  Florian Forster
+  * Copyright (C) 2010       Akkarit Sangpetch
+  * Copyright (C) 2012       Chris Lundquist
++ * Copyright (C) 2017       Saikrishna Arcot
+  *
+  * Permission is hereby granted, free of charge, to any person obtaining a
+  * copy of this software and associated documentation files (the "Software"),
+@@ -26,6 +27,7 @@
+  *   Florian Forster <octo at collectd.org>
+  *   Akkarit Sangpetch <asangpet at andrew.cmu.edu>
+  *   Chris Lundquist <clundquist at bluebox.net>
++ *   Saikrishna Arcot <saiarcot895 at gmail.com>
+  **/
+ #include "collectd.h"
+@@ -34,17 +36,7 @@
+ #include "plugin.h"
+ #include "utils_cache.h"
+-#if HAVE_STDINT_H
+-#define MONGO_HAVE_STDINT 1
+-#else
+-#define MONGO_USE_LONG_LONG_INT 1
+-#endif
+-#include <mongo.h>
+-
+-#if (MONGO_MAJOR == 0) && (MONGO_MINOR < 8)
+-#define bson_alloc() bson_create()
+-#define bson_dealloc(b) bson_dispose(b)
+-#endif
++#include <mongoc.h>
+ struct wm_node_s {
+   char name[DATA_MAX_NAME_LEN];
+@@ -59,8 +51,10 @@
+   char *passwd;
+   _Bool store_rates;
++  _Bool connected;
+-  mongo conn[1];
++  mongoc_client_t *client;
++  mongoc_database_t *database;
+   pthread_mutex_t lock;
+ };
+ typedef struct wm_node_s wm_node_t;
+@@ -68,170 +62,222 @@
+ /*
+  * Functions
+  */
+-static bson *wm_create_bson(const data_set_t *ds, /* {{{ */
+-                            const value_list_t *vl, _Bool store_rates) {
+-  bson *ret;
++static bson_t *wm_create_bson(const data_set_t *ds, /* {{{ */
++                              const value_list_t *vl, _Bool store_rates) {
++  bson_t *ret;
++  bson_t subarray;
+   gauge_t *rates;
+-  ret = bson_alloc(); /* matched by bson_dealloc() */
+-  if (ret == NULL) {
+-    ERROR("write_mongodb plugin: bson_create failed.");
+-    return (NULL);
++  ret = bson_new();
++  if (!ret) {
++    ERROR("write_mongodb plugin: bson_new failed.");
++    return NULL;
+   }
+   if (store_rates) {
+     rates = uc_get_rate(ds, vl);
+     if (rates == NULL) {
+       ERROR("write_mongodb plugin: uc_get_rate() failed.");
+-      return (NULL);
++      bson_destroy(ret);
++      return NULL;
+     }
+   } else {
+     rates = NULL;
+   }
+-  bson_init(ret); /* matched by bson_destroy() */
+-  bson_append_date(ret, "time", (bson_date_t)CDTIME_T_TO_MS(vl->time));
+-  bson_append_string(ret, "host", vl->host);
+-  bson_append_string(ret, "plugin", vl->plugin);
+-  bson_append_string(ret, "plugin_instance", vl->plugin_instance);
+-  bson_append_string(ret, "type", vl->type);
+-  bson_append_string(ret, "type_instance", vl->type_instance);
++  BSON_APPEND_DATE_TIME(ret, "timestamp", CDTIME_T_TO_MS(vl->time));
++  BSON_APPEND_UTF8(ret, "host", vl->host);
++  BSON_APPEND_UTF8(ret, "plugin", vl->plugin);
++  BSON_APPEND_UTF8(ret, "plugin_instance", vl->plugin_instance);
++  BSON_APPEND_UTF8(ret, "type", vl->type);
++  BSON_APPEND_UTF8(ret, "type_instance", vl->type_instance);
+-  bson_append_start_array(ret, "values"); /* {{{ */
+-  for (int i = 0; i < ds->ds_num; i++) {
++  BSON_APPEND_ARRAY_BEGIN(ret, "values", &subarray); /* {{{ */
++  for (size_t i = 0; i < ds->ds_num; i++) {
+     char key[16];
+-    ssnprintf(key, sizeof(key), "%i", i);
++    snprintf(key, sizeof(key), "%zu", i);
+     if (ds->ds[i].type == DS_TYPE_GAUGE)
+-      bson_append_double(ret, key, vl->values[i].gauge);
++      BSON_APPEND_DOUBLE(&subarray, key, vl->values[i].gauge);
+     else if (store_rates)
+-      bson_append_double(ret, key, (double)rates[i]);
++      BSON_APPEND_DOUBLE(&subarray, key, (double)rates[i]);
+     else if (ds->ds[i].type == DS_TYPE_COUNTER)
+-      bson_append_long(ret, key, vl->values[i].counter);
++      BSON_APPEND_INT64(&subarray, key, vl->values[i].counter);
+     else if (ds->ds[i].type == DS_TYPE_DERIVE)
+-      bson_append_long(ret, key, vl->values[i].derive);
++      BSON_APPEND_INT64(&subarray, key, vl->values[i].derive);
+     else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
+-      bson_append_long(ret, key, vl->values[i].absolute);
+-    else
+-      assert(23 == 42);
++      BSON_APPEND_INT64(&subarray, key, vl->values[i].absolute);
++    else {
++      ERROR("write_mongodb plugin: Unknown ds_type %d for index %zu",
++            ds->ds[i].type, i);
++      bson_destroy(ret);
++      return NULL;
++    }
+   }
+-  bson_append_finish_array(ret); /* }}} values */
++  bson_append_array_end(ret, &subarray); /* }}} values */
+-  bson_append_start_array(ret, "dstypes"); /* {{{ */
+-  for (int i = 0; i < ds->ds_num; i++) {
++  BSON_APPEND_ARRAY_BEGIN(ret, "dstypes", &subarray); /* {{{ */
++  for (size_t i = 0; i < ds->ds_num; i++) {
+     char key[16];
+-    ssnprintf(key, sizeof(key), "%i", i);
++    snprintf(key, sizeof(key), "%zu", i);
+     if (store_rates)
+-      bson_append_string(ret, key, "gauge");
++      BSON_APPEND_UTF8(&subarray, key, "gauge");
+     else
+-      bson_append_string(ret, key, DS_TYPE_TO_STRING(ds->ds[i].type));
++      BSON_APPEND_UTF8(&subarray, key, DS_TYPE_TO_STRING(ds->ds[i].type));
+   }
+-  bson_append_finish_array(ret); /* }}} dstypes */
++  bson_append_array_end(ret, &subarray); /* }}} dstypes */
+-  bson_append_start_array(ret, "dsnames"); /* {{{ */
+-  for (int i = 0; i < ds->ds_num; i++) {
++  BSON_APPEND_ARRAY_BEGIN(ret, "dsnames", &subarray); /* {{{ */
++  for (size_t i = 0; i < ds->ds_num; i++) {
+     char key[16];
+-    ssnprintf(key, sizeof(key), "%i", i);
+-    bson_append_string(ret, key, ds->ds[i].name);
++    snprintf(key, sizeof(key), "%zu", i);
++    BSON_APPEND_UTF8(&subarray, key, ds->ds[i].name);
+   }
+-  bson_append_finish_array(ret); /* }}} dsnames */
+-
+-  bson_finish(ret);
++  bson_append_array_end(ret, &subarray); /* }}} dsnames */
+   sfree(rates);
+-  return (ret);
+-} /* }}} bson *wm_create_bson */
+-static int wm_write(const data_set_t *ds, /* {{{ */
+-                    const value_list_t *vl, user_data_t *ud) {
+-  wm_node_t *node = ud->data;
+-  char collection_name[512];
+-  bson *bson_record;
+-  int status;
++  size_t error_location;
++  if (!bson_validate(ret, BSON_VALIDATE_UTF8, &error_location)) {
++    ERROR("write_mongodb plugin: Error in generated BSON document "
++          "at byte %zu",
++          error_location);
++    bson_destroy(ret);
++    return NULL;
++  }
+-  ssnprintf(collection_name, sizeof(collection_name), "collectd.%s",
+-            vl->plugin);
++  return ret;
++} /* }}} bson *wm_create_bson */
+-  bson_record = wm_create_bson(ds, vl, node->store_rates);
+-  if (bson_record == NULL)
+-    return (ENOMEM);
++static int wm_initialize(wm_node_t *node) /* {{{ */
++{
++  char *uri;
+-  pthread_mutex_lock(&node->lock);
++  if (node->connected)
++    return 0;
++
++  INFO("write_mongodb plugin: Connecting to [%s]:%d", node->host, node->port);
+-  if (!mongo_is_connected(node->conn)) {
+-    INFO("write_mongodb plugin: Connecting to [%s]:%i",
+-         (node->host != NULL) ? node->host : "localhost",
+-         (node->port != 0) ? node->port : MONGO_DEFAULT_PORT);
+-    status = mongo_connect(node->conn, node->host, node->port);
+-    if (status != MONGO_OK) {
+-      ERROR("write_mongodb plugin: Connecting to [%s]:%i failed.",
+-            (node->host != NULL) ? node->host : "localhost",
+-            (node->port != 0) ? node->port : MONGO_DEFAULT_PORT);
+-      mongo_destroy(node->conn);
+-      pthread_mutex_unlock(&node->lock);
+-      return (-1);
++  if ((node->db != NULL) && (node->user != NULL) && (node->passwd != NULL)) {
++    uri = ssnprintf_alloc("mongodb://%s:%s@%s:%d/?authSource=%s", node->user,
++                          node->passwd, node->host, node->port, node->db);
++    if (uri == NULL) {
++      ERROR("write_mongodb plugin: Not enough memory to assemble "
++            "authentication string.");
++      mongoc_client_destroy(node->client);
++      node->client = NULL;
++      node->connected = 0;
++      return -1;
+     }
+-    if ((node->db != NULL) && (node->user != NULL) && (node->passwd != NULL)) {
+-      status = mongo_cmd_authenticate(node->conn, node->db, node->user,
+-                                      node->passwd);
+-      if (status != MONGO_OK) {
+-        ERROR("write_mongodb plugin: Authenticating to [%s]%i for database "
+-              "\"%s\" as user \"%s\" failed.",
+-              (node->host != NULL) ? node->host : "localhost",
+-              (node->port != 0) ? node->port : MONGO_DEFAULT_PORT, node->db,
+-              node->user);
+-        mongo_destroy(node->conn);
+-        pthread_mutex_unlock(&node->lock);
+-        return (-1);
+-      }
++    node->client = mongoc_client_new(uri);
++    if (!node->client) {
++      ERROR("write_mongodb plugin: Authenticating to [%s]:%d for database "
++            "\"%s\" as user \"%s\" failed.",
++            node->host, node->port, node->db, node->user);
++      node->connected = 0;
++      sfree(uri);
++      return -1;
++    }
++  } else {
++    uri = ssnprintf_alloc("mongodb://%s:%d", node->host, node->port);
++    if (uri == NULL) {
++      ERROR("write_mongodb plugin: Not enough memory to assemble "
++            "authentication string.");
++      mongoc_client_destroy(node->client);
++      node->client = NULL;
++      node->connected = 0;
++      return -1;
+     }
+-    if (node->timeout > 0) {
+-      status = mongo_set_op_timeout(node->conn, node->timeout);
+-      if (status != MONGO_OK) {
+-        WARNING("write_mongodb plugin: mongo_set_op_timeout(%i) failed: %s",
+-                node->timeout, node->conn->errstr);
+-      }
++    node->client = mongoc_client_new(uri);
++    if (!node->client) {
++      ERROR("write_mongodb plugin: Connecting to [%s]:%d failed.", node->host,
++            node->port);
++      node->connected = 0;
++      sfree(uri);
++      return -1;
+     }
++    sfree(uri);
+   }
+-  /* Assert if the connection has been established */
+-  assert(mongo_is_connected(node->conn));
++  node->database = mongoc_client_get_database(node->client, "collectd");
++  if (!node->database) {
++    ERROR("write_mongodb plugin: error creating/getting database");
++    mongoc_client_destroy(node->client);
++    node->client = NULL;
++    node->connected = 0;
++    return -1;
++  }
+-#if MONGO_MINOR >= 6
+-  /* There was an API change in 0.6.0 as linked below */
+-  /* https://github.com/mongodb/mongo-c-driver/blob/master/HISTORY.md */
+-  status = mongo_insert(node->conn, collection_name, bson_record, NULL);
+-#else
+-  status = mongo_insert(node->conn, collection_name, bson_record);
+-#endif
+-
+-  if (status != MONGO_OK) {
+-    ERROR("write_mongodb plugin: error inserting record: %d", node->conn->err);
+-    if (node->conn->err != MONGO_BSON_INVALID)
+-      ERROR("write_mongodb plugin: %s", node->conn->errstr);
+-    else
+-      ERROR("write_mongodb plugin: Invalid BSON structure, error = %#x",
+-            (unsigned int)bson_record->err);
++  node->connected = 1;
++  return 0;
++} /* }}} int wm_initialize */
+-    /* Disconnect except on data errors. */
+-    if ((node->conn->err != MONGO_BSON_INVALID) &&
+-        (node->conn->err != MONGO_BSON_NOT_FINISHED))
+-      mongo_destroy(node->conn);
++static int wm_write(const data_set_t *ds, /* {{{ */
++                    const value_list_t *vl, user_data_t *ud) {
++  wm_node_t *node = ud->data;
++  mongoc_collection_t *collection = NULL;
++  bson_t *bson_record;
++  bson_error_t error;
++  int status;
++
++  bson_record = wm_create_bson(ds, vl, node->store_rates);
++  if (!bson_record) {
++    ERROR("write_mongodb plugin: error making insert bson");
++    return -1;
+   }
+-  pthread_mutex_unlock(&node->lock);
++  pthread_mutex_lock(&node->lock);
++  if (wm_initialize(node) < 0) {
++    ERROR("write_mongodb plugin: error making connection to server");
++    pthread_mutex_unlock(&node->lock);
++    bson_destroy(bson_record);
++    return -1;
++  }
++
++  collection =
++      mongoc_client_get_collection(node->client, "collectd", vl->plugin);
++  if (!collection) {
++    ERROR("write_mongodb plugin: error creating/getting collection");
++    mongoc_database_destroy(node->database);
++    mongoc_client_destroy(node->client);
++    node->database = NULL;
++    node->client = NULL;
++    node->connected = 0;
++    pthread_mutex_unlock(&node->lock);
++    bson_destroy(bson_record);
++    return -1;
++  }
++
++  status = mongoc_collection_insert(collection, MONGOC_INSERT_NONE, bson_record,
++                                    NULL, &error);
++
++  if (!status) {
++    ERROR("write_mongodb plugin: error inserting record: %s", error.message);
++    mongoc_database_destroy(node->database);
++    mongoc_client_destroy(node->client);
++    node->database = NULL;
++    node->client = NULL;
++    node->connected = 0;
++    pthread_mutex_unlock(&node->lock);
++    bson_destroy(bson_record);
++    mongoc_collection_destroy(collection);
++    return -1;
++  }
+   /* free our resource as not to leak memory */
+-  bson_destroy(bson_record); /* matches bson_init() */
+-  bson_dealloc(bson_record); /* matches bson_alloc() */
++  mongoc_collection_destroy(collection);
++
++  pthread_mutex_unlock(&node->lock);
+-  return (0);
++  bson_destroy(bson_record);
++
++  return 0;
+ } /* }}} int wm_write */
+ static void wm_config_free(void *ptr) /* {{{ */
+@@ -241,8 +287,11 @@
+   if (node == NULL)
+     return;
+-  if (mongo_is_connected(node->conn))
+-    mongo_destroy(node->conn);
++  mongoc_database_destroy(node->database);
++  mongoc_client_destroy(node->client);
++  node->database = NULL;
++  node->client = NULL;
++  node->connected = 0;
+   sfree(node->host);
+   sfree(node);
+@@ -255,17 +304,23 @@
+   node = calloc(1, sizeof(*node));
+   if (node == NULL)
+-    return (ENOMEM);
+-  mongo_init(node->conn);
+-  node->host = NULL;
++    return ENOMEM;
++  mongoc_init();
++  node->host = strdup("localhost");
++  if (node->host == NULL) {
++    sfree(node);
++    return ENOMEM;
++  }
++  node->port = MONGOC_DEFAULT_PORT;
+   node->store_rates = 1;
+   pthread_mutex_init(&node->lock, /* attr = */ NULL);
+   status = cf_util_get_string_buffer(ci, node->name, sizeof(node->name));
+   if (status != 0) {
++    sfree(node->host);
+     sfree(node);
+-    return (status);
++    return status;
+   }
+   for (int i = 0; i < ci->children_num; i++) {
+@@ -311,14 +366,15 @@
+   }
+   if (status == 0) {
+-    char cb_name[DATA_MAX_NAME_LEN];
++    char cb_name[sizeof("write_mongodb/") + DATA_MAX_NAME_LEN];
+-    ssnprintf(cb_name, sizeof(cb_name), "write_mongodb/%s", node->name);
++    snprintf(cb_name, sizeof(cb_name), "write_mongodb/%s", node->name);
+-    status = plugin_register_write(
+-        cb_name, wm_write, &(user_data_t){
+-                               .data = node, .free_func = wm_config_free,
+-                           });
++    status =
++        plugin_register_write(cb_name, wm_write,
++                              &(user_data_t){
++                                  .data = node, .free_func = wm_config_free,
++                              });
+     INFO("write_mongodb plugin: registered write plugin %s %d", cb_name,
+          status);
+   }
+@@ -326,7 +382,7 @@
+   if (status != 0)
+     wm_config_free(node);
+-  return (status);
++  return status;
+ } /* }}} int wm_config_node */
+ static int wm_config(oconfig_item_t *ci) /* {{{ */
+@@ -342,11 +398,9 @@
+               child->key);
+   }
+-  return (0);
++  return 0;
+ } /* }}} int wm_config */
+ void module_register(void) {
+   plugin_register_complex_config("write_mongodb", wm_config);
+ }
+-
+-/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */