Example #1
0
/*
 * Return a freshly allocated List. Since empty non-NIL lists are
 * invalid, new_list() also allocates the head cell of the new list:
 * the caller should be sure to fill in that cell's data.
 */
static List *
new_list(NodeTag type)
{
	List	   *new_list;
	ListCell   *new_head;

	new_head = pgut_new(ListCell);
	new_head->next = NULL;
	/* new_head->data is left undefined! */

	new_list = pgut_new(List);
	new_list->type = type;
	new_list->length = 1;
	new_list->head = new_head;
	new_list->tail = new_head;

	return new_list;
}
Example #2
0
/*
 * Allocate a new cell and make it the head of the specified
 * list. Assumes the list it is passed is non-NIL.
 *
 * The data in the new head cell is undefined; the caller should be
 * sure to fill it in
 */
static void
new_head_cell(List *list)
{
	ListCell   *new_head;

	new_head = pgut_new(ListCell);
	new_head->next = list->head;

	list->head = new_head;
	list->length++;
}
Example #3
0
/*
 * Allocate a new cell and make it the tail of the specified
 * list. Assumes the list it is passed is non-NIL.
 *
 * The data in the new tail cell is undefined; the caller should be
 * sure to fill it in
 */
static void
new_tail_cell(List *list)
{
	ListCell   *new_tail;

	new_tail = pgut_new(ListCell);
	new_tail->next = NULL;

	list->tail->next = new_tail;
	list->tail = new_tail;
	list->length++;
}
Example #4
0
/*
 * Create new parray object.
 * Never returns NULL.
 */
parray *
parray_new(void)
{
    parray *a = pgut_new(parray);

    a->data = NULL;
    a->used = 0;
    a->alloced = 0;

    parray_expand(a, 1024);

    return a;
}
Example #5
0
void
pgut_atexit_push(pgut_atexit_callback callback, void *userdata)
{
	pgut_atexit_item *item;

	AssertArg(callback != NULL);

	item = pgut_new(pgut_atexit_item);
	item->callback = callback;
	item->userdata = userdata;
	item->next = pgut_atexit_stack;

	pgut_atexit_stack = item;
}
Example #6
0
/*
 * Return a shallow copy of the specified list, without the first N elements.
 */
List *
list_copy_tail(List *oldlist, int nskip)
{
	List	   *newlist;
	ListCell   *newlist_prev;
	ListCell   *oldlist_cur;

	if (nskip < 0)
		nskip = 0;				/* would it be better to elog? */

	if (oldlist == NIL || nskip >= oldlist->length)
		return NIL;

	newlist = new_list(oldlist->type);
	newlist->length = oldlist->length - nskip;

	/*
	 * Skip over the unwanted elements.
	 */
	oldlist_cur = oldlist->head;
	while (nskip-- > 0)
		oldlist_cur = oldlist_cur->next;

	/*
	 * Copy over the data in the first remaining cell; new_list() has already
	 * allocated the head cell itself
	 */
	newlist->head->data = oldlist_cur->data;

	newlist_prev = newlist->head;
	oldlist_cur = oldlist_cur->next;
	while (oldlist_cur)
	{
		ListCell   *newlist_cur;

		newlist_cur = pgut_new(ListCell);
		newlist_cur->data = oldlist_cur->data;
		newlist_prev->next = newlist_cur;

		newlist_prev = newlist_cur;
		oldlist_cur = oldlist_cur->next;
	}

	newlist_prev->next = NULL;
	newlist->tail = newlist_prev;

	return newlist;
}
Example #7
0
/*
 * Add a new cell to the list, in the position after 'prev_cell'. The
 * data in the cell is left undefined, and must be filled in by the
 * caller. 'list' is assumed to be non-NIL, and 'prev_cell' is assumed
 * to be non-NULL and a member of 'list'.
 */
static ListCell *
add_new_cell(List *list, ListCell *prev_cell)
{
	ListCell   *new_cell;

	new_cell = pgut_new(ListCell);
	/* new_cell->data is left undefined! */
	new_cell->next = prev_cell->next;
	prev_cell->next = new_cell;

	if (list->tail == prev_cell)
		list->tail = new_cell;

	list->length++;

	return new_cell;
}
Example #8
0
/* FIXME: support recursive error */
static pgutErrorData *
getErrorData(void)
{
#ifdef PGUT_MULTI_THREADED
	pgutErrorData *edata = pthread_getspecific(pgut_edata_key);

	if (edata == NULL)
	{
		edata = pgut_new(pgutErrorData);
		memset(edata, 0, sizeof(pgutErrorData));
		pthread_setspecific(pgut_edata_key, edata);
	}

	return edata;
#else
	static pgutErrorData	edata;

	return &edata;
#endif
}
Example #9
0
/*
 * Return a shallow copy of the specified list.
 */
