The branch, 112-patches has been updated via d528c05948149c63f4c20c472d59b21a3a1dc529 (commit) from 64fb20dcfcff5bc067d97bff39e491e40ca45a3f (commit)
http://gitweb.samba.org/?p=tridge/ctdb.git;a=shortlog;h=112-patches - Log ----------------------------------------------------------------- commit d528c05948149c63f4c20c472d59b21a3a1dc529 Author: Andrew Tridgell <tri...@samba.org> Date: Sun Feb 7 19:02:06 2010 +1100 ctdb: migrate to new dlinklist.h from Samba ----------------------------------------------------------------------- Summary of changes: common/ctdb_io.c | 7 +- lib/util/dlinklist.h | 194 ++++++++++++++++++++++++++++---------------------- 2 files changed, 111 insertions(+), 90 deletions(-) Changeset truncated at 500 lines: diff --git a/common/ctdb_io.c b/common/ctdb_io.c index 3fa784d..b7feed9 100644 --- a/common/ctdb_io.c +++ b/common/ctdb_io.c @@ -194,8 +194,7 @@ static void queue_io_write(struct ctdb_queue *queue) if (n == -1 && errno != EAGAIN && errno != EWOULDBLOCK) { if (pkt->length != pkt->full_length) { /* partial packet sent - we have to drop it */ - TLIST_REMOVE(queue->out_queue, queue->out_queue_tail, - pkt); + DLIST_REMOVE(queue->out_queue, pkt); queue->out_queue_length--; talloc_free(pkt); } @@ -214,7 +213,7 @@ static void queue_io_write(struct ctdb_queue *queue) return; } - TLIST_REMOVE(queue->out_queue, queue->out_queue_tail, pkt); + DLIST_REMOVE(queue->out_queue, pkt); queue->out_queue_length--; talloc_free(pkt); } @@ -295,7 +294,7 @@ int ctdb_queue_send(struct ctdb_queue *queue, uint8_t *data, uint32_t length) EVENT_FD_WRITEABLE(queue->fde); } - TLIST_ADD_END(queue->out_queue, queue->out_queue_tail, pkt); + DLIST_ADD_END(queue->out_queue, pkt, NULL); queue->out_queue_length++; diff --git a/lib/util/dlinklist.h b/lib/util/dlinklist.h index 44747d6..6d525f9 100644 --- a/lib/util/dlinklist.h +++ b/lib/util/dlinklist.h @@ -1,7 +1,8 @@ /* Unix SMB/CIFS implementation. some simple double linked list macros - Copyright (C) Andrew Tridgell 1998 + + Copyright (C) Andrew Tridgell 1998-2010 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -14,7 +15,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, see <http://www.gnu.org/licenses/>. + along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* To use these macros you must have a structure containing a next and @@ -23,55 +24,94 @@ #ifndef _DLINKLIST_H #define _DLINKLIST_H +/* + February 2010 - changed list format to have a prev pointer from the + list head. This makes DLIST_ADD_END() O(1) even though we only have + one list pointer. + + The scheme is as follows: + + 1) with no entries in the list: + list_head == NULL + + 2) with 1 entry in the list: + list_head->next == NULL + list_head->prev == list_head + + 3) with 2 entries in the list: + list_head->next == element2 + list_head->prev == element2 + element2->prev == list_head + element2->next == NULL + + 4) with N entries in the list: + list_head->next == element2 + list_head->prev == elementN + elementN->prev == element{N-1} + elementN->next == NULL -/* hook into the front of the list */ + This allows us to find the tail of the list by using + list_head->prev, which means we can add to the end of the list in + O(1) time + + + Note that the 'type' arguments below are no longer needed, but + are kept for now to prevent an incompatible argument change + */ + + +/* + add an element at the front of a list +*/ #define DLIST_ADD(list, p) \ do { \ if (!(list)) { \ - (list) = (p); \ - (p)->next = (p)->prev = NULL; \ + (p)->prev = (list) = (p); \ + (p)->next = NULL; \ } else { \ + (p)->prev = (list)->prev; \ (list)->prev = (p); \ (p)->next = (list); \ - (p)->prev = NULL; \ (list) = (p); \ - }\ + } \ } while (0) -/* remove an element from a list - element doesn't have to be in list. */ +/* + remove an element from a list + Note that the element doesn't have to be in the list. If it + isn't then this is a no-op +*/ #define DLIST_REMOVE(list, p) \ do { \ if ((p) == (list)) { \ + if ((p)->next) (p)->next->prev = (p)->prev; \ (list) = (p)->next; \ - if (list) (list)->prev = NULL; \ + } else if ((list) && (p) == (list)->prev) { \ + (p)->prev->next = NULL; \ + (list)->prev = (p)->prev; \ } else { \ if ((p)->prev) (p)->prev->next = (p)->next; \ if ((p)->next) (p)->next->prev = (p)->prev; \ } \ - if ((p) != (list)) (p)->next = (p)->prev = NULL; \ + if ((p) != (list)) (p)->next = (p)->prev = NULL; \ } while (0) -/* promote an element to the top of the list */ -#define DLIST_PROMOTE(list, p) \ +/* + find the head of the list given any element in it. + Note that this costs O(N), so you should avoid this macro + if at all possible! +*/ +#define DLIST_HEAD(p, result_head) \ do { \ - DLIST_REMOVE(list, p); \ - DLIST_ADD(list, p); \ -} while (0) + (result_head) = (p); \ + while (DLIST_PREV(result_head)) (result_head) = (result_head)->prev; \ +} while(0) -/* hook into the end of the list - needs a tmp pointer */ -#define DLIST_ADD_END(list, p, type) \ -do { \ - if (!(list)) { \ - (list) = (p); \ - (p)->next = (p)->prev = NULL; \ - } else { \ - type tmp; \ - for (tmp = (list); tmp->next; tmp = tmp->next) ; \ - tmp->next = (p); \ - (p)->next = NULL; \ - (p)->prev = tmp; \ - } \ -} while (0) +/* return the last element in the list */ +#define DLIST_TAIL(list) ((list)?(list)->prev:NULL) + +/* return the previous element in the list. */ +#define DLIST_PREV(p) (((p)->prev && (p)->prev->next != NULL)?(p)->prev:NULL) /* insert 'p' after the given element 'el' in a list. If el is NULL then this is the same as a DLIST_ADD() */ @@ -80,80 +120,62 @@ do { \ if (!(list) || !(el)) { \ DLIST_ADD(list, p); \ } else { \ - p->prev = el; \ - p->next = el->next; \ - el->next = p; \ - if (p->next) p->next->prev = p; \ + (p)->prev = (el); \ + (p)->next = (el)->next; \ + (el)->next = (p); \ + if ((p)->next) (p)->next->prev = (p); \ + if ((list)->prev == (el)) (list)->prev = (p); \ }\ } while (0) -/* demote an element to the end of the list, needs a tmp pointer */ -#define DLIST_DEMOTE(list, p, tmp) \ + +/* + add to the end of a list. + Note that 'type' is ignored +*/ +#define DLIST_ADD_END(list, p, type) \ do { \ - DLIST_REMOVE(list, p); \ - DLIST_ADD_END(list, p, tmp); \ + if (!(list)) { \ + DLIST_ADD(list, p); \ + } else { \ + DLIST_ADD_AFTER(list, p, (list)->prev); \ + } \ } while (0) -/* concatenate two lists - putting all elements of the 2nd list at the - end of the first list */ -#define DLIST_CONCATENATE(list1, list2, type) \ +/* promote an element to the from of a list */ +#define DLIST_PROMOTE(list, p) \ do { \ - if (!(list1)) { \ - (list1) = (list2); \ - } else { \ - type tmp; \ - for (tmp = (list1); tmp->next; tmp = tmp->next) ; \ - tmp->next = (list2); \ - if (list2) { \ - (list2)->prev = tmp; \ - } \ - } \ + DLIST_REMOVE(list, p); \ + DLIST_ADD(list, p); \ } while (0) /* - The TLIST_*() macros are meant for when you have two list pointers, - one pointing at the head of the list and one pointing at the tail - of the list. This makes the common case of adding to the end of the - list and removing from the front of the list efficient - - TLIST stands for "tailed list" - - Note: When initialising the structure containing your lists, make - sure that you set both head and tail to NULL - - Also, do not mix the TLIST_*() macros with the DLIST_* macros! + demote an element to the end of a list. + Note that 'type' is ignored */ - -/* TLIST_ADD_FRONT adds elements to the front of the list. */ -#define TLIST_ADD_FRONT(listhead, listtail, p) \ +#define DLIST_DEMOTE(list, p, type) \ do { \ - DLIST_ADD(listhead, p); \ - if (NULL == (listtail)) { \ - (listtail) = (p); \ - } \ + DLIST_REMOVE(list, p); \ + DLIST_ADD_END(list, p, NULL); \ } while (0) -/* TLIST_ADD_END adds elements to the end of the list. */ -#define TLIST_ADD_END(listhead, listtail, p) \ +/* + concatenate two lists - putting all elements of the 2nd list at the + end of the first list. + Note that 'type' is ignored +*/ +#define DLIST_CONCATENATE(list1, list2, type) \ do { \ - if ((listtail) == NULL) { \ - DLIST_ADD(listhead, p); \ - (listtail) = (listhead); \ + if (!(list1)) { \ + (list1) = (list2); \ } else { \ - (listtail)->next = (p); \ - (p)->prev = (listtail); \ - (p)->next = NULL; \ - (listtail) = (p); \ - } \ -} while (0) - -/* TLIST_REMOVE removes an element from the list */ -#define TLIST_REMOVE(listhead, listtail, p) \ -do { \ - if ((p) == (listtail)) { \ - (listtail) = (p)->prev; \ + (list1)->prev->next = (list2); \ + if (list2) { \ + void *_tmplist = (void *)(list1)->prev; \ + (list1)->prev = (list2)->prev; \ + (list2)->prev = _tmplist; \ + } \ } \ - DLIST_REMOVE(listhead, p); \ } while (0) #endif /* _DLINKLIST_H */ -- CTDB repository