diff --git a/TODO b/TODO index 21d3fd5..990bb26 100644 --- a/TODO +++ b/TODO @@ -27,3 +27,51 @@ VERY BIG TODO: * also concurrent connection don't seem to make a problem. * keep-alive alone again don't seem to be a problem... !!!! if both are active something is screwed up.... !!!! + +- at least some of the problems result in something that I think + is a bug in the glibc implementation of tdelete. + + Under some circumstances tdelete does not search the whole tree. + Here comes some debug output of the code... + + This shows a code fragment that tries to remove a no longer + needed asset from the asset_pool. + + DEBUG: pool release asset --./assets/image/waldschrat.jpg-- + + Twalk over all elements in the tree: + + DEBUG: ./assets/image/waldschrat.jpg(1910357807899405601) => 0xe378a8 + DEBUG: ./assets/js/jquery.js(10519512221325982142) => 0x10d3638 + + Output of each call to tDelete comparison function: + (Notice that the searched asset hash was in the previous Twalk. + + DEBUG: search asset hash: 1910357807899405601 + DEBUG: found: 10519512221325982142, key: ./assets/js/jquery.js + DEBUG: !!!!! NOT FOUND !!!!!!! + DEBUG: find results in (nil) + + Repeated 2 times if non was found... + + DEBUG: search asset hash: 1910357807899405601 + DEBUG: found: 10519512221325982142, key: ./assets/js/jquery.js + DEBUG: !!!!! NOT FOUND !!!!!!! + DEBUG: find results in (nil) + DEBUG: search asset hash: 1910357807899405601 + DEBUG: found: 10519512221325982142, key: ./assets/js/jquery.js + DEBUG: !!!!! NOT FOUND !!!!!!! + DEBUG: find results in (nil) + === + + Again a twalk over all elements... + + DEBUG: ./assets/image/waldschrat.jpg(1910357807899405601) => 0xe378a8 + DEBUG: ./assets/js/jquery.js(10519512221325982142) => 0x10d3638 + + Final statement... + + DEBUG delete 0xe378a8, parent was (nil) + + So, it looks like I should build my own tree implementation... + well in fact it seems that I have to! diff --git a/include/http/response.h b/include/http/response.h index ea89240..b2e56ba 100644 --- a/include/http/response.h +++ b/include/http/response.h @@ -51,7 +51,7 @@ HttpResponse httpResponseMe(); HttpResponse httpResponseLoginForm(); HttpResponse httpResponseRandval(time_t, int); HttpResponse httpResponseSession(Session); -HttpResponse httpResponseAsset(Asset); +HttpResponse httpResponseAsset(const char *, size_t); #endif // __HTTP_RESPONSE_H__ diff --git a/src/asset/asset.c b/src/asset/asset.c index 2f9628f..2aacc41 100644 --- a/src/asset/asset.c +++ b/src/asset/asset.c @@ -20,6 +20,10 @@ * along with this program. If not, see . */ +// for debug +#include + + #include // for mmap @@ -97,9 +101,13 @@ assetCtor(void * _this, va_list * params) NULL, this->size, PROT_READ, MAP_PRIVATE, this->handle, 0); if (MAP_FAILED == this->data) { + close(this->handle); return -1; } + printf("DEBUG file mapped from %p to %p\n", + this->data, this->data + this->size); + this->ref_count = 1; return 0; @@ -112,7 +120,7 @@ static void assetDtor(void * _this) { munmap(this->data, this->size); } - if (0 != this->handle) { + if (0 < this->handle) { close(this->handle); } } diff --git a/src/asset/pool.c b/src/asset/pool.c index 364993c..1c07e20 100644 --- a/src/asset/pool.c +++ b/src/asset/pool.c @@ -20,6 +20,9 @@ * along with this program. If not, see . */ +// for debugging +#include + // for size_t #include @@ -44,6 +47,8 @@ assetPoolGet(const char * path, size_t npath) { Asset asset = NULL; + printf("DEBUG: pool get asset --%s--\n", path); + if (NULL == asset_pool) { asset_pool = new(Hash); } else { @@ -52,9 +57,12 @@ assetPoolGet(const char * path, size_t npath) if (NULL == asset) { asset = new(Asset, path, npath); + printf("DEBUG create asset %p\n", asset); hashAdd(asset_pool, asset); } else { + printf("DEBUG found asset %p\n", asset); asset->ref_count++; + printf("DEBUG increase ref_count to %zu\n", asset->ref_count); } return asset; @@ -63,19 +71,22 @@ assetPoolGet(const char * path, size_t npath) size_t assetPoolRelease(Asset asset) { - if (asset->ref_count <= 1) { - hashDelete( asset_pool, asset->fname, asset->nfname); + printf("DEBUG: pool release asset --%s--\n", asset->fname); - if (NULL != asset) { - delete(asset); - } - - return 0; - } else { + if (asset->ref_count > 1) { asset->ref_count--; - + printf("DEBUG decrease ref_count to %zu\n", asset->ref_count); return asset->ref_count; } + + if (NULL != asset) { + Asset found = (Asset)hashDelete( + asset_pool, asset->fname, asset->nfname); + printf("DEBUG delete %p, parent was %p\n", asset, found); + delete(asset); + } + + return 0; } void diff --git a/src/hash/delete.c b/src/hash/delete.c index a14c70c..cadcf31 100644 --- a/src/hash/delete.c +++ b/src/hash/delete.c @@ -20,9 +20,12 @@ * along with this program. If not, see . */ +#include + #include #include +#include "asset.h" #include "hash.h" #include "utils/hash.h" @@ -31,25 +34,61 @@ inline int hashDeleteComp(const void * a, const void * b) { + if (_Asset == GET_CLASS(b)) { + Asset data = (Asset)b; + printf("DEBUG: search asset hash: %lu\n", + *(const unsigned long*)a); + printf("DEBUG: found: %lu, key: %s\n", + data->hash, data->fname); + } + return hashableGetHash((void*)b) - *(const unsigned long*)a; } +void +action(const void *nodep, const VISIT which, const int depth) +{ + void * datap = *(void **)nodep; + + if (_Asset == GET_CLASS(datap)) { + Asset data = (Asset)datap; + + switch (which) { + case preorder: + break; + case postorder: + printf("DEBUG: %s(%lu) => %p\n", data->fname, data->hash, data); + break; + case endorder: + break; + case leaf: + printf("DEBUG: %s(%lu) => %p\n", data->fname, data->hash, data); + break; + } + } +} + void * hashDelete(Hash this, const char * search, size_t nsearch) { unsigned long hash = sdbm((const unsigned char *)search, nsearch); - void ** _found = tfind(&hash, &(this->root), hashDeleteComp); - void * found; + void * found = NULL; + int count = 0; - if (NULL != _found) { - found = *_found; - } else { - found = NULL; + twalk(this->root, action); + while (found == NULL && count < 3) { + found = tdelete(&hash, &(this->root), hashDeleteComp); + if (found == NULL) { + puts("DEBUG: !!!!! NOT FOUND !!!!!!!"); + void * found = hashGet(this, search, nsearch); + printf("DEBUG: find results in %p\n", found); + } + count++; } + puts("==="); + twalk(this->root, action); - tdelete(&hash, &(this->root), hashDeleteComp); - - return (NULL != found)? found : NULL; + return found; } // vim: set ts=4 sw=4: diff --git a/src/hash/get.c b/src/hash/get.c index 2d64514..cebf06b 100644 --- a/src/hash/get.c +++ b/src/hash/get.c @@ -20,6 +20,8 @@ * along with this program. If not, see . */ +#include + #include #include @@ -37,10 +39,10 @@ hashGetComp(const void * a, const void * b) void * hashGet(Hash this, const char * search, size_t nsearch) { - unsigned long hash = sdbm((const unsigned char *)search, nsearch); - void * found = tfind(&hash, &(this->root), hashGetComp); + unsigned long hash = sdbm((const unsigned char *)search, nsearch); + void ** found = tfind(&hash, &(this->root), hashGetComp); - return (NULL != found)? *(void**)found : NULL; + return (NULL != found)? *found : NULL; } // vim: set ts=4 sw=4: diff --git a/src/hash/interface/hashable.c b/src/hash/interface/hashable.c index 0113388..6c0bc7f 100644 --- a/src/hash/interface/hashable.c +++ b/src/hash/interface/hashable.c @@ -37,7 +37,23 @@ hashableGetHash(void * hashable) { unsigned long ret; - RETCALL(hashable, Hashable, getHash, ret); + //RETCALL(hashable, Hashable, getHash, ret); + do { + struct i_Hashable * iface; + //_CALL(GET_CLASS(hashable), Hashable, getHash); + do { + class_ptr class = GET_CLASS(hashable); + iface = (struct i_Hashable *)IFACE_GET(class, &i_Hashable); + while ((NULL == iface || NULL == iface->getHash) && HAS_PARENT(class)) { + class = class->parent; + iface = (struct i_Hashable *)IFACE_GET(class, &i_Hashable); + } + assert(NULL != iface->getHash); + } while(0); + + ret = iface->getHash(hashable); + } while(0); + return ret; } diff --git a/src/http/message.c b/src/http/message.c index 130338f..60837ac 100644 --- a/src/http/message.c +++ b/src/http/message.c @@ -65,6 +65,8 @@ httpMessageDtor(void * _this) MEM_FREE(this->body); } else { assetPoolRelease(this->asset); + this->asset = NULL; + this->body = NULL; } } diff --git a/src/http/response/asset.c b/src/http/response/asset.c index de080ba..29e727a 100644 --- a/src/http/response/asset.c +++ b/src/http/response/asset.c @@ -55,10 +55,15 @@ HttpResponse -httpResponseAsset(Asset asset) +httpResponseAsset(const char * fname, size_t nfname) { HttpResponse response; HttpMessage message; + Asset asset = assetPoolGet(fname, nfname); + + if (NULL == asset) { + return NULL; + } response = new(HttpResponse, "HTTP/1.1", 200, "OK"); message = (HttpMessage)response; diff --git a/src/http/worker/get_asset.c b/src/http/worker/get_asset.c index d833e0d..66fd0c5 100644 --- a/src/http/worker/get_asset.c +++ b/src/http/worker/get_asset.c @@ -41,7 +41,6 @@ httpWorkerGetAsset( size_t nmatch; HttpHeader header; HttpMessage message; - Asset asset; size_t nfname = strlen(fname); @@ -58,31 +57,25 @@ httpWorkerGetAsset( nmatch = (header->nvalue)[0]; } - asset = assetPoolGet(fname, nfname); + message = (HttpMessage)httpResponseAsset(fname, nfname); - if (NULL == asset) { + if (NULL == message) { return (HttpMessage)httpResponse404(); } - if (asset->netag == nmatch - && 0 == memcmp(asset->etag, match, asset->netag)) { - assetPoolRelease(asset); + if (message->asset->netag == nmatch + && 0 == memcmp(message->asset->etag, match, nmatch)) { + HttpMessage new_message; - return (HttpMessage)httpResponse304( - asset->mime_type, asset->nmime_type, - asset->etag, asset->netag, - asset->mtime, asset->nmtime); - } + new_message = (HttpMessage)httpResponse304( + message->asset->mime_type, message->asset->nmime_type, + message->asset->etag, message->asset->netag, + message->asset->mtime, message->asset->nmtime); - message = (HttpMessage)httpResponseAsset(asset); + delete(message); - if (NULL == message) { - // here we should be somewhat more care about what causes - // the message to be NULL... here this could be also a - // 404 not found.... - assetPoolRelease(asset); - message = (HttpMessage)httpResponse500(); - } + return new_message; + } return message; } diff --git a/src/http/writer/write.c b/src/http/writer/write.c index 0ca12d3..5c25aca 100644 --- a/src/http/writer/write.c +++ b/src/http/writer/write.c @@ -117,12 +117,8 @@ httpWriterWrite(void * _this, Stream st) * By the way, the same is true for reading, * so to say, the parser. */ - // cont = 0; - // break; - - /* to go a step further...we send it to the - * poll cicle again... */ - return -1; + cont = 0; + break; } if (this->written >= this->nheader + this->current->nbody) { diff --git a/src/server/handle_accept.c b/src/server/handle_accept.c index ab028b5..9253a7b 100644 --- a/src/server/handle_accept.c +++ b/src/server/handle_accept.c @@ -44,9 +44,10 @@ serverHandleAccept(Server this, unsigned int i) } acc = socketAccept((0 == i)? this->sock : this->sockSSL, &remoteAddr); - socketNonblock(acc); - if (-1 != acc->handle) { + if (NULL != acc && -1 != acc->handle) { + socketNonblock(acc); + switch(i) { case 0: // no SSL @@ -82,21 +83,24 @@ serverHandleAccept(Server this, unsigned int i) delete(acc); switch(errno) { - case EAGAIN: + case EAGAIN|EWOULDBLOCK: + case EINTR: loggerLog(this->logger, LOGGER_DEBUG, "server accept blocks"); + return -1; break; default: loggerLog(this->logger, LOGGER_DEBUG, "server accept error"); + return -2; break; } } - return (acc)? acc->handle : -1; + return acc->handle; } // vim: set ts=4 sw=4: diff --git a/src/server/run.c b/src/server/run.c index afdb648..c168437 100644 --- a/src/server/run.c +++ b/src/server/run.c @@ -51,7 +51,7 @@ serverRun(Server this) * handle accept */ if (0 != ((this->fds)[0].revents & POLLIN)) { - if (-1 == serverHandleAccept(this, 0)) { + if (0 > serverHandleAccept(this, 0)) { events--; } }