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