From: Eric Bollengier Date: Fri, 5 Feb 2021 08:57:12 +0000 (+0100) Subject: Split alist/ilist X-Git-Tag: Release-11.0.1~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=db771ece939a8d22572334079a5078a7866015d2;p=thirdparty%2Fbacula.git Split alist/ilist ilist and alist are a bit different on some aspects, it's better to split them waiting to fix ilist usage in the cloud module. --- diff --git a/bacula/src/lib/Makefile.in b/bacula/src/lib/Makefile.in index a65471817..5ee28d895 100644 --- a/bacula/src/lib/Makefile.in +++ b/bacula/src/lib/Makefile.in @@ -45,7 +45,7 @@ INCLUDE_FILES = ../baconfig.h ../bacula.h ../bc_types.h \ waitq.h watchdog.h workq.h \ parse_conf.h ini.h \ worker.h lockmgr.h devlock.h output.h bwlimit.h \ - collect.h event.h + collect.h event.h ilist.h # # libbac @@ -62,7 +62,7 @@ LIBBAC_SRCS = attr.c base64.c berrno.c bsys.c binflate.c bget_msg.c \ util.c var.c watchdog.c workq.c btimers.c \ worker.c flist.c bcollector.c collect.c \ address_conf.c breg.c htable.c lockmgr.c devlock.c output.c bwlimit.c \ - bsock_meeting.c bcrc32.c events.c $(EXTRA_SRCS) + bsock_meeting.c bcrc32.c events.c ilist.c $(EXTRA_SRCS) LIBBAC_OBJS_TMP = $(LIBBAC_SRCS:.c=.o) LIBBAC_OBJS = $(LIBBAC_OBJS_TMP:.cc=.o) @@ -230,6 +230,14 @@ alist_test: Makefile libbac.la alist.c unittests.o $(RMF) alist.o $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) alist.c +ilist_test: Makefile libbac.la ilist.c unittests.o + $(RMF) ilist.o + $(CXX) -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) ilist.c + $(LIBTOOL_LINK) $(CXX) $(LDFLAGS) -L. -o $@ ilist.o unittests.o $(DLIB) -lbac -lm $(LIBS) $(OPENSSL_LIBS) + $(LIBTOOL_INSTALL) $(INSTALL_PROGRAM) $@ $(DESTDIR)$(sbindir)/ + $(RMF) ilist.o + $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) ilist.c + dlist_test: Makefile libbac.la dlist.c unittests.o $(RMF) dlist.o $(CXX) -DTEST_PROGRAM $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) dlist.c diff --git a/bacula/src/lib/alist.c b/bacula/src/lib/alist.c index 81f60aba7..1a36eed41 100644 --- a/bacula/src/lib/alist.c +++ b/bacula/src/lib/alist.c @@ -45,7 +45,8 @@ void baselist::grow_list() int new_max_items; /* put() can insert and item anywhere in the list so - it's important to allocate at least last_item+1 items */ + * it's important to allocate at least last_item+1 items + */ int min_grow = MAX(10, last_item+1); if (num_grow < min_grow) { num_grow = min_grow; /* default if not initialized */ @@ -126,7 +127,6 @@ void alist::prepend(void *item) last_item++; } - /* * Append an item to the list */ @@ -137,22 +137,6 @@ void baselist::append(void *item) num_items++; } -/* - * Put an item at a particular index - */ -void ilist::put(int index, void *item) -{ - if (index > last_item) { - last_item = index; - } - grow_list(); - if (items[index] == NULL) { - num_items++; - } - items[index] = item; -} - - /* * Remove an item from the list * Note: you must free the item when @@ -220,34 +204,36 @@ struct FILESET { alist mylist; }; -void check_all_alist_contents(alist *mlist) +void check_all_alist_indexes2(alist *mlist) { bool check_cont = true; - char buf[30]; - int i; + char *bp; + int i = 0; + int nb; - for (i = 0; i < mlist->size(); i++) { - sprintf(buf, "This is item %d", i); - if (strcmp(buf, (char*)mlist->get(i)) != 0){ + foreach_alist_index(i, bp, mlist) { + nb = atoi(bp); + if (nb != i){ + Dmsg2(0, "nb=%d != i=%d\n", nb, i); check_cont = false; } } - ok(check_cont, "Checking alist contents"); + ok(check_cont, "Check all alist indexes 2"); }; -void check_all_ilist_contents(ilist *vlist, int start) +void check_all_alist_contents(alist *mlist) { bool check_cont = true; char buf[30]; int i; - for (i = start; i< vlist->size(); i++) { + for (i = 0; i < mlist->size(); i++) { sprintf(buf, "This is item %d", i); - if (strcmp(buf, (char*)vlist->get(i)) != 0){ + if (strcmp(buf, (char*)mlist->get(i)) != 0){ check_cont = false; } } - ok(check_cont, "Checking ilist contents"); + ok(check_cont, "Checking alist contents"); }; void check_all_alist_indexes(alist *mlist) @@ -274,33 +260,25 @@ void check_alist_destroy_and_delete(alist *mlist) delete mlist; }; -void check_ilist_destroy_delete(ilist *vlist) -{ - vlist->destroy(); - ok(vlist->size() == 0, "Check ilist size after destroy"); - delete vlist; -} - int main() { Unittests alist_test("alist_test"); FILESET *fileset; char buf[30]; alist *mlist; - ilist *vlist; char *bp; int i; bool check_cont; bool check_indx; - Pmsg0(0, "Initialize tests ...\n"); + log("Initialize tests ..."); fileset = (FILESET *)malloc(sizeof(FILESET)); bmemzero(fileset, sizeof(FILESET)); fileset->mylist.init(); ok(fileset && fileset->mylist.empty() && fileset->mylist.max_size() == 0, "Default initialization"); - Pmsg0(0, "Automatic allocation/destruction of alist:\n"); + log("Automatic allocation/destruction of alist:"); for (int i = 0; i < NUMITEMS; i++) { sprintf(buf, "This is item %d", i); @@ -309,12 +287,13 @@ int main() ok(fileset->mylist.size() == NUMITEMS, "Checking size"); check_all_alist_contents(&fileset->mylist); + fileset->mylist.destroy(); ok(fileset->mylist.size() == 0, "Check size after delete"); ok(fileset->mylist.last() == NULL, "Check last after delete"); free(fileset); - Pmsg0(0, "Allocation/destruction using new delete\n"); + log("Allocation/destruction using new delete"); mlist = New(alist(50)); ok(mlist && mlist->empty() && mlist->max_size() == 0, @@ -327,7 +306,7 @@ int main() check_all_alist_contents(mlist); check_alist_destroy_and_delete(mlist); - Pmsg0(0, "Test alist::remove(0)\n"); + log("Test alist::remove(0)"); mlist = New(alist(10, owned_by_alist)); mlist->append(bstrdup("trash")); mlist->append(bstrdup("0")); @@ -342,7 +321,7 @@ int main() check_all_alist_indexes(mlist); check_alist_destroy_and_delete(mlist); - Pmsg0(0, "Test alist::remove(3)\n"); + log("Test alist::remove(3)"); mlist = New(alist(10, owned_by_alist)); mlist->append(bstrdup("0")); mlist->append(bstrdup("1")); @@ -357,7 +336,7 @@ int main() check_all_alist_indexes(mlist); check_alist_destroy_and_delete(mlist); - Pmsg0(0, "Test alist::remove(last)\n"); + log("Test alist::remove(last)"); mlist = New(alist(10, owned_by_alist)); mlist->append(bstrdup("0")); mlist->append(bstrdup("1")); @@ -371,21 +350,23 @@ int main() check_all_alist_indexes(mlist); check_alist_destroy_and_delete(mlist); - Pmsg0(0, "Test alist::remove(last+1)\n"); + log("Test alist::remove(last+1)"); mlist = New(alist(10, owned_by_alist)); mlist->append(bstrdup("0")); mlist->append(bstrdup("1")); mlist->append(bstrdup("2")); mlist->append(bstrdup("3")); mlist->append(bstrdup("4")); + check_all_alist_indexes2(mlist); ok(mlist && mlist->size() == 5, "Checking size"); ok(mlist->last_index() == 5, "Check last_index"); ok(mlist->remove(5) == NULL, "Check remove returns null"); ok(mlist->size() == 5, "Remove test size"); check_all_alist_indexes(mlist); + check_all_alist_indexes2(mlist); check_alist_destroy_and_delete(mlist); - Pmsg0(0, "Test alist::pop()\n"); + log("Test alist::pop()"); mlist = New(alist(10, owned_by_alist)); mlist->append(bstrdup("0")); mlist->append(bstrdup("1")); @@ -399,37 +380,7 @@ int main() check_all_alist_indexes(mlist); check_alist_destroy_and_delete(mlist); - Pmsg0(0, "Test ilist::put()\n"); - vlist = New(ilist(10, owned_by_alist)); - sprintf(buf, "This is item 10"); - vlist->put(10, bstrdup(buf)); - ok(vlist && vlist->size() == 1, "Checking size after put()"); - ok(vlist->last_index() == 10, "Check last_index"); - check_ilist_destroy_delete(vlist); - - Pmsg0(0, "Test ilist with multiple put()\n"); - vlist = New(ilist(50, owned_by_alist)); - sprintf(buf, "This is item 10"); - vlist->put(10, bstrdup(buf)); - ok(vlist && vlist->size() == 1, "Checking size after put()"); - ok(vlist->last_index() == 10, "Check last_index"); - sprintf(buf, "This is item 15"); - vlist->put(15, bstrdup(buf)); - ok(vlist->size() == 2, "Checking size after put()"); - ok(vlist->last_index() == 15, "Check last_index"); - for (i = NUMITEMS; i < NUMITEMS + MORENUMITEMS; i++) { - sprintf(buf, "This is item %d", i); - vlist->put(i, bstrdup(buf)); - } - ok(vlist->size() == 2 + MORENUMITEMS, "Checking size after put()"); - ok(vlist->last_index() == NUMITEMS + MORENUMITEMS - 1, "Check last_index"); - /* check contents, first two sparse elements */ - ok(strcmp("This is item 10", (char *)vlist->get(10)) == 0, "Check ilist content at 10"); - ok(strcmp("This is item 15", (char *)vlist->get(15)) == 0, "Check ilist content at 15"); - check_all_ilist_contents(vlist, NUMITEMS); - check_ilist_destroy_delete(vlist); - - Pmsg0(0, "Test alist::push()\n"); + log("Test alist::push()"); mlist = New(alist(10, owned_by_alist)); check_cont = true; check_indx = true; @@ -445,7 +396,7 @@ int main() } ok(check_cont, "Check all sizes after push"); ok(check_indx, "Check all last_indexes after push"); - Pmsg0(0, "Test alist::pop()\n"); + log("Test alist::pop()"); check_cont = true; for (i = NUMITEMS-1; (bp = (char *)mlist->pop()); i--) { sprintf(buf, "This is item %d", i); @@ -468,6 +419,26 @@ int main() ok(check_cont, "Check get() after pop() contents."); check_alist_destroy_and_delete(mlist); + log("Test alist::foreach_alist_index()"); + mlist = New(alist(10, owned_by_alist)); + mlist->append(bstrdup("0")); + mlist->append(bstrdup("1")); + mlist->append(bstrdup("2")); + mlist->append(bstrdup("3")); + mlist->append(bstrdup("4")); + mlist->append(bstrdup("5")); + mlist->append(bstrdup("6")); + mlist->append(bstrdup("7")); + mlist->append(bstrdup("8")); + mlist->append(bstrdup("9")); + check_all_alist_indexes2(mlist); + ok(mlist && mlist->size() == 10, "Checking size"); + ok(mlist->last_index() == 10, "Check last_index"); + foreach_alist_index(i, bp, mlist) { + ok(i < mlist->size(), "check index"); + ok(bp != NULL, "check element of alist"); + } + check_alist_destroy_and_delete(mlist); return report(); } #endif diff --git a/bacula/src/lib/alist.h b/bacula/src/lib/alist.h index 12f50f2dd..3a86867d3 100644 --- a/bacula/src/lib/alist.h +++ b/bacula/src/lib/alist.h @@ -20,6 +20,8 @@ * Kern Sibbald, June MMIII */ +#ifndef ALIST_H +#define ALIST_H extern bool is_null(const void *ptr); @@ -66,7 +68,9 @@ class baselist : public SMARTALLOC { protected: void **items; /* from 0..n-1 */ int num_items; /* from 1..n */ - int last_item; /* maximum item index (1..n) */ + + int last_item; /* maximum item index (1..n). */ + int max_items; /* maximum possible items (array size) (1..n) */ int num_grow; int cur_item; /* from 1..n */ @@ -105,17 +109,6 @@ public: void *remove(int index) { return remove_item(index);}; }; -/* - * Indexed list -- much like a simplified STL vector - * array of pointers to inserted items - */ -class ilist : public baselist { -public: - ilist(int num = 100, bool own=true): baselist(num, own) {}; - /* put() is not compatible with remove(), prepend() or foreach_alist */ - void put(int index, void *item); -}; - /* * Define index operator [] */ @@ -170,3 +163,5 @@ inline void baselist::grow(int num) { num_grow = num; } + +#endif // ALIST_H diff --git a/bacula/src/lib/ilist.c b/bacula/src/lib/ilist.c new file mode 100644 index 000000000..f75648f27 --- /dev/null +++ b/bacula/src/lib/ilist.c @@ -0,0 +1,219 @@ +/* + Bacula(R) - The Network Backup Solution + + Copyright (C) 2000-2020 Kern Sibbald + + The original author of Bacula is Kern Sibbald, with contributions + from many others, a complete list can be found in the file AUTHORS. + + You may use this file and others of this release according to the + license defined in the LICENSE file, which includes the Affero General + Public License, v3.0 ("AGPLv3") and some additional permissions and + terms pursuant to its AGPLv3 Section 7. + + This notice must be preserved when any source code is + conveyed and/or propagated. + + Bacula(R) is a registered trademark of Kern Sibbald. +*/ +/* + * Bacula array list routines + * + * ilist is a simple malloc'ed array of pointers. For the moment, + * it simply malloc's a bigger array controlled by num_grow. + * Default is to realloc the pointer array for each new member. + * + * Note: the list can have holes (empty items). This is done by + * using get() and put(). + * + * From alist.c + * + */ + +#include "bacula.h" + +/* + * Private grow list function. Used to insure that + * at least one more "slot" is available. + */ +void ilist::grow_list() +{ + int i; + int new_max_items; + + /* put() can insert and item anywhere in the list so + * it's important to allocate at least last_item+1 items + */ + int min_grow = MAX(10, last_item+1); + if (num_grow < min_grow) { + num_grow = min_grow; /* default if not initialized */ + } + + if (items == NULL) { + items = (void **)malloc(num_grow * sizeof(void *)); + for (i=0; i= max_items) { + new_max_items = last_item + num_grow; + items = (void **)realloc(items, new_max_items * sizeof(void *)); + for (i=max_items; i last_item) { + last_item = index; // FIXME: On alist, last_item is pointing after the last item + } + grow_list(); + if (items[index] == NULL) { + num_items++; + } + items[index] = item; +} + + +/* + * Remove an item from the list + * Note: you must free the item when + * you are done with it. + */ +void * ilist::remove_item(int index) +{ + void *item; + if (index < 0 || index >= last_item) { + return NULL; + } + item = items[index]; + + /* last_item is from 1..n, we work from 0..n-1 */ + for (int i=index; i < (last_item-1); i++) { + items[i] = items[i+1]; + } + + items[last_item-1] = NULL; /* The last item is shifted by one, the last slot is always free */ + + last_item--; /* We have shifted all items by 1 */ + num_items--; /* We have 1 item less */ + + return item; +} + + +/* Get the index item -- we should probably allow real indexing here */ +void * ilist::get(int index) +{ + if (items == NULL || index < 0 || index > last_item) { // Difference with alist here + return NULL; + } + return items[index]; +} + +/* Destroy the list and its contents */ +void ilist::destroy() +{ + if (items) { + if (own_items) { + for (int i=0; isize(); i++) { + sprintf(buf, "This is item %d", i); + if (strcmp(buf, (char*)vlist->get(i)) != 0){ + check_cont = false; + } + } + ok(check_cont, "Checking ilist contents"); +}; + +void check_ilist_destroy_delete(ilist *vlist) +{ + vlist->destroy(); + ok(vlist->size() == 0, "Check ilist size after destroy"); + delete vlist; +} + +int main() +{ + Unittests ilist_test("ilist_test"); + char buf[30]; + ilist *vlist; + char *bp; + int i; + bool check_cont; + bool check_indx; + + log("Initialize tests ..."); + log("Test ilist::put()"); + vlist = New(ilist(10, owned_by_ilist)); + sprintf(buf, "This is item 10"); + vlist->put(10, bstrdup(buf)); + ok(vlist && vlist->size() == 1, "Checking size after put()"); + ok(vlist->last_index() == 10, "Check last_index"); + check_ilist_destroy_delete(vlist); + + log("Test ilist with multiple put()"); + vlist = New(ilist(50, owned_by_ilist)); + sprintf(buf, "This is item 10"); + vlist->put(10, bstrdup(buf)); + ok(vlist && vlist->size() == 1, "Checking size after put()"); + ok(vlist->last_index() == 10, "Check last_index"); + sprintf(buf, "This is item 15"); + vlist->put(15, bstrdup(buf)); + ok(vlist->size() == 2, "Checking size after put()"); + ok(vlist->last_index() == 15, "Check last_index"); + for (i = NUMITEMS; i < NUMITEMS + MORENUMITEMS; i++) { + sprintf(buf, "This is item %d", i); + vlist->put(i, bstrdup(buf)); + } + ok(vlist->size() == 2 + MORENUMITEMS, "Checking size after put()"); + ok(vlist->last_index() == NUMITEMS + MORENUMITEMS - 1, "Check last_index"); + /* check contents, first two sparse elements */ + ok(strcmp("This is item 10", (char *)vlist->get(10)) == 0, "Check ilist content at 10"); + ok(strcmp("This is item 15", (char *)vlist->get(15)) == 0, "Check ilist content at 15"); + check_all_ilist_contents(vlist, NUMITEMS); + check_ilist_destroy_delete(vlist); + + return report(); +} +#endif diff --git a/bacula/src/lib/ilist.h b/bacula/src/lib/ilist.h new file mode 100644 index 000000000..7ae3bc711 --- /dev/null +++ b/bacula/src/lib/ilist.h @@ -0,0 +1,120 @@ +/* + Bacula(R) - The Network Backup Solution + + Copyright (C) 2000-2020 Kern Sibbald + + The original author of Bacula is Kern Sibbald, with contributions + from many others, a complete list can be found in the file AUTHORS. + + You may use this file and others of this release according to the + license defined in the LICENSE file, which includes the Affero General + Public License, v3.0 ("AGPLv3") and some additional permissions and + terms pursuant to its AGPLv3 Section 7. + + This notice must be preserved when any source code is + conveyed and/or propagated. + + Bacula(R) is a registered trademark of Kern Sibbald. +*/ + +#ifndef ILIST_H +#define ILIST_H + +extern bool is_null(const void *ptr); + +/* Second arg of init */ +enum { + owned_by_ilist = true, + not_owned_by_ilist = false +}; + +/* + * Array list -- much like a simplified STL vector + * array of pointers to inserted items. + */ +class ilist : public SMARTALLOC { +protected: + void **items; /* from 0..n-1 */ + int num_items; /* from 1..n */ + + int last_item; /* maximum item index (1..n). */ + + int max_items; /* maximum possible items (array size) (1..n) */ + int num_grow; + int cur_item; /* from 1..n */ + bool own_items; + void grow_list(void); + void *remove_item(int index); + +public: + ilist(int num = 100, bool own=true); + ~ilist(); + void init(int num = 100, bool own=true); + void append(void *item); + void *get(int index); + bool empty() const; + int last_index() const { return last_item; }; + int max_size() const { return max_items; }; + void * operator [](int index) const; + int size() const; + void destroy(); + void grow(int num); + + void put(int index, void *item); +}; + +inline bool ilist::empty() const +{ + return num_items == 0; +} + +/* + * This allows us to do explicit initialization, + * allowing us to mix C++ classes inside malloc'ed + * C structures. Define before called in constructor. + */ +inline void ilist::init(int num, bool own) +{ + items = NULL; + num_items = 0; + last_item = 0; + max_items = 0; + num_grow = num; + own_items = own; +} + +/* + * Define index operator [] + */ +inline void * ilist::operator [](int index) const { + if (index < 0 || index >= max_items) { + return NULL; + } + return items[index]; +} + +/* Constructor */ +inline ilist::ilist(int num, bool own) +{ + init(num, own); +} + +/* Destructor */ +inline ilist::~ilist() +{ + destroy(); +} + +/* Current size of list */ +inline int ilist::size() const +{ + return num_items; +} + +/* How much to grow by each time */ +inline void ilist::grow(int num) +{ + num_grow = num; +} + +#endif // ILIST_H diff --git a/bacula/src/lib/lib.h b/bacula/src/lib/lib.h index a5158bebb..ea5c020fa 100644 --- a/bacula/src/lib/lib.h +++ b/bacula/src/lib/lib.h @@ -27,6 +27,7 @@ #include "smartall.h" #include "lockmgr.h" +#include "ilist.h" #include "alist.h" #include "dlist.h" #include "flist.h"