Page MenuHomePhabricator

D10600.id25437.diff
No OneTemporary

D10600.id25437.diff

diff --git a/resources/sql/autopatches/20140928.schema.blamecache.sql b/resources/sql/autopatches/20140928.schema.blamecache.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20140928.schema.blamecache.sql
@@ -0,0 +1,6 @@
+CREATE TABLE {$NAMESPACE}_repository.repository_blamecache (
+ pathId int(10) unsigned NOT NULL,
+ commitId int(10) unsigned NOT NULL,
+ blameDict mediumblob,
+ PRIMARY KEY (pathId,commitId)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2085,6 +2085,7 @@
'PhabricatorRepositoryArcanistProjectPHIDType' => 'applications/repository/phid/PhabricatorRepositoryArcanistProjectPHIDType.php',
'PhabricatorRepositoryArcanistProjectQuery' => 'applications/repository/query/PhabricatorRepositoryArcanistProjectQuery.php',
'PhabricatorRepositoryAuditRequest' => 'applications/repository/storage/PhabricatorRepositoryAuditRequest.php',
+ 'PhabricatorRepositoryBlameCache' => 'applications/repository/storage/PhabricatorRepositoryBlameCache.php',
'PhabricatorRepositoryBranch' => 'applications/repository/storage/PhabricatorRepositoryBranch.php',
'PhabricatorRepositoryCommit' => 'applications/repository/storage/PhabricatorRepositoryCommit.php',
'PhabricatorRepositoryCommitChangeParserWorker' => 'applications/repository/worker/commitchangeparser/PhabricatorRepositoryCommitChangeParserWorker.php',
@@ -5062,6 +5063,7 @@
'PhabricatorRepositoryDAO',
'PhabricatorPolicyInterface',
),
+ 'PhabricatorRepositoryBlameCache' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryBranch' => 'PhabricatorRepositoryDAO',
'PhabricatorRepositoryCommit' => array(
'PhabricatorRepositoryDAO',
diff --git a/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php b/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php
--- a/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php
+++ b/src/applications/diffusion/query/filecontent/DiffusionFileContentQuery.php
@@ -11,6 +11,7 @@
private $needsBlame;
private $fileContent;
private $viewer;
+ private $cachedBlameInfo;
final public static function newFromDiffusionRequest(
DiffusionRequest $request) {
@@ -39,13 +40,62 @@
}
final public function loadFileContent() {
- return $this->executeQuery();
+ if ($this->needsBlame) {
+ $this->loadBlameCache();
+ }
+ $content = $this->executeQuery();
+ return $content;
}
final public function getRawData() {
return $this->fileContent->getCorpus();
}
+
+ /** Blame Cache Functions */
+
+ // Returns array(pathid, lastmodified commitId) for the queried file
+ private function getBlameCacheKey() {
+ $path_id = id(
+ new DiffusionPathIDQuery(
+ array($this->getRequest()->getPath())
+ ))->loadPathIDs();
+ $path_id = array_shift($path_id);
+
+ // FIXME: This one is git specific! Make it work for SVN & Mercurial too
+ $latest_commit = $this->getRequest()->getRepository()
+ ->execxLocalCommand('log -n1 --format="%%H" %s -- %s',
+ $this->getRequest()->getCommit(),
+ $this->getRequest()->getPath());
+ $latest_commit = trim(array_shift($latest_commit));
+
+ // Get the commitId from the Hash
+ $commit_id = id(id(new PhabricatorRepositoryCommit())
+ ->attachRepository($this->getRequest()->getRepository())
+ ->loadOneWhere('commitIdentifier = %s', $latest_commit))->getId();
+
+ return array($path_id, $commit_id);
+ }
+
+ private function loadBlameCache() {
+ $key = $this->getBlameCacheKey();
+ $cache_data =
+ PhabricatorRepositoryBlameCache::loadFromCache($key[0], $key[1]);
+ if ($cache_data) {
+ $this->cachedBlameInfo = $cache_data->getBlameDict();
+ }
+ }
+
+ private function writeBlameCache($blame_dict) {
+ $key = $this->getBlameCacheKey();
+
+ $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
+ PhabricatorRepositoryBlameCache::saveToCache($key[0], $key[1], $blame_dict);
+ unset($unguarded);
+
+ return true;
+ }
+
/**
* Pretty hairy function. If getNeedsBlame is false, this returns
*
@@ -72,34 +122,32 @@
$line_rev_dict = array();
$blame_dict = array();
- if (!$this->getNeedsBlame()) {
+ if (!$this->getNeedsBlame(true)) {
$text_list = explode("\n", $raw_data);
} else if ($raw_data != '') {
- $lines = array();
- foreach (explode("\n", $raw_data) as $k => $line) {
- $lines[$k] = $this->tokenizeLine($line);
-
- list($rev_id, $author, $text) = $lines[$k];
- $text_list[$k] = $text;
- $line_rev_dict[$k] = $rev_id;
- }
-
- $line_rev_dict = $this->processRevList($line_rev_dict);
+ // Check if we have a cached blame
+ if ($this->cachedBlameInfo) {
+ $text_list = explode("\n", $raw_data);
+ $line_rev_dict = $this->cachedBlameInfo;
+ } else {
+ $lines = array();
+ foreach (explode("\n", $raw_data) as $k => $line) {
+ $lines[$k] = $this->tokenizeLine($line);
+
+ list($rev_id, $author, $text) = $lines[$k];
+ $text_list[$k] = $text;
+ $line_rev_dict[$k] = $rev_id;
+ }
- foreach ($lines as $k => $line) {
- list($rev_id, $author, $text) = $line;
- $rev_id = $line_rev_dict[$k];
+ $line_rev_dict = $this->processRevList($line_rev_dict);
- if (!isset($blame_dict[$rev_id])) {
- $blame_dict[$rev_id]['author'] = $author;
- }
+ // Write results to cache
+ $this->writeBlameCache($line_rev_dict);
}
- $repository = $this->getRequest()->getRepository();
-
$commits = id(new DiffusionCommitQuery())
->setViewer($this->getViewer())
- ->withDefaultRepository($repository)
+ ->withDefaultRepository($this->getRequest()->getRepository())
->withIdentifiers(array_unique($line_rev_dict))
->execute();
@@ -115,12 +163,14 @@
foreach ($commits_data as $data) {
$author_phid = $data->getCommitDetail('authorPHID');
- if (!$author_phid) {
- continue;
- }
$commit = $commits[$data->getCommitID()];
$commit_identifier = $commit->getCommitIdentifier();
- $blame_dict[$commit_identifier]['authorPHID'] = $author_phid;
+ if ($author_phid) {
+ $blame_dict[$commit_identifier]['authorPHID'] = $author_phid;
+ } else {
+ $blame_dict[$commit_identifier]['author'] =
+ $data->getCommitDetail('authorName');
+ }
}
}
@@ -136,8 +186,16 @@
return $this;
}
- public function getNeedsBlame() {
- return $this->needsBlame;
+ public function getNeedsBlame($ignore_cache = false) {
+ if ($ignore_cache) {
+ return $this->needsBlame;
+ } else {
+ if (!$this->cachedBlameInfo) {
+ return $this->needsBlame;
+ }
+ }
+
+ return false;
}
public function setViewer(PhabricatorUser $user) {
diff --git a/src/applications/repository/storage/PhabricatorRepositoryBlameCache.php b/src/applications/repository/storage/PhabricatorRepositoryBlameCache.php
new file mode 100644
--- /dev/null
+++ b/src/applications/repository/storage/PhabricatorRepositoryBlameCache.php
@@ -0,0 +1,41 @@
+<?php
+
+final class PhabricatorRepositoryBlameCache extends PhabricatorRepositoryDAO {
+
+ protected $pathId;
+ protected $commitId;
+ protected $blameDict;
+
+ public function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => false,
+ self::CONFIG_TIMESTAMPS => false,
+ self::CONFIG_BINARY => array(
+ 'blameDict' => true,
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function willWriteData(array &$data) {
+ $data['blameDict'] = gzcompress(implode(' ', $data['blameDict']));
+ parent::willWriteData($data);
+ }
+
+ public function willReadData(array &$data) {
+ $data['blameDict'] = explode(' ', gzuncompress($data['blameDict']));
+ parent::willReadData($data);
+ }
+
+ public static function saveToCache($path_id, $commit_id, $blame_dict) {
+ return id(new PhabricatorRepositoryBlameCache())
+ ->setPathId($path_id)
+ ->setCommitId($commit_id)
+ ->setBlameDict($blame_dict)
+ ->replace();
+ }
+
+ public static function loadFromCache($path_id, $commit_id) {
+ return id(new PhabricatorRepositoryBlameCache())
+ ->loadOneWhere('pathId = %d AND commitId = %d', $path_id, $commit_id);
+ }
+}

File Metadata

Mime Type
text/plain
Expires
Mon, May 20, 8:51 AM (1 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6293283
Default Alt Text
D10600.id25437.diff (8 KB)

Event Timeline