ucx update

Tue, 16 Jul 2013 12:14:13 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 16 Jul 2013 12:14:13 +0200
changeset 88
73b3485e96f1
parent 87
bdec069d2239
child 89
5eecce5314d6

ucx update

src/server/config/acl.c file | annotate | diff | comparison | revisions
src/server/config/initconf.c file | annotate | diff | comparison | revisions
src/server/config/keyfile.c file | annotate | diff | comparison | revisions
src/server/config/mimeconf.c file | annotate | diff | comparison | revisions
src/server/config/objconf.c file | annotate | diff | comparison | revisions
src/server/config/serverconf.c file | annotate | diff | comparison | revisions
src/server/daemon/acldata.c file | annotate | diff | comparison | revisions
src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/daemon/configmanager.c file | annotate | diff | comparison | revisions
src/server/daemon/keyfile_auth.c file | annotate | diff | comparison | revisions
src/server/ucx/allocator.c file | annotate | diff | comparison | revisions
src/server/ucx/allocator.h file | annotate | diff | comparison | revisions
src/server/ucx/map.c file | annotate | diff | comparison | revisions
src/server/ucx/map.h file | annotate | diff | comparison | revisions
src/server/ucx/mempool.c file | annotate | diff | comparison | revisions
src/server/ucx/mempool.h file | annotate | diff | comparison | revisions
src/server/ucx/objs.mk file | annotate | diff | comparison | revisions
src/server/ucx/properties.c file | annotate | diff | comparison | revisions
src/server/ucx/properties.h file | annotate | diff | comparison | revisions
src/server/ucx/string.c file | annotate | diff | comparison | revisions
src/server/ucx/string.h file | annotate | diff | comparison | revisions
src/server/webdav/webdav.c file | annotate | diff | comparison | revisions
--- a/src/server/config/acl.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/config/acl.c	Tue Jul 16 12:14:13 2013 +0200
@@ -59,7 +59,7 @@
 }
 
 void free_acl_file(ACLFile *conf) {
-    ucx_mempool_free(conf->parser.mp);
+    ucx_mempool_destroy(conf->parser.mp);
     free(conf);
 }
 
--- a/src/server/config/initconf.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/config/initconf.c	Tue Jul 16 12:14:13 2013 +0200
@@ -55,7 +55,7 @@
 }
 
 void free_init_config(InitConfig *conf) {
-    ucx_mempool_free(conf->parser.mp);
+    ucx_mempool_destroy(conf->parser.mp);
     free(conf);
 }
 
--- a/src/server/config/keyfile.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/config/keyfile.c	Tue Jul 16 12:14:13 2013 +0200
@@ -58,7 +58,7 @@
     if(conf->users) {
         ucx_list_free(conf->users);
     }
-    ucx_mempool_free(conf->parser.mp);
+    ucx_mempool_destroy(conf->parser.mp);
     free(conf);
 }
 
--- a/src/server/config/mimeconf.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/config/mimeconf.c	Tue Jul 16 12:14:13 2013 +0200
@@ -61,7 +61,7 @@
 }
 
 void free_mime_config(MimeConfig *conf) {
-    ucx_mempool_free(conf->parser.mp);
+    ucx_mempool_destroy(conf->parser.mp);
     free(conf);
 }
 
--- a/src/server/config/objconf.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/config/objconf.c	Tue Jul 16 12:14:13 2013 +0200
@@ -70,7 +70,7 @@
     }
 
     // free mempool
-    ucx_mempool_free(conf->parser.mp);
+    ucx_mempool_destroy(conf->parser.mp);
     free(conf);
 }
 
--- a/src/server/config/serverconf.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/config/serverconf.c	Tue Jul 16 12:14:13 2013 +0200
@@ -57,7 +57,7 @@
 }
 
 void free_server_config(ServerConfig *conf) {
-    ucx_mempool_free(conf->parser.mp);
+    ucx_mempool_destroy(conf->parser.mp);
     free(conf);
 }
 
