… | |
… | |
34 | our $connections = new Coro::Semaphore $MAX_CONNECTS || 250; |
34 | our $connections = new Coro::Semaphore $MAX_CONNECTS || 250; |
35 | our $httpevent = new Coro::Signal; |
35 | our $httpevent = new Coro::Signal; |
36 | |
36 | |
37 | our $wait_factor = 0.95; |
37 | our $wait_factor = 0.95; |
38 | |
38 | |
39 | our @transfers = ( |
39 | our $queue_small = new transferqueue $MAX_TRANSFERS_SMALL; |
40 | (new Coro::Semaphore $MAX_TRANSFERS_SMALL), |
40 | our $queue_large = new transferqueue $MAX_TRANSFERS_LARGE; |
41 | (new Coro::Semaphore $MAX_TRANSFERS_LARGE), |
41 | our $queue_index = new transferqueue 5; |
42 | ); |
|
|
43 | |
42 | |
44 | my @newcons; |
43 | my @newcons; |
45 | my @pool; |
44 | my @pool; |
46 | |
45 | |
47 | # one "execution thread" |
46 | # one "execution thread" |
… | |
… | |
157 | $self->{time} = $::NOW; |
156 | $self->{time} = $::NOW; |
158 | |
157 | |
159 | weaken ($Coro::current->{conn} = $self); |
158 | weaken ($Coro::current->{conn} = $self); |
160 | |
159 | |
161 | $::conns++; |
160 | $::conns++; |
|
|
161 | $::maxconns = $::conns if $::conns > $::maxconns; |
162 | |
162 | |
163 | $self; |
163 | $self; |
164 | } |
164 | } |
165 | |
165 | |
166 | sub DESTROY { |
166 | sub DESTROY { |
… | |
… | |
448 | or $self->err(304, "not modified"); |
448 | or $self->err(304, "not modified"); |
449 | |
449 | |
450 | if (-r "$path/index.html") { |
450 | if (-r "$path/index.html") { |
451 | # replace directory "size" by index.html filesize |
451 | # replace directory "size" by index.html filesize |
452 | $self->{stat}[7] = (stat ($self->{path} .= "/index.html"))[7]; |
452 | $self->{stat}[7] = (stat ($self->{path} .= "/index.html"))[7]; |
453 | $self->handle_file; |
453 | $self->handle_file($queue_index); |
454 | } else { |
454 | } else { |
455 | $self->handle_dir; |
455 | $self->handle_dir; |
456 | } |
456 | } |
457 | } |
457 | } |
458 | } elsif (-f _ && -r _) { |
458 | } elsif (-f _ && -r _) { |
459 | -x _ and $self->err(403, "forbidden"); |
459 | -x _ and $self->err(403, "forbidden"); |
460 | $self->handle_file; |
460 | $self->handle_file(-s _ >= $::TRANSFER_SMALL ? $queue_large : $queue_small); |
461 | } else { |
461 | } else { |
462 | $self->err(404, "not found"); |
462 | $self->err(404, "not found"); |
463 | } |
463 | } |
464 | } |
464 | } |
465 | } |
465 | } |
… | |
… | |
477 | }, |
477 | }, |
478 | $idx); |
478 | $idx); |
479 | } |
479 | } |
480 | |
480 | |
481 | sub handle_file { |
481 | sub handle_file { |
482 | my $self = shift; |
482 | my ($self, $queue) = @_; |
483 | my $length = $self->{stat}[7]; |
483 | my $length = $self->{stat}[7]; |
484 | my $queue = $::transfers[$length >= $::TRANSFER_SMALL]; |
|
|
485 | my $hdr = { |
484 | my $hdr = { |
486 | "Last-Modified" => time2str ((stat _)[9]), |
485 | "Last-Modified" => time2str ((stat _)[9]), |
487 | }; |
486 | }; |
488 | |
487 | |
489 | my @code = (200, "ok"); |
488 | my @code = (200, "ok"); |
… | |
… | |
549 | if ($l) { |
548 | if ($l) { |
550 | sysseek $fh, $l, 0; |
549 | sysseek $fh, $l, 0; |
551 | } |
550 | } |
552 | } |
551 | } |
553 | |
552 | |
554 | my $transfer; # transfer guard |
553 | my $transfer = $queue->start_transfer; |
|
|
554 | my $locked; |
555 | my $bufsize = $::WAIT_BUFSIZE; # initial buffer size |
555 | my $bufsize = $::WAIT_BUFSIZE; # initial buffer size |
556 | |
556 | |
557 | $self->{time} = $::NOW; |
|
|
558 | |
|
|
559 | while ($h > 0) { |
557 | while ($h > 0) { |
560 | unless ($transfer) { |
558 | unless ($locked) { |
561 | if ($transfer ||= $queue->timed_guard($::WAIT_INTERVAL)) { |
559 | if ($locked ||= $transfer->try($::WAIT_INTERVAL)) { |
562 | $bufsize = $::BUFSIZE; |
560 | $bufsize = $::BUFSIZE; |
563 | $self->{time} = $::NOW; |
561 | $self->{time} = $::NOW; |
564 | } |
562 | } |
565 | } |
563 | } |
566 | |
564 | |