diff -r de23f8881e9f -r 1fb26aca5093 libidav/session.c --- a/libidav/session.c Mon Mar 14 11:54:55 2016 +0100 +++ b/libidav/session.c Mon Mar 14 17:18:33 2016 +0100 @@ -65,6 +65,12 @@ } sn->handle = curl_easy_init(); curl_easy_setopt(sn->handle, CURLOPT_FOLLOWLOCATION, 1L); + + // create lock manager + DavLockManager *locks = ucx_mempool_malloc(sn->mp, sizeof(DavLockManager)); + locks->resource_locks = ucx_map_new_a(sn->mp->allocator, 16); + locks->collection_locks = NULL; + sn->locks = locks; // set proxy DavProxy *proxy = sstrprefix(url, S("https")) ? context->https_proxy @@ -359,3 +365,126 @@ ucx_map_sstr_put(sn->pathcache, path, href.ptr); } } + + +DavLock* dav_create_lock(DavSession *sn, char *token, char *timeout) { + DavLock *lock = dav_session_malloc(sn, sizeof(DavLock)); + lock->path = NULL; + lock->token = dav_session_strdup(sn, token); + + // TODO: timeout + + return lock; +} + +void dav_destroy_lock(DavSession *sn, DavLock *lock) { + dav_session_free(sn, lock->token); + if(lock->path) { + dav_session_free(sn, lock->path); + } + dav_session_free(sn, lock); +} + +int dav_add_resource_lock(DavSession *sn, char *path, DavLock *lock) { + DavLockManager *locks = sn->locks; + if(ucx_map_cstr_get(locks->resource_locks, path)) { + return -1; + } + + ucx_map_cstr_put(locks->resource_locks, path, lock); + return 0; +} + +static void insert_lock(DavSession *sn, UcxList *elm, UcxList *newelm) { + UcxList *next = elm->next; + if(next) { + next->prev = newelm; + newelm->next = next; + } + newelm->prev = elm; + elm->next = newelm; +} + +int dav_add_collection_lock(DavSession *sn, char *path, DavLock *lock) { + DavLockManager *locks = sn->locks; + if(!locks->collection_locks) { + locks->collection_locks = ucx_list_append_a( + sn->mp->allocator, + NULL, + lock); + lock->path = dav_session_strdup(sn, path); + return 0; + } + + UcxList *elm = locks->collection_locks; + for(;;) { + DavLock *l = elm->data; + int cmp = strcmp(path, l->path); + if(cmp > 0) { + UcxList *newelm = ucx_list_append_a(sn->mp->allocator, NULL, lock); + lock->path = dav_session_strdup(sn, path); + insert_lock(sn, elm, newelm); + } else if(cmp == 0) { + return -1; + } + + if(elm->next) { + elm = elm->next; + } else { + UcxList *newelm = ucx_list_append_a(sn->mp->allocator, NULL, lock); + lock->path = dav_session_strdup(sn, path); + ucx_list_concat(elm, newelm); + break; + } + } + + return 0; +} + +DavLock* dav_get_lock(DavSession *sn, char *path) { + DavLockManager *locks = sn->locks; + + DavLock *lock = ucx_map_cstr_get(locks->resource_locks, path); + if(lock) { + return lock; + } + + sstr_t p = sstr(path); + UCX_FOREACH(elm, locks->collection_locks) { + DavLock *cl = elm->data; + int cmd = strcmp(path, cl->path); + if(cmd == 0) { + return cl; + } else if(sstrprefix(p, sstr(cl->path))) { + return cl; + } else if(cmd > 0) { + break; + } + } + + return NULL; +} + +void dav_remove_lock(DavSession *sn, char *path, DavLock *lock) { + DavLockManager *locks = sn->locks; + + if(ucx_map_cstr_remove(locks->resource_locks, path)) { + return; + } + + UcxList *rm = NULL; + UCX_FOREACH(elm, locks->collection_locks) { + DavLock *cl = elm->data; + if(cl == lock) { + rm = elm; + break; + } + } + + if(rm) { + locks->collection_locks = ucx_list_remove_a( + sn->mp->allocator, + locks->collection_locks, + rm); + } +}