Mercurial > hg > nginx-quic
comparison src/os/unix/ngx_files.c @ 6421:3832b608dc8d
Introduced the ngx_chain_to_iovec() function.
It's similar to ngx_output_chain_to_iovec() and uses only preallocated memory.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Thu, 03 Mar 2016 18:41:05 +0300 |
parents | b5a87b51be24 |
children | 9fd738b85fad |
comparison
equal
deleted
inserted
replaced
6420:3b9fe734a76c | 6421:3832b608dc8d |
---|---|
12 #if (NGX_THREADS) | 12 #if (NGX_THREADS) |
13 #include <ngx_thread_pool.h> | 13 #include <ngx_thread_pool.h> |
14 static void ngx_thread_read_handler(void *data, ngx_log_t *log); | 14 static void ngx_thread_read_handler(void *data, ngx_log_t *log); |
15 #endif | 15 #endif |
16 | 16 |
17 static ssize_t ngx_writev_file(ngx_file_t *file, ngx_array_t *vec, size_t size, | 17 static ngx_chain_t *ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl); |
18 static ssize_t ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec, | |
18 off_t offset); | 19 off_t offset); |
19 | 20 |
20 | 21 |
21 #if (NGX_HAVE_FILE_AIO) | 22 #if (NGX_HAVE_FILE_AIO) |
22 | 23 |
274 | 275 |
275 return fd; | 276 return fd; |
276 } | 277 } |
277 | 278 |
278 | 279 |
279 #define NGX_IOVS 8 | |
280 | |
281 ssize_t | 280 ssize_t |
282 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, | 281 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset, |
283 ngx_pool_t *pool) | 282 ngx_pool_t *pool) |
284 { | 283 { |
285 u_char *prev; | |
286 size_t size; | |
287 ssize_t total, n; | 284 ssize_t total, n; |
288 ngx_array_t vec; | 285 ngx_iovec_t vec; |
289 struct iovec *iov, iovs[NGX_IOVS]; | 286 struct iovec iovs[NGX_IOVS_PREALLOCATE]; |
290 | 287 |
291 /* use pwrite() if there is the only buf in a chain */ | 288 /* use pwrite() if there is the only buf in a chain */ |
292 | 289 |
293 if (cl->next == NULL) { | 290 if (cl->next == NULL) { |
294 return ngx_write_file(file, cl->buf->pos, | 291 return ngx_write_file(file, cl->buf->pos, |
296 offset); | 293 offset); |
297 } | 294 } |
298 | 295 |
299 total = 0; | 296 total = 0; |
300 | 297 |
301 vec.elts = iovs; | 298 vec.iovs = iovs; |
302 vec.size = sizeof(struct iovec); | 299 vec.nalloc = NGX_IOVS_PREALLOCATE; |
303 vec.nalloc = NGX_IOVS; | |
304 vec.pool = pool; | |
305 | 300 |
306 do { | 301 do { |
307 prev = NULL; | |
308 iov = NULL; | |
309 size = 0; | |
310 | |
311 vec.nelts = 0; | |
312 | |
313 /* create the iovec and coalesce the neighbouring bufs */ | 302 /* create the iovec and coalesce the neighbouring bufs */ |
314 | 303 cl = ngx_chain_to_iovec(&vec, cl); |
315 while (cl && vec.nelts < IOV_MAX) { | |
316 if (prev == cl->buf->pos) { | |
317 iov->iov_len += cl->buf->last - cl->buf->pos; | |
318 | |
319 } else { | |
320 iov = ngx_array_push(&vec); | |
321 if (iov == NULL) { | |
322 return NGX_ERROR; | |
323 } | |
324 | |
325 iov->iov_base = (void *) cl->buf->pos; | |
326 iov->iov_len = cl->buf->last - cl->buf->pos; | |
327 } | |
328 | |
329 size += cl->buf->last - cl->buf->pos; | |
330 prev = cl->buf->last; | |
331 cl = cl->next; | |
332 } | |
333 | 304 |
334 /* use pwrite() if there is the only iovec buffer */ | 305 /* use pwrite() if there is the only iovec buffer */ |
335 | 306 |
336 if (vec.nelts == 1) { | 307 if (vec.count == 1) { |
337 iov = vec.elts; | 308 n = ngx_write_file(file, (u_char *) iovs[0].iov_base, |
338 | 309 iovs[0].iov_len, offset); |
339 n = ngx_write_file(file, (u_char *) iov[0].iov_base, | |
340 iov[0].iov_len, offset); | |
341 | 310 |
342 if (n == NGX_ERROR) { | 311 if (n == NGX_ERROR) { |
343 return n; | 312 return n; |
344 } | 313 } |
345 | 314 |
346 return total + n; | 315 return total + n; |
347 } | 316 } |
348 | 317 |
349 n = ngx_writev_file(file, &vec, size, offset); | 318 n = ngx_writev_file(file, &vec, offset); |
350 | 319 |
351 if (n == NGX_ERROR) { | 320 if (n == NGX_ERROR) { |
352 return n; | 321 return n; |
353 } | 322 } |
354 | 323 |
359 | 328 |
360 return total; | 329 return total; |
361 } | 330 } |
362 | 331 |
363 | 332 |
333 static ngx_chain_t * | |
334 ngx_chain_to_iovec(ngx_iovec_t *vec, ngx_chain_t *cl) | |
335 { | |
336 size_t total, size; | |
337 u_char *prev; | |
338 ngx_uint_t n; | |
339 struct iovec *iov; | |
340 | |
341 iov = NULL; | |
342 prev = NULL; | |
343 total = 0; | |
344 n = 0; | |
345 | |
346 for ( /* void */ ; cl; cl = cl->next) { | |
347 size = cl->buf->last - cl->buf->pos; | |
348 | |
349 if (prev == cl->buf->pos) { | |
350 iov->iov_len += size; | |
351 | |
352 } else { | |
353 if (n == vec->nalloc) { | |
354 break; | |
355 } | |
356 | |
357 iov = &vec->iovs[n++]; | |
358 | |
359 iov->iov_base = (void *) cl->buf->pos; | |
360 iov->iov_len = size; | |
361 } | |
362 | |
363 prev = cl->buf->pos + size; | |
364 total += size; | |
365 } | |
366 | |
367 vec->count = n; | |
368 vec->size = total; | |
369 | |
370 return cl; | |
371 } | |
372 | |
373 | |
364 static ssize_t | 374 static ssize_t |
365 ngx_writev_file(ngx_file_t *file, ngx_array_t *vec, size_t size, off_t offset) | 375 ngx_writev_file(ngx_file_t *file, ngx_iovec_t *vec, off_t offset) |
366 { | 376 { |
367 ssize_t n; | 377 ssize_t n; |
368 ngx_err_t err; | 378 ngx_err_t err; |
369 | 379 |
370 ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0, | 380 ngx_log_debug3(NGX_LOG_DEBUG_CORE, file->log, 0, |
371 "writev: %d, %uz, %O", file->fd, size, offset); | 381 "writev: %d, %uz, %O", file->fd, vec->size, offset); |
372 | 382 |
373 #if (NGX_HAVE_PWRITEV) | 383 #if (NGX_HAVE_PWRITEV) |
374 | 384 |
375 eintr: | 385 eintr: |
376 | 386 |
377 n = pwritev(file->fd, vec->elts, vec->nelts, offset); | 387 n = pwritev(file->fd, vec->iovs, vec->count, offset); |
378 | 388 |
379 if (n == -1) { | 389 if (n == -1) { |
380 err = ngx_errno; | 390 err = ngx_errno; |
381 | 391 |
382 if (err == NGX_EINTR) { | 392 if (err == NGX_EINTR) { |
388 ngx_log_error(NGX_LOG_CRIT, file->log, err, | 398 ngx_log_error(NGX_LOG_CRIT, file->log, err, |
389 "pwritev() \"%s\" failed", file->name.data); | 399 "pwritev() \"%s\" failed", file->name.data); |
390 return NGX_ERROR; | 400 return NGX_ERROR; |
391 } | 401 } |
392 | 402 |
393 if ((size_t) n != size) { | 403 if ((size_t) n != vec->size) { |
394 ngx_log_error(NGX_LOG_CRIT, file->log, 0, | 404 ngx_log_error(NGX_LOG_CRIT, file->log, 0, |
395 "pwritev() \"%s\" has written only %z of %uz", | 405 "pwritev() \"%s\" has written only %z of %uz", |
396 file->name.data, n, size); | 406 file->name.data, n, vec->size); |
397 return NGX_ERROR; | 407 return NGX_ERROR; |
398 } | 408 } |
399 | 409 |
400 #else | 410 #else |
401 | 411 |
409 file->sys_offset = offset; | 419 file->sys_offset = offset; |
410 } | 420 } |
411 | 421 |
412 eintr: | 422 eintr: |
413 | 423 |
414 n = writev(file->fd, vec->elts, vec->nelts); | 424 n = writev(file->fd, vec->iovs, vec->count); |
415 | 425 |
416 if (n == -1) { | 426 if (n == -1) { |
417 err = ngx_errno; | 427 err = ngx_errno; |
418 | 428 |
419 if (err == NGX_EINTR) { | 429 if (err == NGX_EINTR) { |
425 ngx_log_error(NGX_LOG_CRIT, file->log, err, | 435 ngx_log_error(NGX_LOG_CRIT, file->log, err, |
426 "writev() \"%s\" failed", file->name.data); | 436 "writev() \"%s\" failed", file->name.data); |
427 return NGX_ERROR; | 437 return NGX_ERROR; |
428 } | 438 } |
429 | 439 |
430 if ((size_t) n != size) { | 440 if ((size_t) n != vec->size) { |
431 ngx_log_error(NGX_LOG_CRIT, file->log, 0, | 441 ngx_log_error(NGX_LOG_CRIT, file->log, 0, |
432 "writev() \"%s\" has written only %z of %uz", | 442 "writev() \"%s\" has written only %z of %uz", |
433 file->name.data, n, size); | 443 file->name.data, n, vec->size); |
434 return NGX_ERROR; | 444 return NGX_ERROR; |
435 } | 445 } |
436 | 446 |
437 file->sys_offset += n; | 447 file->sys_offset += n; |
438 | 448 |