Project

General

Profile

1
<?php
2

    
3
include_once $GLOBALS['THRIFT_ROOT'].'/server/TServer.php';
4

    
5
/**
6
 * A forking implementation of a Thrift server.
7
 *
8
 * @package thrift.server
9
 */
10
class TForkingServer extends TServer {
11
  /**
12
   * Flag for the main serving loop
13
   *
14
   * @var bool
15
   */
16
  private $stop_ = false;
17

    
18
  /**
19
   * List of children.
20
   *
21
   * @var array
22
   */
23
  protected $children_ = array();
24

    
25
  /**
26
   * Listens for new client using the supplied
27
   * transport. We fork when a new connection
28
   * arrives.
29
   *
30
   * @return void
31
   */
32
  public function serve() {
33
    $this->transport_->listen();
34

    
35
    while (!$this->stop_) {
36
      try {
37
        $transport = $this->transport_->accept();
38

    
39
        if ($transport != null) {
40
          $pid = pcntl_fork();
41

    
42
          if ($pid > 0) {
43
            $this->handleParent($transport, $pid);
44
          }
45
          else if ($pid === 0) {
46
            $this->handleChild($transport);
47
          }
48
          else {
49
            throw new TException('Failed to fork');
50
          }
51
        }
52
      }
53
      catch (TTransportException $e) { }
54

    
55
      $this->collectChildren();
56
    }
57
  }
58

    
59
  /**
60
   * Code run by the parent
61
   *
62
   * @param TTransport $transport
63
   * @param int $pid
64
   * @return void
65
   */
66
  private function handleParent(TTransport $transport, $pid) {
67
    $this->children_[$pid] = $transport;
68
  }
69

    
70
  /**
71
   * Code run by the child.
72
   *
73
   * @param TTransport $transport
74
   * @return void
75
   */
76
  private function handleChild(TTransport $transport) {
77
    try {
78
      $inputTransport = $this->inputTransportFactory_->getTransport($transport);
79
      $outputTransport = $this->outputTransportFactory_->getTransport($transport);
80
      $inputProtocol = $this->inputProtocolFactory_->getProtocol($inputTransport);
81
      $outputProtocol = $this->outputProtocolFactory_->getProtocol($outputTransport);
82
      while ($this->processor_->process($inputProtocol, $outputProtocol)) { }
83
      @$transport->close();
84
    }
85
    catch (TTransportException $e) { }
86
    
87
    exit(0);
88
  }
89

    
90
  /**
91
   * Collects any children we may have
92
   *
93
   * @return void
94
   */
95
  private function collectChildren() {
96
    foreach ($this->children_ as $pid => $transport) {
97
      if (pcntl_waitpid($pid, $status, WNOHANG) > 0) {
98
        unset($this->children_[$pid]);
99
        if ($transport) @$transport->close();
100
      }
101
    }
102
  }
103

    
104
  /**
105
   * Stops the server running. Kills the transport
106
   * and then stops the main serving loop
107
   *
108
   * @return void
109
   */
110
  public function stop() {
111
    $this->transport_->close();
112
    $this->stop_ = true;
113
  }
114
}
(1-1/3)