Changeset 1673

Show
Ignore:
Timestamp:
07/21/08 17:03:56 (6 months ago)
Author:
alo
Message:

--

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • cherokee/trunk/ChangeLog

    r1670 r1673  
    112008-07-21  Alvaro Lopez Ortega  <alvaro@alobbs.com> 
     2 
     3        * cherokee/iocache.c, cherokee/iocache.h 
     4        cherokee/connection-protected.h, cherokee/handler_cgi_base.c, 
     5        cherokee/handler_common.c, cherokee/thread.c, cherokee/thread.h, 
     6        cherokee/handler_file.c, cherokee/server-protected.h, 
     7        cherokee/connection.c, cherokee/server.c: The I/O cache has been 
     8        reimplemented. Now it uses the new cherokee_cache_t class. It 
     9        should be faster than its predecessor. 
     10 
     11        * cherokee/cache.c, cherokee/cache.h, cherokee/Makefile.am, 
     12        cherokee/cherokee.h: Added new cherokee_cache_t class. It 
     13        implements a generic cache policy class. 
    214 
    315        * qa/run-tests.py (mainloop_iterator): Fixes a really nasty bug 
  • cherokee/trunk/cherokee/Makefile.am

    r1660 r1673  
    949949bogotime.c \ 
    950950connector.h \ 
    951 connector.c 
     951connector.c \ 
     952cache.h \ 
     953cache.c 
    952954 
    953955libcherokee_client_la_SOURCES = \ 
  • cherokee/trunk/cherokee/cherokee.h

    r1569 r1673  
    4747#include <cherokee/avl.h> 
    4848#include <cherokee/trace.h> 
     49#include <cherokee/cache.h> 
    4950 
    5051/* Server library 
  • cherokee/trunk/cherokee/connection-protected.h

    r1607 r1673  
    200200ret_t cherokee_connection_free                   (cherokee_connection_t  *conn); 
    201201ret_t cherokee_connection_clean                  (cherokee_connection_t  *conn); 
    202 ret_t cherokee_connection_mrproper               (cherokee_connection_t  *conn); 
     202ret_t cherokee_connection_clean_close            (cherokee_connection_t  *conn); 
    203203 
    204204/* Close 
  • cherokee/trunk/cherokee/connection.c

    r1654 r1673  
    207207cherokee_connection_clean (cherokee_connection_t *conn) 
    208208{           
    209         uint32_t           header_len; 
    210         size_t             crlf_len; 
    211         cherokee_server_t *srv = CONN_SRV(conn); 
     209        uint32_t header_len; 
     210        size_t   crlf_len; 
    212211 
    213212        if (conn->io_entry_ref != NULL) { 
    214                 cherokee_iocache_mmap_release (srv->iocache, conn->io_entry_ref); 
    215                 conn->io_entry_ref = NULL;      
     213                cherokee_iocache_entry_unref (&conn->io_entry_ref); 
     214                conn->io_entry_ref = NULL; 
    216215        } 
    217216 
     
    313312 
    314313ret_t  
    315 cherokee_connection_mrproper (cherokee_connection_t *conn) 
    316 
    317         /* Close and clean socket, objects, etc. 
    318          * IGNORING ERRORS in order to not leave things 
    319          * in an uncleaned / undetermined state. 
    320          */ 
    321         conn->keepalive = 0; 
    322  
     314cherokee_connection_clean_close (cherokee_connection_t *conn) 
     315
    323316        /* Close and clean the socket 
    324317         */ 
     
    326319        cherokee_socket_clean (&conn->socket); 
    327320 
     321        /* Make sure the connection Keep-Alive is disabled 
     322         */ 
     323        conn->keepalive = 0; 
     324        cherokee_buffer_clean (&conn->incoming_header); 
     325 
    328326        /* Clean the connection object 
    329327         */ 
    330328        cherokee_connection_clean (conn); 
    331  
    332         /* It is not a keep-alive connection, so we shouldn't 
    333          * keep any previous header 
    334          */ 
    335         cherokee_buffer_clean (&conn->incoming_header); 
    336  
    337329        return ret_ok; 
    338330} 
     
    386378         */ 
    387379        if (conn->io_entry_ref != NULL) { 
    388                 cherokee_iocache_mmap_release (srv->iocache, conn->io_entry_ref); 
     380                cherokee_iocache_entry_unref (&conn->io_entry_ref); 
    389381        } 
    390382 
     
    845837cherokee_connection_linger_read (cherokee_connection_t *conn) 
    846838{ 
    847         ret_t  ret; 
    848         int    retries = 2; 
    849         cherokee_thread_t *thread = CONN_THREAD(conn); 
    850         cherokee_buffer_t *tmp1   = THREAD_TMP_BUF1(thread); 
     839        ret_t              ret; 
     840        size_t             cnt_read = 0; 
     841        int                retries  = 2; 
     842        cherokee_thread_t *thread   = CONN_THREAD(conn); 
     843        cherokee_buffer_t *tmp1     = THREAD_TMP_BUF1(thread); 
    851844 
    852845        while (true) { 
    853                 size_t cnt_read = 0; 
    854  
    855846                /* Read from the socket to nowhere 
    856847                 */ 
     
    868859                case ret_ok: 
    869860                        TRACE(ENTRIES, "read %u, ok\n", cnt_read); 
    870                         if (cnt_read == tmp1->size && --retries > 0) 
     861                        retries--; 
     862                        if (cnt_read == tmp1->size && retries > 0) 
    871863                                continue; 
    872864                        return ret; 
  • cherokee/trunk/cherokee/handler_cgi_base.c

    r1614 r1673  
    722722        /* Get the file information 
    723723         */ 
    724         ret = cherokee_iocache_get_or_create_w_stat (srv->iocache,  
    725                                                      &cgi->xsendfile,  
    726                                                      &cached); 
    727         TRACE (ENTRIES, "iocache: %s, ret=%d\n", cgi->xsendfile.buf, ret); 
     724        if (srv->iocache) { 
     725                ret = cherokee_iocache_autoget (srv->iocache,  
     726                                                &cgi->xsendfile, 
     727                                                iocache_stat, 
     728                                                &cached); 
     729                TRACE (ENTRIES, "iocache: %s, ret=%d\n",  
     730                       cgi->xsendfile.buf, ret); 
     731        } else { 
     732                ret = ret_no_sys; 
     733        } 
     734 
    728735        switch (ret) { 
    729736        case ret_ok: 
     
    751758        cherokee_buffer_add_str (buffer, CRLF); 
    752759 
    753         cherokee_iocache_mmap_release (srv->iocache, cached); 
    754  
     760        cherokee_iocache_entry_unref (&cached); 
    755761        return ret_ok; 
    756762} 
  • cherokee/trunk/cherokee/handler_common.c

    r1614 r1673  
    107107 
    108108static ret_t 
    109 stat_file (cherokee_boolean_t useit, cherokee_iocache_t *iocache, struct stat *nocache_info,  
    110            cherokee_buffer_t *path, cherokee_iocache_entry_t **io_entry, struct stat **info) 
     109stat_file (cherokee_boolean_t         useit,  
     110           cherokee_iocache_t        *iocache,  
     111           struct stat               *nocache_info,  
     112           cherokee_buffer_t         *path,  
     113           cherokee_iocache_entry_t **io_entry, 
     114           struct stat              **info) 
    111115{        
    112116        ret_t ret; 
     
    116120         */ 
    117121        if (useit) { 
    118                 ret = cherokee_iocache_get_or_create_w_stat (iocache, path, io_entry);          
    119                 TRACE (ENTRIES, "%s, use_iocache=1 rer=%d\n", path->buf, ret); 
     122                ret = cherokee_iocache_autoget (iocache, path, iocache_stat, io_entry); 
     123                TRACE (ENTRIES, "%s, use_iocache=1 ret=%d\n", path->buf, ret); 
    120124 
    121125                switch (ret) { 
    122126                case ret_ok: 
     127                case ret_deny: 
    123128                        *info = &(*io_entry)->state; 
    124129                        return ret_ok; 
    125130 
     131                case ret_no_sys: 
     132                        goto without; 
     133 
    126134                case ret_not_found: 
    127135                        return ret_not_found; 
    128  
    129                 case ret_no_sys: 
    130                         goto without; 
    131                 case ret_deny: 
    132                         return ret_deny; 
    133136                default: 
    134137                        return ret_error; 
    135138                } 
    136                  
    137139        } 
    138140 
     
    161163 
    162164 
     165 
    163166ret_t  
    164167cherokee_handler_common_new (cherokee_handler_t **hdl, void *cnt, cherokee_module_props_t *props) 
     
    168171        struct stat               nocache_info; 
    169172        struct stat              *info; 
    170         cherokee_iocache_entry_t *file        = NULL; 
     173        cherokee_iocache_entry_t *io_entry    = NULL; 
    171174        cherokee_iocache_t       *iocache     = NULL; 
    172175        cherokee_boolean_t        use_iocache = true; 
     
    184187         */ 
    185188        cherokee_buffer_add_buffer (&conn->local_directory, &conn->request); 
    186  
    187         cherokee_iocache_get_default (&iocache); 
    188         ret = stat_file (use_iocache, iocache, &nocache_info, &conn->local_directory, &file, &info); 
     189         
     190        if (use_iocache) 
     191                cherokee_iocache_get_default (&iocache); 
     192 
     193        ret = stat_file (use_iocache, iocache, &nocache_info, &conn->local_directory, &io_entry, &info); 
    189194        exists = (ret == ret_ok); 
    190195 
     
    201206                 */ 
    202207                if (! PROP_COMMON(props)->allow_pathinfo) { 
     208                        TRACE(ENTRIES, "Returns conn->error_code: %s\n", "http_not_found"); 
     209                        cherokee_iocache_entry_unref (&io_entry); 
     210 
    203211                        conn->error_code = http_not_found;  
    204212                        return ret_error; 
     
    212220                ret = cherokee_split_pathinfo (&conn->local_directory, begin, true, &pathinfo, &pathinfo_len); 
    213221                if ((ret == ret_not_found) || (pathinfo_len <= 0)) { 
    214                         cherokee_iocache_mmap_release (iocache, file); 
     222                        TRACE(ENTRIES, "Returns conn->error_code: %s\n", "http_not_found"); 
     223                        cherokee_iocache_entry_unref (&io_entry); 
     224 
    215225                        conn->error_code = http_not_found; 
    216226                        return ret_error; 
     
    226236                 */ 
    227237                cherokee_buffer_clean (&conn->local_directory); 
    228                 cherokee_iocache_mmap_release (iocache, file); 
     238                cherokee_iocache_entry_unref (&io_entry); 
    229239 
    230240                TRACE_CONN(conn); 
     
    238248        if (S_ISREG(info->st_mode)) { 
    239249                TRACE (ENTRIES, "going for %s\n", "handler_file"); 
     250                cherokee_iocache_entry_unref (&io_entry); 
     251 
    240252                return cherokee_handler_file_new (hdl, cnt, MODULE_PROPS(PROP_COMMON(props)->props_file)); 
    241253        } 
     
    247259                cherokee_list_t   *i; 
    248260 
    249                 cherokee_iocache_mmap_release (iocache, file); 
     261                cherokee_iocache_entry_unref (&io_entry); 
    250262 
    251263                /* Maybe it has to be redirected 
     
    287299                                cherokee_buffer_add (new_local_dir, index, index_len); 
    288300                                 
    289                                 ret = stat_file (use_iocache, iocache, &nocache_info, new_local_dir, &file, &info); 
     301                                ret = stat_file (use_iocache, iocache, &nocache_info, new_local_dir, &io_entry, &info); 
    290302                                exists = (ret == ret_ok); 
    291                                 cherokee_iocache_mmap_release (iocache, file); 
     303                                cherokee_iocache_entry_unref (&io_entry); 
    292304 
    293305                                if (!exists) 
     
    314326                         */ 
    315327                        cherokee_buffer_add (&conn->local_directory, index, index_len); 
    316                         ret = stat_file (use_iocache, iocache, &nocache_info, &conn->local_directory, &file, &info); 
     328                        ret = stat_file (use_iocache, iocache, &nocache_info, &conn->local_directory, &io_entry, &info); 
    317329 
    318330                        exists =  (ret == ret_ok); 
    319331                        is_dir = ((ret == ret_ok) && S_ISDIR(info->st_mode)); 
    320332 
    321                         cherokee_iocache_mmap_release (iocache, file); 
     333                        cherokee_iocache_entry_unref (&io_entry); 
    322334                        cherokee_buffer_drop_ending (&conn->local_directory, index_len); 
    323335 
     
    346358        /* Unknown request type 
    347359         */ 
     360        TRACE(ENTRIES, "Returns conn->error_code: %s\n", "http_internal_error"); 
    348361        conn->error_code = http_internal_error; 
     362 
    349363        SHOULDNT_HAPPEN; 
    350364        return ret_error; 
  • cherokee/trunk/cherokee/handler_file.c

    r1631 r1673  
    9090        } 
    9191 
     92        /* Post checks 
     93         */ 
     94        if (srv->iocache == NULL) 
     95                props->use_cache = false; 
     96 
    9297        return ret_ok; 
    9398} 
     
    293298         */ 
    294299        fhdl->fd = open (local_file->buf, CHE_O_READ); 
    295         if (fhdl->fd > 0) return ret_ok; 
     300        if (fhdl->fd > 0) 
     301                return ret_ok; 
    296302 
    297303        /* Manage errors 
     
    324330        /* I/O cache 
    325331         */ 
    326         if (HDL_FILE_PROP(fhdl)->use_cache) { 
    327                 ret = cherokee_iocache_get_or_create_w_stat (srv->iocache, local_file, io_entry); 
     332        if (srv->iocache && 
     333            HDL_FILE_PROP(fhdl)->use_cache)  
     334        { 
     335                ret = cherokee_iocache_autoget (srv->iocache, local_file, iocache_stat, io_entry); 
    328336                TRACE (ENTRIES, "%s, use_iocache=1 ret=%d\n", local_file->buf, ret); 
    329337 
     
    380388        ret_t                     ret; 
    381389        char                     *ext; 
     390        cherokee_iocache_entry_t *io_entry = NULL; 
    382391        cherokee_boolean_t        use_io   = false; 
    383392        cherokee_connection_t    *conn     = HANDLER_CONN(fhdl); 
     
    386395        /* Query the I/O cache 
    387396         */ 
    388         ret = stat_local_directory (fhdl, local_file, &conn->io_entry_ref, &fhdl->info); 
    389         if (ret != ret_ok)  
    390                 return ret; 
     397        ret = stat_local_directory (fhdl, local_file, &io_entry, &fhdl->info); 
     398        if (ret != ret_ok) 
     399                goto out; 
    391400 
    392401        /* Ensure it is a file 
     
    394403        if (S_ISDIR(fhdl->info->st_mode)) { 
    395404                conn->error_code = http_access_denied; 
    396                 return ret_error; 
     405                ret = ret_error; 
     406                goto out; 
    397407        } 
    398408 
     
    410420        ret = check_cached (fhdl); 
    411421        if ((ret != ret_ok) || (fhdl->not_modified)) 
    412                 return ret; 
     422                goto out; 
    413423 
    414424        /* Is this file cached in the io cache? 
    415425         */ 
    416         use_io = ((conn->encoder == NULL) && 
     426        use_io = ((srv->iocache != NULL) && 
     427                  (conn->encoder == NULL) && 
    417428                  (HDL_FILE_PROP(fhdl)->use_cache) && 
    418429                  (conn->socket.is_tls == non_TLS) && 
     
    424435         
    425436        if (use_io) { 
    426                 ret = cherokee_iocache_get_or_create_w_mmap (srv->iocache, 
    427                                                              local_file, 
    428                                                              &conn->io_entry_ref,  
    429                                                              &fhdl->fd); 
     437                ret = cherokee_iocache_autoget_fd (srv->iocache, 
     438                                                   local_file, 
     439                                                   iocache_mmap, 
     440                                                   &fhdl->fd, 
     441                                                   &io_entry); 
    430442 
    431443                TRACE (ENTRIES, "iocache looked up, local=%s ret=%d\n",  
     
    439451                        break; 
    440452                default: 
    441                         return ret_error
     453                        goto out
    442454                } 
    443455        } 
     
    445457        /* Maybe open the file 
    446458         */ 
    447         if ((fhdl->fd < 0) && (!use_io)) { 
     459        if (! use_io) { 
    448460                ret = open_local_directory (fhdl, local_file); 
    449461                if (ret != ret_ok) 
    450                         return ret; 
     462                        goto out; 
    451463        } 
    452464 
    453465        /* Is it a directory? 
    454466         */ 
    455         if (S_ISDIR(fhdl->info->st_mode)) { 
     467        if (S_ISDIR (fhdl->info->st_mode)) { 
    456468                conn->error_code = http_access_denied; 
    457                 return ret_error;                
     469                ret = ret_error; 
     470                goto out; 
    458471        } 
    459472 
     
    464477                conn->range_end  = fhdl->info->st_size; 
    465478                conn->error_code = http_range_not_satisfiable; 
    466                 return ret_error; 
     479                ret = ret_error; 
     480                goto out; 
    467481        } 
    468482 
     
    484498         */ 
    485499        if (use_io && 
    486             (conn->io_entry_ref != NULL) && 
    487             (conn->io_entry_ref->mmaped != NULL)) { 
     500            (io_entry != NULL) && 
     501            (io_entry->mmaped != NULL)) { 
    488502                /* Set the mmap info 
    489503                 */ 
    490                 conn->mmaped     = conn->io_entry_ref->mmaped + conn->range_start; 
    491                 conn->mmaped_len = conn->io_entry_ref->mmaped_len - 
    492                         ( conn->range_start + 
    493                          (conn->io_entry_ref->mmaped_len - conn->range_end)); 
     504                conn->io_entry_ref = io_entry; 
     505 
     506                conn->mmaped     = io_entry->mmaped + conn->range_start; 
     507                conn->mmaped_len = io_entry->mmaped_len - 
     508                        (conn->range_start + 
     509                         (io_entry->mmaped_len - conn->range_end)); 
    494510        } else { 
     511                /* Does no longer care about the io_entry 
     512                 */ 
     513                cherokee_iocache_entry_unref (&io_entry); 
     514 
    495515                /* Seek the file if needed 
    496516                 */ 
     
    516536         
    517537        return ret_ok; 
     538 
     539out: 
     540        cherokee_iocache_entry_unref (&io_entry); 
     541        return ret; 
    518542} 
    519543 
  • cherokee/trunk/cherokee/iocache.c

    r1654 r1673  
    2626#include "iocache.h" 
    2727 
    28 #include "avl.h" 
    29 #include "list.h" 
    3028#include "buffer.h" 
    3129#include "server-protected.h" 
     
    4947#define ENTRIES "iocache" 
    5048 
    51 #define FRESHNESS_TIME_STAT 300 
    52 #define FRESHNESS_TIME_MMAP 600 
    53 #define CACHE_SIZE          10 
    54 #define CACHE_SIZE_MAX      50 
     49#define LASTING_MMAP  300  /* 5 mins */ 
     50#define LASTING_STAT  300  /* 5 mins */ 
    5551 
    5652#ifndef O_BINARY 
     
    6763typedef struct { 
    6864        cherokee_iocache_entry_t base; 
    69  
    70         time_t                   stat_update; 
    71         time_t                   mmap_update; 
    72         cint_t                   ref_counter; 
    73         cint_t                   usages; 
    74  
    75         /* unref */ 
    76         cherokee_list_t          to_be_deleted; 
    77         cherokee_buffer_t       *name_ref; 
     65        time_t                   stat_expiration; 
     66        time_t                   mmap_expiration; 
    7867} cherokee_iocache_entry_extension_t; 
    79  
    80  
    81 struct cherokee_iocache { 
    82         cherokee_server_t *srv; 
    83         cherokee_avl_t     files; 
    84         cuint_t            files_num; 
    85         cuint_t            files_max; 
    86         cuint_t            files_usages; 
    87         CHEROKEE_MUTEX_T  (files_lock); 
    88  
    89         /* cleaning up stuff */ 
    90         float              average; 
    91         cherokee_list_t    to_delete; 
    92 }; 
    93  
    9468 
    9569#define PUBL(o) ((cherokee_iocache_entry_t *)(o)) 
    9670#define PRIV(o) ((cherokee_iocache_entry_extension_t *)(o)) 
    9771 
     72/* Global I/O cache object 
     73 */ 
    9874 
    9975static cherokee_iocache_t *global_io = NULL; 
    10076 
    101  
    102 static ret_t  
    103 cherokee_iocache_new (cherokee_iocache_t **iocache, cherokee_server_t *srv) 
    104 
    105         CHEROKEE_NEW_STRUCT (n, iocache); 
    106  
    107         cherokee_avl_init   (&n->files); 
    108         CHEROKEE_MUTEX_INIT (&n->files_lock, NULL); 
    109  
    110         n->files_num     = 0; 
    111         n->files_max     = CACHE_SIZE_MAX; 
    112         n->files_usages  = 0; 
    113         n->srv           = srv; 
    114  
    115         *iocache = n; 
    116         return ret_ok; 
    117 
    118  
     77static ret_t 
     78clean_info_cb (cherokee_cache_entry_t *entry) 
     79
     80        cherokee_iocache_entry_t *ioentry = IOCACHE_ENTRY(entry); 
     81 
     82        TRACE (ENTRIES, "Cleaning cached info: '%s': %s\n",  
     83               entry->key.buf, ioentry->mmaped ? "mmap": "no mmap"); 
     84 
     85        if (ioentry->mmaped) { 
     86                munmap (ioentry->mmaped, ioentry->mmaped_len); 
     87 
     88                ioentry->mmaped     = NULL; 
     89                ioentry->mmaped_len = 0; 
     90        } 
     91 
     92        return ret_ok; 
     93
     94 
     95static ret_t 
     96fetch_info_cb (cherokee_cache_entry_t *entry) 
     97
     98        UNUSED(entry); 
     99        return ret_ok; 
     100
     101 
     102static ret_t 
     103free_cb (cherokee_cache_entry_t *entry) 
     104
     105        UNUSED(entry); 
     106        return ret_ok; 
     107
     108 
     109 
     110static ret_t 
     111iocache_entry_new_cb (cherokee_cache_t        *cache,  
     112                      cherokee_buffer_t       *key, 
     113                      void                    *param, 
     114                      cherokee_cache_entry_t **ret_entry) 
     115
     116        CHEROKEE_NEW_STRUCT(n, iocache_entry_extension); 
     117 
     118        UNUSED(cache); 
     119        UNUSED(param); 
     120 
     121        /* Init its parent class 
     122         */ 
     123        cherokee_cache_entry_init (CACHE_ENTRY(n), key); 
     124 
     125        /* Set the virtual methods 
     126         */ 
     127        CACHE_ENTRY(n)->clean_cb = clean_info_cb; 
     128        CACHE_ENTRY(n)->fetch_cb = fetch_info_cb; 
     129        CACHE_ENTRY(n)->free_cb  = free_cb; 
     130         
     131        /* Init its properties 
     132         */ 
     133        PRIV(n)->stat_expiration = 0; 
     134        PRIV(n)->mmap_expiration = 0; 
     135        PUBL(n)->mmaped          = NULL; 
     136        PUBL(n)->mmaped_len      = 0; 
     137 
     138        /* Return the new object 
     139         */ 
     140        *ret_entry = CACHE_ENTRY(n); 
     141        return ret_ok; 
     142
    119143 
    120144ret_t  
    121 cherokee_iocache_new_default  (cherokee_iocache_t **iocache, cherokee_server_t *srv
     145cherokee_iocache_init (cherokee_iocache_t *iocache
    122146{ 
    123147        ret_t ret; 
    124148 
    125         ret = cherokee_iocache_get_default (iocache); 
    126         if (unlikely (ret != ret_ok)) return ret_ok; 
    127  
    128         (*iocache)->srv = srv; 
    129         return ret_ok; 
    130 
    131  
     149        /* Init the parent (cache policy) class 
     150         */ 
     151        ret = cherokee_cache_init (CACHE(iocache)); 
     152        if (ret != ret_ok) 
     153                return ret; 
     154         
     155        /* Init its virtual methods 
     156         */ 
     157        CACHE(iocache)->new_cb       = iocache_entry_new_cb; 
     158        CACHE(iocache)->new_cb_param = NULL; 
     159 
     160        return ret_ok; 
     161
     162 
     163ret_t  
     164cherokee_iocache_mrproper (cherokee_iocache_t *iocache) 
     165
     166        return cherokee_cache_mrproper (CACHE(iocache)); 
     167
    132168 
    133169ret_t  
     
    137173         
    138174        if (global_io == NULL) { 
    139                 ret = cherokee_iocache_new (&global_io, NULL); 
    140                 if (unlikely (ret != ret_ok)) return ret; 
     175                CHEROKEE_NEW_STRUCT (n, iocache); 
     176 
     177                ret = cherokee_iocache_init (n); 
     178                if (ret != ret_ok)  
     179                        return ret; 
     180 
     181                global_io = n; 
    141182        } 
    142183         
     
    145186} 
    146187 
    147  
    148 static ret_t 
    149 iocache_entry_new (cherokee_iocache_entry_t **entry) 
    150 
    151         CHEROKEE_NEW_STRUCT(n, iocache_entry_extension); 
    152  
    153         PRIV(n)->stat_update = 0; 
    154         PRIV(n)->mmap_update = 0; 
    155         PRIV(n)->usages      = 0; 
    156         PRIV(n)->ref_counter = 0; 
    157  
    158         PRIV(n)->name_ref    = NULL; 
    159         INIT_LIST_HEAD(&PRIV(n)->to_be_deleted); 
    160  
    161         PUBL(n)->mmaped      = NULL; 
    162         PUBL(n)->mmaped_len  = 0; 
    163  
    164         *entry = PUBL(n); 
    165         return ret_ok; 
    166 
    167  
    168 static ret_t 
    169 iocache_entry_free (cherokee_iocache_entry_t *entry) 
    170 
    171         /* Free the object 
     188ret_t  
     189cherokee_iocache_free_default (void) 
     190
     191        ret_t ret; 
     192 
     193        if (global_io == NULL) 
     194                return ret_ok; 
     195 
     196        ret = cherokee_iocache_mrproper (global_io); 
     197        if (ret != ret_ok) 
     198                return ret; 
     199 
     200        free (global_io); 
     201        return ret_ok; 
     202
     203 
     204 
     205/* Cache entry objects 
     206 */ 
     207 
     208ret_t 
     209cherokee_iocache_entry_unref (cherokee_iocache_entry_t **entry) 
     210
     211        return cherokee_cache_entry_unref ((cherokee_cache_entry_t **)entry); 
     212
     213 
     214static ret_t 
     215ioentry_update_stat (cherokee_iocache_entry_t *entry) 
     216
     217        int   re; 
     218        ret_t ret; 
     219 
     220        if (PRIV(entry)->stat_expiration >= cherokee_bogonow_now) { 
     221                TRACE (ENTRIES, "Update stat: %s: updated - skipped\n",  
     222                       CACHE_ENTRY(entry)->key.buf); 
     223                return ret_ok; 
     224        } 
     225 
     226        /* Update stat 
     227         */ 
     228        re = cherokee_stat (CACHE_ENTRY(entry)->key.buf, &entry->state); 
     229        if (re < 0) { 
     230                TRACE(ENTRIES, "Couldn't update stat: %s: errno=%d\n",  
     231                      CACHE_ENTRY(entry)->key.buf, re); 
     232 
     233                switch (errno) { 
     234                case EACCES: 
     235                        ret = ret_deny; 
     236                        goto error; 
     237                case ENOENT: 
     238                        ret = ret_not_found; 
     239                        goto error; 
     240                default: 
     241                        break; 
     242                } 
     243 
     244                return ret_error; 
     245        } 
     246 
     247        TRACE (ENTRIES, "Updated stat: %s\n", CACHE_ENTRY(entry)->key.buf); 
     248 
     249        PRIV(entry)->stat_expiration = cherokee_bogonow_now + LASTING_STAT; 
     250        return ret_ok; 
     251 
     252error: 
     253        return ret; 
     254
     255 
     256static ret_t 
     257ioentry_update_mmap (cherokee_iocache_entry_t *entry,  
     258                     int                      *fd) 
     259
     260        ret_t              ret; 
     261        int                fd_local = -1; 
     262        cherokee_buffer_t *filename = &CACHE_ENTRY(entry)->key; 
     263 
     264        /* Short path 
     265         */ 
     266        if (PRIV(entry)->mmap_expiration >= cherokee_bogonow_now) { 
     267                TRACE(ENTRIES, "Update mmap: %s: updated - skipped\n", filename->buf); 
     268                return ret_ok; 
     269        } 
     270 
     271        /* Check the fd 
     272         */ 
     273        if (fd != NULL) 
     274                fd_local = *fd; 
     275 
     276        /* Only map regular files 
     277         */ 
     278        if (unlikely (! S_ISREG(entry->state.st_mode))) { 
     279                TRACE(ENTRIES, "Not a regular file: %s\n", filename->buf); 
     280                ret = ret_deny; 
     281                goto error; 
     282        } 
     283 
     284        /* Maybe it is already opened 
     285         */ 
     286        if (fd_local < 0) { 
     287                fd_local = open (filename->buf, (O_RDONLY | O_BINARY)); 
     288                if (unlikely (fd_local < 0)) { 
     289                        TRACE(ENTRIES, "Couldn't open(): %s\n", filename->buf); 
     290                        ret = ret_error; 
     291                        goto error; 
     292                } 
     293 
     294                if (fd != NULL) 
     295                        *fd = fd_local; 
     296        } 
     297 
     298        /* Might need to free the previous mmap 
    172299         */ 
    173300        if (entry->mmaped != NULL) { 
     301                TRACE(ENTRIES, "Cleaning previos mmap: %s\n", filename->buf); 
    174302                munmap (entry->mmaped, entry->mmaped_len); 
    175303 
     
    178306        } 
    179307 
    180         /* Free the entry object 
    181          */ 
    182         free (entry); 
    183         return ret_ok; 
    184 
    185  
    186 static ret_t 
    187 iocache_entry_ref (cherokee_iocache_entry_t *entry) 
    188 
    189         PRIV(entry)->ref_counter++; 
    190         return ret_ok; 
    191 
    192  
    193  
    194 static ret_t 
    195 iocache_entry_unref (cherokee_iocache_entry_t *entry) 
    196 
    197         cherokee_iocache_entry_extension_t *priv = PRIV(entry); 
    198  
    199         priv->ref_counter--;     
    200         if (priv->ref_counter > 0) 
    201                 return ret_eagain; 
    202  
    203         return ret_ok; 
    204 
    205  
    206  
    207 static ret_t 
    208 iocache_free_entry (cherokee_iocache_t *iocache, cherokee_iocache_entry_t *entry) 
    209 
    210         ret_t ret; 
    211  
    212         ret = iocache_entry_free (entry); 
    213  
    214         /* Update the obj counter 
    215          */ 
    216         iocache->files_num--; 
    217  
    218         return ret; 
    219 
    220  
    221  
    222 static ret_t 
    223 iocache_entry_update_stat (cherokee_iocache_t *iocache, cherokee_iocache_entry_t *entry, cherokee_buffer_t *filename) 
    224 
    225         int re; 
    226  
    227         re = cherokee_stat (filename->buf, &entry->state); 
    228         if (re < 0) { 
    229                 TRACE(ENTRIES, "Couldn't update stat: errno=%d\n", re); 
    230  
    231                 switch (errno) { 
    232                 case EACCES:  
    233                         return ret_deny; 
    234                 case ENOENT:  
    235                         return ret_not_found; 
    236                 default:      
    237                         break; 
    238                 } 
    239  
    240                 return ret_error; 
    241         } 
    242  
    243         PRIV(entry)->stat_update = cherokee_bogonow_now; 
    244         return ret_ok; 
    245 
    246  
    247  
    248 static ret_t 
    249 iocache_entry_update_mmap (cherokee_iocache_t *iocache, cherokee_iocache_entry_t *entry, cherokee_buffer_t *filename, int fd, int *ret_fd) 
    250 
    251         ret_t ret; 
    252  
    253         TRACE(ENTRIES, "Update mmap: %s\n", filename->buf); 
    254  
    255         /* The stat information has to be fresh enough 
    256          */ 
    257         if (cherokee_bogonow_now >= (PRIV(entry)->stat_update + FRESHNESS_TIME_STAT)) { 
    258                 ret = iocache_entry_update_stat (iocache, entry, filename); 
    259                 if (ret != ret_ok) return ret; 
    260         } 
    261  
    262         /* Only map regular files 
    263          */ 
    264         if (unlikely (! S_ISREG(entry->state.st_mode))) { 
    265                 TRACE(ENTRIES, "Not a regular file: %s\n", filename->buf); 
    266                 return ret_deny; 
    267         } 
    268  
    269         /* Maybe it is already opened 
    270          */ 
    271         if (fd < 0) { 
    272                 fd = open (filename->buf, O_RDONLY|O_BINARY); 
    273                 if (unlikely (fd < 0)) { 
    274                         TRACE(ENTRIES, "Couldn't open(): %s\n", filename->buf); 
    275                         return ret_error; 
    276                 } 
    277         } 
    278  
    279         *ret_fd = fd; 
    280  
    281         /* Might need to free the previous mmap 
    282          */ 
    283         if (entry->mmaped != NULL) { 
    284                 munmap (entry->mmaped, entry->mmaped_len); 
    285  
    286                 entry->mmaped     = NULL; 
    287                 entry->mmaped_len = 0; 
    288         } 
    289  
    290         /* Do it 
     308        /* Map the file into memory 
    291309         */ 
    292310        entry->mmaped = 
     
    295313                      PROT_READ,            /* int     prot   */ 
    296314                      MAP_OPTIONS,          /* int     flag   */ 
    297                       fd,                   /* int     fd     */ 
     315