List *
list_copy(List *oldlist)
{
	List	   *newlist;
	ListCell   *newlist_prev;
	ListCell   *oldlist_cur;

	if (oldlist == NIL)
		return NIL;

	newlist = new_list(oldlist->type);
	newlist->length = oldlist->length;

	/*
	 * Copy over the data in the first cell; new_list() has already allocated
	 * the head cell itself
	 */
	newlist->head->data = oldlist->head->data;

	newlist_prev = newlist->head;
	oldlist_cur = oldlist->head->next;
	while (oldlist_cur)
	{
		ListCell   *newlist_cur;

		newlist_cur = pgut_new(ListCell);
		newlist_cur->data = oldlist_cur->data;
		newlist_prev->next = newlist_cur;

		newlist_prev = newlist_cur;
		oldlist_cur = oldlist_cur->next;
	}

	newlist_prev->next = NULL;
	newlist->tail = newlist_prev;

	return newlist;
}
/*
 * parse_checkpoint
 */
bool
parse_checkpoint(const char *message, const char *timestamp)
{
	static CheckpointLog	*ckpt = NULL;

	List	*params;

	if ((params = capture(message, msg_checkpoint_starting, NUM_CHECKPOINT_STARTING)) != NIL)
	{
		/* log for checkpoint starting */

		const char		*type = (char *) list_nth(params, 0);
		const char		*flags = (char *) list_nth(params, 1);
		CheckpointType	 ckpt_type;

		if (strcmp(type, "checkpoint") == 0)
			ckpt_type = CKPT_TYPE_CHECKPOINT;
		else if (strcmp(type, "restartpoint") == 0)
			ckpt_type = CKPT_TYPE_RESTARTPOINT;
		else
		{
			/* not a checkpoint log */
			list_free_deep(params);
			return false;
		}

		/* ignore shutdown checkpoint */
		if (strstr(flags, "shutdown"))
		{
			free(ckpt);
			ckpt = NULL;
			list_free_deep(params);
			return true;	/* handled, but forget */
		}

		if (ckpt == NULL)
			ckpt = pgut_new(CheckpointLog);

		/* copy type, flags and start timestamp */
		ckpt->type = ckpt_type;
		strlcpy(ckpt->flags, flags, sizeof(ckpt->flags));
		strlcpy(ckpt->start, timestamp, sizeof(ckpt->start));

		list_free_deep(params);
		return true;
	}

	if ((params = capture(message, msg_checkpoint_complete, NUM_CHECKPOINT_COMPLETE)) != NIL ||
		(params = capture(message, msg_restartpoint_complete, NUM_RESTARTPOINT_COMPLETE)) != NIL)
	{
		/* log for checkpoint complete */

		/* ignore if we have not seen any checkpoint start */
		if (ckpt == NULL)
		{
			list_free_deep(params);
			return true;	/* handled, but forget */
		}

		/* send checkpoint log to writer */
		ckpt->params = params;
		ckpt->base.type = QUEUE_CHECKPOINT;
		ckpt->base.free = (QueueItemFree) Checkpoint_free;
		ckpt->base.exec = (QueueItemExec) Checkpoint_exec;
		writer_send((QueueItem *) ckpt);

		ckpt = NULL;

		return true;
	}

	/* not a checkpoint log */
	return false;
}
Example #11
0
PGconn *
pgut_connect(const char *info, YesNo prompt, int elevel)
{
	char	   *passwd;
	StringInfoData add_pass;

	if (prompt == YES)
	{
		passwd = prompt_for_password();
		initStringInfo(&add_pass);
		appendStringInfoString(&add_pass, info);
		appendStringInfo(&add_pass, " password=%s ", passwd);
	}
	else
	{
		passwd = NULL;
		add_pass.data = NULL;
	}

	/* Start the connection. Loop until we have a password if requested by backend. */
	for (;;)
	{
		PGconn	   *conn;
		CHECK_FOR_INTERRUPTS();

		if (!passwd)
			conn = PQconnectdb(info);
		else
			conn = PQconnectdb(add_pass.data);

		if (PQstatus(conn) == CONNECTION_OK)
		{
			pgutConn *c;

			c = pgut_new(pgutConn);
			c->conn = conn;
			c->cancel = NULL;

			pgut_conn_lock();
			c->next = pgut_connections;
			pgut_connections = c;
			pgut_conn_unlock();

			if (add_pass.data != NULL)
				termStringInfo(&add_pass);
			free(passwd);

			return conn;
		}

		if (conn && PQconnectionNeedsPassword(conn) && prompt != NO)
		{
			PQfinish(conn);
			free(passwd);
			passwd = prompt_for_password();
			if (add_pass.data != NULL)
	 			resetStringInfo(&add_pass);
			else
	 			initStringInfo(&add_pass);
			appendStringInfoString(&add_pass, info);
			appendStringInfo(&add_pass, " password=%s ", passwd);
			continue;
		}

		if (add_pass.data != NULL)
			termStringInfo(&add_pass);
		free(passwd);

		ereport(elevel,
			(errcode(E_PG_CONNECT),
			 errmsg("could not connect to database with \"%s\": %s",
				info, PQerrorMessage(conn))));
		PQfinish(conn);
		return NULL;
	}
}