Logo Search packages:      
Sourcecode: caudium version File versions

cache.h

/*
 * Caudium - An extensible World Wide Web server
 * Copyright  2000-2005 The Caudium Group
 * Copyright  1994-2001 Roxen Internet Software
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */


/*
 * include for sqlfs.pike
 *
 * $Id: cache.h,v 1.3.2.3 2005/01/03 17:01:16 kiwi Exp $
 */


class sqlfs_cache {
    /*
     * I am the object cache object.
     * -----------------------------
     * I maintain a memory cache of all things that are asked of class
     * sqlfs_read(), I also age these entries, so that if they are too old
     * by the time they are asked for again, I discard what I have and
     * leave it at that.
     * If the TTL is set to 0 then I cache things forever.
     *
     * TODO: General tidy up
     *        - Most of the functionality should be removed from the public
     *          methods and put into private ones.
     *
     */

    mapping cache;
    int ttl;
    float reqs;
    float hits;
    int verbose_status_output;

    /*
     * Constructor
     * -----------
     * This creates the empty mapping for storage, and it also
     * sets the time to live for cached objects either by an int (secs)
     * MUST BE passed to it when cloned.
     */

    void create ( int cache_for, int fart ) {
      ttl = cache_for;
      cache = ([ ]);
        verbose_status_output = fart;
    }

    /*
     * Public methods
     * --------------
     * These are the methods called by external routines, they are used to
     * store, retrieve, and check freshness of the cache.
     * Also, status() is called by the Roxen FS module to place in the config
     * interface.
     * flush() is used by some contob->set* routines to remove objects from
     * the cache, and also by the Roxen FS module if id->pragma[ "no-cache" ]
     */

    void store ( string filepath, string operation, mixed value ) {
      filepath = fix_path( filepath );
      if ( cache[ filepath ] ) {
          cache[ filepath ] += ([ operation : ([ "value" : value,
                                       "timestamp" : time()
                                     ]),
                            "hits" : 0
                          ]);
      } else {
          cache += ([ filepath : ([ operation : ([ "value" : value,
                                         "timestamp" : time()
                                       ]),
                              "hits" : 0
                            ])
                  ]);
      }
    }

    mixed retrieve( string filepath, string operation ) {
        filepath = fix_path( filepath );
      if ( !cache[ filepath ] ) {
          return 0;
      } else if ( !cache[ filepath ][ operation ] ) {
          return 0;
      } else if ( cache[ filepath ][ operation ][ "timestamp" ] < time() - ttl ) {
          if ( ttl == 0 ) {
            cache[ filepath ][ "hits" ]++;
                return cache[ filepath ][ operation ][ "value" ];
          } else {
                flush( filepath, operation );
            return 0;
          }
      } else {
            cache[ filepath ][ "hits" ]++;
          return cache[ filepath ][ operation ][ "value" ];
      }
    }

    int have( string filepath, string operation ) {
        filepath = fix_path( filepath );
      reqs++;
      if ( !cache[ filepath ] ) {
          return 0;
      } else if ( !cache[ filepath ][ operation ] ) {
          return 0;
      } else if ( cache[ filepath ][ operation ][ "timestamp" ] < time() - ttl ) {
          if ( ttl == 0 ) {
            hits++;
            return 1;
          } else {
                flush( filepath, operation );
            return 0;
          }
      } else {
            hits++;
          return 1;
      }
    }

    void flush( void|string filepath, void|string operation ) {
      if ( filepath ) {
            filepath = fix_path( filepath );
          if ( operation ) {
            cache[ filepath ] = m_delete( cache[ filepath ], operation );
          } else {
            cache = m_delete( cache, filepath );
          }
      } else {
          cache = ([ ]);
      }
    }

    string status() {
      string table = "";
        string indexname;
      foreach( indices( cache ), indexname ){
          if ( verbose_status_output == 0 ) {
            if ( sizeof( cache[ indexname ] ) < 3 ) {
                continue;
            }
          }
          table +=
            "<tr><td>" +
            indexname +
            "</td><td>" +
            sprintf( "%d", cache[ indexname ][ "hits" ] ) +
            "</td><td>" +
            sprintf( "%d", sizeof( cache[ indexname ] ) -1 ) +
                "</td></tr>\n";
      }
      string hitrate;
      if ( catch ( hitrate = sprintf( "%:2f", hits / reqs * 100 ) + "%" ) ) {
          return
                "<font size=+1><b>SQL Filesystem Cache Status</b></font><br><br>\n" +
            "<b>Cache Empty</b><br><br>\n";
      }
      return
          "<font size=+1><b>SQL Filesystem Cache Status</b></font><br><br>\n" +
          "<b>Number of cached objects:</b> " + sprintf( "%d", sizeof( cache ) ) + "<br>\n" +
          "<b>Cache hitrate:</b> " + hitrate + "<br>\n" +
          // "<b>Cache TTL:</b> " + sprintf( "%d", ttl ) + "<br>\n" +
          "<b>Cache Size (KB):</b> " + sprintf( "%d", cache_size() ) + "<br>\n" +
          "<br>\n" +
          "<table border=1>\n" +
          "<tr><td colspan=3><font size=+1><b>Cache Contents</b></font></td></tr>\n" +
          "<tr><td><b>File</b></td><td><b>Hits</b></td><td><b>Buckets used</b></td></tr>\n" +
          table +
          "</table>\n" +
          "<font size=-1>(due to the way the directory parsing module looks for index files it is possible there will be files in the cache that don't exist)<font><br>\n" +
            "<br>\n";
    }

    /*
     * Private methods
     * ---------------
     * These methods are used internally to the class.
     * fix_path() is used by all the public methods to make sure that we
     * don't wind up with cache inconsistencies (ie difference between "narf"
     * and "narf/").
     */

    private int cache_size() {
      int mem = 0;
        mixed var;
      array tmpstor = ({ });
      foreach( indices( cache ), var ) {
            mixed var2;
          foreach( indices( var ), var2 ) {
            tmpstor += ({ var2 });
          }
      }
      foreach( indices( tmpstor ), var ) {
          mem += sizeof( var );
      }
      tmpstor = ({ });
        return mem;
    }

    private string fix_path( string filepath ) {
        // there really must be a better way to do this!
      if ( filepath == "" ) {
          filepath = "/";
      }
      if ( filepath[ 0 ] != '/' ) {
          filepath = "/" + filepath;
      }
      if ( filepath[ -1 ] == '/' ) {
            filepath = filepath[ 0..sizeof( filepath ) - 2 ];
      }
      return filepath;
    }

}

Generated by  Doxygen 1.6.0   Back to index