--- a/src/server/daemon/acldata.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/daemon/acldata.c	Tue Jul 16 12:14:13 2013 +0200
@@ -52,7 +52,7 @@
     if(ref == 0) {
         UcxMapIterator i = ucx_map_iterator(acldata->namedACLs);
         WSAcl *acl;
-        UCX_MAP_FOREACH(acl, i) {
+        UCX_MAP_FOREACH(key, acl, i) {
             free(acl->ace);
             free(acl->ece);
             if(acl->acl.authprompt) {
--- a/src/server/daemon/config.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/daemon/config.c	Tue Jul 16 12:14:13 2013 +0200
@@ -256,7 +256,7 @@
         //int b = 0;
         UcxMapIterator iter = ucx_map_iterator(serverconfig->host_vs);
         VirtualServer *vs;
-        UCX_MAP_FOREACH(vs, iter) {
+        UCX_MAP_FOREACH(key, vs, iter) {
             if(!sstrcmp(vsname, vs->name)) {
                 listener->default_vs.vs = vs;
                 break;
@@ -316,6 +316,7 @@
         f->data = NULL;
         f->file = sstrdup(file);
         f->reload = mime_conf_reload;
+        f->last_modified = 0;
         
         // load the file content
         //f->reload(f, cfg);
@@ -535,6 +536,7 @@
             f->data = NULL;
             f->file = sstrdup(file);
             f->reload = keyfile_reload;
+            f->last_modified = 0;
             //f->reload(f, cfg);
             if(cfgmgr_reload_file(f, cfg, NULL)) {
                 free(f->file.ptr);
@@ -617,6 +619,7 @@
         f->data = NULL;
         f->file = sstrdup(file);
         f->reload = object_conf_reload;
+        f->last_modified = 0;
         //f->reload(f, cfg);
         if(cfgmgr_reload_file(f, cfg, NULL)) {
             free(f->file.ptr);
@@ -640,6 +643,7 @@
         aclf->data = NULL;
         aclf->file = sstrdup(file);
         aclf->reload = acl_conf_reload;
+        aclf->last_modified = 0;
         //aclf->reload(aclf, cfg);
         if(cfgmgr_reload_file(aclf, cfg, NULL)) {
             free(aclf->file.ptr);
@@ -820,7 +824,7 @@
         printf("free MimeConfig %"PRIxPTR"\n", (intptr_t)conf);
         UcxMapIterator i = ucx_map_iterator(conf->map);
         char *str;
-        UCX_MAP_FOREACH(str, i) {
+        UCX_MAP_FOREACH(key, str, i) {
             free(str);
         }
         ucx_map_free(conf->map);
--- a/src/server/daemon/configmanager.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/daemon/configmanager.c	Tue Jul 16 12:14:13 2013 +0200
@@ -77,10 +77,12 @@
     if(f->last_modified != s.st_mtime) {
         /* reload the file */
         printf("reload: %s\n", f->file.ptr);
-        log_ereport(
-                LOG_INFORM,
-                "reload configuration file: %s",
-                f->file.ptr);
+        if(f->last_modified != 0) {
+            log_ereport(
+                    LOG_INFORM,
+                    "reload configuration file: %s",
+                    f->file.ptr);
+        }
         f->reload(f, conf);
         f->last_modified = s.st_mtime;
         if(reload) {
@@ -96,7 +98,7 @@
     /* check config files */  
     UcxMapIterator iter = ucx_map_iterator(config_files);
     ConfigFile *f;
-    UCX_MAP_FOREACH(f, iter) {
+    UCX_MAP_FOREACH(key, f, iter) {
         if(cfgmgr_reload_file(f, current_config, &cfgreload) == -1) {
             return -1;
         }
--- a/src/server/daemon/keyfile_auth.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/daemon/keyfile_auth.c	Tue Jul 16 12:14:13 2013 +0200
@@ -54,7 +54,7 @@
     if(ref == 0) { 
         UcxMapIterator i = ucx_map_iterator(keyfile->users);
         KeyfileUser *user;
-        UCX_MAP_FOREACH(user, i) {
+        UCX_MAP_FOREACH(key, user, i) {
             free(user->user.name);
             free(user->hash);
             for(int i=0;i<user->numgroups;i++) {
--- a/src/server/ucx/allocator.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/allocator.c	Tue Jul 16 12:14:13 2013 +0200
@@ -29,6 +29,19 @@
 #include <stdlib.h>
 #include "allocator.h"
 
+UcxAllocator default_allocator = {
+    NULL,
+    ucx_default_malloc,
+    ucx_default_calloc,
+    ucx_default_realloc,
+    ucx_default_free
+};
+
+UcxAllocator *ucx_default_allocator() {
+    UcxAllocator *allocator = &default_allocator;
+    return allocator;
+}
+
 void *ucx_default_malloc(void *ignore, size_t n) {
     return malloc(n);
 }
@@ -40,3 +53,7 @@
 void *ucx_default_realloc(void *ignore, void *data, size_t n) {
     return realloc(data, n);
 }
+
+void ucx_default_free(void *ignore, void *data) {
+    free(data);
+}
--- a/src/server/ucx/allocator.h	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/allocator.h	Tue Jul 16 12:14:13 2013 +0200
@@ -38,20 +38,26 @@
 typedef void*(*ucx_allocator_malloc)(void *pool, size_t n);
 typedef void*(*ucx_allocator_calloc)(void *pool, size_t n, size_t size);
 typedef void*(*ucx_allocator_realloc)(void *pool, void *data, size_t n);
+typedef void(*ucx_allocator_free)(void *pool, void *data);
 
 typedef struct {
     void *pool;
-    ucx_allocator_malloc malloc;
-    ucx_allocator_calloc calloc;
+    ucx_allocator_malloc  malloc;
+    ucx_allocator_calloc  calloc;
     ucx_allocator_realloc realloc;
+    ucx_allocator_free    free;
 } UcxAllocator;
 
+UcxAllocator *ucx_default_allocator();
+
 void *ucx_default_malloc(void *ignore, size_t n);
 void *ucx_default_calloc(void *ignore, size_t n, size_t size);
 void *ucx_default_realloc(void *ignore, void *data, size_t n);
+void ucx_default_free(void *ignore, void *data);
 
 #define UCX_ALLOCATOR_DEFAULT {NULL, \
-        ucx_default_malloc, ucx_default_calloc, ucx_default_realloc}
+        ucx_default_malloc, ucx_default_calloc, ucx_default_realloc, \
+        ucx_default_free }
 
 #ifdef	__cplusplus
 }
--- a/src/server/ucx/map.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/map.c	Tue Jul 16 12:14:13 2013 +0200
@@ -32,18 +32,30 @@
 #include "map.h"
 
 UcxMap *ucx_map_new(size_t size) {
+    return ucx_map_new_allocator(size, NULL);
+}
+
+UcxMap *ucx_map_new_allocator(size_t size, UcxAllocator *allocator) {
     if(size == 0) {
         size = 16;
     }
+       
+    if(!allocator) {
+        allocator = ucx_default_allocator();
+    }
     
-    UcxMap *map = (UcxMap*)malloc(sizeof(UcxMap));
+    UcxMap *map = (UcxMap*)allocator->malloc(allocator->pool, sizeof(UcxMap));
     if(map == NULL) {
         return NULL;
     }
-
-    map->map = (UcxMapElement**)calloc(size, sizeof(UcxMapElement*));
+    
+    map->allocator = allocator;
+    map->map = (UcxMapElement**)allocator->calloc(
+            allocator->pool,
+            size,
+            sizeof(UcxMapElement*));
     if(map->map == NULL) {
-        free(map);
+        allocator->free(allocator->pool, map);
         return NULL;
     }
     map->size = size;
@@ -58,25 +70,25 @@
         if (elem != NULL) {
             do {
                 UcxMapElement *next = elem->next;
-                free(elem->key.data);
-                free(elem);
+                map->allocator->free(map->allocator->pool, elem->key.data);
+                map->allocator->free(map->allocator->pool, elem);
                 elem = next;
             } while (elem != NULL);
         }
     }
-    free(map->map);
+    map->allocator->free(map->allocator->pool, map->map);
 }
 
 void ucx_map_free(UcxMap *map) {
     ucx_map_free_elmlist(map);
-    free(map);
+    map->allocator->free(map->allocator->pool, map);
 }
 
 int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to,
         copy_func fnc, void *data) {
     UcxMapIterator i = ucx_map_iterator(from);
     void *value;
-    UCX_MAP_FOREACH(value, i) {
+    UCX_MAP_FOREACH(key, value, i) {
         int ret = ucx_map_put(to, i.cur->key, fnc ? fnc(value, data) : value);
         if(ret != 0) {
             return 1;
@@ -102,9 +114,13 @@
         oldmap.map = map->map;
         oldmap.size = map->size;
         oldmap.count = map->count;
+        oldmap.allocator = map->allocator;
         
         map->size = (map->count * 5) >> 1;
-        map->map = (UcxMapElement**)calloc(map->size, sizeof(UcxMapElement*));
+        map->map = (UcxMapElement**)map->allocator->calloc(
+                map->allocator->pool,
+                map->size,
+                sizeof(UcxMapElement*));
         if(map->map == NULL) {
             *map = oldmap;
             return 1;
@@ -119,6 +135,8 @@
 }
 
 int ucx_map_put(UcxMap *map, UcxKey key, void *data) {
+    UcxAllocator *allocator = map->allocator;
+    
     if(key.hash == 0) {
         key.hash = ucx_hash((char*)key.data, key.len);
     }
@@ -133,7 +151,9 @@
     }
     
     if (elm == NULL || elm->key.hash != key.hash) {
-        UcxMapElement *e = (UcxMapElement*)malloc(sizeof(UcxMapElement));
+        UcxMapElement *e = (UcxMapElement*)allocator->malloc(
+                allocator->pool,
+                sizeof(UcxMapElement));
         if(e == NULL) {
             return -1;
         }
@@ -148,7 +168,7 @@
     }
     
     if(elm->key.data == NULL) {
-        void *kd = malloc(key.len);
+        void *kd = allocator->malloc(allocator->pool, key.len);
         if (kd == NULL) {
             return -1;
         }
@@ -181,7 +201,7 @@
                     } else {
                         map->map[slot] = elm->next;
                     }
-                    free(elm);
+                    map->allocator->free(map->allocator->pool, elm);
                     map->count--;
                 }
 
@@ -262,7 +282,7 @@
     return i;
 }
 
-int ucx_map_iter_next(UcxMapIterator *i, void **elm) {
+int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm) {
     UcxMapElement *e = i->cur;
     
     if(e == NULL) {
@@ -276,6 +296,7 @@
             if(e->data != NULL) {
                 i->cur = e;
                 *elm = e->data;
+                *key = e->key;
                 return 0;
             }
 
@@ -292,123 +313,3 @@
     return 1;
 }
 
-int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator,
-        ucx_map_coder decoder, void* decdata) {
-
-    int c; int r, n;
-
-    char *key, *value;
-
-    while ((c = fgetc(f)) > 0) {
-        /* Discard leading spaces and comments */
-        if (c < 33) continue;
-        if (c == '#' || c == '!') {
-            while ((c = (char) fgetc(f)) > 0) {
-                if (c == '\n') break;
-            }
-            continue;
-        }
-
-        /* read into key buffer */
-        n = 16;
-        key = (char*) malloc(n);
-        r = 0;
-        do {
-            if (c == '=') break;
-            if (r > n - 2) {
-                n *= 2;
-                key = (char*) realloc(key, n);
-            }
-            key[r] = c;
-            r++;
-        } while ((c = fgetc(f)) > 0);
-        if (c <= 0) {
-            free(key);
-            return 1;
-        }
-        key[r] = 0;
-        while (key[--r] == ' ') key[r] = 0;
-
-        /* skip whitespaces */
-        while ((c = fgetc(f)) > 0) {
-            if (c > 32) break;
-        }
-        if (c <= 0) {
-            free(key);
-            return 1;
-        }
-
-        /* read into value buffer */
-        n = 64;
-        value = (char*) malloc(n);
-        r = 0;
-        do {
-            if (c == '\n') break;
-            if (r > n - 2) {
-                n *= 2;
-                value = (char*) realloc(value, n);
-            }
-            value[r] = c;
-            r++;
-        } while ((c = fgetc(f)) > 0);
-        value[r] = 0;
-        while (value[--r] < 33) value[r] = 0;
-
-        if (decoder) {
-            size_t decodedSize;
-            void *decoded = decoder(value, decdata, &decodedSize);
-            free(value);
-            value = (char*) decoded;
-            r = decodedSize;
-        } else {
-            r += 2;
-            value = (char*) realloc(value, r);
-        }
-
-        if (allocator.pool) {
-            void *pooledValue = allocator.malloc(allocator.pool, r);
-            memcpy(pooledValue, value, r);
-            free(value);
-            value = (char*) pooledValue;
-        }
-
-        ucx_map_cstr_put(map, key, value);
-        free(key);
-    }
-
-    return 0;
-}
-
-int ucx_map_store_enc(UcxMap *map, FILE *f,
-        ucx_map_coder encoder, void *encdata) {
-    UcxMapIterator iter = ucx_map_iterator(map);
-    char *k, *v;
-    sstr_t key, value;
-    size_t written;
-
-    UCX_MAP_FOREACH(v, iter) {
-        k = (char*) iter.cur->key.data;
-        key = sstrn(k, iter.cur->key.len);
-        if (encoder) {
-            size_t encodedSize;
-            void *encoded = encoder(v, encdata, &encodedSize);
-            value = sstrn((char*) encoded,encodedSize - 1);
-        } else {
-            value = sstr(v);
-        }
-
-        written = 0;
-        written += fwrite(key.ptr, 1, key.length, f);
-        written += fwrite(" = ", 1, 3, f);
-        written += fwrite(value.ptr, 1, value.length, f);
-        written += fwrite("\n", 1, 1, f);
-
-        if (encoder) {
-            free(value.ptr);
-        }
-
-        if (written != key.length + value.length + 4) return 1;
-    }
-
-    return 0;
-}
--- a/src/server/ucx/map.h	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/map.h	Tue Jul 16 12:14:13 2013 +0200
@@ -38,8 +38,8 @@
 extern "C" {
 #endif
 
-#define UCX_MAP_FOREACH(elm,iter) \
-        for(;ucx_map_iter_next(&iter,(void**)&elm)==0;)
+#define UCX_MAP_FOREACH(key,elm,iter) \
+        for(UcxKey key;ucx_map_iter_next(&iter,&key, (void**)&elm)==0;)
 
 typedef struct UcxMap          UcxMap;
 typedef struct UcxKey          UcxKey;
@@ -55,6 +55,7 @@
 typedef void*(*ucx_map_coder)(void*,void*,size_t*);
 
 struct UcxMap {
+    UcxAllocator  *allocator;
     UcxMapElement **map;
     size_t        size;
     size_t        count;
@@ -80,6 +81,7 @@
 
 
 UcxMap *ucx_map_new(size_t size);
+UcxMap *ucx_map_new_allocator(size_t size, UcxAllocator *allocator);
 void ucx_map_free(UcxMap *map);
 /* you cannot clone maps with more than 390 mio entries */
 int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to,
@@ -92,11 +94,11 @@
 void* ucx_map_remove(UcxMap *map, UcxKey key);
 
 #define ucx_map_sstr_put(m, s, d) \
-    ucx_map_put(m, ucx_key(s.ptr, s.length), d)
+    ucx_map_put(m, ucx_key(s.ptr, s.length), (void*)d)
 #define ucx_map_cstr_put(m, s, d) \
-    ucx_map_put(m, ucx_key((void*)s, strlen(s)), d)
+    ucx_map_put(m, ucx_key((void*)s, strlen(s)), (void*)d)
 #define ucx_map_int_put(m, i, d) \
-    ucx_map_put(m, ucx_key((void*)&i, sizeof(i)), d)
+    ucx_map_put(m, ucx_key((void*)&i, sizeof(i)), (void*)d)
 
 #define ucx_map_sstr_get(m, s) \
     ucx_map_get(m, ucx_key(s.ptr, s.length))
@@ -118,17 +120,8 @@
 
 UcxMapIterator ucx_map_iterator(UcxMap *map);
 
-int ucx_map_iter_next(UcxMapIterator *i, void **elm);
-
-/* use macros for string maps only, values are not encoded */
-#define ucx_map_load(map, f, alloc) ucx_map_load_enc(map, f, alloc, NULL, NULL)
-#define ucx_map_store(map, f) ucx_map_store_enc(map, f, NULL, NULL)
+int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm);
 
-int ucx_map_load_enc(UcxMap *map, FILE *f, UcxAllocator allocator,
-        ucx_map_coder decoder, void* decdata);
-/* encoders shall provide null terminated strings*/
-int ucx_map_store_enc(UcxMap *map, FILE *f,
-        ucx_map_coder encoder, void* encdata);
 
 #ifdef	__cplusplus
 }
--- a/src/server/ucx/mempool.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/mempool.c	Tue Jul 16 12:14:13 2013 +0200
@@ -112,7 +112,7 @@
                 return newm + sizeof(ucx_destructor);
             }
         }
-        fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
+        fprintf(stderr, "FATAL: 0x%08"PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
           (intptr_t)ptr, (intptr_t)pool);
         exit(1);
     } else {
@@ -120,14 +120,37 @@
     }
 }
 
-void ucx_mempool_free(UcxMempool *pool) {
+void ucx_mempool_free(UcxMempool *pool, void *ptr) {
+    ucx_memchunk *chunk = (ucx_memchunk*)((char*)ptr-sizeof(ucx_destructor));
+    for(size_t i=0 ; i<pool->ndata ; i++) {
+        if(chunk == pool->data[i]) {
+            if(chunk->destructor != NULL) {
+                chunk->destructor(&chunk->c);
+            }
+            free(chunk);
+            size_t last_index = pool->ndata - 1;
+            if(i != last_index) {
+                pool->data[i] = pool->data[last_index];
+            }
+            pool->ndata--;
+            return;
+        }
+    }
+    fprintf(stderr, "FATAL: 0x%08"PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
+            (intptr_t)ptr, (intptr_t)pool);
+    exit(1);
+}
+
+void ucx_mempool_destroy(UcxMempool *pool) {
     ucx_memchunk *chunk;
     for(size_t i=0 ; i<pool->ndata ; i++) {
         chunk = (ucx_memchunk*) pool->data[i];
-        if(chunk->destructor != NULL) {
-            chunk->destructor(&chunk->c);
+        if(chunk) {
+            if(chunk->destructor != NULL) {
+                chunk->destructor(&chunk->c);
+            }
+            free(chunk);
         }
-        free(chunk);
     }
     free(pool->data);
     free(pool);
@@ -145,3 +168,17 @@
     rd->ptr = ptr;
     ucx_mempool_set_destr(rd, ucx_mempool_shared_destr);
 }
+
+UcxAllocator* ucx_mempool_allocator(UcxMempool *pool) {
+    UcxAllocator *allocator = (UcxAllocator*)ucx_mempool_malloc(
+            pool, sizeof(UcxAllocator));
+    if(!allocator) {
+        return NULL;
+    }
+    allocator->malloc = (ucx_allocator_malloc)ucx_mempool_malloc;
+    allocator->calloc = (ucx_allocator_calloc)ucx_mempool_calloc;
+    allocator->realloc = (ucx_allocator_realloc)ucx_mempool_realloc;
+    allocator->free = (ucx_allocator_free)ucx_mempool_free;
+    allocator->pool = pool;
+    return allocator;
+}
--- a/src/server/ucx/mempool.h	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/mempool.h	Tue Jul 16 12:14:13 2013 +0200
@@ -45,10 +45,6 @@
     size_t size;
 } UcxMempool;
 
-#define UCX_ALLOCATOR_MEMPOOL(pool) {pool, \
-    (ucx_allocator_malloc) ucx_mempool_malloc, \
-    (ucx_allocator_calloc) ucx_mempool_calloc, \
-    (ucx_allocator_realloc) ucx_mempool_realloc}
 
 #define ucx_mempool_new_default() ucx_mempool_new(16)
 UcxMempool *ucx_mempool_new(size_t n);
@@ -57,12 +53,14 @@
 void *ucx_mempool_malloc(UcxMempool *pool, size_t n);
 void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize);
 void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n);
+void ucx_mempool_free(UcxMempool *pool, void *ptr);
 
-void ucx_mempool_free(UcxMempool *pool);
+void ucx_mempool_destroy(UcxMempool *pool);
 
 void ucx_mempool_set_destr(void *ptr, ucx_destructor func);
 void ucx_mempool_reg_destr(UcxMempool *pool, void *ptr, ucx_destructor destr);
 
+UcxAllocator* ucx_mempool_allocator(UcxMempool *pool);
 
 #ifdef	__cplusplus
 }
--- a/src/server/ucx/objs.mk	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/objs.mk	Tue Jul 16 12:14:13 2013 +0200
@@ -38,6 +38,9 @@
 UCXOBJ += allocator.o
 UCXOBJ += utils.o
 UCXOBJ += buffer.o
+UCXOBJ += test.o
+UCXOBJ += properties.o
+UCXOBJ += logging.o
 
 UCXOBJS = $(UCXOBJ:%=$(UCX_OBJPRE)%)
 UCXSOURCE = $(UCXOBJ:%.o=ucx/%.c)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/properties.c	Tue Jul 16 12:14:13 2013 +0200
@@ -0,0 +1,265 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "properties.h"
+
+UcxProperties *ucx_properties_new() {
+    UcxProperties *parser = (UcxProperties*)malloc(
+            sizeof(UcxProperties));
+    if(!parser) {
+        return NULL;
+    }
+    
+    parser->buffer = NULL;
+    parser->buflen = 0;
+    parser->pos = 0;
+    parser->tmp = NULL;
+    parser->tmplen = 0;
+    parser->tmpcap = 0;
+    parser->error = 0;
+    parser->delimiter = '=';
+    parser->comment1 = '#';
+    parser->comment2 = 0;
+    parser->comment3 = 0;   
+    
+    return parser;
+}
+
+void ucx_properties_free(UcxProperties *parser) {
+    if(parser->tmp) {
+        free(parser->tmp);
+    }
+    free(parser);
+}
+
+void ucx_properties_fill(UcxProperties *parser, char *buf, size_t len) {
+    parser->buffer = buf;
+    parser->buflen = len;
+    parser->pos = 0;
+}
+
+static void parser_tmp_append(UcxProperties *parser, char *buf, size_t len) {
+    if(parser->tmpcap - parser->tmplen < len) {
+        size_t newcap = parser->tmpcap + len + 64;
+        parser->tmp = (char*)realloc(parser->tmp, newcap);
+        parser->tmpcap = newcap;
+    }
+    memcpy(parser->tmp + parser->tmplen, buf, len);
+    parser->tmplen += len;
+}
+
+int ucx_properties_next(UcxProperties *parser, sstr_t *name, sstr_t *value)  {   
+    if(parser->tmplen > 0) {
+        char *buf = parser->buffer + parser->pos;
+        size_t len = parser->buflen - parser->pos;
+        sstr_t str = sstrn(buf, len);
+        sstr_t nl = sstrchr(str, '\n');
+        if(nl.ptr) {
+            size_t newlen = (size_t)(nl.ptr - buf) + 1;
+            parser_tmp_append(parser, buf, newlen);
+            // the tmp buffer contains exactly one line now
+            
+            char *orig_buf = parser->buffer;
+            size_t orig_len = parser->buflen;
+            
+            parser->buffer = parser->tmp;
+            parser->buflen = parser->tmplen;
+            parser->pos = 0;    
+            parser->tmp = NULL;
+            parser->tmpcap = 0;
+            parser->tmplen = 0;
+            // run ucx_properties_next with the tmp buffer as main buffer
+            int ret = ucx_properties_next(parser, name, value);
+            
+            // restore original buffer
+            parser->tmp = parser->buffer;
+            parser->buffer = orig_buf;
+            parser->buflen = orig_len;
+            parser->pos = newlen;
+            
+            /*
+             * if ret == 0 the tmp buffer contained just space or a comment
+             * we parse again with the original buffer to get a name/value
+             * or a new tmp buffer
+             */
+            return ret ? ret : ucx_properties_next(parser, name, value);
+        } else {
+            parser_tmp_append(parser, buf, len);
+            return 0;
+        }
+    } else if(parser->tmp) {
+        free(parser->tmp);
+        parser->tmp = NULL;
+    }
+    
+    char comment1 = parser->comment1;
+    char comment2 = parser->comment2;
+    char comment3 = parser->comment3;
+    char delimiter = parser->delimiter;
+    
+    // get one line and parse it
+    while(parser->pos < parser->buflen) {
+        char *buf = parser->buffer + parser->pos;
+        size_t len = parser->buflen - parser->pos;
+        
+        /*
+         * First we check if we have at least one line. We also get indices of
+         * delimiter and comment chars
+         */
+        size_t delimiter_index = 0;
+        size_t comment_index = 0;
+        int has_comment = 0;
+
+        size_t i = 0;
+        char c = 0;
+        for(;i<len;i++) {
+            c = buf[i];
+            if(c == comment1 || c == comment2 || c == comment3) {
+                if(comment_index == 0) {
+                    comment_index = i;
+                    has_comment = 1;
+                }
+            } else if(c == delimiter) {
+                if(delimiter_index == 0 && !has_comment) {
+                    delimiter_index = i;
+                }
+            } else if(c == '\n') {
+                break;
+            }
+        }
+
+        if(c != '\n') {
+            // we don't have enough data for a line
+            // store remaining bytes in temporary buffer for next round
+            parser->tmpcap = len + 128;
+            parser->tmp = (char*)malloc(parser->tmpcap);
+            parser->tmplen = len;
+            memcpy(parser->tmp, buf, len);
+            return 0;
+        }
+        
+        sstr_t line = has_comment ? sstrn(buf, comment_index) : sstrn(buf, i);
+        // check line
+        if(delimiter_index == 0) {
+            line = sstrtrim(line);
+            if(line.length != 0) {
+                parser->error = 1;
+            }
+        } else {
+            sstr_t n = sstrn(buf, delimiter_index);
+            sstr_t v = sstrn(buf+delimiter_index+1, i-delimiter_index-1); 
+            n = sstrtrim(n);
+            v = sstrtrim(v);
+            if(n.length != 0 || v.length != 0) {
+                *name = n;
+                *value = v;
+                parser->pos += i + 1;
+                return 1;
+            } else {
+                parser->error = 1;
+            }
+        }
+        
+        parser->pos += i + 1;
+    }
+    
+    return 0;
+}
+
+int ucx_properties2map(UcxProperties *parser, UcxMap *map) {
+    sstr_t name;
+    sstr_t value;
+    while(ucx_properties_next(parser, &name, &value)) {
+        name = sstrdup_alloc(map->allocator, name);
+        if(!name.ptr) {
+            return 1;
+        }
+        value = sstrdup_alloc(map->allocator, value);
+        if(!value.ptr) {
+            map->allocator->free(map->allocator->pool, value.ptr);
+            return 1;
+        }
+        if(ucx_map_sstr_put(map, name, value.ptr)) {
+            map->allocator->free(map->allocator->pool, name.ptr);
+            map->allocator->free(map->allocator->pool, value.ptr);
+            return 1;
+        }
+    }
+    if(parser->error) {
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+int ucx_properties_load(UcxMap *map, FILE *file) {
+    UcxProperties *parser = ucx_properties_new();
+    if(!parser || !map || !file) {
+        return 1;
+    }
+    
+    int error = 0;
+    size_t r;
+    char buf[1024];
+    while((r = fread(buf, 1, 1024, file)) != 0) {
+        ucx_properties_fill(parser, buf, r);
+        if(ucx_properties2map(parser, map)) {
+            error = 1;
+            break;
+        }
+    }
+    
+    ucx_properties_free(parser);
+    return error;
+}
+
+int ucx_properties_store(UcxMap *map, FILE *file) {
+    UcxMapIterator iter = ucx_map_iterator(map);
+    char *v;
+    sstr_t value;
+    size_t written;
+
+    UCX_MAP_FOREACH(k, v, iter) {
+        value = sstr(v);
+
+        written = 0;
+        written += fwrite(k.data, 1, k.len, file);
+        written += fwrite(" = ", 1, 3, file);
+        written += fwrite(value.ptr, 1, value.length, file);
+        written += fwrite("\n", 1, 1, file);
+
+        if (written != k.len + value.length + 4) return 1;
+    }
+
+    return 0;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ucx/properties.h	Tue Jul 16 12:14:13 2013 +0200
@@ -0,0 +1,68 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PROPERTIES_H
+#define	PROPERTIES_H
+
+#include "ucx.h"
+#include "map.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    char   *buffer;
+    size_t buflen;
+    size_t pos;
+    char   *tmp;
+    size_t tmplen;
+    size_t tmpcap;
+    int    error;
+    char   delimiter;
+    char   comment1;
+    char   comment2;
+    char   comment3;
+} UcxProperties;
+
+
+UcxProperties *ucx_properties_new();
+void ucx_properties_free(UcxProperties *parser);
+void ucx_properties_fill(UcxProperties *parser, char *buf, size_t len);
+int ucx_properties_next(UcxProperties *parser, sstr_t *name, sstr_t *value);
+int ucx_properties2map(UcxProperties *parser, UcxMap *map);
+
+int ucx_properties_load(UcxMap *map, FILE *file);
+int ucx_properties_store(UcxMap *map, FILE *file);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* PROPERTIES_H */
+
--- a/src/server/ucx/string.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/string.c	Tue Jul 16 12:14:13 2013 +0200
@@ -31,6 +31,7 @@
 #include <stdarg.h>
 
 #include "string.h"
+#include "allocator.h"
 
 sstr_t sstr(char *s) {
     sstr_t string;
@@ -106,6 +107,18 @@
     return new_sstr;
 }
 
+sstr_t sstrchr(sstr_t s, int c) {
+    for(size_t i=0;i<s.length;i++) {
+        if(s.ptr[i] == c) {
+            return sstrsubs(s, i);
+        }
+    }
+    sstr_t n;
+    n.ptr = NULL;
+    n.length = 0;
+    return n;
+}
+
 sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n) {
     if (d.length == 0) {
         return NULL;
@@ -168,16 +181,30 @@
 sstr_t sstrdup(sstr_t s) {
     sstr_t newstring;
     newstring.ptr = (char*) malloc(s.length + 1);
-    newstring.length = 0;
     if (newstring.ptr) {
         newstring.length = s.length;
         newstring.ptr[newstring.length] = 0;
-
+        
         memcpy(newstring.ptr, s.ptr, s.length);
     } else {
         newstring.length = 0;
     }
+    
+    return newstring;
+}
 
+sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s) {
+    sstr_t newstring;
+    newstring.ptr = (char*)allocator->malloc(allocator->pool, s.length + 1);
+    if (newstring.ptr) {
+        newstring.length = s.length;
+        newstring.ptr[newstring.length] = 0;
+        
+        memcpy(newstring.ptr, s.ptr, s.length);
+    } else {
+        newstring.length = 0;
+    }
+    
     return newstring;
 }
 
@@ -218,7 +245,6 @@
     return newstr;
 }
 
-
 // webserver extension
 
 int sstr_startswith(sstr_t string, sstr_t cmp) {
--- a/src/server/ucx/string.h	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/ucx/string.h	Tue Jul 16 12:14:13 2013 +0200
@@ -30,6 +30,7 @@
 #define	_SSTRING_H
 
 #include "ucx.h"
+#include "allocator.h"
 #include "mempool.h"
 #include "../public/nsapi.h"
 #include <stddef.h>
@@ -94,6 +95,11 @@
 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length);
 
 /*
+ * 
+ */
+sstr_t sstrchr(sstr_t s, int c);
+
+/*
  * splits s into n parts
  *
  * s    the string to split
@@ -114,13 +120,14 @@
 int sstrcmp(sstr_t s1, sstr_t s2);
 
 sstr_t sstrdup(sstr_t s);
+sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s);
 
 sstr_t sstrtrim(sstr_t string);
 
 // webserver extension
 int sstr_startswith(sstr_t string, sstr_t cmp);
 sstr_t sstrdup_mp(UcxMempool *pool, sstr_t s);
-sstr_t sstrdup_pool(pool_handle_t *pool, sstr_t s);
+sstr_t sstrdup_pool(pool_handle_t *pool, sstr_t s); 
 
 #ifdef	__cplusplus
 }
--- a/src/server/webdav/webdav.c	Thu Jul 11 14:21:23 2013 +0200
+++ b/src/server/webdav/webdav.c	Tue Jul 16 12:14:13 2013 +0200
@@ -316,7 +316,7 @@
     sbuf_puts(out, "<D:multistatus");
     UcxMapIterator nsiter = ucx_map_iterator(davrq->nsmap->map);
     XmlNs *ns;
-    UCX_MAP_FOREACH(ns, nsiter) {
+    UCX_MAP_FOREACH(key, ns, nsiter) {
         sbuf_puts(out, " xmlns:");
         sbuf_puts(out, ns->prefix);
         sbuf_puts(out, "=\"");
@@ -422,7 +422,7 @@
     sbuf_puts(davrq->out, "<D:multistatus");
     UcxMapIterator nsiter = ucx_map_iterator(davrq->nsmap->map);
     XmlNs *ns;
-    UCX_MAP_FOREACH(ns, nsiter) {
+    UCX_MAP_FOREACH(key, ns, nsiter) {
         sbuf_puts(davrq->out, " xmlns:");
         sbuf_puts(davrq->out, ns->prefix);
         sbuf_puts(davrq->out, "=\"");
@@ -791,7 +791,7 @@
     
     UcxMapIterator iter = ucx_map_iterator(propstat->map);
     UcxDlist *proplist;
-    UCX_MAP_FOREACH(proplist, iter) { 
+    UCX_MAP_FOREACH(key, proplist, iter) { 
         if(proplist) {
             sbuf_puts(out, "<D:propstat>\n<D:prop>\n");
             

mercurial