BitLab 0.1.0
BitLab: A Browser for the Bitcoin P2P Network and Blockchain
Loading...
Searching...
No Matches
log.h File Reference
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <pthread.h>

Go to the source code of this file.

Data Structures

struct  logger
 The logger structure used to store the logger for the logging system. More...
 
struct  loggers
 The loggers structure used to store the loggers for the logging system. More...
 

Macros

#define MAX_LOG_FILES   10
 
#define MAX_FILENAME_LENGTH   256
 
#define BITLAB_LOG   "bitlab.log"
 
#define LOG_BITLAB_STARTED   "BitLab started ----------------------------------------------------------------------------------------"
 
#define LOG_BITLAB_FINISHED   "BitLab finished successfully"
 
#define LOCKED_FILE_RETRY_TIME   1000
 
#define LOCKED_FILE_TIMEOUT   5000000
 

Typedefs

typedef struct logger logger
 The logger structure used to store the logger for the logging system.
 
typedef struct loggers loggers
 The loggers structure used to store the loggers for the logging system.
 

Enumerations

enum  log_level {
  LOG_DEBUG , LOG_INFO , LOG_WARN , LOG_ERROR ,
  LOG_FATAL
}
 The log level enumeration used to define the level of logging that is being used. More...
 

Functions

const char * create_logs_dir ()
 Create logs directory used to create the logs directory if it does not exist.
 
void init_logging (const char *filename)
 Initialize logging used to initialize the logging system, open and preserve the log file.
 
void log_message (log_level level, const char *filename, const char *source_file, const char *format,...)
 Log a message used to log a message to the console or a file.
 
void finish_logging ()
 Finish logging used to finish logging and close the log file.
 

Macro Definition Documentation

◆ BITLAB_LOG

#define BITLAB_LOG   "bitlab.log"

Definition at line 11 of file log.h.

◆ LOCKED_FILE_RETRY_TIME

#define LOCKED_FILE_RETRY_TIME   1000

Definition at line 15 of file log.h.

◆ LOCKED_FILE_TIMEOUT

#define LOCKED_FILE_TIMEOUT   5000000

Definition at line 16 of file log.h.

◆ LOG_BITLAB_FINISHED

#define LOG_BITLAB_FINISHED   "BitLab finished successfully"

Definition at line 13 of file log.h.

◆ LOG_BITLAB_STARTED

#define LOG_BITLAB_STARTED   "BitLab started ----------------------------------------------------------------------------------------"

Definition at line 12 of file log.h.

◆ MAX_FILENAME_LENGTH

#define MAX_FILENAME_LENGTH   256

Definition at line 10 of file log.h.

◆ MAX_LOG_FILES

#define MAX_LOG_FILES   10

Definition at line 9 of file log.h.

Typedef Documentation

◆ logger

typedef struct logger logger

The logger structure used to store the logger for the logging system.

Parameters
filenameThe filename of the log file.
fileThe file pointer for the log file.

◆ loggers

typedef struct loggers loggers

The loggers structure used to store the loggers for the logging system.

Parameters
log_mutexThe mutex for the loggers.
arrayThe array of loggers.
is_initializingThe flag to indicate if the loggers are initializing.

Enumeration Type Documentation

◆ log_level

enum log_level

The log level enumeration used to define the level of logging that is being used.

Parameters
LOG_DEBUGDebug level logging
LOG_INFOInformation level logging
LOG_WARNWarning level logging
LOG_ERRORError level logging
LOG_FATALFatal level logging
Enumerator
LOG_DEBUG 
LOG_INFO 
LOG_WARN 
LOG_ERROR 
LOG_FATAL 

Definition at line 27 of file log.h.

28{
34} log_level;
log_level
The log level enumeration used to define the level of logging that is being used.
Definition log.h:28
@ LOG_ERROR
Definition log.h:32
@ LOG_INFO
Definition log.h:30
@ LOG_DEBUG
Definition log.h:29
@ LOG_FATAL
Definition log.h:33
@ LOG_WARN
Definition log.h:31

Function Documentation

◆ create_logs_dir()

const char * create_logs_dir ( )

Create logs directory used to create the logs directory if it does not exist.

Returns
The logs directory.

Definition at line 20 of file log.c.

21{
22 const char* home = getenv("HOME");
23 if (home == NULL)
24 return NULL;
25 const char* suffix = "/.bitlab/logs";
26 char* logs_dir = malloc(strlen(home) + strlen(suffix) + 1);
27 if (logs_dir == NULL)
28 return NULL;
29 strcpy(logs_dir, home);
30 strcat(logs_dir, suffix);
31 return logs_dir;
32}
static const char * logs_dir
Definition log.c:18

References logs_dir.

Referenced by init_logging(), and log_message().

