--- docs/manual/mod/directives.html.en (revision 1696322) +++ docs/manual/mod/directives.html.en (working copy) @@ -592,6 +592,7 @@
  • SessionDBDUpdateLabel
  • SessionEnv
  • SessionExclude
  • +
  • SessionExpiryUpdateInterval
  • SessionHeader
  • SessionInclude
  • SessionMaxAge
  • --- docs/manual/mod/mod_session.xml (revision 1696322) +++ docs/manual/mod/mod_session.xml (working copy) @@ -487,4 +487,41 @@ + +SessionExpiryUpdateInterval +Define the number of seconds a session's expiry may change without +being written +SessionExpiryUpdateInterval interval +SessionExpiryUpdateInterval 0 +server config +virtual host +directory +.htaccess + + + +

    The SessionExpiryUpdateInterval directive allows + sessions to avoid the cost associated with writing the session each request + when only the expiry time has changed. This can be used to make a website + more efficient or reduce load on a database when using + mod_session_dbd. The session is always written if the data + stored in the session has changed or the expiry has changed by more than the + configured interval.

    + +

    Setting the interval to zero disables this directive, and the session + expiry is refreshed each request.

    + +

    This directive only has an effect when combined with + SessionMaxAge to enable session + expiry. Sessions without an expiry are only written when the data stored in + the session has changed.

    + + Warning +

    Because the session expiry may not be refreshed with each request, it's + possible for sessions to expire up to interval seconds early. + Using a small interval usually provides sufficient savings while having a + minimal effect on expiry resolution.

    +
    +
    + --- docs/manual/mod/mod_session.html.en (revision 1696322) +++ docs/manual/mod/mod_session.html.en (working copy) @@ -78,6 +78,7 @@
  • Session
  • SessionEnv
  • SessionExclude
  • +
  • SessionExpiryUpdateInterval
  • SessionHeader
  • SessionInclude
  • SessionMaxAge
  • @@ -411,6 +412,40 @@
    top
    +

    SessionExpiryUpdateInterval Directive

    + + + + + + + +
    Description:Define the number of seconds a session's expiry may change without +being written
    Syntax:SessionExpiryUpdateInterval interval
    Default:SessionExpiryUpdateInterval 0
    Context:server config, virtual host, directory, .htaccess
    Status:Extension
    Module:mod_session
    +

    The SessionExpiryUpdateInterval directive allows + sessions to avoid the cost associated with writing the session each request + when only the expiry time has changed. This can be used to make a website + more efficient or reduce load on a database when using + mod_session_dbd. The session is always written if the data + stored in the session has changed or the expiry has changed by more than the + configured interval.

    + +

    Setting the interval to zero disables this directive, and the session + expiry is refreshed each request.

    + +

    This directive only has an effect when combined with + SessionMaxAge to enable session + expiry. Sessions without an expiry are only written when the data stored in + the session has changed.

    + +

    Warning

    +

    Because the session expiry may not be refreshed with each request, it's + possible for sessions to expire up to interval seconds early. + Using a small interval usually provides sufficient savings while having a + minimal effect on expiry resolution.

    + +
    +
    top

    SessionHeader Directive

    --- modules/session/mod_session.c (revision 1696322) +++ modules/session/mod_session.c (working copy) @@ -177,6 +177,7 @@ { if (z) { apr_time_t now = apr_time_now(); + apr_time_t initialExpiry = z->expiry; int rv = 0; session_dir_conf *dconf = ap_get_module_config(r->per_dir_config, @@ -207,6 +208,18 @@ z->expiry = now + z->maxage * APR_USEC_PER_SEC; } + /* don't save if the only change is the expiry by a small amount */ + if (!z->dirty && dconf->expiry_update_time + && (z->expiry - initialExpiry + < dconf->expiry_update_time * APR_USEC_PER_SEC)) { + return APR_SUCCESS; + } + + /* also don't save sessions that didn't change at all */ + if (!z->dirty && !z->maxage) { + return APR_SUCCESS; + } + /* encode the session */ rv = ap_run_session_encode(r, z); if (OK != rv) { @@ -551,6 +564,9 @@ new->env_set = add->env_set || base->env_set; new->includes = apr_array_append(p, base->includes, add->includes); new->excludes = apr_array_append(p, base->excludes, add->excludes); + new->expiry_update_time = (add->expiry_update_set == 0) ? + base->expiry_update_time : add->expiry_update_time; + new->expiry_update_set = add->expiry_update_set || base->expiry_update_set; return new; } @@ -620,7 +636,18 @@ return NULL; } +static const char * + set_session_expiry_update(cmd_parms * parms, void *dconf, const char *arg) +{ + session_dir_conf *conf = dconf; + conf->expiry_update_time = atol(arg); + conf->expiry_update_set = 1; + + return NULL; +} + + static const command_rec session_cmds[] = { AP_INIT_FLAG("Session", set_session_enable, NULL, RSRC_CONF|OR_AUTHCFG, @@ -635,6 +662,8 @@ "URL prefixes to include in the session. Defaults to all URLs"), AP_INIT_TAKE1("SessionExclude", add_session_exclude, NULL, RSRC_CONF|OR_AUTHCFG, "URL prefixes to exclude from the session. Defaults to no URLs"), + AP_INIT_TAKE1("SessionExpiryUpdateInterval", set_session_expiry_update, NULL, RSRC_CONF|OR_AUTHCFG, + "length of time for which a session's expiry time may change without having to be rewritten. Zero to disable"), {NULL} }; --- modules/session/mod_session.h (revision 1696322) +++ modules/session/mod_session.h (working copy) @@ -115,6 +115,9 @@ * URLs included if empty */ apr_array_header_t *excludes; /* URL prefixes to be excluded. No * URLs excluded if empty */ + long expiry_update_time; /* seconds the session expiry may change and + * not have to be rewritten */ + int expiry_update_set; } session_dir_conf; /** --- modules/session/mod_session_dbd.c (revision 1696322) +++ modules/session/mod_session_dbd.c (working copy) @@ -245,6 +245,9 @@ /* put the session in the notes so we don't have to parse it again */ apr_table_setn(m->notes, note, (char *)zz); + /* don't cache pages with a session */ + apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); + return OK; } @@ -409,9 +412,6 @@ if (conf->name_set || conf->name2_set) { char *oldkey = NULL, *newkey = NULL; - /* don't cache pages with a session */ - apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); - /* if the session is new or changed, make a new session ID */ if (z->uuid) { oldkey = apr_pcalloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); --- modules/session/mod_session_cookie.c (revision 1696322) +++ modules/session/mod_session_cookie.c (working copy) @@ -60,9 +60,6 @@ session_cookie_dir_conf *conf = ap_get_module_config(r->per_dir_config, &session_cookie_module); - /* don't cache auth protected pages */ - apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); - /* create RFC2109 compliant cookie */ if (conf->name_set) { if (z->encoded && z->encoded[0]) { @@ -162,6 +159,9 @@ /* put the session in the notes so we don't have to parse it again */ apr_table_setn(m->notes, note, (char *)zz); + /* don't cache auth protected pages */ + apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); + return OK; }
    Description:Import session updates from a given HTTP response header