Completed
Push — master ( c49b4a...2b6b4e )
by Tim
14s queued 11s
created

StandardGarbageCollector   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 154
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 32
dl 0
loc 154
rs 10
c 0
b 0
f 0
wmc 11

7 Methods

Rating   Name   Duplication   Size   Complexity  
A injectApplication() 0 3 1
A log() 0 3 1
A iterate() 0 8 1
A getApplication() 0 3 1
A bootstrap() 0 19 2
A collectGarbage() 0 46 4
A getDefaultTimeout() 0 3 1
1
<?php
2
3
/**
4
 * \AppserverIo\Appserver\PersistenceContainer\GarbageCollectors\StandardGarbageCollector
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2015 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/appserver-io/appserver
18
 * @link      http://www.appserver.io
19
 */
20
21
namespace AppserverIo\Appserver\PersistenceContainer\GarbageCollectors;
22
23
use Psr\Log\LogLevel;
24
use AppserverIo\Logger\LoggerUtils;
25
use AppserverIo\Appserver\Core\AbstractDaemonThread;
26
use AppserverIo\Psr\Application\ApplicationInterface;
27
use AppserverIo\Psr\EnterpriseBeans\BeanContextInterface;
28
29
/**
30
 * The garbage collector for the stateful session beans.
31
 *
32
 * @author    Tim Wagner <[email protected]>
33
 * @copyright 2015 TechDivision GmbH <[email protected]>
34
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
35
 * @link      https://github.com/appserver-io/appserver
36
 * @link      http://www.appserver.io
37
 */
