Esempio n. 1
0
void
PgNotifyTransferEvents(Pg_ConnectionId * connid)
{
	PGnotify   *notify;

	while ((notify = PQnotifies(connid->conn)) != NULL)
	{
		NotifyEvent *event = (NotifyEvent *) ckalloc(sizeof(NotifyEvent));

		event->header.proc = Pg_Notify_EventProc;
		event->notify = notify;
		event->connid = connid;
		Tcl_QueueEvent((Tcl_Event *) event, TCL_QUEUE_TAIL);
	}

	/*
	 * This is also a good place to check for unexpected closure of the
	 * connection (ie, backend crash), in which case we must shut down the
	 * notify event source to keep Tcl from trying to select() on the now-
	 * closed socket descriptor.  But don't kill on-connection-loss
	 * events; in fact, register one.
	 */
	if (PQsocket(connid->conn) < 0)
		PgConnLossTransferEvents(connid);
}
Esempio n. 2
0
void
conn_notifies_process(connectionObject *self)
{
    PGnotify *pgn = NULL;
    PyObject *notify = NULL;
    PyObject *pid = NULL, *channel = NULL, *payload = NULL;
    PyObject *tmp = NULL;

    static PyObject *append;

    if (!append) {
        if (!(append = Text_FromUTF8("append"))) {
            goto error;
        }
    }

    while ((pgn = PQnotifies(self->pgconn)) != NULL) {

        Dprintf("conn_notifies_process: got NOTIFY from pid %d, msg = %s",
                (int) pgn->be_pid, pgn->relname);

        if (!(pid = PyInt_FromLong((long)pgn->be_pid))) { goto error; }
        if (!(channel = conn_text_from_chars(self, pgn->relname))) { goto error; }
        if (!(payload = conn_text_from_chars(self, pgn->extra))) { goto error; }

        if (!(notify = PyObject_CallFunctionObjArgs((PyObject *)&notifyType,
                pid, channel, payload, NULL))) {
            goto error;
        }

        Py_DECREF(pid); pid = NULL;
        Py_DECREF(channel); channel = NULL;
        Py_DECREF(payload); payload = NULL;

        if (!(tmp = PyObject_CallMethodObjArgs(
                self->notifies, append, notify, NULL))) {
            goto error;
        }
        Py_DECREF(tmp); tmp = NULL;

        Py_DECREF(notify); notify = NULL;
        PQfreemem(pgn); pgn = NULL;
    }
    return;  /* no error */

error:
    if (pgn) { PQfreemem(pgn); }
    Py_XDECREF(tmp);
    Py_XDECREF(notify);
    Py_XDECREF(pid);
    Py_XDECREF(channel);
    Py_XDECREF(payload);

    /* TODO: callers currently don't expect an error from us */
    PyErr_Clear();

}
Esempio n. 3
0
/*
 * PrintNotifications: check for asynchronous notifications, and print them out
 */
