aboutsummaryrefslogtreecommitdiffhomepage
path: root/application/bookmark/BookmarkIO.php
diff options
context:
space:
mode:
Diffstat (limited to 'application/bookmark/BookmarkIO.php')
-rw-r--r--application/bookmark/BookmarkIO.php49
1 files changed, 35 insertions, 14 deletions
diff --git a/application/bookmark/BookmarkIO.php b/application/bookmark/BookmarkIO.php
index ae9ffcb4..f40fa476 100644
--- a/application/bookmark/BookmarkIO.php
+++ b/application/bookmark/BookmarkIO.php
@@ -1,7 +1,12 @@
1<?php 1<?php
2 2
3declare(strict_types=1);
4
3namespace Shaarli\Bookmark; 5namespace Shaarli\Bookmark;
4 6
7use malkusch\lock\mutex\Mutex;
8use malkusch\lock\mutex\NoMutex;
9use Shaarli\Bookmark\Exception\DatastoreNotInitializedException;
5use Shaarli\Bookmark\Exception\EmptyDataStoreException; 10use Shaarli\Bookmark\Exception\EmptyDataStoreException;
6use Shaarli\Bookmark\Exception\NotWritableDataStoreException; 11use Shaarli\Bookmark\Exception\NotWritableDataStoreException;
7use Shaarli\Config\ConfigManager; 12use Shaarli\Config\ConfigManager;
@@ -26,11 +31,14 @@ class BookmarkIO
26 */ 31 */
27 protected $conf; 32 protected $conf;
28 33
34
35 /** @var Mutex */
36 protected $mutex;
37
29 /** 38 /**
30 * string Datastore PHP prefix 39 * string Datastore PHP prefix
31 */ 40 */
32 protected static $phpPrefix = '<?php /* '; 41 protected static $phpPrefix = '<?php /* ';
33
34 /** 42 /**
35 * string Datastore PHP suffix 43 * string Datastore PHP suffix
36 */ 44 */
@@ -41,35 +49,46 @@ class BookmarkIO
41 * 49 *
42 * @param ConfigManager $conf instance 50 * @param ConfigManager $conf instance
43 */ 51 */
44 public function __construct($conf) 52 public function __construct(ConfigManager $conf, Mutex $mutex = null)
45 { 53 {
54 if ($mutex === null) {
55 // This should only happen with legacy classes
56 $mutex = new NoMutex();
57 }
46 $this->conf = $conf; 58 $this->conf = $conf;
47 $this->datastore = $conf->get('resource.datastore'); 59 $this->datastore = $conf->get('resource.datastore');
60 $this->mutex = $mutex;
48 } 61 }
49 62
50 /** 63 /**
51 * Reads database from disk to memory 64 * Reads database from disk to memory
52 * 65 *
53 * @return BookmarkArray instance 66 * @return Bookmark[]
54 * 67 *
55 * @throws NotWritableDataStoreException Data couldn't be loaded 68 * @throws NotWritableDataStoreException Data couldn't be loaded
56 * @throws EmptyDataStoreException Datastore doesn't exist 69 * @throws EmptyDataStoreException Datastore file exists but does not contain any bookmark
70 * @throws DatastoreNotInitializedException File does not exists
57 */ 71 */
58 public function read() 72 public function read()
59 { 73 {
60 if (! file_exists($this->datastore)) { 74 if (! file_exists($this->datastore)) {
61 throw new EmptyDataStoreException(); 75 throw new DatastoreNotInitializedException();
62 } 76 }
63 77
64 if (!is_writable($this->datastore)) { 78 if (!is_writable($this->datastore)) {
65 throw new NotWritableDataStoreException($this->datastore); 79 throw new NotWritableDataStoreException($this->datastore);
66 } 80 }
67 81
82 $content = null;
83 $this->mutex->synchronized(function () use (&$content) {
84 $content = file_get_contents($this->datastore);
85 });
86
68 // Note that gzinflate is faster than gzuncompress. 87 // Note that gzinflate is faster than gzuncompress.
69 // See: http://www.php.net/manual/en/function.gzdeflate.php#96439 88 // See: http://www.php.net/manual/en/function.gzdeflate.php#96439
70 $links = unserialize(gzinflate(base64_decode( 89 $links = unserialize(gzinflate(base64_decode(
71 substr(file_get_contents($this->datastore), 90 substr($content, strlen(self::$phpPrefix), -strlen(self::$phpSuffix))
72 strlen(self::$phpPrefix), -strlen(self::$phpSuffix))))); 91 )));
73 92
74 if (empty($links)) { 93 if (empty($links)) {
75 if (filesize($this->datastore) > 100) { 94 if (filesize($this->datastore) > 100) {
@@ -84,7 +103,7 @@ class BookmarkIO
84 /** 103 /**
85 * Saves the database from memory to disk 104 * Saves the database from memory to disk
86 * 105 *
87 * @param BookmarkArray $links instance. 106 * @param Bookmark[] $links
88 * 107 *
89 * @throws NotWritableDataStoreException the datastore is not writable 108 * @throws NotWritableDataStoreException the datastore is not writable
90 */ 109 */
@@ -98,11 +117,13 @@ class BookmarkIO
98 throw new NotWritableDataStoreException(dirname($this->datastore)); 117 throw new NotWritableDataStoreException(dirname($this->datastore));
99 } 118 }
100 119
101 file_put_contents( 120 $data = self::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self::$phpSuffix;
102 $this->datastore,
103 self::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self::$phpSuffix
104 );
105 121
106 invalidateCaches($this->conf->get('resource.page_cache')); 122 $this->mutex->synchronized(function () use ($data) {
123 file_put_contents(
124 $this->datastore,
125 $data
126 );
127 });
107 } 128 }
108} 129}