Ticket #390: patch
File patch, 16.6 KB (added by , 15 years ago) |
---|
-
common/utils.h
28 28 #include <string> 29 29 using std::string; 30 30 31 #include "debuglog.h" 31 32 #include "str.h" 32 33 33 34 #include <cstdlib> … … 102 103 fdcloser(int fd_) : fd(fd_) {} 103 104 ~fdcloser() { 104 105 if (fd >= 0) { 106 IOLOG_CLOSE(1, fd); 105 107 (void)close(fd); 106 108 } 107 109 } -
common/debuglog.h
417 417 418 418 #endif 419 419 420 #define XAPIAN_DEBUG_FILEIO 1 421 #ifdef XAPIAN_DEBUG_FILEIO 422 423 #include <string> 424 #include "safeunistd.h" 425 #include "omtime.h" 426 427 class IoLogger { 428 const char type; 429 int fd; 430 std::string message; 431 bool is_done; 432 OmTime start; 433 public: 434 // Constructor used for open 435 IoLogger(const char type_, const char * filename); 436 IoLogger(const char type_, const std::string & filename); 437 438 // Constructor used for read and write 439 IoLogger(const char type_, int fd_, off_t offset, int bytes); 440 441 // Constructor used for close / sync 442 IoLogger(const char type_, int fd_); 443 444 void done(int fd_); 445 void done(); 446 ~IoLogger() { done(); } 447 }; 448 449 #define IOLOG_OPEN(var, filename) \ 450 IoLogger iolog_##var('o', (filename)) 451 #define IOLOG_CLOSE(var, fd) \ 452 IoLogger iolog_##var('c', (fd)) 453 #define IOLOG_PREAD(var, fd, offset, bytes) \ 454 IoLogger iolog_##var('r', (fd), (offset), (bytes)) 455 #define IOLOG_PWRITE(var, fd, offset, bytes) \ 456 IoLogger iolog_##var('w', (fd), (offset), (bytes)) 457 #define IOLOG_SYNC(var, fd) \ 458 IoLogger iolog_##var('s', (fd)) 459 #define IOLOG_OPENED(var, fd) iolog_##var.done((fd)) 460 #define IOLOG_DONE(var) iolog_##var.done() 461 462 #else 463 464 #define IOLOG_OPEN(var, filename) 465 #define IOLOG_CLOSE(var, fd) 466 #define IOLOG_PREAD(var, fd, offset, bytes) 467 #define IOLOG_PWRITE(var, fd, offset, bytes) 468 #define IOLOG_SYNC(var, fd) 469 #define IOLOG_OPENED(var, fd) 470 #define IOLOG_DONE(var) 471 472 #endif 473 474 420 475 #endif // XAPIAN_INCLUDED_DEBUGLOG_H -
common/debuglog.cc
141 141 } 142 142 143 143 #endif // XAPIAN_DEBUG_VERBOSE 144 145 // FIXME - don't need to include this when config is in config.h 146 #include "debuglog.h" 147 #ifdef XAPIAN_DEBUG_FILEIO 148 149 #include "debuglog.h" 150 151 #include "str.h" 152 153 #include <sys/types.h> 154 #include <sys/stat.h> 155 #include "safeerrno.h" 156 #include "safefcntl.h" 157 #include "safeunistd.h" 158 159 #include <cstdlib> // For getenv(). 160 #include <cstring> // For strerror(). 161 #include <string> 162 163 164 /// Class which writes the messages from IoLogger to disk 165 class IoLoggerWriter { 166 int fd; 167 public: 168 IoLoggerWriter() : fd(-1) {} 169 void init(); 170 void write(const std::string & message); 171 }; 172 173 void 174 IoLoggerWriter::init() 175 { 176 fd = -2; // Stop init() being called again. 177 const char * f = getenv("XAPIAN_IO_LOG"); 178 if (f && *f) { 179 if (f[0] == '-' && f[1] == '\0') { 180 // Filename "-" means "log to stderr". 181 fd = 2; 182 } else { 183 std::string fnm, pid; 184 while (*f) { 185 if (*f == '%' && f[1] == 'p') { 186 // Replace %p in the filename with the process id. 187 if (pid.empty()) pid = str(getpid()); 188 fnm += pid; 189 f += 2; 190 } else { 191 fnm += *f++; 192 } 193 } 194 195 fd = open(fnm.c_str(), O_CREAT|O_WRONLY|O_SYNC|O_APPEND, 0644); 196 if (fd == -1) { 197 fd = -2; 198 LOGLINE(ALWAYS, PACKAGE_STRING": Failed to open debug log '" 199 << fnm << "' (" << strerror(errno) << ')'); 200 } 201 } 202 } 203 } 204 205 void 206 IoLoggerWriter::write(const std::string & line) 207 { 208 if (fd == -1) init(); 209 if (fd < 0) return; 210 211 const char * p = line.data(); 212 size_t to_do = line.size(); 213 while (to_do) { 214 ssize_t n = ::write(fd, p, to_do); 215 if (n < 0) { 216 // Retry if interrupted by a signal. 217 if (errno == EINTR) continue; 218 219 // Upon other errors, close the log file, moan to the debug log, 220 // and stop logging. 221 (void)close(fd); 222 LOGLINE(ALWAYS, PACKAGE_STRING": Failed to write log output (" 223 << strerror(errno) << ')'); 224 fd = -2; 225 return; 226 } 227 p += n; 228 to_do -= n; 229 } 230 } 231 232 IoLoggerWriter xapian_iologger__; 233 234 IoLogger::IoLogger(const char type_, const char * filename) 235 : type(type_), fd(-1), is_done(false), start(OmTime::now()) 236 { 237 message = filename; 238 } 239 240 IoLogger::IoLogger(const char type_, const std::string & filename) 241 : type(type_), fd(-1), is_done(false), start(OmTime::now()) 242 { 243 message = filename; 244 } 245 246 IoLogger::IoLogger(const char type_, int fd_, off_t offset, int bytes) 247 : type(type_), fd(fd_), is_done(false), start(OmTime::now()) 248 { 249 message = str(offset) + "," + str(bytes); 250 } 251 252 IoLogger::IoLogger(const char type_, int fd_) 253 : type(type_), fd(fd_), is_done(false), start(OmTime::now()) 254 { 255 } 256 257 void IoLogger::done() 258 { 259 if (is_done) return; 260 is_done = true; 261 262 std::string line; 263 line += type; 264 line += str(fd); 265 line += ','; 266 long long t = start.as_double() * 1000000.0; 267 line += str(t); 268 line += ','; 269 t = ((OmTime::now() - start).as_double()) * 1000000.0; 270 line += str(t); 271 line += ','; 272 line += message; 273 line += '\n'; 274 xapian_iologger__.write(line); 275 } 276 277 void IoLogger::done(int fd_) 278 { 279 fd = fd_; 280 done(); 281 } 282 283 #endif // XAPIAN_DEBUG_FILEIO -
backends/chert/chert_btreebase.cc
21 21 22 22 #include <config.h> 23 23 24 #include "debuglog.h" 24 25 #include "safeerrno.h" 25 26 #ifdef __WIN32__ 26 27 # include "msvc_posix_wrapper.h" … … 174 175 ChertTable_base::read(const string & name, char ch, string &err_msg) 175 176 { 176 177 string basename = name + "base" + ch; 178 IOLOG_OPEN(1, basename); 177 179 #ifdef __WIN32__ 178 180 int h = msvc_posix_open(basename.c_str(), O_RDONLY | O_BINARY); 179 181 #else 180 182 int h = open(basename.c_str(), O_RDONLY | O_BINARY); 181 183 #endif 184 IOLOG_OPENED(1, h); 182 185 183 186 if (h == -1) { 184 187 err_msg += "Couldn't open " + basename + ": " + strerror(errno) + "\n"; … … 307 310 } 308 311 buf += pack_uint(revision); // REVISION2 309 312 313 IOLOG_OPEN(1, filename); 310 314 #ifdef __WIN32__ 311 315 int h = msvc_posix_open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); 312 316 #else 313 317 int h = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); 314 318 #endif 319 IOLOG_OPENED(1, h); 315 320 if (h < 0) { 316 321 string message = string("Couldn't open base ") 317 322 + filename + " to write: " + strerror(errno); -
backends/chert/chert_version.cc
20 20 21 21 #include <config.h> 22 22 23 #include "debuglog.h" 23 24 #include "safeerrno.h" 24 25 25 26 #include <xapian/error.h> … … 71 72 uuid_generate(uuid); 72 73 memcpy(buf + MAGIC_LEN + 4, (void*)uuid, 16); 73 74 75 IOLOG_OPEN(1, filename); 74 76 int fd = ::open(filename.c_str(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666); 77 IOLOG_OPENED(1, fd); 75 78 76 79 if (fd < 0) { 77 80 string msg("Failed to create chert version file: "); … … 82 85 try { 83 86 chert_io_write(fd, buf, VERSIONFILE_SIZE); 84 87 } catch (...) { 88 IOLOG_CLOSE(2, fd); 85 89 (void)close(fd); 86 90 throw; 87 91 } 88 92 93 IOLOG_CLOSE(3, fd); 89 94 if (close(fd) != 0) { 90 95 string msg("Failed to create chert version file: "); 91 96 msg += filename; 92 97 throw Xapian::DatabaseOpeningError(msg, errno); 93 98 } 99 IOLOG_DONE(3); 94 100 } 95 101 96 102 void 97 103 ChertVersion::read_and_check() 98 104 { 105 IOLOG_OPEN(1, filename); 99 106 int fd = ::open(filename.c_str(), O_RDONLY|O_BINARY); 107 IOLOG_OPENED(1, fd); 100 108 101 109 if (fd < 0) { 102 110 string msg = filename; … … 110 118 try { 111 119 size = chert_io_read(fd, buf, VERSIONFILE_SIZE + 1, 0); 112 120 } catch (...) { 121 IOLOG_CLOSE(2, fd); 113 122 (void)close(fd); 114 123 throw; 115 124 } 125 IOLOG_CLOSE(3, fd); 116 126 (void)close(fd); 127 IOLOG_DONE(3); 117 128 118 129 if (size != VERSIONFILE_SIZE) { 119 130 CompileTimeAssert(VERSIONFILE_SIZE == VERSIONFILE_SIZE_LITERAL); -
backends/chert/chert_table.cc
214 214 */ 215 215 Assert(n / CHAR_BIT < base.get_bit_map_size()); 216 216 217 IOLOG_PREAD(1, handle, off_t(block_size) * n, block_size); 217 218 #ifdef HAVE_PREAD 218 219 off_t offset = off_t(block_size) * n; 219 220 int m = block_size; … … 277 278 latest_revision_number = revision_number; 278 279 } 279 280 281 IOLOG_PWRITE(1, handle, off_t(block_size) * n, block_size); 280 282 #ifdef HAVE_PWRITE 281 283 off_t offset = off_t(block_size) * n; 282 284 int m = block_size; … … 1352 1354 1353 1355 if (!valid_base) { 1354 1356 if (handle >= 0) { 1357 IOLOG_CLOSE(1, handle); 1355 1358 ::close(handle); 1359 IOLOG_DONE(1); 1356 1360 handle = -1; 1357 1361 } 1358 1362 string message = "Error opening table `"; … … 1502 1506 } 1503 1507 int flags = O_RDWR | O_BINARY; 1504 1508 if (create_db) flags |= O_CREAT | O_TRUNC; 1509 IOLOG_OPEN(1, name + "DB"); 1505 1510 handle = ::open((name + "DB").c_str(), flags, 0666); 1511 IOLOG_OPENED(1, handle); 1506 1512 if (handle < 0) { 1507 1513 // lazy doesn't make a lot of sense with create_db anyway, but ENOENT 1508 1514 // with O_CREAT means a parent directory doesn't exist. … … 1518 1524 } 1519 1525 1520 1526 if (!basic_open(revision_supplied, revision_)) { 1527 IOLOG_CLOSE(2, handle); 1521 1528 ::close(handle); 1529 IOLOG_DONE(2); 1522 1530 handle = -1; 1523 1531 if (!revision_supplied) { 1524 1532 throw Xapian::DatabaseOpeningError("Failed to open for writing"); … … 1769 1777 if (handle >= 0) { 1770 1778 // If an error occurs here, we just ignore it, since we're just 1771 1779 // trying to free everything. 1780 IOLOG_CLOSE(1, handle); 1772 1781 (void)::close(handle); 1782 IOLOG_DONE(1); 1773 1783 handle = -1; 1774 1784 } 1775 1785 … … 1864 1874 1865 1875 // Do this as late as possible to allow maximum time for writes to be 1866 1876 // committed. 1877 IOLOG_SYNC(1, handle); 1867 1878 if (!chert_io_sync(handle)) { 1879 IOLOG_DONE(1); 1880 IOLOG_CLOSE(2, handle); 1868 1881 (void)::close(handle); 1882 IOLOG_DONE(2); 1869 1883 handle = -1; 1870 1884 throw Xapian::DatabaseError("Can't commit new revision - failed to flush DB to disk"); 1871 1885 } 1886 IOLOG_DONE(1); 1872 1887 1873 1888 // Save to "<table>.tmp" and then rename to "<table>.base<letter>" so 1874 1889 // that a reader can't try to read a partially written base file. … … 2006 2021 if (handle == -2) { 2007 2022 ChertTable::throw_database_closed(); 2008 2023 } 2024 IOLOG_OPEN(1, name + "DB"); 2009 2025 handle = ::open((name + "DB").c_str(), O_RDONLY | O_BINARY); 2026 IOLOG_OPENED(1, handle); 2010 2027 if (handle < 0) { 2011 2028 if (lazy) { 2012 2029 // This table is optional when reading! … … 2021 2038 } 2022 2039 2023 2040 if (!basic_open(revision_supplied, revision_)) { 2041 IOLOG_CLOSE(2, handle); 2024 2042 ::close(handle); 2043 IOLOG_DONE(2); 2025 2044 handle = -1; 2026 2045 if (revision_supplied) { 2027 2046 // The requested revision was not available. -
backends/flint/flint_version.cc
20 20 21 21 #include <config.h> 22 22 23 #include "debuglog.h" 23 24 #include "safeerrno.h" 24 25 25 26 #include <xapian/error.h> … … 68 69 v[2] = static_cast<unsigned char>((FLINT_VERSION >> 16) & 0xff); 69 70 v[3] = static_cast<unsigned char>((FLINT_VERSION >> 24) & 0xff); 70 71 72 IOLOG_OPEN(1, filename); 71 73 int fd = ::open(filename.c_str(), O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0666); 74 IOLOG_OPENED(1, fd); 72 75 73 76 if (fd < 0) { 74 77 string msg("Failed to create flint version file: "); … … 79 82 try { 80 83 flint_io_write(fd, buf, VERSIONFILE_SIZE); 81 84 } catch (...) { 85 IOLOG_CLOSE(2, fd); 82 86 (void)close(fd); 83 87 throw; 84 88 } 85 89 90 IOLOG_CLOSE(3, fd); 86 91 if (close(fd) != 0) { 87 92 string msg("Failed to create flint version file: "); 88 93 msg += filename; 89 94 throw Xapian::DatabaseOpeningError(msg, errno); 90 95 } 96 IOLOG_DONE(3); 91 97 92 98 uuid_clear(uuid); 93 99 ensure_uuid(); … … 95 101 96 102 void FlintVersion::read_and_check(bool readonly) 97 103 { 104 IOLOG_OPEN(1, filename); 98 105 int fd = ::open(filename.c_str(), O_RDONLY|O_BINARY); 106 IOLOG_OPENED(1, fd); 99 107 100 108 if (fd < 0) { 101 109 string msg("Failed to open flint version file for reading: "); … … 109 117 try { 110 118 size = flint_io_read(fd, buf, VERSIONFILE_SIZE + 1, 0); 111 119 } catch (...) { 120 IOLOG_CLOSE(2, fd); 112 121 (void)close(fd); 113 122 throw; 114 123 } 124 IOLOG_CLOSE(3, fd); 115 125 (void)close(fd); 126 IOLOG_DONE(3); 116 127 117 128 if (size != VERSIONFILE_SIZE) { 118 129 string msg("Flint version file "); -
backends/flint/flint_table.cc
228 228 */ 229 229 Assert(n / CHAR_BIT < base.get_bit_map_size()); 230 230 231 IOLOG_PREAD(1, handle, off_t(block_size) * n, block_size); 231 232 #ifdef HAVE_PREAD 232 233 off_t offset = off_t(block_size) * n; 233 234 int m = block_size; … … 291 292 latest_revision_number = revision_number; 292 293 } 293 294 295 IOLOG_PWRITE(1, handle, off_t(block_size) * n, block_size); 294 296 #ifdef HAVE_PWRITE 295 297 off_t offset = off_t(block_size) * n; 296 298 int m = block_size; … … 1341 1343 1342 1344 if (!valid_base) { 1343 1345 if (handle >= 0) { 1346 IOLOG_CLOSE(1, handle); 1344 1347 ::close(handle); 1348 IOLOG_DONE(1); 1345 1349 handle = -1; 1346 1350 } 1347 1351 string message = "Error opening table `"; … … 1489 1493 } 1490 1494 int flags = O_RDWR | O_BINARY; 1491 1495 if (create_db) flags |= O_CREAT | O_TRUNC; 1496 IOLOG_OPEN(1, name + "DB"); 1492 1497 handle = ::open((name + "DB").c_str(), flags, 0666); 1498 IOLOG_OPENED(1, handle); 1493 1499 if (handle < 0) { 1494 1500 // lazy doesn't make a lot of sense with create_db anyway, but ENOENT 1495 1501 // with O_CREAT means a parent directory doesn't exist. … … 1505 1511 } 1506 1512 1507 1513 if (!basic_open(revision_supplied, revision_)) { 1514 IOLOG_CLOSE(2, handle); 1508 1515 ::close(handle); 1516 IOLOG_DONE(2); 1509 1517 handle = -1; 1510 1518 if (!revision_supplied) { 1511 1519 throw Xapian::DatabaseOpeningError("Failed to open for writing"); … … 1756 1764 if (handle >= 0) { 1757 1765 // If an error occurs here, we just ignore it, since we're just 1758 1766 // trying to free everything. 1767 IOLOG_CLOSE(1, handle); 1759 1768 (void)::close(handle); 1769 IOLOG_DONE(1); 1760 1770 handle = -1; 1761 1771 } 1762 1772 … … 1852 1862 1853 1863 // Do this as late as possible to allow maximum time for writes to be 1854 1864 // committed. 1865 IOLOG_SYNC(1, handle); 1855 1866 if (!flint_io_sync(handle)) { 1867 IOLOG_DONE(1); 1868 IOLOG_CLOSE(2, handle); 1856 1869 (void)::close(handle); 1870 IOLOG_DONE(2); 1857 1871 handle = -1; 1858 1872 throw Xapian::DatabaseError("Can't commit new revision - failed to flush DB to disk"); 1859 1873 } 1874 IOLOG_DONE(1); 1860 1875 1861 1876 // Save to "<table>.tmp" and then rename to "<table>.base<letter>" so 1862 1877 // that a reader can't try to read a partially written base file. … … 1992 2007 if (handle == -2) { 1993 2008 FlintTable::throw_database_closed(); 1994 2009 } 2010 IOLOG_OPEN(1, name + "DB"); 1995 2011 handle = ::open((name + "DB").c_str(), O_RDONLY | O_BINARY); 2012 IOLOG_OPENED(1, handle); 1996 2013 if (handle < 0) { 1997 2014 if (lazy) { 1998 2015 // This table is optional when reading! … … 2007 2024 } 2008 2025 2009 2026 if (!basic_open(revision_supplied, revision_)) { 2027 IOLOG_CLOSE(2, handle); 2010 2028 ::close(handle); 2029 IOLOG_DONE(2); 2011 2030 handle = -1; 2012 2031 if (revision_supplied) { 2013 2032 // The requested revision was not available. -
backends/flint/flint_btreebase.cc
21 21 22 22 #include <config.h> 23 23 24 #include "debuglog.h" 24 25 #include "safeerrno.h" 25 26 #ifdef __WIN32__ 26 27 # include "msvc_posix_wrapper.h" … … 170 171 FlintTable_base::read(const string & name, char ch, string &err_msg) 171 172 { 172 173 string basename = name + "base" + ch; 174 IOLOG_OPEN(1, basename); 173 175 #ifdef __WIN32__ 174 176 int h = msvc_posix_open(basename.c_str(), O_RDONLY | O_BINARY); 175 177 #else 176 178 int h = open(basename.c_str(), O_RDONLY | O_BINARY); 177 179 #endif 180 IOLOG_OPENED(1, h); 178 181 179 182 if (h == -1) { 180 183 err_msg += "Couldn't open " + basename + ": " + strerror(errno) + "\n"; … … 303 306 } 304 307 buf += F_pack_uint(revision); // REVISION2 305 308 309 IOLOG_OPEN(1, filename); 306 310 #ifdef __WIN32__ 307 311 int h = msvc_posix_open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); 308 312 #else 309 313 int h = open(filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); 310 314 #endif 315 IOLOG_OPENED(1, h); 311 316 if (h < 0) { 312 317 string message = string("Couldn't open base ") 313 318 + filename + " to write: " + strerror(errno);