static void
PrintNotifications(void)
{
	PGnotify   *notify;

	while ((notify = PQnotifies(pset.db)))
	{
		fprintf(pset.queryFout, gettext("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
				notify->relname, notify->be_pid);
		fflush(pset.queryFout);
		PQfreemem(notify);
	}
}
Esempio n. 4
0
pgNotification *pgConn::GetNotification()
{
	pgNotify *notify;

	notify = PQnotifies(conn);
	if (!notify)
		return NULL;

	pgNotification *ret = new pgNotification;
	ret->name = wxString(notify->relname, *conv);
	ret->pid = notify->be_pid;
	ret->data = wxString(notify->extra, *conv);

	return ret;
}
Esempio n. 5
0
CAMLprim value PQnotifies_stub(value v_conn)
{
  CAMLparam1(v_conn);
  CAMLlocal1(v_str);
  PGnotify *noti = PQnotifies(get_conn(v_conn));

  if (noti) {
    value v_pair;
    v_str = make_string(noti->relname);
    v_pair = caml_alloc_small(2, 0);
    Field(v_pair, 0) = v_str;
    Field(v_pair, 1) = Val_int(noti->be_pid);
    PQfreemem(noti);
    CAMLreturn(make_some(v_pair));
  }
  else CAMLreturn(v_None);
}
Esempio n. 6
0
File: common.c Progetto: GisKook/Gis
/*
 * PrintNotifications: check for asynchronous notifications, and print them out
 */
static void
PrintNotifications(void)
{
	PGnotify   *notify;

	while ((notify = PQnotifies(pset.db)))
	{
		/* for backward compatibility, only show payload if nonempty */
		if (notify->extra[0])
			fprintf(pset.queryFout, _("Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n"),
					notify->relname, notify->extra, notify->be_pid);
		else
			fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"),
					notify->relname, notify->be_pid);
		fflush(pset.queryFout);
		PQfreemem(notify);
	}
}
Esempio n. 7
0
void PGDatabase::GetNotify(pgdb_monitor_callback pmc, void* param)
{
	PGnotify   *notify;
	struct pgdb_monitor_result pmr;
    while (true)
    {
        /*
         * Sleep until something happens on the connection.  We use select(2)
         * to wait for input, but you could also use poll() or similar
         * facilities.
         */
        int         sock;
        fd_set      input_mask;

        sock = PQsocket(m_pConnect);

        if (sock < 0)
            break;              /* shouldn't happen */

        FD_ZERO(&input_mask);
        FD_SET(sock, &input_mask);

        if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
        {
            fprintf(stderr, "select() failed: %s\n", strerror(errno));
        }

        /* Now check for input */
        PQconsumeInput(m_pConnect);
        while ((notify = PQnotifies(m_pConnect)) != NULL)
        {
			memset(pmr.tablename, 0 , MAXTABLENAMELEN);
			memset(pmr.opvalues, 0 , MAXOPVALUELEN);
			memcpy(pmr.tablename, notify->relname, strlen(notify->relname));
			memcpy(pmr.opvalues, notify->extra, strlen(notify->extra));
			pmc(&pmr,param);

            PQfreemem(notify);
        }
    }
}
Esempio n. 8
0
char *pl_read(PGconn *conn) {
  // Sleep until something happens on the connection.  We use select(2)
  //to wait for input, but you could also use poll() or similar
  // facilities.
  int         sock;
  fd_set      input_mask;
  PGnotify   *notify;
  char *not_name;

  sock = PQsocket(conn);

  if (sock < 0) {
    fprintf(stderr, "shouldn't happen: sock < 0");
    exit_nicely(conn);
  }

  FD_ZERO(&input_mask);
  FD_SET(sock, &input_mask);

 try_again:
  if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
    {
      fprintf(stderr, "select() failed: %s\n", strerror(errno));
      exit_nicely(conn);
    }

  // Now check for input
  PQconsumeInput(conn);
  if ((notify = PQnotifies(conn)) != NULL)
    {
      fprintf(stderr,
              "ASYNC NOTIFY of '%s' received from backend pid %d\n",
              notify->relname, notify->be_pid);
      not_name = (char *)malloc((strlen(notify->relname) + 1) * sizeof(char));
      strcpy(not_name, notify->relname);
      PQfreemem(notify);
      return not_name;
    } else {
    goto try_again;
  }
}
Esempio n. 9
0
/*
 * call-seq:
 *    conn.get_notify()  -> ary or nil
 *    conn.get_notify() { |rel,pid,msg| .... } -> obj
 *
 * Returns a notifier.  If there is no unprocessed notifier, it returns +nil+.
 */
VALUE
pgconn_get_notify( VALUE self)
{
    struct pgconn_data *c;
    PGnotify *notify;
    VALUE rel, pid, ext;
    VALUE ret;

    Data_Get_Struct( self, struct pgconn_data, c);
    if (PQconsumeInput( c->conn) == 0)
        pg_raise_connexec( c);
    notify = PQnotifies( c->conn);
    if (notify == NULL)
        return Qnil;
    rel = pgconn_mkstring( c, notify->relname);
    pid = INT2FIX( notify->be_pid),
    ext = pgconn_mkstring( c, notify->extra);
    ret = rb_ary_new3( 3, rel, pid, ext);
    PQfreemem( notify);
    return rb_block_given_p() ? rb_yield( ret) : ret;
}
Esempio n. 10
0
File: psql.c Progetto: aosm/X11
LispObj *
Lisp_PQnotifies(LispBuiltin *builtin)
/*
 pq-notifies connection
 */
{
    LispObj *result, *code, *cod = COD;
    PGconn *conn;
    PGnotify *notifies;

    LispObj *connection;

    connection = ARGUMENT(0);

    if (!CHECKO(connection, PGconn_t))
	LispDestroy("%s: cannot convert %s to PGconn*",
		    STRFUN(builtin), STROBJ(connection));
    conn = (PGconn*)(connection->data.opaque.data);

    if ((notifies = PQnotifies(conn)) == NULL)
	return (NIL);

    GCDisable();
    code = CONS(ATOM("MAKE-PG-NOTIFY"),
		  CONS(KEYWORD("RELNAME"),
		       CONS(STRING(notifies->relname),
			    CONS(KEYWORD("BE-PID"),
				 CONS(REAL(notifies->be_pid), NIL)))));
    COD = CONS(code, COD);
    GCEnable();
    result = EVAL(code);
    COD = cod;

    free(notifies);

    return (result);
}
Esempio n. 11
0
/* ----------
 * slon_localListenThread
 *
 *	Listen for events on the local database connection. This means,
 *	events generated by the local node only.
 * ----------
 */
