1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
5 * Copyright (C) 2001-2008, Eduardo Silva P.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Library General Public License for more details.
17 * Youu should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26 #include <arpa/inet.h>
27 #include <netinet/in.h>
33 #include <sys/ioctl.h>
35 #include <sys/types.h>
37 #include <sys/times.h>
41 #include "http_status.h"
53 #include <sys/sysinfo.h>
55 void mk_logger_target_add(int fd
, char *target
)
57 struct log_target
*new, *aux
;
59 new = mk_mem_malloc(sizeof(struct log_target
));
76 struct log_target
*mk_logger_match(int fd
)
78 struct log_target
*aux
;
93 void *mk_logger_worker_init(void *args
)
95 int efd
, max_events
= config
->nhosts
;
97 struct log_target
*target
= 0;
106 * Linux set a pipe size usingto the PAGE_SIZE,
107 * check linux/include/pipe_fs_i.h for details:
109 * #define PIPE_SIZE PAGE_SIZE
111 * In the same header file we can found that every
112 * pipe has 16 pages, so our real memory allocation
113 * is: (PAGE_SIZE*PIPE_BUFFERS)
119 * it means the maximum data that a monkey log pipe can contain.
123 /* Monkey allow just 75% of a pipe capacity */
124 pipe_size
= sysconf(_SC_PAGESIZE
) * 16;
125 buffer_limit
= (pipe_size
* MK_LOGFILE_PIPE_LIMIT
);
128 efd
= mk_epoll_create(max_events
);
132 /* Add access log file */
133 if( h
->log_access
[0] > 0 ) {
134 mk_epoll_add_client(efd
, h
->log_access
[0], MK_EPOLL_BEHAVIOR_DEFAULT
);
135 mk_logger_target_add(h
->log_access
[0], h
->access_log_path
);
137 /* Add error log file */
138 if( h
->log_error
[0] > 0 ) {
139 mk_epoll_add_client(efd
, h
->log_error
[0], MK_EPOLL_BEHAVIOR_DEFAULT
);
140 mk_logger_target_add(h
->log_error
[0], h
->error_log_path
);
145 timeout
= time(NULL
) + MK_LOGFILE_TIMEOUT
;
147 /* Reading pipe buffer */
151 struct epoll_event events
[max_events
];
152 int num_fds
= epoll_wait(efd
, events
, max_events
, -1);
154 clk
= log_current_utime
;
159 for (i
= 0; i
< num_fds
; i
++) {
160 target
= mk_logger_match(events
[i
].data
.fd
);
163 printf("\nERROR matching host/epoll_fd");
168 err
= ioctl(target
->fd
, FIONREAD
, &bytes
);
174 if (bytes
< buffer_limit
&& clk
<= timeout
) {
178 timeout
= clk
+ MK_LOGFILE_TIMEOUT
;
179 flog
= open(target
->target
, O_WRONLY
| O_CREAT
, 0644);
182 printf("\n* error: check your logfile file permission");
187 lseek(flog
, 0, SEEK_END
);
188 slen
= splice(events
[i
].data
.fd
, NULL
, flog
,
189 NULL
, bytes
, SPLICE_F_MOVE
);
199 struct mk_iov
*mk_logger_iov_get()
201 return pthread_getspecific(mk_cache_iov_log
);
204 void mk_logger_iov_free(struct mk_iov
*iov
)
206 mk_iov_free_marked(iov
);
209 /* Registra en archivos de logs: accesos
211 int mk_logger_write_log(struct client_request
*cr
, struct log_info
*log
,
215 mk_pointer
*status
, method
, protocol
;
216 struct sched_list_node
*sched
;
217 struct sched_connection
*conx
;
219 if (log
->status
!= S_LOG_ON
) {
223 iov
= mk_logger_iov_get();
225 sched
= mk_sched_get_thread_conf();
226 conx
= mk_sched_get_connection(sched
, cr
->socket
);
228 /* client IP address */
229 mk_iov_add_entry(iov
, conx
->ipv4
.data
, conx
->ipv4
.len
,
230 mk_logfile_iov_dash
, MK_IOV_NOT_FREE_BUF
);
232 /* Date/time when object was requested */
233 mk_iov_add_entry(iov
, log_current_time
.data
, log_current_time
.len
,
234 mk_iov_space
, MK_IOV_NOT_FREE_BUF
);
236 /* Register a successfull request */
237 if (log
->final_response
== M_HTTP_OK
238 || log
->final_response
== M_REDIR_MOVED_T
) {
239 /* HTTP method required */
240 method
= mk_http_method_check_str(log
->method
);
241 mk_iov_add_entry(iov
, method
.data
, method
.len
, mk_iov_space
,
242 MK_IOV_NOT_FREE_BUF
);
244 /* HTTP URI required */
245 mk_iov_add_entry(iov
, log
->uri
.data
, log
->uri
.len
,
246 mk_iov_space
, MK_IOV_NOT_FREE_BUF
);
250 protocol
= mk_http_protocol_check_str(log
->protocol
);
251 mk_iov_add_entry(iov
, protocol
.data
, protocol
.len
,
252 mk_iov_space
, MK_IOV_NOT_FREE_BUF
);
255 /* HTTP status code */
256 status
= (mk_pointer
*)
257 mk_http_status_get(log
->final_response
);
258 mk_iov_add_entry(iov
, status
->data
, status
->len
,
259 mk_iov_space
, MK_IOV_NOT_FREE_BUF
);
262 mk_iov_add_entry(iov
,
264 log
->size_p
.len
, mk_iov_lf
, MK_IOV_NOT_FREE_BUF
);
266 /* Send info to pipe */
267 mk_iov_send(h
->log_access
[1], iov
, MK_IOV_SEND_TO_PIPE
);
269 else { /* Register some error */
270 mk_iov_add_entry(iov
,
272 log
->error_msg
.len
, mk_iov_space
, MK_IOV_NOT_FREE_BUF
);
274 /* Check for error extra details */
275 if (log
->error_details
.data
) {
276 mk_iov_add_entry(iov
,
277 log
->error_details
.data
,
278 log
->error_details
.len
,
280 MK_IOV_NOT_FREE_BUF
);
283 mk_iov_add_entry(iov
, mk_iov_lf
.data
,
284 mk_iov_lf
.len
, mk_iov_none
, MK_IOV_NOT_FREE_BUF
);
287 mk_iov_send(h
->log_error
[1], iov
, MK_IOV_SEND_TO_PIPE
);
289 mk_logger_iov_free(iov
);
293 /* Write Monkey's PID */
294 int mk_logger_register_pid()
298 remove(config
->pid_file_path
);
299 config
->pid_status
= VAR_OFF
;
300 if ((pid_file
= fopen(config
->pid_file_path
, "w")) == NULL
) {
301 puts("Error: I can't log pid of monkey");
304 fprintf(pid_file
, "%i", getpid());
306 config
->pid_status
= VAR_ON
;
311 /* Elimina log del PID */
312 int mk_logger_remove_pid()
314 mk_user_undo_uidgid();
315 return remove(config
->pid_file_path
);