Passenger: CachedFileStat.h Source File

- Main Page
- Modules
- Classes
- Files

- File List

# CachedFileStat.h

    00001 /*
    00002  *  Phusion Passenger - http://www.modrails.com/
    00003  *  Copyright (C) 2009  Phusion
    00004  *
    00005  *  Phusion Passenger is a trademark of Hongli Lai & Ninh Bui.
    00006  *
    00007  *  This program is free software; you can redistribute it and/or modify
    00008  *  it under the terms of the GNU General Public License as published by
    00009  *  the Free Software Foundation; version 2 of the License.
    00010  *
    00011  *  This program is distributed in the hope that it will be useful,
    00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00014  *  GNU General Public License for more details.
    00015  *
    00016  *  You should have received a copy of the GNU General Public License along
    00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
    00018  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    00019  */
    00020 #ifndef _PASSENGER_CACHED_FILE_STAT_H_
    00021 #define _PASSENGER_CACHED_FILE_STAT_H_
    00022
    00023 #include <sys/types.h>
    00024 #include <sys/stat.h>
    00025 #include <unistd.h>
    00026 #include <time.h>
    00027
    00028 #ifdef __cplusplus
    00029
    00030 #include <errno.h>
    00031 #include <string>
    00032 #include <oxt/system_calls.hpp>
    00033
    00034 #include "SystemTime.h"
    00035
    00036 namespace Passenger {
    00037
    00038 using namespace std;
    00039 using namespace oxt;
    00040
    00041 /**
    00042  * CachedFileStat allows one to stat() a file at a throttled rate, in order
    00043  * to minimize stress on the filesystem. It does this by caching the old stat
    00044  * data for a specified amount of time.
    00045  */
    00046 class CachedFileStat {
    00047 private:
    00048         /** The last return value of stat(). */
    00049         int last_result;
    00050
    00051         /** The errno set by the last stat() call. */
    00052         int last_errno;
    00053
    00054         /** The filename of the file to stat. */
    00055         string filename;
    00056
    00057         /** The last time a stat() was performed. */
    00058         time_t last_time;
    00059
    00060         /**
    00061          * Checks whether <em>interval</em> seconds have elapsed since <em>begin</em>
    00062          * The current time is returned via the <tt>currentTime</tt> argument,
    00063          * so that the caller doesn't have to call time() again if it needs the current
    00064          * time.
    00065          *
    00066          * @pre begin <= time(NULL)
    00067          * @return Whether <tt>interval</tt> seconds have elapsed since <tt>begin</tt>.
    00068          * @throws SystemException Something went wrong while retrieving the time.
    00069          * @throws boost::thread_interrupted
    00070          */
    00071         bool expired(time_t begin, unsigned int interval, time_t &currentTime) {
    00072                 currentTime = SystemTime::get();
    00073                 return (unsigned int) (currentTime - begin) >= interval;
    00074         }
    00075
    00076 public:
    00077         /** The cached stat info. */
    00078         struct stat info;
    00079
    00080         /**
    00081          * Creates a new CachedFileStat object. The file will not be
    00082          * stat()ted until you call refresh().
    00083          *
    00084          * @param filename The file to stat.
    00085          */
    00086         CachedFileStat(const string &filename) {
    00087                 memset(&info, 0, sizeof(struct stat));
    00088                 last_result = -1;
    00089                 last_errno = 0;
    00090                 this->filename = filename;
    00091                 last_time = 0;
    00092         }
    00093
    00094         /**
    00095          * Re-stat() the file, if necessary. If <tt>throttleRate</tt> seconds have
    00096          * passed since the last time stat() was called, then the file will be
    00097          * re-stat()ted.
    00098          *
    00099          * The stat information, which may either be the result of a new stat() call
    00100          * or just the old cached information, is be available in the <tt>info</tt>
    00101          * member.
    00102          *
    00103          * @return 0 if the stat() call succeeded or if no stat() was performed,
    00104          *         -1 if something went wrong while statting the file. In the latter
    00105          *         case, <tt>errno</tt> will be populated with an appropriate error code.
    00106          * @throws SystemException Something went wrong while retrieving the
    00107          *         system time. stat() errors will <em>not</em> result in SystemException
    00108          *         being thrown.
    00109          * @throws boost::thread_interrupted
    00110          */
    00111         int refresh(unsigned int throttleRate) {
    00112                 time_t currentTime;
    00113
    00114                 if (expired(last_time, throttleRate, currentTime)) {
    00115                         last_result = syscalls::stat(filename.c_str(), &info);
    00116                         last_errno = errno;
    00117                         last_time = currentTime;
    00118                         return last_result;
    00119                 } else {
    00120                         errno = last_errno;
    00121                         return last_result;
    00122                 }
    00123         }
    00124 };
    00125
    00126 } // namespace Passenger
    00127
    00128 #endif /* __cplusplus */
    00129
    00130
    00131 #ifdef __cplusplus
    00132         extern "C" {
    00133 #endif
    00134
    00135 /**
    00136  * CachedMultiFileStat allows one to stat() files at a throttled rate, in order
    00137  * to minimize stress on the filesystem. It does this by caching the old stat
    00138  * data for a specified amount of time.
    00139  *
    00140  * Unlike CachedFileStat, which can only stat() one specific file per
    00141  * CachedFileStat object, CachedMultiFileStat can stat() any file. The
    00142  * number of cached stat() information is limited by the given cache size.
    00143  *
    00144  * This class is fully thread-safe.
    00145  */
    00146 typedef struct CachedMultiFileStat CachedMultiFileStat;
    00147
    00148 CachedMultiFileStat *cached_multi_file_stat_new(unsigned int max_size);
    00149 void cached_multi_file_stat_free(CachedMultiFileStat *mstat);
    00150 int  cached_multi_file_stat_perform(CachedMultiFileStat *mstat,
    00151                                     const char *filename,
    00152                                     struct stat *buf,
    00153                                     unsigned int throttle_rate);
    00154
    00155 #ifdef __cplusplus
    00156         }
    00157 #endif
    00158
    00159 #endif /* _PASSENGER_CACHED_FILE_STAT_H_ */
    00160