Completed
Push — master ( 9eb332...ef5bef )
by Arne
02:27
created

AbstractLockAdapter::setIdentity()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A AbstractLockAdapter::__destruct() 0 4 1
1
<?php
2
3
namespace Storeman\LockAdapter;
4
5
use Psr\Log\LoggerAwareInterface;
6
use Psr\Log\LoggerInterface;
7
use Psr\Log\NullLogger;
8
use Storeman\Config\Configuration;
9
10
abstract class AbstractLockAdapter implements LockAdapterInterface, LoggerAwareInterface
11
{
12
    /**
13
     * @var int[]
14
     */
15
    protected $lockDepthMap = [];
16
17
    /**
18
     * @var Configuration
19
     */
20
    protected $configuration;
21
22
    /**
23
     * @var LoggerInterface
24
     */
25
    protected $logger;
26
27
    public function __construct(Configuration $configuration)
28
    {
29
        $this->configuration = $configuration;
30
        $this->logger = new NullLogger();
31
    }
32
33
    /**
34
     * {@inheritdoc}
35
     */
36
    public function setLogger(LoggerInterface $logger): void
37
    {
38
        $this->logger = $logger;
39
    }
40
41
    public function isLocked(string $name): bool
42
    {
43
        return $this->hasLock($name) || $this->doGetLock($name) !== null;
44
    }
45
46
    public function hasLock(string $name): bool
47
    {
48
        return array_key_exists($name, $this->lockDepthMap);
49
    }
50
51
    public function getLock(string $name): ?Lock
52
    {
53
        return $this->doGetLock($name);
54
    }
55
56
    public function acquireLock(string $name, int $timeout = null): bool
57
    {
58
        $this->logger->info(sprintf(
59
            "Lock '{$name}' with %s timeout requested. Current lock depth: %s",
60
            is_int($timeout) ? "{$timeout}s" : 'indefinite',
61
            array_key_exists($name, $this->lockDepthMap) ? $this->lockDepthMap[$name] : '0'
62
        ));
63
64
        if (!array_key_exists($name, $this->lockDepthMap))
65
        {
66
            $success = $this->doAcquireLock($name, $timeout);
67
68
            if (!$success)
69
            {
70
                $this->logger->notice("Failed to acquire lock '{$name}'");
71
72
                return false;
73
            }
74
75
            $this->logger->notice("Successfully acquired lock '{$name}'");
76
77
            $this->lockDepthMap[$name] = 0;
78
        }
79
80
        $this->lockDepthMap[$name]++;
81
82
        $this->logger->info("Lock depth for '{$name}' changed to {$this->lockDepthMap[$name]}");
83
84
        return true;
85
    }
86
87
    public function releaseLock(string $name): bool
88
    {
89
        if (array_key_exists($name, $this->lockDepthMap))
90
        {
91
            $this->logger->info("Lock release for '{$name}' requested. Current lock depth: {$this->lockDepthMap[$name]}");
92
93
            if (--$this->lockDepthMap[$name] === 0)
94
            {
95
                $this->logger->notice("Releasing lock '{$name}'...");
96
97
                $this->doReleaseLock($name);
98
99
                unset($this->lockDepthMap[$name]);
100
            }
101
        }
102
        else
103
        {
104
            $this->logger->info("Requested lock release for non-hold lock '{$name}'. Doing nothing.");
105
        }
106
107
        return true;
108
    }
109
110
    public function __destruct()
111
    {
112
        $this->releaseAcquiredLocks();
113
    }
114
115
    protected function releaseAcquiredLocks()
116
    {
117
        $this->logger->info("Releasing all acquired locks: " . ($this->lockDepthMap ? implode(',', array_keys($this->lockDepthMap)) : '-'));
118
119
        foreach (array_keys($this->lockDepthMap) as $lockName)
120
        {
121
            $this->doReleaseLock($lockName);
122
        }
123
124
        $this->lockDepthMap = [];
125
    }
126
127
    protected function getNewLockPayload(string $name): string
128
    {
129
        return (new Lock($name, $this->configuration->getIdentity()))->getPayload();
130
    }
131
132
    abstract protected function doGetLock(string $name): ?Lock;
133
    abstract protected function doAcquireLock(string $name, int $timeout = null): bool;
134
    abstract protected function doReleaseLock(string $name): void;
135
}
136