On 17 Jan 2007, at 12:15, Giuliano Gavazzi wrote:

note that I am still calling store_headers, for it has side effects (presumably the stuff you say it should do). But store_disk_headers should not, unless it overwrites the headers when called again with the correct size. But this is not the case with the original code, and after my patch from above it would end up writing a header which was the concatenation of the wrong and the right one...

well, I do not know if this is platform specific, but on MacOS 10.4 + Case-sensitive Journaled HFS+ there is a problem in store_headers:

            apr_off_t off=0;
            rv = apr_file_seek(dobj->hfd, APR_SET, &off);

does not rewind if the file has been opened with APR_FOPEN_BUFFERED. Now, I am not sure what buffered means here, but the file is on disk, perhaps because apr_file_flush has been called at the end of the first pass of store_headers. Anyway, because of APR_FOPEN_BUFFERED apr_file_seek will call setptr instead of lseek, and I presume that setptr will just rewind the (now empty) buffer.

There is another potential problem in store_headers, if the headers file is found open but not for writing, it is reopened, but not rewind. Doesn't this imply append?


         if(!(flags & APR_WRITE)) {
            apr_file_close(dobj->hfd);
            rv = apr_file_open(&dobj->hfd, dobj->hdrsfile,
                    APR_WRITE | APR_BINARY | APR_BUFFERED, 0, r->pool);
            if (rv != APR_SUCCESS) {
                dobj->hfd = NULL;
                return rv;
            }



One of the points of those patches are to solve the "thundering herd" problem, simply described as when a frequently accessed object is expired all accesses are served directly by your backend until one access has completed successfully and the cache has been able to store it. This is Bad if it causes your backend to grind to a halt.


well, I will test with a sleep in the dynamic page and hammer it with ab, as I am doing regularly for testing...


I have done some testing and I can see what you mean: it happens when the backend response goes beyond the default 10s of conf->updtimeout.



To avoid this, the header is always written when the cache thinks it should cache something. Other requests will find this header, and if the size is unknown they will wait until it's updated with the correct size, otherwise they will do read-while-caching and return the contents as the file is being cached.


this explains why the file is flushed, or the other processes might find an empty one. As pointed above we should just either close and reopen the headers file or open it without the APR_FOPEN_BUFFERED flag set. Then we can let again store_disk_headers do its job regardless of the state of the size.

g

Reply via email to