Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvwatcher.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * The WvFileWatcher class provides support for files which sometimes 00006 * have data appended at the end. It only polls as often as your select() 00007 * delay, so be careful! 00008 * 00009 * The file is rewound and reopened if its inode changes or its 00010 * length gets shorter, under the assumption that we will want to see the 00011 * entire contents of the new file. 00012 * 00013 * See wvwatcher.h. 00014 */ 00015 #include "wvwatcher.h" 00016 #include <sys/time.h> 00017 #include <errno.h> 00018 00019 WvFileWatcher::WvFileWatcher(const char *_filename, int _mode) 00020 : WvFile(_filename, _mode), filename(_filename) 00021 { 00022 once_ok = WvFile::isok(); 00023 openmode = _mode; 00024 fpos = 0; 00025 if (stat(filename, &last_st) && WvFile::isok()) 00026 { 00027 errnum = errno; 00028 close(); 00029 once_ok = false; 00030 } 00031 } 00032 00033 00034 bool WvFileWatcher::isok() const 00035 { 00036 return once_ok; 00037 } 00038 00039 00040 bool WvFileWatcher::make_ok(bool retry) 00041 { 00042 // if the inode has changed, or the size is smaller than last 00043 // time, or we cannot stat the file, close it and start over. 00044 struct stat st; 00045 if (getrfd() >= 0 00046 && (stat(filename, &st) 00047 || st.st_ino != last_st.st_ino || st.st_size < last_st.st_size)) 00048 { 00049 close(); 00050 } 00051 00052 // make sure the file is open 00053 while (!WvFile::isok()) 00054 { 00055 fpos = 0; 00056 if (!open(filename, openmode) && retry) 00057 sleep(1); 00058 if (!retry && !WvFile::isok()) 00059 return false; // no such luck 00060 } 00061 00062 stat(filename, &last_st); 00063 return true; 00064 } 00065 00066 00067 size_t WvFileWatcher::uread(void *buf, size_t size) 00068 { 00069 size_t len; 00070 if (!once_ok) return 0; // this is never going to work 00071 00072 if (select(0)) 00073 { 00074 len = WvFile::uread(buf, size); 00075 fpos += len; 00076 return len; 00077 } 00078 00079 return 0; 00080 } 00081 00082 00083 size_t WvFileWatcher::uwrite(const void *buf, size_t size) 00084 { 00085 size_t len; 00086 if (!once_ok) return 0; 00087 make_ok(true); 00088 len = WvFile::uwrite(buf, size); 00089 fpos += len; 00090 return len; 00091 } 00092 00093 00094 // since you cannot really select() on a real file, we fake it: 00095 // pre_select() returns true if the file is longer than it was last time, 00096 // or you want to write to it. Otherwise the file is "not ready." 00097 // Because this happens in pre_select, the file will only be checked as 00098 // often as your select() delay. So infinite delays are a bad idea! 00099 bool WvFileWatcher::pre_select(SelectInfo &si) 00100 { 00101 struct stat st; 00102 00103 if (!once_ok) return false; 00104 00105 if (si.wants.writable) 00106 return true; // always writable 00107 00108 if (!si.wants.readable) 00109 return false; // what are you asking? 00110 00111 // readable if the current location pointer is < size 00112 if (getrfd() >= 0 && si.wants.readable 00113 && !fstat(getrfd(), &st) && fpos < st.st_size) 00114 return true; 00115 00116 // get the file open, at least 00117 if (make_ok(false)) 00118 { 00119 // writable as long as file is open 00120 if (si.wants.writable) 00121 return true; 00122 00123 if (si.wants.readable && fpos < last_st.st_size) 00124 return true; 00125 } 00126 00127 return false; 00128 }

Generated on Tue Oct 5 01:09:21 2004 for WvStreams by doxygen 1.3.7