2

I need to put on a php script that has to serve only one request at a time. That is, if a user requests the page, it must not serve him until a previous request is not completely handled.

I would play with application variables in order to accomplish that, but I see that php doesn't have anything like that, if I well understood.

I tried to use apc then, putting together this code:

<?php

  while (apc_fetch('foo')) {
    echo "waiting...\n";
    sleep(1);
  }

  $foo = true;
  apc_store('foo', $foo);

  echo "results.";
  sleep(10);

  apc_delete('foo');

?>

but if I open twice this page, what I see is just results. in both. I was expecting to read some waiting... as well, since when I load the page for the second time, the first one should have set foo to true.

Is this a legit (but mistaken) use of apc? Am I using the wrong tool?

etuardu
  • 5,066
  • 3
  • 46
  • 58
  • 1
    isn't this the standard behavior of apache (serving one user request at a time) (when working with one processor) ? Whatever, why not using flock() or a PHP session variable ? (can't answer for apc, sorry) – Jscti Nov 22 '12 at 12:59
  • You are at a completely wrong path here, what you're describing will never work. Let's assume that you have request 1 that's being executed and request 2 is queued - request 2 won't say "waiting", it'll hang the browser until the server executes the code for request 2. That's as far as you can go, you can delay execution or you can simply choose not to execute any working code and notify your client #2 that request cannot be completed at this time. There's no "live update" available here. – N.B. Nov 22 '12 at 13:00
  • The right way to do something like this is using semaphores. A quick Google shows me that PHP supports them. – Bart Friederichs Nov 22 '12 at 13:01
  • @N.B. not quite. You can throw a lot of data (e.g. ``) to the browser and flush that. At least Firefox will then show the "waiting...". It's ugly and shouldn't be used on production servers, but it works. – Bart Friederichs Nov 22 '12 at 13:02
  • If I would have to implement a thing like this, I'd use Ajax to dynamically update my page and some kind of database-oriented semaphore or queue. – Bart Friederichs Nov 22 '12 at 13:04
  • possible duplicate of [best way to obtain a lock in php](http://stackoverflow.com/questions/325806/best-way-to-obtain-a-lock-in-php) – Leigh Nov 22 '12 at 13:09
  • @BartFriederichs - the point is that you get a single reply from the PHP script, it's not chunked by default, you can't get a reply, display it and get another reply from the same resource unless you explicitly request it (or use mechanisms that aren't HTTP). – N.B. Nov 22 '12 at 13:53

3 Answers3

0
<?php

  while ($var = apc_fetch('foo')) {
    echo "apc_fetch positive, got ".var_export( $var, true)."\n";
    sleep(1);
  }
  echo "apc_fetch was negative, continuing. \n";

  $foo = "asd";
  apc_store('foo', $foo);
  if( !apc_fetch('foo')) {
     echo "Btw, apc_store was not successful with foo\n";
  }

  echo date('c').": results.";
  flush();
  sleep(10);

  apc_delete('foo');

?>
Antti Rytsölä
  • 1,485
  • 14
  • 24
0

I don't like to answer to my own questions, but in the end this is the most simple way I found to do what I wanted:

<?php

$fp = fopen("lock.txt", "r");

if (flock($fp, LOCK_EX)) {  // acquire

  echo "processing...";

  //if (isset($_GET['sleep'])) sleep(5); // decomment this line to test:
                                         // load "script.php?sleep=1" and then
                                         // load "script.php". The second page will
                                         // wait until the first one ends.

  flock($fp, LOCK_UN); // release

} else {
  // exception handling
  echo "ERROR: unable to flock()";
}

fclose($fp);

?>
etuardu
  • 5,066
  • 3
  • 46
  • 58
-1

Is your apc setup correct? apc_fetch returns false on errors.

Steffen
  • 56
  • 2