<?php
+declare(strict_types=1);
+
namespace Shaarli\Bookmark;
+use malkusch\lock\mutex\Mutex;
+use malkusch\lock\mutex\NoMutex;
use Shaarli\Bookmark\Exception\DatastoreNotInitializedException;
use Shaarli\Bookmark\Exception\EmptyDataStoreException;
use Shaarli\Bookmark\Exception\NotWritableDataStoreException;
*/
protected $conf;
+
+ /** @var Mutex */
+ protected $mutex;
+
/**
* string Datastore PHP prefix
*/
protected static $phpPrefix = '<?php /* ';
-
/**
* string Datastore PHP suffix
*/
*
* @param ConfigManager $conf instance
*/
- public function __construct($conf)
+ public function __construct(ConfigManager $conf, Mutex $mutex = null)
{
+ if ($mutex === null) {
+ // This should only happen with legacy classes
+ $mutex = new NoMutex();
+ }
$this->conf = $conf;
$this->datastore = $conf->get('resource.datastore');
+ $this->mutex = $mutex;
}
/**
* Reads database from disk to memory
*
- * @return BookmarkArray instance
+ * @return Bookmark[]
*
* @throws NotWritableDataStoreException Data couldn't be loaded
* @throws EmptyDataStoreException Datastore file exists but does not contain any bookmark
throw new NotWritableDataStoreException($this->datastore);
}
+ $content = null;
+ $this->mutex->synchronized(function () use (&$content) {
+ $content = file_get_contents($this->datastore);
+ });
+
// Note that gzinflate is faster than gzuncompress.
// See: http://www.php.net/manual/en/function.gzdeflate.php#96439
$links = unserialize(gzinflate(base64_decode(
- substr(file_get_contents($this->datastore),
- strlen(self::$phpPrefix), -strlen(self::$phpSuffix)))));
+ substr($content, strlen(self::$phpPrefix), -strlen(self::$phpSuffix))
+ )));
if (empty($links)) {
if (filesize($this->datastore) > 100) {
/**
* Saves the database from memory to disk
*
- * @param BookmarkArray $links instance.
+ * @param Bookmark[] $links
*
* @throws NotWritableDataStoreException the datastore is not writable
*/
throw new NotWritableDataStoreException(dirname($this->datastore));
}
- file_put_contents(
- $this->datastore,
- self::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self::$phpSuffix
- );
+ $data = self::$phpPrefix.base64_encode(gzdeflate(serialize($links))).self::$phpSuffix;
+
+ $this->mutex->synchronized(function () use ($data) {
+ file_put_contents(
+ $this->datastore,
+ $data
+ );
+ });
}
}