◆ finish_logging()

void finish_logging ( )

Finish logging used to finish logging and close the log file.

Definition at line 199 of file log.c.

200{
201 while (logs.is_initializing)
202 {
203 usleep(10000); // 10 ms
204 }
205 pthread_mutex_lock(&logs.log_mutex);
206 for (int i = 0; i < MAX_LOG_FILES; ++i)
207 {
208 if (logs.array[i] != NULL)
209 {
210 fclose(logs.array[i]->file);
211 if (logs.array[i]->filename != NULL)
212 free(logs.array[i]->filename);
213 free(logs.array[i]);
214 logs.array[i] = NULL;
215 }
216 }
217 pthread_mutex_unlock(&logs.log_mutex);
218 if (logs_dir != NULL)
219 {
220 free((void*)logs_dir);
221 logs_dir = NULL;
222 }
223}
static struct loggers logs
Definition log.c:16
#define MAX_LOG_FILES
Definition log.h:9
char * filename
Definition log.h:44
FILE * file
Definition log.h:45
logger * array[MAX_LOG_FILES]
Definition log.h:58
int is_initializing
Definition log.h:59
pthread_mutex_t log_mutex
Definition log.h:57
void usleep(unsigned int usec)

References loggers::array, logger::file, logger::filename, loggers::is_initializing, loggers::log_mutex, logs, logs_dir, MAX_LOG_FILES, and usleep().

Referenced by run_bitlab().

◆ init_logging()

void init_logging ( const char *  filename)

Initialize logging used to initialize the logging system, open and preserve the log file.

Parameters
log_fileThe log file to write to.

Definition at line 34 of file log.c.

35{
37 if (logs_dir != NULL)
38 {
39 free((void*)logs_dir);
40 }
42 struct stat st = { 0 };
43
44 if (stat(logs_dir, &st) == -1)
45 {
46 if (mkdir(logs_dir, 0700) != 0)
47 {
48 perror("Failed to create logs directory");
50 free((void*)logs_dir); // Free logs_dir on error
51 logs_dir = NULL;
52 return;
53 }
54 }
55
56 char full_path[BUFFER_SIZE];
57 snprintf(full_path, sizeof(full_path), "%s/%s", logs_dir, filename);
58
59 pthread_mutex_lock(&logs.log_mutex);
60 for (int i = 0; i < MAX_LOG_FILES; ++i)
61 {
62 if (logs.array[i] == NULL)
63 {
64 logs.array[i] = (struct logger*)malloc(sizeof(logger));
65 logs.array[i]->filename = (char*)malloc(strlen(full_path) + 1);
66 if (logs.array[i]->filename == NULL)
67 {
68 perror("Failed to allocate memory for filename");
69 free(logs.array[i]);
70 logs.array[i] = NULL;
71 break;
72 }
73 snprintf(logs.array[i]->filename, strlen(full_path) + 1, "%s", full_path);
74 logs.array[i]->file = fopen(full_path, "a");
75 if (logs.array[i]->file == NULL)
76 {
77 perror("Failed to open log file");
78 free(logs.array[i]->filename);
79 free(logs.array[i]);
80 logs.array[i] = NULL;
81 }
82 break;
83 }
84 }
86 pthread_mutex_unlock(&logs.log_mutex);
87}
const char * create_logs_dir()
Create logs directory used to create the logs directory if it does not exist.
Definition log.c:20
The logger structure used to store the logger for the logging system.
Definition log.h:43
#define BUFFER_SIZE
Definition utils.h:12

References loggers::array, BUFFER_SIZE, create_logs_dir(), logger::file, logger::filename, loggers::is_initializing, loggers::log_mutex, logs, logs_dir, and MAX_LOG_FILES.

Referenced by connect_to_peer(), and run_bitlab().

◆ log_message()

void log_message ( log_level  level,
const char *  filename,
const char *  source_file,
const char *  format,
  ... 
)

Log a message used to log a message to the console or a file.

Parameters
levelThe log level.
log_fileThe file that the log message is destined for.
source_fileThe source file that the log message is from.
formatThe format of the log message.
...The arguments for the format.

Definition at line 89 of file log.c.

