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.php43
1 files changed, 32 insertions, 11 deletions
diff --git a/application/bookmark/BookmarkIO.php b/application/bookmark/BookmarkIO.php
index 6bf7f365..c78dbe41 100644
--- a/application/bookmark/BookmarkIO.php
+++ b/application/bookmark/BookmarkIO.php
@@ -1,7 +1,11 @@
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;
5use Shaarli\Bookmark\Exception\DatastoreNotInitializedException; 9use Shaarli\Bookmark\Exception\DatastoreNotInitializedException;
6use Shaarli\Bookmark\Exception\EmptyDataStoreException; 10use Shaarli\Bookmark\Exception\EmptyDataStoreException;
7use Shaarli\Bookmark\Exception\NotWritableDataStoreException; 11use Shaarli\Bookmark\Exception\NotWritableDataStoreException;
@@ -27,11 +31,14 @@ class BookmarkIO
27 */ 31 */
28 protected $conf; 32 protected $conf;
29 33
34
35 /** @var Mutex */
36 protected $mutex;
37
30 /** 38 /**
31 * string Datastore PHP prefix 39 * string Datastore PHP prefix
32 */ 40 */
33 protected static $phpPrefix = '<?php /* '; 41 protected static $phpPrefix = '<?php /* ';
34
35 /** 42 /**
36 * string Datastore PHP suffix 43 * string Datastore PHP suffix
37 */ 44 */
@@ -42,16 +49,21 @@ class BookmarkIO
42 * 49 *
43 * @param ConfigManager $conf instance 50 * @param ConfigManager $conf instance
44 */ 51 */
45 public function __construct($conf) 52 public function __construct(ConfigManager $conf, Mutex $mutex = null)
46 { 53 {
54 if ($mutex === null) {
55 // This should only happen with legacy classes
56 $mutex = new NoMutex();
57 }
47 $this->conf = $conf; 58 $this->conf = $conf;
48 $this->datastore = $conf->get('resource.datastore'); 59 $this->datastore = $conf->get('resource.datastore');
60 $this->mutex = $mutex;
49 } 61 }
50 62
51 /** 63 /**
52 * Reads database from disk to memory 64 * Reads database from disk to memory
53 * 65 *
54 * @return BookmarkArray instance 66 * @return Bookmark[]
55 * 67 *
56 * @throws NotWritableDataStoreException Data couldn't be loaded 68 * @throws NotWritableDataStoreException Data couldn't be loaded
57 * @throws EmptyDataStoreException Datastore file exists but does not contain any bookmark 69 * @throws EmptyDataStoreException Datastore file exists but does not contain any bookmark
@@ -67,11 +79,16 @@ class BookmarkIO
67 throw new NotWritableDataStoreException($this->datastore); 79 throw new NotWritableDataStoreException($this->datastore);
68 } 80 }
69 81
82 $content = null;
83 $this->mutex->synchronized(function () use (&$content) {
84 $content = file_get_contents($this->datastore);
85 });
86
70 // Note that gzinflate is faster than gzuncompress. 87 // Note that gzinflate is faster than gzuncompress.
71 // See: http://www.php.net/manual/en/function.gzdeflate.php#96439 88 // See: http://www.php.net/manual/en/function.gzdeflate.php#96439
72 $links = unserialize(gzinflate(base64_decode( 89 $links = unserialize(gzinflate(base64_decode(
73 substr(file_get_contents($this->datastore), 90 substr($content, strlen(self::$phpPrefix), -strlen(self::$phpSuffix))
74 strlen(self::$phpPrefix), -strlen(self::$phpSuffix))))); 91 )));
75 92
76 if (empty($links)) { 93 if (empty($links)) {
77 if (filesize($this->datastore) > 100) { 94 if (filesize($this->datastore) > 100) {
@@ -86,7 +103,7 @@ class BookmarkIO
86 /** 103 /**
87 * Saves the database from memory to disk 104 * Saves the database from memory to disk
88 * 105 *
89 * @param BookmarkArray $links instance. 106 * @param Bookmark[] $links
90 * 107 *
91 * @throws NotWritableDataStoreException the datastore is not writable 108 * @throws NotWritableDataStoreException the datastore is not writable
92 */ 109 */
@@ -95,14 +112,18 @@ class BookmarkIO
95 if (is_file($this->datastore) && !is_writeable($this->datastore)) { 112 if (is_file($this->datastore) && !is_writeable($this->datastore)) {
96 // The datastore exists but is not writeable 113 // The datastore exists but is not writeable
97 throw new NotWritableDataStoreException($this->datastore); 114 throw new NotWritableDataStoreException($this->datastore);
98 } else if (!is_file($this->datastore) && !is_writeable(dirname($this->datastore))) { 115 } elseif (!is_file($this->datastore) && !is_writeable(dirname($this->datastore))) {
99 // The datastore does not exist and its parent directory is not writeable 116 // The datastore does not exist and its parent directory is not writeable
100 throw new NotWritableDataStoreException(dirname($this->datastore)); 117 throw new NotWritableDataStoreException(dirname($this->datastore));
101 } 118 }
102 119
103 file_put_contents( 120 $data = self::$phpPrefix . base64_encode(gzdeflate(serialize($links))) . self::$phpSuffix;
104 $this->datastore, 121
105 self::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self::$phpSuffix 122 $this->mutex->synchronized(function () use ($data) {
106 ); 123 file_put_contents(
124 $this->datastore,
125 $data
126 );
127 });
107 } 128 }
108} 129}