void *
localListenThread_main(/* @unused@ */ void *dummy)
{
	SlonConn   *conn;
	SlonDString query1;
	PGconn	   *dbconn;
	PGresult   *res;
	int			ntuples;
	int			tupno;
	PGnotify   *notification;
	char		restart_notify[256];
	int			restart_request;
	int poll_sleep = 0;
	int         node_lock_obtained=0;

	slon_log(SLON_INFO, "localListenThread: thread starts\n");

	/*
	 * Connect to the local database
	 */
	if ((conn = slon_connectdb(rtcfg_conninfo, "local_listen")) == NULL)
		slon_retry();
	dbconn = conn->dbconn;

	/*
	 * Initialize local data
	 */
	dstring_init(&query1);
	sprintf(restart_notify, "_%s_Restart", rtcfg_cluster_name);

	/*
	 * Listen for local events
	 */
	(void) slon_mkquery(&query1,
		     "listen \"_%s_Restart\"; ",
		     rtcfg_cluster_name);
	res = PQexec(dbconn, dstring_data(&query1));
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		slon_log(SLON_FATAL,
				 "localListenThread: \"%s\" - %s\n",
				 dstring_data(&query1), PQresultErrorMessage(res));
		PQclear(res);
		dstring_free(&query1);
		pthread_mutex_lock(&slon_wait_listen_lock);
		slon_listen_started=0;
		pthread_cond_signal(&slon_wait_listen_cond);
		pthread_mutex_unlock(&slon_wait_listen_lock);
		slon_retry();
	}
	PQclear(res);

	/*
	 * Check that we are the only slon daemon connected.
	 */