90{
91 if (logs_dir == NULL)
92 {
94 if (logs_dir == NULL)
95 {
96 fprintf(stderr, "Failed to create logs directory\n");
97 return;
98 }
99 }
100
101 char full_path[BUFFER_SIZE];
102 snprintf(full_path, sizeof(full_path), "%s/%s", logs_dir, filename);
103
104 pthread_mutex_lock(&logs.log_mutex);
105
106 FILE* log = NULL;
107 for (int i = 0; i < MAX_LOG_FILES; ++i)
108 {
109 if (logs.array[i] != NULL && !strcmp(logs.array[i]->filename, full_path))
110 {
111 log = logs.array[i]->file;
112 break;
113 }
114 }
115
116 if (log == NULL)
117 {
118 // Try to create and open the log file if it doesn't exist
119 log = fopen(full_path, "a");
120 if (log == NULL)
121 {
122 pthread_mutex_unlock(&logs.log_mutex);
123 fprintf(stderr, "Failed to create or open log file: %s\n", full_path);
124 return;
125 }
126
127 // Add the new log file to the logs array
128 for (int i = 0; i < MAX_LOG_FILES; ++i)
129 {
130 if (logs.array[i] == NULL)
131 {
132 logs.array[i] = (struct logger*)malloc(sizeof(logger));
133 logs.array[i]->filename = (char*)malloc(strlen(full_path) + 1);
134 if (logs.array[i]->filename == NULL)
135 {
136 perror("Failed to allocate memory for filename");
137 free(logs.array[i]);
138 logs.array[i] = NULL;
139 fclose(log);
140 pthread_mutex_unlock(&logs.log_mutex);
141 return;
142 }
143 snprintf(logs.array[i]->filename, strlen(full_path) + 1, "%s", full_path);
144 logs.array[i]->file = log;
145 break;
146 }
147 }
148 }
149
150 int timeout = 0;
151 int error = 0;
152
153 error = flock(fileno(log), LOCK_EX | LOCK_NB);
154 while (error == -1 && (errno == EWOULDBLOCK || errno == EAGAIN))
155 {
157 timeout += LOCKED_FILE_RETRY_TIME;
158
159 if (timeout > LOCKED_FILE_TIMEOUT)
160 {
161 fprintf(stderr, "Log file locking timed out: %s\n", full_path);
162 pthread_mutex_unlock(&logs.log_mutex);
163 return;
164 }
165 error = flock(fileno(log), LOCK_EX | LOCK_NB);
166 }
167
168 fseek(log, 0, SEEK_END);
169
170 const char* level_str;
171 switch (level)
172 {
173 case LOG_DEBUG: level_str = "DEBUG"; break;
174 case LOG_INFO: level_str = "INFO"; break;
175 case LOG_WARN: level_str = "WARN"; break;
176 case LOG_ERROR: level_str = "ERROR"; break;
177 case LOG_FATAL: level_str = "FATAL"; break;
178 default: level_str = "UNKNOWN"; break;
179 }
180
181 char timestamp[TIMESTAMP_LENGTH];
183
184 char message[1024];
185 va_list args;
186 va_start(args, format);
187 vsnprintf(message, sizeof(message), format, args);
188 va_end(args);
189
190 fprintf(log, "%s - %s - %s - %s\n", timestamp, level_str, source_file, message);
191
192 fflush(log);
193
194 flock(fileno(log), LOCK_UN);
195
196 pthread_mutex_unlock(&logs.log_mutex);
197}
#define LOCKED_FILE_RETRY_TIME
Definition log.h:15
#define LOCKED_FILE_TIMEOUT
Definition log.h:16
int fileno(FILE *__stream)
void get_formatted_timestamp(char *buffer, size_t buffer_size)
Get the formatted timestamp.
Definition utils.c:25
#define TIMESTAMP_LENGTH
Definition utils.h:11

References loggers::array, BUFFER_SIZE, create_logs_dir(), logger::file, logger::filename, fileno(), get_formatted_timestamp(), LOCKED_FILE_RETRY_TIME, LOCKED_FILE_TIMEOUT, LOG_DEBUG, LOG_ERROR, LOG_FATAL, LOG_INFO, loggers::log_mutex, LOG_WARN, logs, logs_dir, MAX_LOG_FILES, TIMESTAMP_LENGTH, and usleep().

Referenced by add_peer_to_queue(), build_inv_message(), cli_clear(), cli_connect(), cli_disconnect(), cli_echo(), cli_exec_line(), cli_exit(), cli_getaddr(), cli_getblocks(), cli_getdata(), cli_getheaders(), cli_help(), cli_history(), cli_info(), cli_inv(), cli_list(), cli_peer_discovery(), cli_ping(), cli_tx(), cli_whoami(), connect_to_peer(), disconnect(), force_stop_peer_discovery(), handle_cli(), handle_inv_message(), handle_peer_discovery(), init_program_state(), is_in_private_network(), is_valid_domain_address(), lookup_address(), peer_communication(), run_bitlab(), send_addr(), send_getaddr_and_wait(), send_getblocks_and_wait(), send_getdata_and_wait(), send_getheaders_and_wait(), send_headers(), send_inv_and_wait(), send_ping(), send_tx(), send_verack(), set_peer_discovery(), set_peer_discovery_dns_domain(), start_peer_discovery_progress(), thread_runner(), and write_var_int().