Line data Source code
1 :
2 : #ifndef DDEBUG
3 : #define DDEBUG 0
4 : #endif
5 : #include "ddebug.h"
6 :
7 :
8 : #include "ngx_http_lua_common.h"
9 : #include "ngx_http_lua_log_ringbuf.h"
10 :
11 :
12 : typedef struct {
13 : double time;
14 : unsigned len;
15 : unsigned log_level;
16 : } ngx_http_lua_log_ringbuf_header_t;
17 :
18 :
19 : enum {
20 : HEADER_LEN = sizeof(ngx_http_lua_log_ringbuf_header_t)
21 : };
22 :
23 :
24 : static void *ngx_http_lua_log_ringbuf_next_header(
25 : ngx_http_lua_log_ringbuf_t *rb);
26 : static void ngx_http_lua_log_ringbuf_append(
27 : ngx_http_lua_log_ringbuf_t *rb, int log_level, void *buf, int n);
28 : static size_t ngx_http_lua_log_ringbuf_free_spaces(
29 : ngx_http_lua_log_ringbuf_t *rb);
30 :
31 :
32 : void
33 0 : ngx_http_lua_log_ringbuf_init(ngx_http_lua_log_ringbuf_t *rb, void *buf,
34 : size_t len)
35 : {
36 0 : rb->data = buf;
37 0 : rb->size = len;
38 :
39 0 : rb->tail = rb->data;
40 0 : rb->head = rb->data;
41 0 : rb->sentinel = rb->data + rb->size;
42 0 : rb->count = 0;
43 0 : rb->filter_level = NGX_LOG_DEBUG;
44 :
45 0 : return;
46 : }
47 :
48 :
49 : void
50 0 : ngx_http_lua_log_ringbuf_reset(ngx_http_lua_log_ringbuf_t *rb)
51 : {
52 0 : rb->tail = rb->data;
53 0 : rb->head = rb->data;
54 0 : rb->sentinel = rb->data + rb->size;
55 0 : rb->count = 0;
56 :
57 0 : return;
58 : }
59 :
60 :
61 : /*
62 : * get the next data header, it'll skip the useless data space or
63 : * placehold data
64 : */
65 : static void *
66 0 : ngx_http_lua_log_ringbuf_next_header(ngx_http_lua_log_ringbuf_t *rb)
67 : {
68 : /* useless data */
69 0 : if (rb->size - (rb->head - rb->data) < HEADER_LEN)
70 : {
71 0 : return rb->data;
72 : }
73 :
74 : /* placehold data */
75 0 : if (rb->head >= rb->sentinel) {
76 0 : return rb->data;
77 : }
78 :
79 0 : return rb->head;
80 : }
81 :
82 :
83 : /* append data to ring buffer directly */
84 : static void
85 0 : ngx_http_lua_log_ringbuf_append(ngx_http_lua_log_ringbuf_t *rb,
86 : int log_level, void *buf, int n)
87 : {
88 : ngx_http_lua_log_ringbuf_header_t *head;
89 : ngx_time_t *tp;
90 :
91 0 : head = (ngx_http_lua_log_ringbuf_header_t *) rb->tail;
92 0 : head->len = n;
93 0 : head->log_level = log_level;
94 :
95 0 : tp = ngx_timeofday();
96 0 : head->time = tp->sec + tp->msec / 1000.0L;
97 :
98 0 : rb->tail += HEADER_LEN;
99 0 : ngx_memcpy(rb->tail, buf, n);
100 0 : rb->tail += n;
101 0 : rb->count++;
102 :
103 0 : if (rb->tail > rb->sentinel) {
104 0 : rb->sentinel = rb->tail;
105 : }
106 :
107 0 : return;
108 : }
109 :
110 :
111 : /* throw away data at head */
112 : static void
113 0 : ngx_http_lua_log_ringbuf_throw_away(ngx_http_lua_log_ringbuf_t *rb)
114 : {
115 : ngx_http_lua_log_ringbuf_header_t *head;
116 :
117 0 : if (rb->count == 0) {
118 0 : return;
119 : }
120 :
121 0 : head = (ngx_http_lua_log_ringbuf_header_t *) rb->head;
122 :
123 0 : rb->head += HEADER_LEN + head->len;
124 0 : rb->count--;
125 :
126 0 : if (rb->count == 0) {
127 0 : ngx_http_lua_log_ringbuf_reset(rb);
128 : }
129 :
130 0 : rb->head = ngx_http_lua_log_ringbuf_next_header(rb);
131 :
132 0 : return;
133 : }
134 :
135 :
136 : /* size of free spaces */
137 : static size_t
138 0 : ngx_http_lua_log_ringbuf_free_spaces(ngx_http_lua_log_ringbuf_t *rb)
139 : {
140 0 : if (rb->count == 0) {
141 0 : return rb->size;
142 : }
143 :
144 0 : if (rb->tail > rb->head) {
145 0 : return rb->data + rb->size - rb->tail;
146 : }
147 :
148 0 : return rb->head - rb->tail;
149 : }
150 :
151 :
152 : /*
153 : * try to write log data to ring buffer, throw away old data
154 : * if there was not enough free spaces.
155 : */
156 : ngx_int_t
157 0 : ngx_http_lua_log_ringbuf_write(ngx_http_lua_log_ringbuf_t *rb, int log_level,
158 : void *buf, size_t n)
159 : {
160 0 : if (n + HEADER_LEN > rb->size) {
161 0 : return NGX_ERROR;
162 : }
163 :
164 0 : if (ngx_http_lua_log_ringbuf_free_spaces(rb) < n + HEADER_LEN) {
165 : /* if the right space is not enough, mark it as placehold data */
166 0 : if ((size_t)(rb->data + rb->size - rb->tail) < n + HEADER_LEN) {
167 :
168 0 : while (rb->head >= rb->tail && rb->count) {
169 : /* head is after tail, so we will throw away all data between
170 : * head and sentinel */
171 0 : ngx_http_lua_log_ringbuf_throw_away(rb);
172 : }
173 :
174 0 : rb->sentinel = rb->tail;
175 0 : rb->tail = rb->data;
176 : }
177 :
178 0 : while (ngx_http_lua_log_ringbuf_free_spaces(rb) < n + HEADER_LEN) {
179 0 : ngx_http_lua_log_ringbuf_throw_away(rb);
180 : }
181 : }
182 :
183 0 : ngx_http_lua_log_ringbuf_append(rb, log_level, buf, n);
184 :
185 0 : return NGX_OK;
186 : }
187 :
188 :
189 : /* read log from ring buffer, do reset if all of the logs were readed. */
190 : ngx_int_t
191 0 : ngx_http_lua_log_ringbuf_read(ngx_http_lua_log_ringbuf_t *rb, int *log_level,
192 : void **buf, size_t *n, double *log_time)
193 : {
194 : ngx_http_lua_log_ringbuf_header_t *head;
195 :
196 0 : if (rb->count == 0) {
197 0 : return NGX_ERROR;
198 : }
199 :
200 0 : head = (ngx_http_lua_log_ringbuf_header_t *) rb->head;
201 :
202 0 : if (rb->head >= rb->sentinel) {
203 0 : return NGX_ERROR;
204 : }
205 :
206 0 : *log_level = head->log_level;
207 0 : *n = head->len;
208 0 : rb->head += HEADER_LEN;
209 0 : *buf = rb->head;
210 0 : rb->head += head->len;
211 :
212 0 : if (log_time) {
213 0 : *log_time = head->time;
214 : }
215 :
216 0 : rb->count--;
217 :
218 0 : if (rb->count == 0) {
219 0 : ngx_http_lua_log_ringbuf_reset(rb);
220 : }
221 :
222 0 : rb->head = ngx_http_lua_log_ringbuf_next_header(rb);
223 :
224 0 : return NGX_OK;
225 : }
|