38
class StandardGarbageCollector extends AbstractDaemonThread
39
{
40
41
    /**
42
     * The timeout to wait inside the garbage collector's while() loop.
43
     *
44
     * @var integer
45
     */
46
    const GARBAGE_COLLECTION_TIMEOUT = 5000000;
47
48
    /**
49
     * Injects the application instance.
50
     *
51
     * @param \AppserverIo\Psr\Application\ApplicationInterface $application The application instance
52
     *
53
     * @return void
54
     */
55
    public function injectApplication(ApplicationInterface $application)
56
    {
57
        $this->application = $application;
0 ignored issues
show
Bug Best Practice introduced by
The property application does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
58
    }
59
60
    /**
61
     * Returns the application instance.
62
     *
63
     * @return \AppserverIo\Psr\Application\ApplicationInterface The application instance
64
     */
65
    public function getApplication()
66
    {
67
        return $this->application;
68
    }
69
70
    /**
71
     * This method will be invoked before the while() loop starts and can be used
72
     * to implement some bootstrap functionality.
73
     *
74
     * @return void
75
     */
76
    public function bootstrap()
77
    {
78
79
        // setup autoloader
80
        require SERVER_AUTOLOADER;
81
82
        // enable garbage collection
83
        gc_enable();
84
85
        // synchronize the application instance and register the class loaders
86
        $application = $this->getApplication();
87
        $application->registerClassLoaders();
0 ignored issues
show
Bug introduced by
The method registerClassLoaders() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

87
        $application->/** @scrutinizer ignore-call */ 
88
                      registerClassLoaders();
Loading history...
88
89
        // register the applications annotation registries
90
        $application->registerAnnotationRegistries();
0 ignored issues
show
Bug introduced by
The method registerAnnotationRegistries() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

90
        $application->/** @scrutinizer ignore-call */ 
91
                      registerAnnotationRegistries();
Loading history...
91
92
        // try to load the profile logger
93
        if ($this->profileLogger = $this->getApplication()->getInitialContext()->getLogger(LoggerUtils::PROFILE)) {
0 ignored issues
show
Bug Best Practice introduced by
The property profileLogger does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Bug introduced by
The method getInitialContext() does not exist on AppserverIo\Psr\Application\ApplicationInterface. It seems like you code against a sub-type of AppserverIo\Psr\Application\ApplicationInterface such as AppserverIo\Appserver\Application\Application. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
        if ($this->profileLogger = $this->getApplication()->/** @scrutinizer ignore-call */ getInitialContext()->getLogger(LoggerUtils::PROFILE)) {
Loading history...
94
            $this->profileLogger->appendThreadContext('persistence-container-garbage-collector');
95
        }
96
    }
97
98
    /**
99
     * This is invoked on every iteration of the daemons while() loop.
100
     *
101
     * @param integer $timeout The timeout before the daemon wakes up
102
     *
103
     * @return void
104
     */
105
    public function iterate($timeout)
106
    {
107
108
        // call parent method and sleep for the default timeout
109
        parent::iterate($timeout);
110
111
        // collect the SFSBs that timed out
112
        $this->collectGarbage();
113
    }
114
115
    /**
116
     * Collects the SFSBs that has been timed out
117
     *
118
     * @return void
119
     */
120
    public function collectGarbage()
121
    {
122
123
        // we need the bean manager that handles all the beans
124
        /** @var \AppserverIo\Psr\EnterpriseBeans\BeanContextInterface $beanManager */
125
        $beanManager = $this->getApplication()->search(BeanContextInterface::IDENTIFIER);
126
127
        // load the map with the stateful session beans
128
        /** @var \AppserverIo\Storage\StorageInterface $statefulSessionBeans */
129
        $statefulSessionBeans = $beanManager->getStatefulSessionBeans();
0 ignored issues
show
Bug introduced by
The method getStatefulSessionBeans() does not exist on AppserverIo\Psr\Enterpri...ns\BeanContextInterface. It seems like you code against a sub-type of AppserverIo\Psr\Enterpri...ns\BeanContextInterface such as AppserverIo\Appserver\Pe...ceContainer\BeanManager. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

129
        /** @scrutinizer ignore-call */ 
130
        $statefulSessionBeans = $beanManager->getStatefulSessionBeans();
Loading history...
130
131
        // initialize the timestamp with the actual time
132
        $actualTime = time();
133
134
        // load the map with the SFSB lifetime data
135
        $lifetimeMap = $statefulSessionBeans->getLifetime();
0 ignored issues
show
Bug introduced by
The method getLifetime() does not exist on AppserverIo\Storage\StorageInterface. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

135
        /** @scrutinizer ignore-call */ 
136
        $lifetimeMap = $statefulSessionBeans->getLifetime();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
136
137
        // initialize the counter for the SFSBs
138
        $counter = 0;
139
140
        // iterate over the applications sessions with stateful session beans
141
        foreach ($lifetimeMap as $identifier => $lifetime) {
142
            // check the lifetime of the stateful session beans
143
            if ($lifetime < $actualTime) {
144
                // if the stateful session bean has timed out, remove it
145
                $statefulSessionBeans->remove($identifier, array($beanManager, 'destroyBeanInstance'));
0 ignored issues
show
Unused Code introduced by
The call to AppserverIo\Storage\StorageInterface::remove() has too many arguments starting with array($beanManager, 'destroyBeanInstance'). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

145
                $statefulSessionBeans->/** @scrutinizer ignore-call */ 
146
                                       remove($identifier, array($beanManager, 'destroyBeanInstance'));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
146
                // write a log message
147
                $this->log(LogLevel::DEBUG, sprintf('Successfully removed SFSB %s', $identifier));
148
                // reduce CPU load
149
                usleep(1000);
150
            } else {
151
                // raise the counter
152
                $counter++;
153
                // write a log message
154
                $this->log(LogLevel::DEBUG, sprintf('Lifetime %s of SFSB %s is > %s', $lifetime, $identifier, $actualTime));
155
            }
156
        }
157
158
        // write a log message with size of SFSBs to be garbage collected
159
        $this->log(LogLevel::DEBUG, sprintf('Found %d SFSBs be garbage collected', $counter));
160
161
        // profile the size of the sessions
162
        /** @var \Psr\Log\LoggerInterface $this->profileLogger */
163
        if ($this->profileLogger) {
164
            $this->profileLogger->debug(
165
                sprintf('Processed standard garbage collector, handling %d SFSBs', sizeof($statefulSessionBeans))
166
            );
167
        }
168
    }
169
170
    /**
171
     * Returns the default timeout.
172
     *
173
     * @return integer The default timeout in microseconds
174
     */
175
    public function getDefaultTimeout()
176
    {
177
        return StandardGarbageCollector::GARBAGE_COLLECTION_TIMEOUT;
178
    }
179
180
    /**
181
     * This is a very basic method to log some stuff by using the error_log() method of PHP.
182
     *
183
     * @param mixed  $level   The log level to use
184
     * @param string $message The message we want to log
185
     * @param array  $context The context we of the message
186
     *
187
     * @return void
188
     */
189
    public function log($level, $message, array $context = array())
190
    {
191
        $this->getApplication()->getInitialContext()->getSystemLogger()->log($level, $message, $context);
192
    }
193
}
194