void
test_mongo_sync_cmd_kill_cursors_net (void)
{
  mongo_packet *p;
  mongo_sync_connection *conn;
  bson *b;
  gint i;
  mongo_reply_packet_header rh;
  gint64 cid;

  begin_network_tests (3);

  conn = mongo_sync_connect (config.primary_host, config.primary_port, TRUE);
  mongo_sync_conn_set_auto_reconnect (conn, TRUE);

  b = bson_new ();
  for (i = 0; i < 40; i++)
    {
      bson_reset (b);
      bson_append_string (b, "test-name", __FILE__, -1);
      bson_append_int32 (b, "seq", i);
      bson_finish (b);

      mongo_sync_cmd_insert (conn, config.ns, b, NULL);
    }
  bson_free (b);

  b = bson_new ();
  bson_append_string (b, "test-name", __FILE__, -1);
  bson_finish (b);

  p = mongo_sync_cmd_query (conn, config.ns,
			    MONGO_WIRE_FLAG_QUERY_NO_CURSOR_TIMEOUT,
			    0, 2, b, NULL);
  mongo_wire_reply_packet_get_header (p, &rh);
  cid = rh.cursor_id;
  mongo_wire_packet_free (p);

  ok (mongo_sync_cmd_kill_cursors (conn, 1, cid) == TRUE,
      "mongo_sync_kill_cursors() works");

  p = mongo_sync_cmd_query (conn, config.ns,
			    MONGO_WIRE_FLAG_QUERY_NO_CURSOR_TIMEOUT,
			    0, 2, b, NULL);
  bson_free (b);
  mongo_wire_reply_packet_get_header (p, &rh);
  cid = rh.cursor_id;
  mongo_wire_packet_free (p);
  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (3);

  ok (mongo_sync_cmd_kill_cursors (conn, 1, cid) == TRUE,
      "mongo_sync_cmd_kill_cursors() automatically reconnects");

  mongo_sync_disconnect (conn);

  test_mongo_sync_cmd_kill_cursors_net_secondary ();

  end_network_tests ();
}
Beispiel #2
0
void
test_mongo_wire_packet_new (void)
{
  mongo_packet *p;

  ok ((p = mongo_wire_packet_new ()) != NULL,
      "mongo_wire_packet_new() works");
  mongo_wire_packet_free (NULL);
  pass ("mongo_wire_packet_free(NULL) works");
  mongo_wire_packet_free (p);
  pass ("mongo_wire_packet_free() works");
}
Beispiel #3
0
void
test_mongo_sync_cmd_custom_net_secondary (void)
{
  mongo_sync_connection *conn;
  bson *cmd;
  mongo_packet *p;

  skip (!config.secondary_host, 1,
	"Secondary server not configured");

  conn = mongo_sync_connect (config.secondary_host, config.secondary_port,
			     TRUE);
  cmd = bson_build (BSON_TYPE_INT32, "getnonce", 1,
		    BSON_TYPE_NONE);
  bson_finish (cmd);

  p = mongo_sync_cmd_custom (conn, config.db, cmd);
  ok (p != NULL,
      "mongo_sync_cmd_custom() works on the secondary too");
  mongo_wire_packet_free (p);

  bson_free (cmd);
  mongo_sync_disconnect (conn);

  endskip;
}
void
test_mongo_sync_cmd_kill_cursors_net_secondary (void)
{
  mongo_packet *p;
  mongo_sync_connection *conn;
  bson *b;

  mongo_reply_packet_header rh;
  gint64 cid;

  skip (!config.secondary_host, 1,
	"Secondary server not configured");

  conn = mongo_sync_connect (config.secondary_host, config.secondary_port,
			     TRUE);
  b = bson_new ();
  bson_append_string (b, "test-name", __FILE__, -1);
  bson_finish (b);

  p = mongo_sync_cmd_query (conn, config.ns,
			    MONGO_WIRE_FLAG_QUERY_NO_CURSOR_TIMEOUT,
			    0, 2, b, NULL);
  bson_free (b);
  mongo_wire_reply_packet_get_header (p, &rh);
  cid = rh.cursor_id;
  mongo_wire_packet_free (p);

  ok (mongo_sync_cmd_kill_cursors (conn, 1, cid) == TRUE,
      "mongo_sync_cmd_kill_cursors() works on secondary too");

  mongo_sync_disconnect (conn);

  endskip;
}
Beispiel #5
0
void
test_mongo_wire_cmd_custom (void)
{
  bson *cmd;
  mongo_packet *p;

  mongo_packet_header hdr;
  const guint8 *data;
  gint32 data_size;

  bson_cursor *c;
  gint32 pos;

  cmd = bson_new ();
  bson_append_int32 (cmd, "getnonce", 1);

  ok (mongo_wire_cmd_custom (1, "test", 0, NULL) == NULL,
      "mongo_wire_cmd_custom() fails with a NULL command");
  ok (mongo_wire_cmd_custom (1, "test", 0, cmd) == NULL,
      "mongo_wire_cmd_custom() fails with an unfinished command");
  bson_finish (cmd);
  ok (mongo_wire_cmd_custom (1, NULL, 0, cmd) == NULL,
      "mongo_wire_cmd_custom() fails with a NULL db");

  ok ((p = mongo_wire_cmd_custom (1, "test", 0, cmd)) != NULL,
      "mongo_wire_cmd_custom() works");
  bson_free (cmd);

  /* Verify the header */
  mongo_wire_packet_get_header (p, &hdr);
  cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
	  "Packet data size looks fine");
  cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
	  "Packet header length is OK");
  cmp_ok (hdr.id, "==", 1, "Packet request ID is ok");
  cmp_ok (hdr.resp_to, "==", 0, "Packet reply ID is ok");

  /*
   * Test the created request
   */

  /* pos = zero + collection_name + NULL + skip + ret */
  pos = sizeof (gint32) + strlen ("test.$cmd") + 1 + sizeof (gint32) * 2;
  ok ((cmd = bson_new_from_data (data + pos,
				 _DOC_SIZE (data, pos) - 1)) != NULL,
      "Packet contains a BSON document");
  bson_finish (cmd);

  ok ((c = bson_find (cmd, "getnonce")) != NULL,
      "BSON object contains a 'getnonce' key");
  cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
	  "'getnonce' key has the correct type");
  ok (bson_cursor_next (c) == FALSE,
      "'getnonce' key is the last in the object");

  bson_cursor_free (c);
  bson_free (cmd);
  mongo_wire_packet_free (p);
}
void
test_mongo_packet_recv_ssl (void)
{
  mongo_connection c, *conn;
  mongo_packet *p;
  bson *b;

  c.fd = -1;

  ok (mongo_packet_recv (NULL) == NULL,
      "mongo_packet_recv() fails with a NULL connection");
  ok (errno == ENOTCONN,
      "mongo_packet_recv() sets errno to ENOTCONN if connection is NULL");

  ok (mongo_packet_recv (&c) == NULL,
      "mongo_packet_recv() fails if the FD is less than zero");
  ok (errno == EBADF,
      "mongo_packet_recv() sets errno to EBADF is the FD is bad");

  begin_ssl_tests (2);

  b = bson_new ();
  bson_append_int32 (b, "getnonce", 1);
  bson_finish (b);

  p = mongo_wire_cmd_custom (42, config.db, 0, b);
  bson_free (b);

  conn = mongo_ssl_connect (config.primary_host, config.primary_port, config.ssl_settings);
  mongo_packet_send (conn, p);
  mongo_wire_packet_free (p);

  ok ((p = mongo_packet_recv (conn)) != NULL,
      "mongo_packet_recv() works");
  mongo_wire_packet_free (p);

  close (conn->fd);
  sleep (3);

  ok (mongo_packet_recv (conn) == NULL,
      "mongo_packet_recv() fails on a closed socket");

  mongo_disconnect (conn);

  end_ssl_tests ();
}
void
test_func_mongo_sync_auto_reconnect (void)
{
  mongo_sync_connection *conn;
  bson *b;
  mongo_packet *p;

  b = bson_new ();
  bson_append_int32 (b, "f_sync_auto_reconnect", 1);
  bson_finish (b);

  conn = mongo_sync_connect (config.primary_host, config.primary_port,
			     TRUE);
  ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE);

  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (1);

  ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
      "Inserting fails with auto-reconnect turned off, and a broken "
      "connection");

  mongo_sync_conn_set_auto_reconnect (conn, TRUE);

  ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE,
      "Inserting works with auto-reconnect turned on, and a broken "
      "connection");

  mongo_sync_conn_set_auto_reconnect (conn, FALSE);

  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (1);

  ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
      "Turning off auto-reconnect works");

  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (1);

  p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, b, NULL);
  ok (p == NULL,
      "Query fails with auto-reconnect turned off");

  mongo_sync_conn_set_auto_reconnect (conn, TRUE);
  p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, b, NULL);
  ok (p != NULL,
      "Query does reconnect with auto-reconnect turned on");
  mongo_wire_packet_free (p);

  mongo_sync_disconnect (conn);
}
Beispiel #8
0
void
test_mongo_sync_cmd_custom_net (void)
{
  mongo_sync_connection *conn;
  bson *cmd;
  mongo_packet *p;

  begin_network_tests (3);

  conn = mongo_sync_connect (config.primary_host, config.primary_port, TRUE);
  mongo_sync_cmd_is_master (conn);
  mongo_sync_conn_set_auto_reconnect (conn, TRUE);

  cmd = bson_build (BSON_TYPE_INT32, "getnonce", 1,
		    BSON_TYPE_NONE);
  bson_finish (cmd);

  p = mongo_sync_cmd_custom (conn, config.db, cmd);
  ok (p != NULL,
      "mongo_sync_cmd_custom() works");
  mongo_wire_packet_free (p);

  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (3);

  p = mongo_sync_cmd_custom (conn, config.db, cmd);
  ok (p != NULL,
      "mongo_sync_cmd_custom() automatically reconnects");
  mongo_wire_packet_free (p);

  bson_free (cmd);
  mongo_sync_disconnect (conn);

  test_mongo_sync_cmd_custom_net_secondary ();

  end_network_tests ();
}
void
test_mongo_wire_packet_get_set_header_raw (void)
{
  mongo_packet *p;
  mongo_packet_header ph1, ph2;

  p = mongo_wire_packet_new ();

  ok (mongo_wire_packet_get_header_raw (NULL, &ph2) == FALSE,
      "mongo_wire_packet_get_header_raw() should fail with a NULL packet");
  ok (mongo_wire_packet_get_header_raw (p, NULL) == FALSE,
      "mongo_wire_packet_get_header_raw() should fail with a NULL header");
  ok (mongo_wire_packet_set_header_raw (NULL, &ph1) == FALSE,
      "mongo_wire_packet_set_header_raw() should fail with a NULL packet");
  ok (mongo_wire_packet_set_header_raw (p, NULL) == FALSE,
      "mongo_wire_packet_set_header_raw() should fail with a NULL header");

  ok (mongo_wire_packet_get_header_raw (p, &ph2),
      "mongo_wire_packet_get_header_raw() works on a fresh packet");
  /* Need to convert from LE, because _new() sets the length to LE. */
  cmp_ok (GINT32_FROM_LE (ph2.length), "==", sizeof (mongo_packet_header),
          "Initial packet length is the length of the header");

  ph1.length = sizeof (mongo_packet_header);
  ph1.id = 1;
  ph1.resp_to = 0;
  ph1.opcode = 1000;

  memset (&ph2, 0, sizeof (mongo_packet_header));

  ok (mongo_wire_packet_set_header_raw (p, &ph1),
      "mongo_wire_packet_set_header_raw() works");
  ok (mongo_wire_packet_get_header_raw (p, &ph2),
      "mongo_wire_packet_get_header_raw() works");

  cmp_ok (ph1.length, "==", ph2.length,
          "Packet lengths match");
  cmp_ok (ph1.id, "==", ph2.id,
          "Sequence IDs match");
  cmp_ok (ph1.resp_to, "==", ph2.resp_to,
          "Response IDs match");
  cmp_ok (ph1.opcode, "==", ph2.opcode,
          "OPCodes match");

  mongo_wire_packet_free (p);
}
Beispiel #10
0
void
test_func_mongo_sync_ssl_insert_query (void)
{
  mongo_sync_connection *conn = NULL;
  bson *test_doc = bson_new ();
  mongo_packet *p = NULL;
  //gchar *test_string =  g_strdup_printf ("%s:%s:%d", __FILE__, __func__, __LINE__);
  gchar *test_string = g_strdup ("test_func_mongo_sync_ssl_insert_query");
  bson_append_string (test_doc, test_string, "ok", -1);
  bson_finish (test_doc);
  
  conn = mongo_sync_ssl_connect (config.primary_host, config.primary_port, TRUE, config.ssl_settings);
  //conn = mongo_sync_connect (config.primary_host, config.primary_port, TRUE);
  mongo_sync_conn_set_auto_reconnect (conn, TRUE);
  
  ok (conn != NULL, "connection works without whitelists");

  ok (mongo_sync_cmd_insert (conn, config.ns, test_doc, NULL) == TRUE, "inserting a document works via SSL");

  p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, test_doc, NULL);

  ok (p != NULL, 
       "querying the recently inserted document works via SSL");

  mongo_wire_packet_free (p);

  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (3);

  ok (mongo_sync_cmd_delete (conn, config.ns, 0, test_doc) == TRUE, "automatic reconnection over SSL should work (at this time: attempting delete command)");

  /* ok (mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, test_doc, NULL) == NULL, "test document should not exist after delete");
    */
    
  mongo_sync_disconnect (conn);
  bson_free (test_doc);
  g_free (test_string);
}
void
test_mongo_connection_get_requestid (void)
{
  mongo_connection c, *conn;
  mongo_packet *p;
  bson *b;
  gint reqid;

  c.request_id = 42;

  ok (mongo_connection_get_requestid (NULL) == -1,
      "mongo_connection_get_requestid() fails with a NULL connection");
  ok (mongo_connection_get_requestid (&c) == 42,
      "mongo_connection_get_requestid() works");

  begin_network_tests (2);

  b = bson_new ();
  bson_append_int32 (b, "getnonce", 1);
  bson_finish (b);

  p = mongo_wire_cmd_custom (42, config.db, 0, b);
  bson_free (b);

  conn = mongo_connect (config.primary_host, config.primary_port);
  cmp_ok ((reqid = mongo_connection_get_requestid (conn)), "==", 0,
	  "Initial request id is 0");
  mongo_packet_send (conn, p);
  mongo_wire_packet_free (p);

  cmp_ok (reqid, "<", mongo_connection_get_requestid (conn),
	  "Old request ID is smaller than the new one");

  mongo_disconnect (conn);

  end_network_tests ();
}
void
test_func_mongo_sync_oidtest (void)
{
    mongo_sync_connection *conn;
    bson *boid, *reply = NULL;
    bson_cursor *c;
    mongo_packet *p;
    guint8 *oid;
    const guint8 *noid;

    mongo_util_oid_init (0);

    oid = mongo_util_oid_new (1);
    boid = bson_new ();
    bson_append_oid (boid, "driverOIDTest", oid);
    bson_finish (boid);

    conn = mongo_sync_connect (config.primary_host, config.primary_port,
                               FALSE);

    p = mongo_sync_cmd_custom (conn, config.db, boid);
    ok (p != NULL,
        "driverOIDTest(OID) custom command works");
    mongo_wire_reply_packet_get_nth_document (p, 1, &reply);
    bson_finish (reply);

    c = bson_find (reply, "oid");
    bson_cursor_get_oid (c, &noid);
    ok (memcmp (oid, noid, 12) == 0,
        "driverOIDTest(OID) returns the same OID");
    bson_cursor_free (c);

    mongo_sync_disconnect (conn);
    mongo_wire_packet_free (p);
    bson_free (boid);
    bson_free (reply);
}
Beispiel #13
0
mongo_packet *
mongo_packet_recv (mongo_connection *conn)
{
  mongo_packet *p;
  guint8 *data;
  guint32 size;
  mongo_packet_header h;

  if (!conn)
    {
      errno = ENOTCONN;
      return NULL;
    }

  if (conn->fd < 0)
    {
      errno = EBADF;
      return NULL;
    }

  memset (&h, 0, sizeof (h));
  if (recv (conn->fd, &h, sizeof (mongo_packet_header), MSG_NOSIGNAL) !=
      sizeof (mongo_packet_header))
    {
      return NULL;
    }

  h.length = GINT32_FROM_LE (h.length);
  h.id = GINT32_FROM_LE (h.id);
  h.resp_to = GINT32_FROM_LE (h.resp_to);
  h.opcode = GINT32_FROM_LE (h.opcode);

  p = mongo_wire_packet_new ();

  if (!mongo_wire_packet_set_header_raw (p, &h))
    {
      int e = errno;

      mongo_wire_packet_free (p);
      errno = e;
      return NULL;
    }

  size = h.length - sizeof (mongo_packet_header);
  data = g_new0 (guint8, size);
  if ((guint32)recv (conn->fd, data, size, MSG_NOSIGNAL) != size)
    {
      int e = errno;

      g_free (data);
      mongo_wire_packet_free (p);
      errno = e;
      return NULL;
    }

  if (!mongo_wire_packet_set_data (p, data, size))
    {
      int e = errno;

      g_free (data);
      mongo_wire_packet_free (p);
      errno = e;
      return NULL;
    }

  g_free (data);

  return p;
}
Beispiel #14
0
int
mongo_dump (config_t *config)
{
  mongo_sync_connection *conn;
  bson *b;
  int fd;

  mongo_packet *p;
  mongo_reply_packet_header rh;
  gint64 cid;
  gdouble cnt, pos = 0;

  gchar *error;
  int e;

  VLOG ("Connecting to %s:%d/%s.%s...\n", config->host, config->port,
	config->db, config->coll);

  conn = mongo_sync_connect (config->host, config->port, config->slaveok);
  if (!conn)
    {
      e = errno;

      mongo_sync_cmd_get_last_error (conn, config->db, &error);
      fprintf (stderr, "Error connecting to %s:%d: %s\n", config->host,
	       config->port, (error) ? error : strerror (e));
      g_free (error);
      exit (1);
    }

  if (config->master_sync)
    {
      VLOG ("Syncing to master...\n");
      conn = mongo_sync_reconnect (conn, TRUE);
      if (!conn)
	{
	  e = errno;

	  mongo_sync_cmd_get_last_error (conn, config->db, &error);
	  fprintf (stderr, "Error reconnecting to the master of %s:%d: %s\n",
		   config->host, config->port, (error) ? error : strerror (e));
	  exit (1);
	}
    }

  VLOG ("Counting documents...\n");
  cnt = mongo_sync_cmd_count (conn, config->db, config->coll, NULL);
  if (cnt < 0)
    {
      e = errno;

      mongo_sync_cmd_get_last_error (conn, config->db, &error);
      fprintf (stderr, "Error counting documents in %s.%s: %s\n",
	       config->db, config->coll, (error) ? error : strerror (e));
      mongo_sync_disconnect (conn);
      exit (1);
    }

  VLOG ("Opening output file '%s'...\n", config->output);
  if (strcmp (config->output, "-") == 0)
    fd = 1;
  else
    {
      fd = open (config->output, O_RDWR | O_CREAT | O_TRUNC, 0600);
      if (fd == -1)
	{
	  fprintf (stderr, "Error opening output file '%s': %s\n",
		   config->output, strerror (errno));
	  mongo_sync_disconnect (conn);
	  exit (1);
	}
    }

  VLOG ("Launching initial query...\n");
  b = bson_new ();
  bson_finish (b);
  p = mongo_sync_cmd_query (conn, config->ns,
			    MONGO_WIRE_FLAG_QUERY_NO_CURSOR_TIMEOUT,
			    0, 10, b, NULL);
  if (!p)
    {
      e = errno;

      bson_free (b);
      unlink (config->output);
      close (fd);

      mongo_sync_cmd_get_last_error (conn, config->db, &error);
      fprintf (stderr, "Error retrieving the cursor: %s\n",
	       (error) ? error : strerror (e));
      mongo_sync_disconnect (conn);
      exit (1);
    }
  bson_free (b);

  mongo_wire_reply_packet_get_header (p, &rh);
  cid = rh.cursor_id;
  pos = mongo_dump_packet (config, p, pos, fd);
  mongo_wire_packet_free (p);

  while (pos < cnt)
    {
      gdouble pr = (pos + 10) / cnt;

      VLOG ("\rDumping... %03.2f%%", ((pr > 1) ? 1 : pr) * 100);
      if (config->verbose)
	fflush (stderr);

      p = mongo_sync_cmd_get_more (conn, config->ns, 10, cid);
      if (!p)
	{
	  e = errno;

	  unlink (config->output);
	  close (fd);

	  mongo_sync_cmd_get_last_error (conn, config->db, &error);
	  fprintf (stderr, "Error advancing the cursor: %s\n",
		   (error) ? error : strerror (e));

	  mongo_sync_disconnect (conn);
	  exit (1);
	}
      pos = mongo_dump_packet (config, p, pos, fd);
      mongo_wire_packet_free (p);
    }

  close (fd);
  mongo_sync_disconnect (conn);

  return 0;
}
Beispiel #15
0
void
test_mongo_wire_cmd_insert_n (void)
{
  bson *ins, *tmp;
  const bson *docs[10];
  mongo_packet *p;

  mongo_packet_header hdr;
  const guint8 *data;
  gint32 data_size;

  bson_cursor *c;
  gint32 pos;

  ins = test_bson_generate_full ();
  tmp = bson_new ();

  docs[0] = ins;
  docs[1] = tmp;
  docs[2] = ins;
  docs[3] = ins;
  docs[4] = NULL;
  docs[5] = ins;

  ok (mongo_wire_cmd_insert_n (1, NULL, 1, docs) == NULL,
      "mongo_wire_cmd_insert_n() fails with a NULL namespace");
  ok (mongo_wire_cmd_insert_n (1, "test.ns", 1, NULL) == NULL,
      "mongo_wire_cmd_insert_n() fails with no documents");
  ok (mongo_wire_cmd_insert_n (1, "test.ns", 0, docs) == NULL,
      "mongo_wire_cmd_insert_n() fails with no documents");
  ok (mongo_wire_cmd_insert_n (1, "test.ns", 2, docs) == NULL,
      "mongo_wire_cmd_insert_n() fails with an unfinished document");
  bson_finish (tmp);
  ok (mongo_wire_cmd_insert_n (1, "test.ns", 5, docs) == NULL,
      "mongo_wire_cmd_insert_n() fails with a NULL document in the array");
  ok ((p = mongo_wire_cmd_insert_n (1, "test.ns", 3, docs)) != NULL,
      "mongo_wire_cmd_insert() works");
  bson_free (ins);
  bson_free (tmp);

  /* Test basic header data */
  mongo_wire_packet_get_header (p, &hdr);
  cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
	  "Packet data size appears fine");

  cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
	  "Packet header length is correct");
  cmp_ok (hdr.id, "==", 1, "Header ID is ok");
  cmp_ok (hdr.resp_to, "==", 0, "Response ID is ok");

  /*
   * Test the first document
   */

  /* pos = zero + collection_name + NULL */
  pos = sizeof (gint32) + strlen ("test.ns") + 1;
  ok ((ins = bson_new_from_data (data + pos,
				 _DOC_SIZE (data, pos) - 1)) != NULL,
      "First document is included");
  bson_finish (ins);

  ok ((c = bson_find (ins, "int32")) != NULL,
      "BSON contains 'int32'");
  cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
	  "int32 has correct type");
  bson_cursor_next (c);
  cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT64,
	  "next element has correct type too");
  ok (bson_cursor_next (c) == FALSE,
      "No more data after the update BSON object");
  bson_cursor_free (c);

  /*
   * Test the second document
   */
  pos += bson_size (ins);
  ok ((tmp = bson_new_from_data (data + pos,
				 _DOC_SIZE (data, pos) - 1)) != NULL,
      "Second document is included");
  bson_finish (tmp);
  cmp_ok (bson_size (tmp), "==", 5,
	  "Second document is empty");

  bson_free (ins);
  bson_free (tmp);
  mongo_wire_packet_free (p);
}
void
test_func_mongo_sync_auto_reconnect_cache (void)
{
  mongo_sync_conn_recovery_cache *cache;
  mongo_sync_connection *conn;
  bson *b;
  mongo_packet *p;
  GList *hosts;
  gchar *primary_addr;
  const gchar *error_msg;

  primary_addr = g_strdup_printf ("%s:%d", config.primary_host, config.primary_port);

  b = bson_new ();
  bson_append_int32 (b, "f_sync_auto_reconnect", 1);
  bson_finish (b);

  cache = mongo_sync_conn_recovery_cache_new ();

  mongo_sync_conn_recovery_cache_seed_add (cache,
                                           config.primary_host,
                                           config.primary_port);

  conn = mongo_sync_connect_recovery_cache (cache,
                                            TRUE);

  ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE);

  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (1);

  ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
      "Inserting fails with auto-reconnect turned off, and a broken "
      "connection");

  error_msg = mongo_sync_conn_get_last_error (conn);

  ok (error_msg != NULL, "We have an error msg when insert fails.");

  mongo_sync_conn_set_auto_reconnect (conn, TRUE);

  ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == TRUE,
      "Inserting works with auto-reconnect turned on, and a broken "
      "connection");

  error_msg = mongo_sync_conn_get_last_error (conn);

  ok (error_msg == NULL,
      "After a succesful insert we shouldn't have an error msg.");

  mongo_sync_conn_set_auto_reconnect (conn, FALSE);

  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (1);

  ok (mongo_sync_cmd_insert (conn, config.ns, b, NULL) == FALSE,
      "Turning off auto-reconnect works");

  skip (!config.secondary_host, 7,
        "Secondary host not set up");

  shutdown (conn->super.fd, SHUT_RDWR);
  sleep (1);

  p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, b, NULL);
  ok (p == NULL,
      "Query fails with auto-reconnect turned off");

  error_msg = mongo_sync_conn_get_last_error(conn);
  ok (error_msg != NULL, "We have an error msg after a failure query.");

  mongo_sync_conn_set_auto_reconnect (conn, TRUE);
  p = mongo_sync_cmd_query (conn, config.ns, 0, 0, 1, b, NULL);
  ok (p != NULL,
      "Query does reconnect with auto-reconnect turned on");

  ok (mongo_sync_conn_get_last_error(conn) == NULL,
      "We shouldn't have any error messages after a successful operation.");

  mongo_wire_packet_free (p);

  hosts = conn->rs.hosts;

  ok (cache->rs.hosts == NULL,
      "cache is discarded due to connect replace during auto-reconnect");

  ok ((conn->rs.hosts != NULL) &&
      (g_list_length (conn->rs.hosts) > 0),
      "hosts is filled in mongo_sync_connection");

  mongo_sync_disconnect (conn);

  ok ((cache->rs.hosts != NULL) &&
      (cache->rs.hosts == hosts) &&
      (g_list_length (cache->rs.hosts) > 0),
      "cache is filled by disconnect()");

  mongo_sync_conn_recovery_cache_free (cache);

  endskip;

  g_free (primary_addr);
}
Beispiel #17
0
NEOERR* mmg_query(mmg_conn *db, char *dsn, char *prefix, HDF *outnode)
{
    int count;
    char key[LEN_HDF_KEY];
    HDF *node, *cnode;
    bson *doc;
    NEOERR *err;
    
    MCS_NOT_NULLB(db, dsn);

    db->p = mongo_sync_cmd_query(db->con, dsn, db->flags & 0x3FF, db->skip, db->limit,
                                 db->docq, db->docs);
    if (!db->p) {
        if (errno == ENOENT) {
            mtc_noise("queried %s 0 result", dsn);
            if (db->flags & MMG_FLAG_EMPTY) {
                if (db->query_callback && !db->incallback) {
                    /*
                     * empty result, call callback
                     */
                    db->incallback = true;

                    err = db->query_callback(db, NULL, true);
                    TRACE_NOK(err);

                    db->incallback = false;

                    db->query_callback = NULL;
                    db->callbackdata = NULL;
                }
                return STATUS_OK;
            }
            return nerr_raise(NERR_NOT_FOUND, "无此记录");
        }
        return nerr_raise(NERR_DB, "query: %s %d", strerror(errno), errno);
    }

    /*
     * process result
     */
    if (outnode || (db->query_callback && !db->incallback)) {
        if (outnode) node = outnode; /* need store result */
        else hdf_init(&node);

        db->c = mongo_sync_cursor_new(db->con, dsn, db->p);
        if (!db->c) return nerr_raise(NERR_DB, "cursor: %s", strerror(errno));

        cnode = NULL;
        count = 0;
        while (mongo_sync_cursor_next(db->c) && count < db->limit) {
            memset(key, sizeof(key), 0x0);
            
            if (prefix) {
                if (!(db->flags & MMG_FLAG_MIXROWS) && db->limit > 1)
                    snprintf(key, sizeof(key), "%s.%d", prefix, count);
                else snprintf(key, sizeof(key), "%s", prefix);
            } else {
                if (!(db->flags & MMG_FLAG_MIXROWS) && db->limit > 1)
                    sprintf(key, "%d", count);
                else key[0] = '\0';
            }
            
            doc = mongo_sync_cursor_get_data(db->c);
            err = mbson_export_to_hdf(node, doc, key, MBSON_EXPORT_TYPE, true);
            if (err != STATUS_OK) return nerr_pass(err);

            if (!cnode) cnode = hdf_get_obj(node, key);
            count++;
        }
        db->rescount = count;

        mongo_sync_cursor_free(db->c);
        db->c = NULL;
        db->p = NULL;
        
        mtc_noise("queried %s %d result", dsn, count);

        /*
         * call callback at last. because we don't want declare more mmg_conn*
         * it's safe to do new query in callback on result stored (db->c freeed)
         * we can call mmg_query() recursive, the callback won't.
         */
        if (db->query_callback && !db->incallback) {
            db->incallback = true;

            count = 0;
            while (cnode) {
                count++;
                if (db->rescount == count) err = db->query_callback(db, cnode, true);
                else err = db->query_callback(db, cnode, false);
                TRACE_NOK(err);
                
                cnode = hdf_obj_next(cnode);
            }
            
            db->incallback = false;

            /*
             * query_callback can't be shared with multiply query
             * later query must set them again even if TheSameOne
             */
            db->query_callback = NULL;
            db->callbackdata = NULL;
        }

        if (!outnode) hdf_destroy(&node);
    } else {
        /* don't need result */
        mongo_wire_packet_free(db->p);
        db->c = NULL;
        db->p = NULL;
    }

    return STATUS_OK;
}
Beispiel #18
0
void
test_mongo_wire_cmd_update (void)
{
  bson *sel, *upd, *tmp;
  mongo_packet *p;

  mongo_packet_header hdr;
  const guint8 *data;
  gint32 data_size;

  bson_cursor *c;
  gint32 pos;

  sel = bson_new ();
  bson_append_null (sel, "_id");
  bson_finish (sel);

  upd = test_bson_generate_full ();

  ok (mongo_wire_cmd_update (1, NULL, 0, sel, upd) == NULL,
      "mongo_wire_cmd_update() with a NULL namespace should fail");
  ok (mongo_wire_cmd_update (1, "test.ns", 0, NULL, upd) == NULL,
      "mongo_wire_cmd_update() with a NULL selector should fail");
  ok (mongo_wire_cmd_update (1, "test.ns", 0, sel, NULL) == NULL,
      "mongo_wire_cmd_update() with a NULL update should fail");

  tmp = bson_new ();
  ok (mongo_wire_cmd_update (1, "test.ns", 0, tmp, upd) == NULL,
      "mongo_wire_cmd_update() fails with an unfinished selector");
  ok (mongo_wire_cmd_update (1, "test.ns", 0, sel, tmp) == NULL,
      "mongo_wire_cmd_update() fails with an unfinished update");
  bson_free (tmp);

  ok ((p = mongo_wire_cmd_update (1, "test.ns", 0, sel, upd)) != NULL,
      "mongo_wire_cmd_update() works");

  bson_free (sel);

  mongo_wire_packet_get_header (p, &hdr);
  cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
          "Packet data size looks fine");
  cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
          "Packet header length is OK");
  cmp_ok (hdr.id, "==", 1, "Packet request ID is ok");
  cmp_ok (hdr.resp_to, "==", 0, "Packet reply ID is ok");

  /*
   * Verify the selector object.
   */

  /* pos = zero + collection_name + NULL + flags */
  pos = sizeof (gint32) + strlen ("test.ns") + 1 + sizeof (gint32);
  ok ((sel = bson_new_from_data (data + pos, (gint32)data[pos] - 1)) != NULL,
      "Packet contains a valid BSON selector document");
  bson_finish (sel);

  ok ((c = bson_find (sel, "_id")) != NULL,
      "BSON contains an _id");
  cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_NULL,
          "_id has correct type");
  bson_cursor_free (c);
  bson_free (sel);

  /*
   * Verify the update object
   */
  pos += (gint32)data[pos];
  ok ((tmp = bson_new_from_data (data + pos,
                                 bson_stream_doc_size (data, pos) - 1)) != NULL,
      "Packet contains a valid BSON update document");
  bson_finish (tmp);
  cmp_ok (bson_size (upd), "==", bson_size (tmp),
          "Packet's update document has the correct size");

  ok ((c = bson_find (tmp, "int32")) != NULL,
      "BSON contains 'int32'");
  cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
          "int32 has correct type");
  bson_cursor_next (c);
  cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT64,
          "next element has correct type too");
  ok (bson_cursor_next (c) == FALSE,
      "No more data after the update BSON object");

  bson_cursor_free (c);
  bson_free (tmp);
  bson_free (upd);
  mongo_wire_packet_free (p);
}
Beispiel #19
0
void
test_mongo_wire_cmd_delete (void)
{
  mongo_packet *p;
  bson *s, *tmp;

  mongo_packet_header hdr;
  const guint8 *data;
  gint32 data_size;

  gint32 pos;
  bson_cursor *c;

  s = test_bson_generate_full ();
  tmp = bson_new ();

  ok (mongo_wire_cmd_delete (1, NULL, 0, s) == NULL,
      "mongo_wire_cmd_delete() fails with a NULL namespace");
  ok (mongo_wire_cmd_delete (1, "test.ns", 0, NULL) == NULL,
      "mongo_wire_cmd_delete() fails with a NULL selector");
  ok (mongo_wire_cmd_delete (1, "test.ns", 0, tmp) == NULL,
      "mongo_wire_cmd_delete() fails with an unfinished selector");
  bson_free (tmp);

  ok ((p = mongo_wire_cmd_delete (1, "test.ns", 0, s)) != NULL,
      "mongo_wire_cmd_delete() works");
  bson_free (s);

  /* Test basic header data */
  mongo_wire_packet_get_header (p, &hdr);
  cmp_ok ((data_size = mongo_wire_packet_get_data (p, &data)), "!=", -1,
	  "Packet data size appears fine");

  cmp_ok (hdr.length, "==", sizeof (mongo_packet_header) + data_size,
	  "Packet header length is correct");
  cmp_ok (hdr.id, "==", 1, "Header ID is ok");
  cmp_ok (hdr.resp_to, "==", 0, "Response ID is ok");

  /*
   * Test the constructed request
   */

  /* pos = zero + ns + NULL + flags */
  pos = sizeof (gint32) + strlen ("test.ns") + 1 + sizeof (gint32);

  ok ((s = bson_new_from_data (data + pos,
			       _DOC_SIZE (data, pos) - 1)) != NULL,
      "Packet contains a valid BSON update document");
  bson_finish (s);

  ok ((c = bson_find (s, "int32")) != NULL,
      "BSON contains 'int32'");
  cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT32,
	  "int32 has correct type");
  bson_cursor_next (c);
  cmp_ok (bson_cursor_type (c), "==", BSON_TYPE_INT64,
	  "next element has correct type too");
  ok (bson_cursor_next (c) == FALSE,
      "No more data after the update BSON object");

  bson_cursor_free (c);
  bson_free (s);

  mongo_wire_packet_free (p);
}