Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like IPC often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use IPC, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 18 | class IPC extends Generic |
||
| 19 | { |
||
| 20 | /** |
||
| 21 | * Event base |
||
| 22 | * @var EventLoop |
||
| 23 | */ |
||
| 24 | public $loop; |
||
| 25 | |||
| 26 | /** |
||
| 27 | * Break main loop? |
||
| 28 | * @var boolean |
||
| 29 | */ |
||
| 30 | protected $breakMainLoop = false; |
||
| 31 | |||
| 32 | /** |
||
| 33 | * Reload ready? |
||
| 34 | * @var boolean |
||
| 35 | */ |
||
| 36 | protected $reloadReady = false; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * Update? |
||
| 40 | * @var boolean |
||
| 41 | */ |
||
| 42 | public $update = false; |
||
| 43 | |||
| 44 | |||
| 45 | /** |
||
| 46 | * If true, we do not register signals automatically at start |
||
| 47 | * @var boolean |
||
| 48 | */ |
||
| 49 | protected $delayedSigReg = true; |
||
| 50 | |||
| 51 | /** |
||
| 52 | * Instances count |
||
| 53 | * @var array |
||
| 54 | */ |
||
| 55 | public $instancesCount = []; |
||
| 56 | |||
| 57 | /** |
||
| 58 | * File watcher |
||
| 59 | * @var FileWatcher |
||
| 60 | */ |
||
| 61 | public $fileWatcher; |
||
| 62 | |||
| 63 | /** |
||
| 64 | * If true, we do not register signals automatically at start |
||
| 65 | * @var boolean |
||
| 66 | */ |
||
| 67 | public $reload = false; |
||
| 68 | |||
| 69 | /** @var */ |
||
| 70 | public $IPCManager; |
||
| 71 | |||
| 72 | /** |
||
| 73 | * Runtime of Worker process. |
||
| 74 | * @return void |
||
| 75 | */ |
||
| 76 | protected function run() |
||
| 108 | |||
| 109 | /** |
||
| 110 | * Setup settings on start. |
||
| 111 | * @return void |
||
| 112 | */ |
||
| 113 | protected function prepareSystemEnv() |
||
| 114 | { |
||
| 115 | proc_nice(Daemon::$config->ipcthreadpriority->value); |
||
| 116 | register_shutdown_function([$this, 'shutdown']); |
||
| 117 | |||
| 118 | $this->setTitle( |
||
| 119 | Daemon::$runName . ': IPC process' |
||
| 120 | . (Daemon::$config->pidfile->value !== Daemon::$config->defaultpidfile->value |
||
| 121 | ? ' (' . Daemon::$config->pidfile->value . ')' : '') |
||
| 122 | ); |
||
| 123 | |||
| 124 | if (isset(Daemon::$config->group->value)) { |
||
| 125 | $sg = posix_getgrnam(Daemon::$config->group->value); |
||
| 126 | } |
||
| 127 | |||
| 128 | if (isset(Daemon::$config->user->value)) { |
||
| 129 | $su = posix_getpwnam(Daemon::$config->user->value); |
||
| 130 | } |
||
| 131 | |||
| 132 | if (Daemon::$config->chroot->value !== '/') { |
||
| 133 | View Code Duplication | if (posix_getuid() != 0) { |
|
| 134 | $this->log('You must have the root privileges to change root.'); |
||
| 135 | exit(0); |
||
| 136 | } elseif (!chroot(Daemon::$config->chroot->value)) { |
||
| 137 | Daemon::log('Couldn\'t change root to \'' . Daemon::$config->chroot->value . '\'.'); |
||
| 138 | exit(0); |
||
| 139 | } |
||
| 140 | } |
||
| 141 | |||
| 142 | View Code Duplication | if (isset(Daemon::$config->group->value)) { |
|
| 143 | if ($sg === false) { |
||
| 144 | $this->log('Couldn\'t change group to \'' . Daemon::$config->group->value . '\'. You must replace config-variable \'group\' with existing group.'); |
||
| 145 | exit(0); |
||
| 146 | } elseif (($sg['gid'] != posix_getgid()) && (!posix_setgid($sg['gid']))) { |
||
| 147 | $this->log('Couldn\'t change group to \'' . Daemon::$config->group->value . "'. Error (" . ($errno = posix_get_last_error()) . '): ' . posix_strerror($errno)); |
||
| 148 | exit(0); |
||
| 149 | } |
||
| 150 | } |
||
| 151 | |||
| 152 | View Code Duplication | if (isset(Daemon::$config->user->value)) { |
|
| 153 | if ($su === false) { |
||
| 154 | $this->log('Couldn\'t change user to \'' . Daemon::$config->user->value . '\', user not found. You must replace config-variable \'user\' with existing username.'); |
||
| 155 | exit(0); |
||
| 156 | } elseif (($su['uid'] != posix_getuid()) && (!posix_setuid($su['uid']))) { |
||
| 157 | $this->log('Couldn\'t change user to \'' . Daemon::$config->user->value . "'. Error (" . ($errno = posix_get_last_error()) . '): ' . posix_strerror($errno)); |
||
| 158 | exit(0); |
||
| 159 | } |
||
| 160 | } |
||
| 161 | |||
| 162 | View Code Duplication | if (Daemon::$config->cwd->value !== '.') { |
|
| 163 | if (!@chdir(Daemon::$config->cwd->value)) { |
||
| 164 | $this->log('Couldn\'t change directory to \'' . Daemon::$config->cwd->value . '.'); |
||
| 165 | } |
||
| 166 | } |
||
| 167 | } |
||
| 168 | |||
| 169 | /** |
||
| 170 | * Log something |
||
| 171 | * @param string - Message. |
||
| 172 | * @param string $message |
||
| 173 | * @return void |
||
| 174 | */ |
||
| 175 | public function log($message) |
||
| 179 | |||
| 180 | /** |
||
| 181 | * Reloads additional config-files on-the-fly. |
||
| 182 | * @return void |
||
| 183 | */ |
||
| 184 | protected function update() |
||
| 193 | |||
| 194 | /** |
||
| 195 | * Shutdown thread |
||
| 196 | * @param boolean - Hard? If hard, we shouldn't wait for graceful shutdown of the running applications. |
||
| 197 | * @return boolean|null - Ready? |
||
| 198 | */ |
||
| 199 | public function shutdown($hard = false) |
||
| 230 | |||
| 231 | /** |
||
| 232 | * Handler of the SIGINT (hard shutdown) signal in worker process. |
||
| 233 | * @return void |
||
| 234 | */ |
||
| 235 | protected function sigint() |
||
| 243 | |||
| 244 | /** |
||
| 245 | * Handler of the SIGTERM (graceful shutdown) signal in worker process. |
||
| 246 | * @return void |
||
| 247 | */ |
||
| 248 | protected function sigterm() |
||
| 256 | |||
| 257 | /** |
||
| 258 | * Handler of the SIGQUIT (graceful shutdown) signal in worker process. |
||
| 259 | * @return void |
||
| 260 | */ |
||
| 261 | public function sigquit() |
||
| 269 | |||
| 270 | /** |
||
| 271 | * Handler of the SIGTSTP (graceful stop) signal in worker process. |
||
| 272 | * @return void |
||
| 273 | */ |
||
| 274 | protected function sigtstp() |
||
| 282 | |||
| 283 | /** |
||
| 284 | * Handler of the SIGHUP (reload config) signal in worker process. |
||
| 285 | * @return void |
||
| 286 | */ |
||
| 287 | View Code Duplication | public function sighup() |
|
| 299 | |||
| 300 | /** |
||
| 301 | * Handler of the SIGUSR1 (re-open log-file) signal in worker process. |
||
| 302 | * @return void |
||
| 303 | */ |
||
| 304 | public function sigusr1() |
||
| 312 | |||
| 313 | /** |
||
| 314 | * Handler of the SIGUSR2 (graceful shutdown for update) signal in worker process. |
||
| 315 | * @return void |
||
| 316 | */ |
||
| 317 | public function sigusr2() |
||
| 323 | |||
| 324 | /** |
||
| 325 | * Handler of the SIGTTIN signal in worker process. |
||
| 326 | * @return void |
||
| 327 | */ |
||
| 328 | public function sigttin() |
||
| 331 | |||
| 332 | /** |
||
| 333 | * Handler of the SIGXSFZ signal in worker process. |
||
| 334 | * @return void |
||
| 335 | */ |
||
| 336 | public function sigxfsz() |
||
| 340 | |||
| 341 | /** |
||
| 342 | * Handler of non-known signals. |
||
| 343 | * @return void |
||
| 344 | */ |
||
| 345 | View Code Duplication | public function sigunknown($signo) |
|
| 355 | } |
||
| 356 |