/** * Get the name of the lock to use specific to the database name of the current application, as a SQL-escaped string. */ protected static function lockNamePostfix() { if (!self::$lockNamePostfix) { self::$lockNamePostfix = Convert::raw2sql('_' . DB::query('select database()')->value()); } return self::$lockNamePostfix; }
/** * Returns a single queue object according to a particular priority and freshness measure. * This method removes any duplicates and makes the object as "regenerating", so other calls to this method * don't grab the same object. * If we are using MySQLDatabase with InnoDB, we do row-level locking when updating the dataobject to allow for * distributed cache rebuilds * @static * @param $freshness * @param $sortOrder */ protected static function get_queue_object($freshness, $interval = null, $sortOrder = array('Priority' => 'DESC', 'ID' => 'ASC')) { $className = __CLASS__; $queueObject = null; $filterQuery = array("Freshness" => $freshness); if ($interval) { $filterQuery["LastEdited:LessThan"] = $interval; } $query = self::get(); if ($query->Count() > 0) { $offset = 0; $filteredQuery = $query->filter($filterQuery)->sort($sortOrder); if ($filteredQuery->Count() > 0) { if (DB::getConn() instanceof MySQLDatabase) { //locking currently only works on MySQL do { $queueObject = $filteredQuery->limit(1, $offset)->first(); //get first item if ($queueObject) { $lockName = md5($queueObject->URLSegment . $className); } //try to locking the item's URL, keep trying new URLs until we find one that is free to lock $offset++; } while ($queueObject && !LockMySQL::isFreeToLock($lockName)); if ($queueObject) { $lockSuccess = LockMySQL::getLock($lockName); //acquire a lock with the URL of the queue item we have just fetched if ($lockSuccess) { self::remove_duplicates($queueObject->ID); //remove any duplicates self::mark_as_regenerating($queueObject); //mark as regenerating so nothing else grabs it LockMySQL::releaseLock($lockName); //return the object and release the lock } } } else { $queueObject = $filteredQuery->first(); self::remove_duplicates($queueObject->ID); self::mark_as_regenerating($queueObject); } } } return $queueObject; //return the object or null }