00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "libts.h"
00031
00032 #include <errno.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036
00037 #include "Error.h"
00038
00039 #include "P_EventSystem.h"
00040 #include "I_Machine.h"
00041 #include "LogSock.h"
00042
00043 #include "LogField.h"
00044 #include "LogFilter.h"
00045 #include "LogFormat.h"
00046 #include "LogBuffer.h"
00047 #include "LogFile.h"
00048 #include "LogHost.h"
00049 #include "LogObject.h"
00050 #include "LogUtils.h"
00051 #include "LogConfig.h"
00052 #include "Log.h"
00053
00054
00055
00056
00057
00058
00059
00060
00061 LogFile::LogFile(const char *name, const char *header, LogFileFormat format,
00062 uint64_t signature, size_t ascii_buffer_size, size_t max_line_size)
00063 : m_file_format(format),
00064 m_name(ats_strdup(name)),
00065 m_header(ats_strdup(header)),
00066 m_signature(signature),
00067 m_meta_info(NULL),
00068 m_max_line_size(max_line_size)
00069 {
00070 delete m_meta_info;
00071 m_meta_info = NULL;
00072 m_fd = -1;
00073 m_start_time = 0L;
00074 m_end_time = 0L;
00075 m_bytes_written = 0;
00076 m_size_bytes = 0;
00077 m_ascii_buffer_size = (ascii_buffer_size < max_line_size ? max_line_size : ascii_buffer_size);
00078
00079 Debug("log-file", "exiting LogFile constructor, m_name=%s, this=%p", m_name, this);
00080 }
00081
00082
00083
00084
00085
00086
00087
00088 LogFile::LogFile (const LogFile& copy)
00089 : m_file_format (copy.m_file_format),
00090 m_name (ats_strdup (copy.m_name)),
00091 m_header (ats_strdup (copy.m_header)),
00092 m_signature (copy.m_signature),
00093 m_meta_info (NULL),
00094 m_ascii_buffer_size (copy.m_ascii_buffer_size),
00095 m_max_line_size (copy.m_max_line_size),
00096 m_fd (-1),
00097 m_start_time (0L),
00098 m_end_time (0L),
00099 m_bytes_written (0)
00100 {
00101 ink_release_assert(m_ascii_buffer_size >= m_max_line_size);
00102
00103 Debug("log-file", "exiting LogFile copy constructor, m_name=%s, this=%p",
00104 m_name, this);
00105 }
00106
00107
00108
00109
00110 LogFile::~LogFile()
00111 {
00112 Debug("log-file", "entering LogFile destructor, this=%p", this);
00113 close_file();
00114
00115 ats_free(m_name);
00116 ats_free(m_header);
00117 delete m_meta_info;
00118 Debug("log-file", "exiting LogFile destructor, this=%p", this);
00119 }
00120
00121
00122
00123
00124
00125
00126
00127 bool LogFile::exists(const char *pathname)
00128 {
00129 ink_assert(pathname != NULL);
00130 return (pathname && ::access(pathname, F_OK) == 0);
00131 }
00132
00133
00134
00135
00136
00137 void
00138 LogFile::change_name(const char *new_name)
00139 {
00140 ats_free(m_name);
00141 m_name = ats_strdup(new_name);
00142 }
00143
00144
00145
00146
00147
00148 void
00149 LogFile::change_header(const char *header)
00150 {
00151 ats_free(m_header);
00152 m_header = ats_strdup(header);
00153 }
00154
00155
00156
00157
00158
00159
00160
00161
00162 int
00163 LogFile::open_file()
00164 {
00165 if (is_open()) {
00166 return LOG_FILE_NO_ERROR;
00167 }
00168
00169 if (m_name && !strcmp(m_name, "stdout")) {
00170 m_fd = STDOUT_FILENO;
00171 return LOG_FILE_NO_ERROR;
00172 }
00173
00174
00175
00176
00177 bool file_exists = LogFile::exists(m_name);
00178
00179 if (file_exists) {
00180 if (!m_meta_info) {
00181
00182
00183
00184
00185 m_meta_info = new MetaInfo(m_name);
00186 }
00187 } else {
00188
00189
00190 m_meta_info = new MetaInfo(m_name, LogUtils::timestamp(), m_signature);
00191 }
00192
00193 int flags, perms;
00194
00195 if (m_file_format == LOG_FILE_PIPE) {
00196 if (mkfifo(m_name, S_IRUSR | S_IWUSR) < 0) {
00197 if (errno != EEXIST) {
00198 Error("Could not create named pipe %s for logging: %s", m_name, strerror(errno));
00199 return LOG_FILE_COULD_NOT_CREATE_PIPE;
00200 }
00201 } else {
00202 Debug("log-file", "Created named pipe %s for logging", m_name);
00203 }
00204 flags = O_WRONLY | O_NDELAY;
00205 perms = 0;
00206 } else {
00207 flags = O_WRONLY | O_APPEND | O_CREAT;
00208 perms = Log::config->logfile_perm;
00209 }
00210
00211 Debug("log-file", "attempting to open %s", m_name);
00212 m_fd =::open(m_name, flags, perms);
00213
00214 if (m_fd < 0) {
00215
00216
00217
00218 if (errno != ENXIO) {
00219 Error("Error opening log file %s: %s", m_name, strerror(errno));
00220 return LOG_FILE_COULD_NOT_OPEN_FILE;
00221 }
00222 Debug("log-file", "no readers for pipe %s", m_name);
00223 return LOG_FILE_NO_PIPE_READERS;
00224 }
00225
00226 int e = do_filesystem_checks();
00227 if (e != 0) {
00228 m_fd = -1;
00229 return LOG_FILE_FILESYSTEM_CHECKS_FAILED;
00230 }
00231
00232
00233 m_bytes_written = lseek( m_fd, 0, SEEK_CUR );
00234
00235 Debug("log-file", "LogFile %s is now open (fd=%d)", m_name, m_fd);
00236
00237
00238
00239
00240
00241
00242
00243 if (!file_exists) {
00244 if (m_file_format != LOG_FILE_BINARY && m_header != NULL) {
00245 Debug("log-file", "writing header to LogFile %s", m_name);
00246 writeln(m_header, strlen(m_header), m_fd, m_name);
00247 }
00248 }
00249
00250 RecIncrRawStat(log_rsb, this_thread()->mutex->thread_holding,
00251 log_stat_log_files_open_stat, 1);
00252
00253 return LOG_FILE_NO_ERROR;
00254 }
00255
00256
00257
00258
00259
00260
00261
00262 void
00263 LogFile::close_file()
00264 {
00265 if (is_open()) {
00266 ::close(m_fd);
00267 Debug("log-file", "LogFile %s (fd=%d) is closed", m_name, m_fd);
00268 m_fd = -1;
00269
00270 RecIncrRawStat(log_rsb, this_thread()->mutex->thread_holding,
00271 log_stat_log_files_open_stat, -1);
00272 }
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282 bool LogFile::rolled_logfile(char *path)
00283 {
00284 const int
00285 target_len = (int) strlen(LOGFILE_ROLLED_EXTENSION);
00286 int
00287 len = (int) strlen(path);
00288 if (len > target_len) {
00289 char *
00290 str = &path[len - target_len];
00291 if (!strcmp(str, LOGFILE_ROLLED_EXTENSION)) {
00292 return true;
00293 }
00294 }
00295 return false;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324 int
00325 LogFile::roll(long interval_start, long interval_end)
00326 {
00327
00328
00329
00330 if (m_name == NULL || !LogFile::exists(m_name)) {
00331 Debug("log-file", "Roll not needed for %s; file doesn't exist", (m_name) ? m_name : "no_name");
00332 return 0;
00333 }
00334
00335
00336 if (!m_meta_info) {
00337 m_meta_info = new MetaInfo(m_name);
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 char roll_name[MAXPATHLEN];
00350 char start_time_ext[64];
00351 char end_time_ext[64];
00352 time_t start, end;
00353
00354
00355
00356
00357 close_file();
00358
00359
00360
00361
00362
00363 start = 0L;
00364 end = (interval_end >= m_end_time) ? interval_end : m_end_time;
00365
00366 if (m_meta_info->data_from_metafile()) {
00367
00368
00369
00370
00371
00372
00373
00374 m_meta_info->get_creation_time(&start);
00375 } else {
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388 start = (m_start_time < interval_start) ? m_start_time : interval_start;
00389 }
00390
00391
00392
00393
00394
00395 LogUtils::timestamp_to_str((long) start, start_time_ext, 64);
00396 LogUtils::timestamp_to_str((long) end, end_time_ext, 64);
00397 snprintf(roll_name, MAXPATHLEN, "%s%s%s.%s-%s%s",
00398 m_name,
00399 LOGFILE_SEPARATOR_STRING,
00400 Machine::instance()->hostname, start_time_ext, end_time_ext, LOGFILE_ROLLED_EXTENSION);
00401
00402
00403
00404
00405
00406
00407
00408 int version = 1;
00409 while (LogFile::exists(roll_name)) {
00410 Note("The rolled file %s already exists; adding version "
00411 "tag %d to avoid clobbering the existing file.", roll_name, version);
00412 snprintf(roll_name, MAXPATHLEN, "%s%s%s.%s-%s.%d%s",
00413 m_name,
00414 LOGFILE_SEPARATOR_STRING,
00415 Machine::instance()->hostname, start_time_ext, end_time_ext, version, LOGFILE_ROLLED_EXTENSION);
00416 version++;
00417 }
00418
00419
00420
00421
00422
00423 if (::rename(m_name, roll_name) < 0) {
00424 Warning("Traffic Server could not rename logfile %s to %s, error %d: "
00425 "%s.", m_name, roll_name, errno, strerror(errno));
00426 return 0;
00427 }
00428
00429
00430 m_start_time = 0;
00431 m_bytes_written = 0;
00432
00433 Debug("log-file", "The logfile %s was rolled to %s.", m_name, roll_name);
00434
00435 return 1;
00436 }
00437
00438
00439
00440
00441
00442
00443
00444 int
00445 LogFile::preproc_and_try_delete(LogBuffer * lb)
00446 {
00447 int ret = -1;
00448 LogBufferHeader *buffer_header;
00449
00450 if (lb == NULL) {
00451 Note("Cannot write LogBuffer to LogFile %s; LogBuffer is NULL", m_name);
00452 return -1;
00453 }
00454
00455 ink_atomic_increment(&lb->m_references, 1);
00456
00457 if ((buffer_header = lb->header()) == NULL) {
00458 Note("Cannot write LogBuffer to LogFile %s; LogBufferHeader is NULL",
00459 m_name);
00460 goto done;
00461 }
00462 if (buffer_header->entry_count == 0) {
00463
00464 Note("LogBuffer with 0 entries for LogFile %s, nothing to write", m_name);
00465 goto done;
00466 }
00467
00468
00469
00470
00471
00472
00473 if (!m_start_time)
00474 m_start_time = buffer_header->low_timestamp;
00475 m_end_time = buffer_header->high_timestamp;
00476
00477 if (m_file_format == LOG_FILE_BINARY) {
00478
00479
00480
00481
00482
00483
00484
00485
00486 LogFlushData *flush_data = new LogFlushData(this, lb);
00487
00488 ProxyMutex *mutex = this_thread()->mutex;
00489
00490 RecIncrRawStat(log_rsb, mutex->thread_holding, log_stat_num_flush_to_disk_stat,
00491 lb->header()->entry_count);
00492
00493 RecIncrRawStat(log_rsb, mutex->thread_holding, log_stat_bytes_flush_to_disk_stat,
00494 lb->header()->byte_count);
00495
00496 ink_atomiclist_push(Log::flush_data_list, flush_data);
00497
00498 Log::flush_notify->signal();
00499
00500
00501
00502
00503 return 0;
00504 }
00505 else if (m_file_format == LOG_FILE_ASCII || m_file_format == LOG_FILE_PIPE) {
00506 write_ascii_logbuffer3(buffer_header);
00507 ret = 0;
00508 }
00509 else {
00510 Note("Cannot write LogBuffer to LogFile %s; invalid file format: %d",
00511 m_name, m_file_format);
00512 }
00513
00514 done:
00515 LogBuffer::destroy(lb);
00516 return ret;
00517 }
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 int
00530 LogFile::write_ascii_logbuffer(LogBufferHeader * buffer_header, int fd, const char *path, const char *alt_format)
00531 {
00532 ink_assert(buffer_header != NULL);
00533 ink_assert(fd >= 0);
00534
00535 char fmt_buf[LOG_MAX_FORMATTED_BUFFER];
00536 char fmt_line[LOG_MAX_FORMATTED_LINE];
00537 LogBufferIterator iter(buffer_header);
00538 LogEntryHeader *entry_header;
00539 int fmt_buf_bytes = 0;
00540 int fmt_line_bytes = 0;
00541 int bytes = 0;
00542
00543 LogFormatType format_type;
00544 char *fieldlist_str;
00545 char *printf_str;
00546
00547 switch (buffer_header->version) {
00548 case LOG_SEGMENT_VERSION:
00549 format_type = (LogFormatType) buffer_header->format_type;
00550
00551 fieldlist_str = buffer_header->fmt_fieldlist();
00552 printf_str = buffer_header->fmt_printf();
00553 break;
00554
00555 default:
00556 Note("Invalid LogBuffer version %d in write_ascii_logbuffer; "
00557 "current version is %d", buffer_header->version, LOG_SEGMENT_VERSION);
00558 return 0;
00559 }
00560
00561 while ((entry_header = iter.next())) {
00562 fmt_line_bytes = LogBuffer::to_ascii(entry_header, format_type,
00563 &fmt_line[0], LOG_MAX_FORMATTED_LINE,
00564 fieldlist_str, printf_str, buffer_header->version, alt_format);
00565 ink_assert(fmt_line_bytes > 0);
00566
00567 if (fmt_line_bytes > 0) {
00568 if ((fmt_line_bytes + fmt_buf_bytes) >= LOG_MAX_FORMATTED_BUFFER) {
00569 if (!Log::config->logging_space_exhausted) {
00570 bytes += writeln(fmt_buf, fmt_buf_bytes, fd, path);
00571 }
00572 fmt_buf_bytes = 0;
00573 }
00574 ink_assert(fmt_buf_bytes < LOG_MAX_FORMATTED_BUFFER);
00575 ink_assert(fmt_line_bytes < LOG_MAX_FORMATTED_BUFFER - fmt_buf_bytes);
00576 memcpy(&fmt_buf[fmt_buf_bytes], fmt_line, fmt_line_bytes);
00577 fmt_buf_bytes += fmt_line_bytes;
00578 ink_assert(fmt_buf_bytes < LOG_MAX_FORMATTED_BUFFER);
00579 fmt_buf[fmt_buf_bytes] = '\n';
00580 fmt_buf_bytes += 1;
00581 }
00582 }
00583 if (fmt_buf_bytes > 0) {
00584 if (!Log::config->logging_space_exhausted) {
00585 ink_assert(fmt_buf_bytes < LOG_MAX_FORMATTED_BUFFER);
00586 bytes += writeln(fmt_buf, fmt_buf_bytes, fd, path);
00587 }
00588 }
00589
00590 return bytes;
00591 }
00592
00593 int
00594 LogFile::write_ascii_logbuffer3(LogBufferHeader * buffer_header, const char *alt_format)
00595 {
00596 Debug("log-file", "entering LogFile::write_ascii_logbuffer3 for %s " "(this=%p)", m_name, this);
00597 ink_assert(buffer_header != NULL);
00598
00599 ProxyMutex *mutex = this_thread()->mutex;
00600 LogBufferIterator iter(buffer_header);
00601 LogEntryHeader *entry_header;
00602 int fmt_entry_count = 0;
00603 int fmt_buf_bytes = 0;
00604 int total_bytes = 0;
00605
00606 LogFormatType format_type;
00607 char *fieldlist_str;
00608 char *printf_str;
00609 char *ascii_buffer;
00610
00611 switch (buffer_header->version) {
00612 case LOG_SEGMENT_VERSION:
00613 format_type = (LogFormatType) buffer_header->format_type;
00614 fieldlist_str = buffer_header->fmt_fieldlist();
00615 printf_str = buffer_header->fmt_printf();
00616 break;
00617
00618 default:
00619 Note("Invalid LogBuffer version %d in write_ascii_logbuffer; "
00620 "current version is %d", buffer_header->version, LOG_SEGMENT_VERSION);
00621 return 0;
00622 }
00623
00624 while ((entry_header = iter.next())) {
00625 fmt_entry_count = 0;
00626 fmt_buf_bytes = 0;
00627
00628 if (m_file_format == LOG_FILE_PIPE)
00629 ascii_buffer = (char *)malloc(m_max_line_size);
00630 else
00631 ascii_buffer = (char *)malloc(m_ascii_buffer_size);
00632
00633
00634
00635 do {
00636 if (entry_header->entry_len >= m_max_line_size) {
00637 Warning("Log is too long(%" PRIu32 "), it would be truncated. max_len:%zu",
00638 entry_header->entry_len, m_max_line_size);
00639 }
00640
00641 int bytes = LogBuffer::to_ascii(entry_header, format_type,
00642 &ascii_buffer[fmt_buf_bytes],
00643 m_max_line_size - 1,
00644 fieldlist_str, printf_str,
00645 buffer_header->version,
00646 alt_format);
00647
00648 if (bytes > 0) {
00649 fmt_buf_bytes += bytes;
00650 ascii_buffer[fmt_buf_bytes] = '\n';
00651 ++fmt_buf_bytes;
00652 ++fmt_entry_count;
00653 } else {
00654 Error("Failed to convert LogBuffer to ascii, have dropped (%" PRIu32 ") bytes.",
00655 entry_header->entry_len);
00656
00657 RecIncrRawStat(log_rsb, mutex->thread_holding,
00658 log_stat_num_lost_before_flush_to_disk_stat,
00659 fmt_entry_count);
00660
00661 RecIncrRawStat(log_rsb, mutex->thread_holding,
00662 log_stat_bytes_lost_before_flush_to_disk_stat,
00663 fmt_buf_bytes);
00664 }
00665
00666
00667
00668
00669 if (m_file_format == LOG_FILE_PIPE)
00670 break;
00671
00672 if (m_ascii_buffer_size - fmt_buf_bytes < m_max_line_size)
00673 break;
00674 } while ((entry_header = iter.next()));
00675
00676
00677
00678 LogFlushData *flush_data = new LogFlushData(this, ascii_buffer, fmt_buf_bytes);
00679
00680 RecIncrRawStat(log_rsb, mutex->thread_holding, log_stat_num_flush_to_disk_stat,
00681 fmt_entry_count);
00682
00683 RecIncrRawStat(log_rsb, mutex->thread_holding, log_stat_bytes_flush_to_disk_stat,
00684 fmt_buf_bytes);
00685
00686 ink_atomiclist_push(Log::flush_data_list, flush_data);
00687
00688 Log::flush_notify->signal();
00689
00690 total_bytes += fmt_buf_bytes;
00691 }
00692
00693 return total_bytes;
00694 }
00695
00696
00697
00698
00699
00700
00701
00702
00703 int
00704 LogFile::writeln(char *data, int len, int fd, const char *path)
00705 {
00706 int total_bytes = 0;
00707
00708 if (len > 0 && data && fd >= 0) {
00709 struct iovec wvec[2];
00710 memset(&wvec, 0, sizeof(iovec));
00711 memset(&wvec[1], 0, sizeof(iovec));
00712 int bytes_this_write, vcnt = 1;
00713
00714 #if defined(solaris)
00715 wvec[0].iov_base = (caddr_t) data;
00716 #else
00717 wvec[0].iov_base = (void *) data;
00718 #endif
00719 wvec[0].iov_len = (size_t) len;
00720
00721 if (data[len - 1] != '\n') {
00722 #if defined(solaris)
00723 wvec[1].iov_base = (caddr_t) "\n";
00724 #else
00725 wvec[1].iov_base = (void *) "\n";
00726 #endif
00727 wvec[1].iov_len = (size_t) 1;
00728 vcnt++;
00729 }
00730
00731 if ((bytes_this_write = (int)::writev(fd, (const struct iovec *) wvec, vcnt)) < 0) {
00732 Warning("An error was encountered in writing to %s: %s.", ((path) ? path : "logfile"), strerror(errno));
00733 } else
00734 total_bytes = bytes_this_write;
00735 }
00736 return total_bytes;
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749 void
00750 LogFile::check_fd()
00751 {
00752 static bool failure_last_call = false;
00753 static unsigned stat_check_count = 1;
00754
00755 if ((stat_check_count % Log::config->file_stat_frequency) == 0) {
00756
00757
00758
00759
00760
00761
00762 if (m_name && !LogFile::exists(m_name)) {
00763 close_file();
00764 }
00765 stat_check_count = 0;
00766 }
00767 stat_check_count++;
00768
00769 int err = open_file();
00770
00771 if (err != LOG_FILE_NO_ERROR && err != LOG_FILE_NO_PIPE_READERS) {
00772 if (!failure_last_call) {
00773 LogUtils::manager_alarm(LogUtils::LOG_ALARM_ERROR, "Traffic Server could not open logfile %s.", m_name);
00774 Warning("Traffic Server could not open logfile %s: %s.", m_name, strerror(errno));
00775 }
00776 failure_last_call = true;
00777 return;
00778 }
00779
00780 failure_last_call = false;
00781 }
00782
00783 void
00784 LogFile::display(FILE * fd)
00785 {
00786 fprintf(fd, "Logfile: %s, %s\n", get_name(), (is_open())? "file is open" : "file is not open");
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800 void
00801 MetaInfo::_build_name(const char *filename)
00802 {
00803 int i = -1, l = 0;
00804 char c;
00805 while (c = filename[l], c != 0) {
00806 if (c == '/') {
00807 i = l;
00808 }
00809 ++l;
00810 }
00811
00812
00813
00814 _filename = (char *)ats_malloc(l + 7);
00815
00816 if (i < 0) {
00817 ink_string_concatenate_strings(_filename, ".", filename, ".meta", NULL);
00818 } else {
00819 memcpy(_filename, filename, i + 1);
00820 ink_string_concatenate_strings(&_filename[i + 1], ".", &filename[i + 1]
00821 , ".meta", NULL);
00822 }
00823 }
00824
00825 void
00826 MetaInfo::_read_from_file()
00827 {
00828 _flags |= DATA_FROM_METAFILE;
00829 int fd = open(_filename, O_RDONLY);
00830 if (fd < 0) {
00831 Warning("Could not open metafile %s for reading: %s", _filename, strerror(errno));
00832 } else {
00833 _flags |= FILE_OPEN_SUCCESSFUL;
00834 SimpleTokenizer tok('=', SimpleTokenizer::OVERWRITE_INPUT_STRING);
00835 int line_number = 1;
00836 while (ink_file_fd_readline(fd, BUF_SIZE, _buffer) > 0) {
00837 tok.setString(_buffer);
00838 char *t = tok.getNext();
00839 if (t) {
00840 if (strcmp(t, "creation_time") == 0) {
00841 t = tok.getNext();
00842 if (t) {
00843 _creation_time = (time_t) ink_atoi64(t);
00844 _flags |= VALID_CREATION_TIME;
00845 }
00846 } else if (strcmp(t, "object_signature") == 0) {
00847 t = tok.getNext();
00848 if (t) {
00849 _log_object_signature = ink_atoi64(t);
00850 _flags |= VALID_SIGNATURE;
00851 Debug("log-meta", "MetaInfo::_read_from_file\n"
00852 "\tfilename = %s\n"
00853 "\tsignature string = %s\n" "\tsignature value = %" PRIu64 "", _filename, t, _log_object_signature);
00854 }
00855 } else if (line_number == 1) {
00856 ink_release_assert(!"no panda support");
00857 }
00858 }
00859 ++line_number;
00860 }
00861 close(fd);
00862 }
00863 }
00864
00865 void
00866 MetaInfo::_write_to_file()
00867 {
00868 int fd = open(_filename, O_WRONLY | O_CREAT | O_TRUNC,
00869 Log::config->logfile_perm);
00870
00871 if (fd <= 0) {
00872 Warning("Could not open metafile %s for writing: %s", _filename, strerror(errno));
00873 } else {
00874 int n;
00875 if (_flags & VALID_CREATION_TIME) {
00876 n = snprintf(_buffer, BUF_SIZE, "creation_time = %lu\n", (unsigned long) _creation_time);
00877
00878 ink_release_assert(n <= BUF_SIZE);
00879 if (write(fd, _buffer, n) == -1) {
00880 Warning("Could not write creation_time");
00881 }
00882 }
00883 if (_flags & VALID_SIGNATURE) {
00884 n = snprintf(_buffer, BUF_SIZE, "object_signature = %" PRIu64 "\n", _log_object_signature);
00885
00886 ink_release_assert(n <= BUF_SIZE);
00887 if (write(fd, _buffer, n) == -1) {
00888 Warning("Could not write object_signaure");
00889 }
00890 Debug("log-meta", "MetaInfo::_write_to_file\n"
00891 "\tfilename = %s\n"
00892 "\tsignature value = %" PRIu64 "\n" "\tsignature string = %s", _filename, _log_object_signature, _buffer);
00893 }
00894 }
00895 close(fd);
00896 }