1 /** @file
2 
3   Base class for log files
4 
5   @section license License
6 
7   Licensed to the Apache Software Foundation (ASF) under one
8   or more contributor license agreements.  See the NOTICE file
9   distributed with this work for additional information
10   regarding copyright ownership.  The ASF licenses this file
11   to you under the Apache License, Version 2.0 (the
12   "License"); you may not use this file except in compliance
13   with the License.  You may obtain a copy of the License at
14 
15       http://www.apache.org/licenses/LICENSE-2.0
16 
17   Unless required by applicable law or agreed to in writing, software
18   distributed under the License is distributed on an "AS IS" BASIS,
19   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20   See the License for the specific language governing permissions and
21   limitations under the License.
22 
23  */
24 
25 #pragma once
26 
27 #include <cstdarg>
28 #include <cstdio>
29 #include <sys/time.h>
30 #include <cstdint>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 
35 #include "ink_memory.h"
36 #include "ink_string.h"
37 #include "ink_file.h"
38 #include "ink_cap.h"
39 #include "ink_time.h"
40 #include "SimpleTokenizer.h"
41 
42 #define LOGFILE_ROLLED_EXTENSION ".old"
43 #define LOGFILE_SEPARATOR_STRING "_"
44 #define LOGFILE_DEFAULT_PERMS (0644)
45 #define LOGFILE_ROLL_MAXPATHLEN 4096
46 #define BASELOGFILE_DEBUG_MODE \
47   0 // change this to 1 to enable debug messages
48     // TODO find a way to enable this from autotools
49 
50 typedef enum {
51   LL_Debug = 0, // process does not die
52   LL_Note,      // process does not die
53   LL_Warning,   // process does not die
54   LL_Error,     // process does not die
55   LL_Fatal,     // causes process termination
56 } LogLogPriorityLevel;
57 
58 #define log_log_trace(...)                         \
59   do {                                             \
60     if (BASELOGFILE_DEBUG_MODE)                    \
61       BaseLogFile::log_log(LL_Debug, __VA_ARGS__); \
62   } while (0)
63 
64 #define log_log_error(...)                         \
65   do {                                             \
66     if (BASELOGFILE_DEBUG_MODE)                    \
67       BaseLogFile::log_log(LL_Error, __VA_ARGS__); \
68   } while (0)
69 
70 /*
71  *
72  * BaseMetaInfo class
73  *
74  * Used to store persistent information between ATS instances
75  *
76  */
77 class BaseMetaInfo
78 {
79 public:
80   enum {
81     DATA_FROM_METAFILE = 1, // metadata was read (or attempted to)
82     // from metafile
83     VALID_CREATION_TIME = 2, // creation time is valid
84     VALID_SIGNATURE     = 4, // signature is valid
85     // (i.e., creation time only)
86     FILE_OPEN_SUCCESSFUL = 8 // metafile was opened successfully
87   };
88 
89   enum {
90     BUF_SIZE = 640 // size of read/write buffer
91   };
92 
93 private:
94   char *_filename;                // the name of the meta file
95   time_t _creation_time;          // file creation time
96   uint64_t _log_object_signature; // log object signature
97   int _flags;                     // metainfo status flags
98   char _buffer[BUF_SIZE];         // read/write buffer
99 
100   void _read_from_file();
101   void _write_to_file();
102   void _build_name(const char *filename);
103 
104 public:
BaseMetaInfo(const char * filename)105   BaseMetaInfo(const char *filename) : _flags(0)
106   {
107     _build_name(filename);
108     _read_from_file();
109   }
110 
BaseMetaInfo(char * filename,time_t creation)111   BaseMetaInfo(char *filename, time_t creation) : _creation_time(creation), _log_object_signature(0), _flags(VALID_CREATION_TIME)
112   {
113     _build_name(filename);
114     _write_to_file();
115   }
116 
BaseMetaInfo(char * filename,time_t creation,uint64_t signature)117   BaseMetaInfo(char *filename, time_t creation, uint64_t signature)
118     : _creation_time(creation), _log_object_signature(signature), _flags(VALID_CREATION_TIME | VALID_SIGNATURE)
119   {
120     _build_name(filename);
121     _write_to_file();
122   }
123 
~BaseMetaInfo()124   ~BaseMetaInfo() { ats_free(_filename); }
125   bool
get_creation_time(time_t * time)126   get_creation_time(time_t *time)
127   {
128     if (_flags & VALID_CREATION_TIME) {
129       *time = _creation_time;
130       return true;
131     } else {
132       return false;
133     }
134   }
135 
136   bool
get_log_object_signature(uint64_t * signature)137   get_log_object_signature(uint64_t *signature)
138   {
139     if (_flags & VALID_SIGNATURE) {
140       *signature = _log_object_signature;
141       return true;
142     } else {
143       return false;
144     }
145   }
146 
147   bool
data_from_metafile()148   data_from_metafile() const
149   {
150     return (_flags & DATA_FROM_METAFILE ? true : false);
151   }
152 
153   bool
file_open_successful()154   file_open_successful()
155   {
156     return (_flags & FILE_OPEN_SUCCESSFUL ? true : false);
157   }
158 };
159 
160 /*
161  *
162  * BaseLogFile Class
163  *
164  */
165 class BaseLogFile
166 {
167 public:
168   // member functions
169   BaseLogFile()        = delete;
170   BaseLogFile &operator=(const BaseLogFile &) = delete;
171   BaseLogFile(const char *name);
172   BaseLogFile(const char *name, uint64_t sig);
173   BaseLogFile(const BaseLogFile &);
174   ~BaseLogFile();
175   int roll();
176   int roll(long interval_start, long interval_end);
177   static bool rolled_logfile(char *path);
178   static bool exists(const char *pathname);
179   int open_file(int perm = -1);
180   int close_file();
181   void change_name(const char *new_name);
182   void display(FILE *fd = stdout);
183   const char *
get_name()184   get_name() const
185   {
186     return m_name;
187   }
188   bool
is_open()189   is_open()
190   {
191     return (m_fp != nullptr);
192   }
193   off_t
get_size_bytes()194   get_size_bytes() const
195   {
196     return m_bytes_written;
197   }
198   bool
is_init()199   is_init()
200   {
201     return m_is_init;
202   }
203   const char *
get_hostname()204   get_hostname() const
205   {
206     return m_hostname;
207   }
208   void
set_hostname(const char * hn)209   set_hostname(const char *hn)
210   {
211     m_hostname = ats_strdup(hn);
212   }
213 
214   static void log_log(LogLogPriorityLevel priority, const char *format, ...);
215 
216   // member variables
217   enum {
218     LOG_FILE_NO_ERROR = 0,
219     LOG_FILE_COULD_NOT_OPEN_FILE,
220   };
221 
222   FILE *m_fp               = nullptr;
223   long m_start_time        = time(nullptr);
224   long m_end_time          = 0L;
225   uint64_t m_bytes_written = 0;
226 
227 private:
228   // member functions
229   int timestamp_to_str(long timestamp, char *buf, int size);
230 
231   // member variables
232   ats_scoped_str m_name;
233   ats_scoped_str m_hostname;
234   bool m_is_regfile         = false;
235   bool m_is_init            = false;
236   BaseMetaInfo *m_meta_info = nullptr;
237   uint64_t m_signature      = 0;
238   bool m_has_signature      = false;
239 };
240