function State::setMultiple
Same name and namespace in other branches
- 11.x core/lib/Drupal/Core/State/State.php \Drupal\Core\State\State::setMultiple()
- 10 core/lib/Drupal/Core/State/State.php \Drupal\Core\State\State::setMultiple()
- 9 core/lib/Drupal/Core/State/State.php \Drupal\Core\State\State::setMultiple()
- 8.9.x core/lib/Drupal/Core/State/State.php \Drupal\Core\State\State::setMultiple()
Saves key/value pairs.
Parameters
array $data: An associative array of key/value pairs.
Overrides StateInterface::setMultiple
File
-
core/
lib/ Drupal/ Core/ State/ State.php, line 104
Class
- State
- Provides the state system using a key value store.
Namespace
Drupal\Core\StateCode
public function setMultiple(array $data) {
$lock_name = $this->getCid() . ':' . CacheCollector::class;
$lock_acquired = $this->lock
->acquire($lock_name);
$this->lazyLoadCache();
foreach ($data as $key => $value) {
$this->registerKeySetDuringRequest($key, $value, parent::get($key));
if (isset(self::$deprecatedState[$key])) {
// phpcs:ignore Drupal.Semantics.FunctionTriggerError
@trigger_error(self::$deprecatedState[$key]['message'], E_USER_DEPRECATED);
$data[self::$deprecatedState[$key]['replacement']] = $value;
unset($data[$key]);
}
}
$this->keyValueStore
->setMultiple($data);
// If another request had a cache miss before this request, and also hasn't
// written to cache yet, then it may already have read the previous value
// from the database and could write it to the cache at the end of the
// request. To avoid this race condition, attempt to acquire a lock and
// write to the cache immediately. This allows the race condition detection
// in CacheCollector::updateCache() to work. We write to the cache whether
// or not we acquire the lock, because CacheCollector::updateCache() handles
// the case where there was no cache item at the beginning of the request,
// but one was written by another request before ::updateCache() is called
// - the new cache item functions as a tombstone record in this case.
foreach ($data as $key => $value) {
$this->storage[$key] = $value;
// The key might have been marked for deletion.
unset($this->keysToRemove[$key]);
$this->persist($key);
}
if (!$lock_acquired) {
// If we were unable to acquire a lock, immediately write the cache item
// anyway. This acts as a tombstone for other requests that have not
// reached a cache write yet: writing an (empty) item makes a concurrent
// request that loaded a different item - or no item - detect the change
// by content in ::updateCache() and back out. It also ensures that the
// end of this request will detect that the cache item has changed.
$this->cache
->set($this->getCid(), [], CacheBackendInterface::CACHE_PERMANENT, $this->tags);
$this->cacheInvalidated = TRUE;
// Wait for the lock to become available for a maximum of one second, then
// attempt to acquire the lock again. If we can't acquire the lock, then
// the one second that has passed should have given most processes that
// were in progress time to complete anyway.
$this->lock
->wait($lock_name, 1);
$lock_acquired = $this->lock
->acquire($lock_name);
// If we were unable to acquire the lock even after waiting, write the
// cache item a second time, this will override any cache writes in the
// interim.
if (!$lock_acquired) {
$this->cache
->set($this->getCid(), [], CacheBackendInterface::CACHE_PERMANENT, $this->tags);
}
}
if ($lock_acquired) {
// Write the new value within the lock. A concurrent request that read an
// earlier cache item will detect the change when it compares the data
// fingerprint in CacheCollector::updateCache(), even if both writes
// happened within the same millisecond. This is why no sleep is needed to
// force distinct cache item creation timestamps.
// @see \Drupal\Core\Cache\CacheCollector::updateCache()
$this->cache
->set($this->getCid(), $data, CacheBackendInterface::CACHE_PERMANENT, $this->tags);
// Because we've updated the cache within a lock here, we don't need to do
// so again at the end of the request. Other requests can safely start
// rebuilding the cache after this point.
$this->lock
->release($lock_name);
$this->cacheInvalidated = FALSE;
$this->keysToPersist = [];
$this->keysToRemove = [];
}
}
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.