#define NODELOCKERROR "ERROR:  duplicate key violates unique constraint \"sl_nodelock-pkey\""

	(void) slon_mkquery(&query1,
				 "select %s.cleanupNodelock(); "
				 "insert into %s.sl_nodelock values ("
				 "    %d, 0, \"pg_catalog\".pg_backend_pid()); ",
				 rtcfg_namespace, rtcfg_namespace,
				 rtcfg_nodeid);
	while(!node_lock_obtained)
	{
		res = PQexec(dbconn, dstring_data(&query1));
		if (PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			slon_log(SLON_FATAL,
					 "localListenThread: \"%s\" - %s\n",
					 dstring_data(&query1), PQresultErrorMessage(res));
			if (strncmp(NODELOCKERROR, PQresultErrorMessage(res), strlen(NODELOCKERROR)) == 0) {
				slon_log(SLON_FATAL,
						 "Do you already have a slon running against this node?\n");
				slon_log(SLON_FATAL,
						 "Or perhaps a residual idle backend connection from a dead slon?\n");
				PQclear(res);
				if(worker_restarted)
				{
					sleep(5);
					continue;
				}
				else
				{
					dstring_free(&query1);					
					pthread_mutex_lock(&slon_wait_listen_lock);
					slon_listen_started=0;
					pthread_cond_signal(&slon_wait_listen_cond);
					pthread_mutex_unlock(&slon_wait_listen_lock);
					slon_abort();
				}
			}
		    
			PQclear(res);
			dstring_free(&query1);
			slon_abort();
		}
		PQclear(res);
		node_lock_obtained=1;
	
	}

	/*
	 * Flag the main thread that the coast is clear and he can launch all
	 * other threads.
	 */
	pthread_mutex_lock(&slon_wait_listen_lock);
	slon_listen_started=1;
	pthread_cond_signal(&slon_wait_listen_cond);
	pthread_mutex_unlock(&slon_wait_listen_lock);

	/*
	 * Process all events, then wait for notification and repeat until
	 * shutdown time has arrived.
	 */
	while (true)
	{
		/*
		 * Start the transaction
		 */
		res = PQexec(dbconn, "start transaction; "
					 "set transaction isolation level serializable;");
		if (PQresultStatus(res) != PGRES_COMMAND_OK)
		{
			slon_log(SLON_FATAL,
					 "localListenThread: cannot start transaction - %s\n",
					 PQresultErrorMessage(res));
			PQclear(res);
			dstring_free(&query1);
			slon_retry();
			break;
		}
		PQclear(res);

		/*
		 * Drain notifications.
		 */
		(void) PQconsumeInput(dbconn);
		restart_request = false;
		while ((notification = PQnotifies(dbconn)) != NULL)
		{
			if (strcmp(restart_notify, notification->relname) == 0)
				restart_request = true;
			(void) PQfreemem(notification);
		}
		if (restart_request)
		{
			slon_log(SLON_INFO,
					 "localListenThread: got restart notification\n");
#ifndef WIN32
			slon_restart();
#else
			/* XXX */
			/* Win32 defer to service manager to restart for now */
			slon_restart();
#endif
		}

		/*
		 * Query the database for new local events
		 */
		(void) slon_mkquery(&query1,
					 "select ev_seqno, ev_timestamp, "
					 "       'dummy', 'dummy', 'dummy', "
					 "       ev_type, "
					 "       ev_data1, ev_data2, ev_data3, ev_data4, "
					 "       ev_data5, ev_data6, ev_data7, ev_data8 "
					 "from %s.sl_event "
					 "where  ev_origin = '%d' "
					 "       and ev_seqno > '%s' "
					 "order by ev_seqno",
					 rtcfg_namespace, rtcfg_nodeid, rtcfg_lastevent);
		res = PQexec(dbconn, dstring_data(&query1));
		if (PQresultStatus(res) != PGRES_TUPLES_OK)
		{
			slon_log(SLON_FATAL,
					 "localListenThread: \"%s\" - %s\n",
					 dstring_data(&query1), PQresultErrorMessage(res));
			PQclear(res);
			dstring_free(&query1);
			slon_retry();
			break;
		}
		ntuples = PQntuples(res);

		for (tupno = 0; tupno < ntuples; tupno++)
		{
			char	   *ev_type;

			/*
			 * Remember the event sequence number for confirmation
			 */
			strcpy(rtcfg_lastevent, PQgetvalue(res, tupno, 0));

			/*
			 * Get the event type and process configuration events
			 */
			ev_type = PQgetvalue(res, tupno, 5);
			slon_log(SLON_DEBUG2, "localListenThread: "
					 "Received event %d,%s %s\n",
					 rtcfg_nodeid, PQgetvalue(res, tupno, 0),
					 ev_type);

			if (strcmp(ev_type, "SYNC") == 0)
			{
				/*
				 * SYNC - nothing to do
				 */
			}
			else if (strcmp(ev_type, "STORE_NODE") == 0)
			{
				/*
				 * STORE_NODE
				 */
				int			no_id;
				char	   *no_comment;

				no_id = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				no_comment = PQgetvalue(res, tupno, 7);

				if (no_id != rtcfg_nodeid)
					rtcfg_storeNode(no_id, no_comment);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "ENABLE_NODE") == 0)
			{
				/*
				 * ENABLE_NODE
				 */
				int			no_id;

				no_id = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);

				if (no_id != rtcfg_nodeid)
					rtcfg_enableNode(no_id);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "DROP_NODE") == 0)
			{
				/*
				 * DROP_NODE
				 */
				int			no_id;
				char		notify_query[256];
				PGresult   *notify_res;

				no_id = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);

				/*
				 * Deactivate the node in the runtime configuration
				 */
				rtcfg_disableNode(no_id);

				/*
				 * And cause the replication daemon to restart to get rid of
				 * it.
				 */
				snprintf(notify_query, sizeof(notify_query),
						 "notify \"_%s_Restart\";",
						 rtcfg_cluster_name);
				notify_res = PQexec(dbconn, notify_query);
				if (PQresultStatus(notify_res) != PGRES_COMMAND_OK)
				{
					slon_log(SLON_FATAL, "localListenThread: \"%s\" %s\n",
							 notify_query, PQresultErrorMessage(notify_res));
					PQclear(notify_res);
					slon_restart();
				}
				PQclear(notify_res);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "CLONE_NODE") == 0)
			{
				/*
				 * CLONE_NODE
				 */
				int			no_id;
				int			no_provider;
				char	   *no_comment;

				no_id = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				no_provider = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);
				no_comment = PQgetvalue(res, tupno, 8);

				rtcfg_storeNode(no_id, no_comment);
			}
			else if (strcmp(ev_type, "STORE_PATH") == 0)
			{
				/*
				 * STORE_PATH
				 */
				int			pa_server;
				int			pa_client;
				char	   *pa_conninfo;
				int			pa_connretry;

				pa_server = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				pa_client = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);
				pa_conninfo = PQgetvalue(res, tupno, 8);
				pa_connretry = (int)strtol(PQgetvalue(res, tupno, 9), NULL, 10);

				if (pa_client == rtcfg_nodeid)
					rtcfg_storePath(pa_server, pa_conninfo, pa_connretry);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "DROP_PATH") == 0)
			{
				/*
				 * DROP_PATH
				 */
				int			pa_server;
				int			pa_client;

				pa_server = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				pa_client = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);

				if (pa_client == rtcfg_nodeid)
					rtcfg_dropPath(pa_server);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "STORE_LISTEN") == 0)
			{
				/*
				 * STORE_LISTEN
				 */
				int			li_origin;
				int			li_provider;
				int			li_receiver;

				li_origin = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				li_provider = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);
				li_receiver = (int)strtol(PQgetvalue(res, tupno, 8), NULL, 10);

				if (li_receiver == rtcfg_nodeid)
					rtcfg_storeListen(li_origin, li_provider);
			}
			else if (strcmp(ev_type, "DROP_LISTEN") == 0)
			{
				/*
				 * DROP_LISTEN
				 */
				int			li_origin;
				int			li_provider;
				int			li_receiver;

				li_origin = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				li_provider = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);
				li_receiver = (int)strtol(PQgetvalue(res, tupno, 8), NULL, 10);

				if (li_receiver == rtcfg_nodeid)
					rtcfg_dropListen(li_origin, li_provider);
			}
			else if (strcmp(ev_type, "STORE_SET") == 0)
			{
				/*
				 * STORE_SET
				 */
				int			set_id;
				int			set_origin;
				char	   *set_comment;

				set_id = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				set_origin = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);
				set_comment = PQgetvalue(res, tupno, 8);

				rtcfg_storeSet(set_id, set_origin, set_comment);
			}
			else if (strcmp(ev_type, "DROP_SET") == 0)
			{
				/*
				 * DROP_SET
				 */
				int			set_id;

				set_id = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);

				rtcfg_dropSet(set_id);
			}
			else if (strcmp(ev_type, "MERGE_SET") == 0)
			{
				/*
				 * MERGE_SET
				 */
				int			set_id;
				int			add_id;

				set_id = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				add_id = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);

				rtcfg_dropSet(add_id);
			}
			else if (strcmp(ev_type, "SET_ADD_TABLE") == 0)
			{
				/*
				 * SET_ADD_TABLE
				 */

				/*
				 * Nothing to do ATM ... we don't support adding tables to
				 * subscribed sets and table information is not maintained in
				 * the runtime configuration.
				 */
			}
			else if (strcmp(ev_type, "SET_ADD_SEQUENCE") == 0)
			{
				/*
				 * SET_ADD_SEQUENCE
				 */

				/*
				 * Nothing to do ATM ... we don't support adding sequences to
				 * subscribed sets and table information is not maintained in
				 * the runtime configuration.
				 */
			}
			else if (strcmp(ev_type, "SET_DROP_TABLE") == 0)
			{
				/*
				 * SET_DROP_TABLE
				 */

				/*
				 * Nothing to do ATM ... table information is not maintained
				 * in the runtime configuration.
				 */
			}
			else if (strcmp(ev_type, "SET_DROP_SEQUENCE") == 0)
			{
				/*
				 * SET_DROP_SEQUENCE
				 */

				/*
				 * Nothing to do ATM ... table information is not maintained
				 * in the runtime configuration.
				 */
			}
			else if (strcmp(ev_type, "SET_MOVE_TABLE") == 0)
			{
				/*
				 * SET_MOVE_TABLE
				 */

				/*
				 * Nothing to do ATM ... table information is not maintained
				 * in the runtime configuration.
				 */
			}
			else if (strcmp(ev_type, "SET_MOVE_SEQUENCE") == 0)
			{
				/*
				 * SET_MOVE_SEQUENCE
				 */

				/*
				 * Nothing to do ATM ... table information is not maintained
				 * in the runtime configuration.
				 */
			}
			else if (strcmp(ev_type, "ADJUST_SEQ") == 0)
			{
				/*
				 * ADJUST_SEQ
				 */
			}
			else if (strcmp(ev_type, "STORE_TRIGGER") == 0)
			{
				/*
				 * STORE_TRIGGER
				 */

				/*
				 * Nothing to do ATM
				 */
			}
			else if (strcmp(ev_type, "DROP_TRIGGER") == 0)
			{
				/*
				 * DROP_TRIGGER
				 */

				/*
				 * Nothing to do ATM
				 */
			}
			else if (strcmp(ev_type, "MOVE_SET") == 0)
			{
				/*
				 * MOVE_SET
				 */
				int			set_id;
				int			old_origin;
				int			new_origin;
				PGresult   *res2;
				SlonDString query2;
				int			sub_provider;

				set_id = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				old_origin = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);
				new_origin = (int)strtol(PQgetvalue(res, tupno, 8), NULL, 10);

				/*
				 * We have been the old origin of the set, so according to the
				 * rules we must have a provider now.
				 */
				dstring_init(&query2);
				(void) slon_mkquery(&query2,
							 "select sub_provider from %s.sl_subscribe "
					     "    where sub_receiver = %d and sub_set = %d",
					     rtcfg_namespace, rtcfg_nodeid, set_id);
				res2 = PQexec(dbconn, dstring_data(&query2));
				if (PQresultStatus(res2) != PGRES_TUPLES_OK)
				{
					slon_log(SLON_FATAL, "localListenThread: \"%s\" %s\n",
							 dstring_data(&query2),
							 PQresultErrorMessage(res2));
					dstring_free(&query2);
					PQclear(res2);
					slon_retry();
				}
				if (PQntuples(res2) != 1)
				{
					slon_log(SLON_FATAL, "localListenThread: MOVE_SET "
							 "but no provider found for set %d\n",
							 set_id);
					dstring_free(&query2);
					PQclear(res2);
					slon_retry();
				}

				sub_provider =
					(int)strtol(PQgetvalue(res2, 0, 0), NULL, 10);
				PQclear(res2);
				dstring_free(&query2);

				rtcfg_moveSet(set_id, old_origin, new_origin, sub_provider);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "FAILOVER_SET") == 0)
			{
				/*
				 * FAILOVER_SET
				 */

				/*
				 * Nothing to do. The stored procedure will restart this
				 * daemon anyway.
				 */
			}
			else if (strcmp(ev_type, "SUBSCRIBE_SET") == 0)
			{
				/*
				 * SUBSCRIBE_SET
				 */
				int			sub_set;
				int			sub_provider;
				int			sub_receiver;
				char	   *sub_forward;

				sub_set = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				sub_provider = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);
				sub_receiver = (int)strtol(PQgetvalue(res, tupno, 8), NULL, 10);
				sub_forward = PQgetvalue(res, tupno, 9);

				if (sub_receiver == rtcfg_nodeid)
					rtcfg_storeSubscribe(sub_set, sub_provider, sub_forward);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "ENABLE_SUBSCRIPTION") == 0)
			{
				/*
				 * ENABLE_SUBSCRIPTION
				 */
				int			sub_set;
				int			sub_provider;
				int			sub_receiver;
				char	   *sub_forward;

				sub_set = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				sub_provider = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);
				sub_receiver = (int)strtol(PQgetvalue(res, tupno, 8), NULL, 10);
				sub_forward = PQgetvalue(res, tupno, 9);

				if (sub_receiver == rtcfg_nodeid)
					rtcfg_enableSubscription(sub_set, sub_provider, sub_forward);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "UNSUBSCRIBE_SET") == 0)
			{
				/*
				 * UNSUBSCRIBE_SET
				 */
				int			sub_set;
				int			sub_receiver;

				sub_set = (int)strtol(PQgetvalue(res, tupno, 6), NULL, 10);
				sub_receiver = (int)strtol(PQgetvalue(res, tupno, 7), NULL, 10);

				if (sub_receiver == rtcfg_nodeid)
					rtcfg_unsubscribeSet(sub_set);

				rtcfg_reloadListen(dbconn);
			}
			else if (strcmp(ev_type, "DDL_SCRIPT") == 0)
			{
				/*
				 * DDL_SCRIPT
				 */

				/*
				 * Nothing to do ATM
				 */
			}
			else if (strcmp(ev_type, "ACCEPT_SET") == 0)
			{
				/*
				 * ACCEPT_SET
				 */

				/*
				 * Nothing to do locally
				 */
				slon_log(SLON_DEBUG1, "localListenThread: ACCEPT_SET\n");
				rtcfg_reloadListen(dbconn);
			}
			else
			{
				slon_log(SLON_FATAL,
					 "localListenThread: event %s: Unknown event type: %s\n",
						 rtcfg_lastevent, ev_type);
				slon_abort();
			}
		}

		PQclear(res);

		/*
		 * If there were events, commit the transaction.
		 */
		if (ntuples > 0)
		{
			poll_sleep = 0;  /* drop polling time back to 0... */
			res = PQexec(dbconn, "commit transaction");
			if (PQresultStatus(res) != PGRES_COMMAND_OK)
			{
				slon_log(SLON_FATAL,
						 "localListenThread: \"%s\" - %s\n",
						 dstring_data(&query1), PQresultErrorMessage(res));
				PQclear(res);
				dstring_free(&query1);
				slon_retry();
				break;
			}
			PQclear(res);
		}
		else
		{
			/*
			 * No database events received. Rollback instead.
			 */

			/* Increase the amount of time to sleep, to a max of sync_interval_timeout */
			poll_sleep += sync_interval;
			if (poll_sleep > sync_interval_timeout) {
				poll_sleep = sync_interval_timeout;
			}
			res = PQexec(dbconn, "rollback transaction;");
			if (PQresultStatus(res) != PGRES_COMMAND_OK)
			{
				slon_log(SLON_FATAL,
						 "localListenThread: \"rollback transaction;\" - %s\n",
						 PQresultErrorMessage(res));
				PQclear(res);
				slon_retry();
				break;
			}
			PQclear(res);
		}

		/*
		 * Wait for notify or for timeout
		 */
		if (sched_wait_time(conn, SCHED_WAIT_SOCK_READ, poll_sleep) != SCHED_STATUS_OK)
			break;
	}

	/*
	 * The scheduler asked us to shutdown. Free memory and close the DB
	 * connection.
	 */
	dstring_free(&query1);
	slon_disconnectdb(conn);
#ifdef SLON_MEMDEBUG
	conn = NULL;
#endif

	slon_log(SLON_INFO, "localListenThread: thread done\n");
	pthread_exit(NULL);
}
Esempio n. 12
0
int
main(int argc, char **argv)
{
	const char *conninfo;
	PGconn	   *conn;
	PGresult   *res;
	PGnotify   *notify;
	int			nnotifies;

	/*
	 * If the user supplies a parameter on the command line, use it as the
	 * conninfo string; otherwise default to setting dbname=postgres and using
	 * environment variables or defaults for all other connection parameters.
	 */
	if (argc > 1)
		conninfo = argv[1];
	else
		conninfo = "dbname = postgres";

	/* Make a connection to the database */
	conn = PQconnectdb(conninfo);

	/* Check to see that the backend connection was successfully made */
	if (PQstatus(conn) != CONNECTION_OK)
	{
		fprintf(stderr, "Connection to database failed: %s",
				PQerrorMessage(conn));
		exit_nicely(conn);
	}

	/*
	 * Issue LISTEN command to enable notifications from the rule's NOTIFY.
	 */
	res = PQexec(conn, "LISTEN TBL2");
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		fprintf(stderr, "LISTEN command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely(conn);
	}

	/*
	 * should PQclear PGresult whenever it is no longer needed to avoid memory
	 * leaks
	 */
	PQclear(res);

	/* Quit after four notifies are received. */
	nnotifies = 0;
	while (nnotifies < 4)
	{
		/*
		 * Sleep until something happens on the connection.  We use select(2)
		 * to wait for input, but you could also use poll() or similar
		 * facilities.
		 */
		int			sock;
		fd_set		input_mask;

		sock = PQsocket(conn);

		if (sock < 0)
			break;				/* shouldn't happen */

		FD_ZERO(&input_mask);
		FD_SET(sock, &input_mask);

		if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
		{
			fprintf(stderr, "select() failed: %s\n", strerror(errno));
			exit_nicely(conn);
		}

		/* Now check for input */
		PQconsumeInput(conn);
		while ((notify = PQnotifies(conn)) != NULL)
		{
			fprintf(stderr,
					"ASYNC NOTIFY of '%s' received from backend pid %d\n",
					notify->relname, notify->be_pid);
			PQfreemem(notify);
			nnotifies++;
		}
	}

	fprintf(stderr, "Done.\n");

	/* close the connection to the database and cleanup */
	PQfinish(conn);

	return 0;
}
Esempio n. 13
0
int
hb_main(const char* conninfo)
{
	PGconn	   *conn;
	PGresult   *res;
	PGnotify   *notify;
	int			nnotifies;
	int checked;
	int result;

	char number[5];
	char notify_buf[1024];

	srand((unsigned)time(NULL));

	/* Make a connection to the database */
	conn = PQconnectdb(conninfo);

	/* Check to see that the backend connection was successfully made */
	if (PQstatus(conn) != CONNECTION_OK)
	{
		elog(WARNING, "Connection to database failed: %s",
				PQerrorMessage(conn));
		exit_nicely(conn);
	}

	/*
	 * Issue LISTEN command to enable notifications from the rule's NOTIFY.
	 */
	res = PQexec(conn, "LISTEN HB_SV");
	if (PQresultStatus(res) != PGRES_COMMAND_OK)
	{
		elog(WARNING, "LISTEN command failed: %s", PQerrorMessage(conn));
		PQclear(res);
		exit_nicely(conn);
	}

	/*
	 * should PQclear PGresult whenever it is no longer needed to avoid memory
	 * leaks
	 */
	PQclear(res);

	/* Set Secret Number */
	memset(number, 0x00, 5);
	create_random_number(number);
	elog(LOG , "hb_worker: set secret number=%s\n", number);

	/* Quit after four notifies are received. */
	nnotifies = 0;
	while (1)
	{
		/*
		 * Sleep until something happens on the connection.  We use select(2)
		 * to wait for input, but you could also use poll() or similar
		 * facilities.
		 */
		int			sock;
		fd_set		input_mask;

		sock = PQsocket(conn);

		if (sock < 0)
			break;				/* shouldn't happen */

		FD_ZERO(&input_mask);
		FD_SET(sock, &input_mask);

		if (select(sock + 1, &input_mask, NULL, NULL, NULL) < 0)
		{
			elog(WARNING, "select() failed: %s\n", strerror(errno));
			exit_nicely(conn);
		}

		/* Now check for input */
		PQconsumeInput(conn);
		while ((notify = PQnotifies(conn)) != NULL)
		{
			checked = check_number(notify->extra);
			switch (checked) {
				case NUMBER_COMMAND:
					result = compare_numbers(number, notify->extra);
					if (GET_HITS(result) == 4) {
						// Notify Game Clear, and Set new number.
						elog(LOG, "hb_worker: NOTIFY HB_CL,'4 Hit! Conguratulatoins!, next new game.'\n");
						strcpy(notify_buf, "NOTIFY HB_CL,'4 Hit! Conguratulatoins!, next new game.'");
						PQexec(conn, notify_buf);
						create_random_number(number);
						elog(LOG, "hb_worker: set secret number=%s\n", number);

					} else {
						// Notify Hit&blow
						elog(LOG, "NOTIFY HB_CL,'%d Hit / %d Blow.'",
							GET_HITS(result), GET_BLOWS(result));
						sprintf(notify_buf, "NOTIFY HB_CL,'%d Hit / %d Blow.'",
							GET_HITS(result), GET_BLOWS(result));
						PQexec(conn, notify_buf);
					}
					break;
				case START_COMMAND:
					// Set New number.
					elog(LOG, "hb_worker: Set New number.");
					create_random_number(number);
					break;
				case QUIT_COMMAND:
					// nop
					break;
				case INVALID_COMMAND:
				default:
					// NOTIFY error status
					sprintf(notify_buf, "NOTIFY HB_CL,'Invalid data.(%s)'", notify->extra);
					PQexec(conn, notify_buf);
					break;
			}
			

			PQfreemem(notify);
			nnotifies++;
		}
	}

	elog(LOG, "Done.\n");

	/* close the connection to the database and cleanup */
	PQfinish(conn);

	return 0;
}
bool EpollPostgresql::epollEvent(const uint32_t &events)
{
    if(conn==NULL)
    {
        std::cerr << "epollEvent() conn==NULL" << std::endl;
        return false;
    }

    const ConnStatusType &connStatusType=PQstatus(conn);
    if(connStatusType!=CONNECTION_OK)
    {
        if(connStatusType==CONNECTION_MADE)
        {
            started=true;
            std::cout << "Connexion CONNECTION_MADE" << std::endl;
        }
        else if(connStatusType==CONNECTION_STARTED)
        {
            started=true;
            std::cout << "Connexion CONNECTION_STARTED" << std::endl;
        }
        else if(connStatusType==CONNECTION_AWAITING_RESPONSE)
            std::cout << "Connexion CONNECTION_AWAITING_RESPONSE" << std::endl;
        else
        {
            if(connStatusType==CONNECTION_BAD)
            {
                started=false;
                std::cerr << "Connexion not ok: CONNECTION_BAD" << std::endl;
                //return false;
            }
            else if(connStatusType==CONNECTION_AUTH_OK)
                std::cerr << "Connexion not ok: CONNECTION_AUTH_OK" << std::endl;
            else if(connStatusType==CONNECTION_SETENV)
                std::cerr << "Connexion not ok: CONNECTION_SETENV" << std::endl;
            else if(connStatusType==CONNECTION_SSL_STARTUP)
                std::cerr << "Connexion not ok: CONNECTION_SSL_STARTUP" << std::endl;
            else if(connStatusType==CONNECTION_NEEDED)
                std::cerr << "Connexion not ok: CONNECTION_NEEDED" << std::endl;
            else
                std::cerr << "Connexion not ok: " << connStatusType << std::endl;
        }
    }
    if(connStatusType!=CONNECTION_BAD)
    {
        const PostgresPollingStatusType &postgresPollingStatusType=PQconnectPoll(conn);
        if(postgresPollingStatusType==PGRES_POLLING_FAILED)
        {
            std::cerr << "Connexion status: PGRES_POLLING_FAILED" << std::endl;
            return false;
        }
    }

    if(events & EPOLLIN)
    {
        const int PQconsumeInputVar=PQconsumeInput(conn);
        PGnotify *notify;
        while((notify = PQnotifies(conn)) != NULL)
        {
            std::cerr << "ASYNC NOTIFY of '" << notify->relname << "' received from backend PID " << notify->be_pid << std::endl;
            PQfreemem(notify);
        }
        if(/*PQisBusy(conn)==0, produce blocking, when server is unbusy this this never call*/true)
        {
            if(result!=NULL)
                clear();
            tuleIndex=-1;
            ntuples=0;
            result=PQgetResult(conn);
            if(result==NULL)
                std::cerr << "query async send failed: " << errorMessage() << ", PQgetResult(conn) have returned NULL" << std::endl;
            else
            {
                auto end = std::chrono::high_resolution_clock::now();
                std::chrono::duration<double, std::milli> elapsed = end-start;
                const uint32_t &ms=elapsed.count();
                if(ms>5000)
                {
                    if(queriesList.empty())
                        std::cerr << "query too slow, take " << ms << "ms" << std::endl;
                    else
                        std::cerr << queriesList.front().query << ": query too slow, take " << ms << "ms" << std::endl;
                }
                #ifdef DEBUG_MESSAGE_CLIENT_SQL
                else
                {
                    if(queriesList.empty())
                        std::cout << "query take " << ms << "ms" << std::endl;
                    else
                        std::cout << queriesList.front().query << ": query take " << ms << "ms" << std::endl;
                }
                #endif
                start = std::chrono::high_resolution_clock::now();
                while(result!=NULL)
                {
                    const ExecStatusType &execStatusType=PQresultStatus(result);
                    if(execStatusType!=PGRES_TUPLES_OK && execStatusType!=PGRES_COMMAND_OK)
                    {
                        #ifdef DEBUG_MESSAGE_CLIENT_SQL
                        std::cerr << simplifiedstrCoPG << ", ";
                        #endif
                        if(queriesList.empty())
                            std::cerr << "Query to database failed: " << errorMessage() << std::endl;
                        else
                            std::cerr << "Query to database failed: " << errorMessage() << queriesList.front().query << std::endl;
                        abort();//prevent continue running to prevent data corruption
                        tuleIndex=0;
                    }
                    else
                        ntuples=PQntuples(result);
                    if(!queue.empty())
                    {
                        CallBack callback=queue.front();
                        if(callback.method!=NULL)
                            callback.method(callback.object);
                        queue.erase(queue.cbegin());
                    }
                    if(result!=NULL)
                        clear();
                    if(!queriesList.empty())
                        queriesList.erase(queriesList.cbegin());
                    if(!queriesList.empty())
                        if(!sendNextQuery())
                            return false;
                    result=PQgetResult(conn);
                }
            }
        }
        else
            std::cout << "PostgreSQL events with EPOLLIN: PQisBusy: " << std::to_string(PQconsumeInputVar) << std::endl;
    }
    if(events & (EPOLLRDHUP | EPOLLHUP | EPOLLERR))
    {
        started=false;
        if(events == EPOLLRDHUP)
        {
            std::cerr << "Database disconnected, try reconnect: " << errorMessage() << std::endl;
            syncDisconnect();
            conn=NULL;
            syncReconnect();
        }
    }
    return true;
}