mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-19 21:32:43 +01:00
Fix improper selection of the chunk engine as a writable engine
Summary: Fixes T7621. The engine selection code started out making sense, but didn't make as much sense by the time I was done with it. Specifically, from the vanilla file upload, we may incorrectly try to write directly to the chunk storage engine. This is incorrect, and produces a confusing/bad error. Make chunk storage engines explicit and don't try to do single-file one-shot writes to them. Test Plan: - Tried to upload a large file with vanilla uploader, got better error message. - Uploaded small and large files with drag and drop. - Viewed {nav Files > Help/Options}. Reviewers: btrahan Reviewed By: btrahan Subscribers: epriestley Maniphest Tasks: T7621 Differential Revision: https://secure.phabricator.com/D12110
This commit is contained in:
parent
bd2eaad04f
commit
b7fa55ff93
4 changed files with 85 additions and 45 deletions
|
@ -10,15 +10,8 @@ final class PhabricatorStorageSetupCheck extends PhabricatorSetupCheck {
|
||||||
* @phutil-external-symbol class PhabricatorStartup
|
* @phutil-external-symbol class PhabricatorStartup
|
||||||
*/
|
*/
|
||||||
protected function executeChecks() {
|
protected function executeChecks() {
|
||||||
$chunk_engine_active = false;
|
$engines = PhabricatorFileStorageEngine::loadWritableChunkEngines();
|
||||||
|
$chunk_engine_active = (bool)$engines;
|
||||||
$engines = PhabricatorFileStorageEngine::loadWritableEngines();
|
|
||||||
foreach ($engines as $engine) {
|
|
||||||
if ($engine->isChunkEngine()) {
|
|
||||||
$chunk_engine_active = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$chunk_engine_active) {
|
if (!$chunk_engine_active) {
|
||||||
$doc_href = PhabricatorEnv::getDocLink('Configuring File Storage');
|
$doc_href = PhabricatorEnv::getDocLink('Configuring File Storage');
|
||||||
|
|
|
@ -18,6 +18,7 @@ final class PhabricatorFilesApplicationStorageEnginePanel
|
||||||
|
|
||||||
$engines = PhabricatorFileStorageEngine::loadAllEngines();
|
$engines = PhabricatorFileStorageEngine::loadAllEngines();
|
||||||
$writable_engines = PhabricatorFileStorageEngine::loadWritableEngines();
|
$writable_engines = PhabricatorFileStorageEngine::loadWritableEngines();
|
||||||
|
$chunk_engines = PhabricatorFileStorageEngine::loadWritableChunkEngines();
|
||||||
|
|
||||||
$yes = pht('Yes');
|
$yes = pht('Yes');
|
||||||
$no = pht('No');
|
$no = pht('No');
|
||||||
|
@ -44,7 +45,7 @@ final class PhabricatorFilesApplicationStorageEnginePanel
|
||||||
$test = $no;
|
$test = $no;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($writable_engines[$key])) {
|
if (isset($writable_engines[$key]) || isset($chunk_engines[$key])) {
|
||||||
$rowc[] = 'highlighted';
|
$rowc[] = 'highlighted';
|
||||||
} else {
|
} else {
|
||||||
$rowc[] = null;
|
$rowc[] = null;
|
||||||
|
|
|
@ -85,24 +85,20 @@ final class FileAllocateConduitAPIMethod
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are any non-chunk engines which this file can fit into,
|
||||||
|
// just tell the client to upload the file.
|
||||||
$engines = PhabricatorFileStorageEngine::loadStorageEngines($length);
|
$engines = PhabricatorFileStorageEngine::loadStorageEngines($length);
|
||||||
if ($engines) {
|
if ($engines) {
|
||||||
|
|
||||||
// Pick the first engine. If the file is small enough to fit into a
|
|
||||||
// single engine without chunking, this will be a non-chunk engine and
|
|
||||||
// we'll just tell the client to upload the file.
|
|
||||||
$engine = head($engines);
|
|
||||||
if ($engine) {
|
|
||||||
if (!$engine->isChunkEngine()) {
|
|
||||||
return array(
|
return array(
|
||||||
'upload' => true,
|
'upload' => true,
|
||||||
'filePHID' => null,
|
'filePHID' => null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, this is a large file and we need to perform a chunked
|
// Otherwise, this is a large file and we want to perform a chunked
|
||||||
// upload.
|
// upload if we have a chunk engine available.
|
||||||
|
$chunk_engines = PhabricatorFileStorageEngine::loadWritableChunkEngines();
|
||||||
|
if ($chunk_engines) {
|
||||||
$chunk_properties = $properties;
|
$chunk_properties = $properties;
|
||||||
|
|
||||||
if ($hash) {
|
if ($hash) {
|
||||||
|
@ -111,14 +107,14 @@ final class FileAllocateConduitAPIMethod
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$file = $engine->allocateChunks($length, $chunk_properties);
|
$chunk_engine = head($chunk_engines);
|
||||||
|
$file = $chunk_engine->allocateChunks($length, $chunk_properties);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'upload' => true,
|
'upload' => true,
|
||||||
'filePHID' => $file->getPHID(),
|
'filePHID' => $file->getPHID(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// None of the storage engines can accept this file.
|
// None of the storage engines can accept this file.
|
||||||
if (PhabricatorFileStorageEngine::loadWritableEngines()) {
|
if (PhabricatorFileStorageEngine::loadWritableEngines()) {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
* @task construct Constructing an Engine
|
* @task construct Constructing an Engine
|
||||||
* @task meta Engine Metadata
|
* @task meta Engine Metadata
|
||||||
* @task file Managing File Data
|
* @task file Managing File Data
|
||||||
|
* @task load Loading Storage Engines
|
||||||
*/
|
*/
|
||||||
abstract class PhabricatorFileStorageEngine {
|
abstract class PhabricatorFileStorageEngine {
|
||||||
|
|
||||||
|
@ -188,12 +189,17 @@ abstract class PhabricatorFileStorageEngine {
|
||||||
abstract public function deleteFile($handle);
|
abstract public function deleteFile($handle);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* -( Loading Storage Engines )-------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select viable default storage engines according to configuration. We'll
|
* Select viable default storage engines according to configuration. We'll
|
||||||
* select the MySQL and Local Disk storage engines if they are configured
|
* select the MySQL and Local Disk storage engines if they are configured
|
||||||
* to allow a given file.
|
* to allow a given file.
|
||||||
*
|
*
|
||||||
* @param int File size in bytes.
|
* @param int File size in bytes.
|
||||||
|
* @task load
|
||||||
*/
|
*/
|
||||||
public static function loadStorageEngines($length) {
|
public static function loadStorageEngines($length) {
|
||||||
$engines = self::loadWritableEngines();
|
$engines = self::loadWritableEngines();
|
||||||
|
@ -213,6 +219,10 @@ abstract class PhabricatorFileStorageEngine {
|
||||||
return $writable;
|
return $writable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task load
|
||||||
|
*/
|
||||||
public static function loadAllEngines() {
|
public static function loadAllEngines() {
|
||||||
static $engines;
|
static $engines;
|
||||||
|
|
||||||
|
@ -246,28 +256,72 @@ abstract class PhabricatorFileStorageEngine {
|
||||||
return $engines;
|
return $engines;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function loadWritableEngines() {
|
|
||||||
|
/**
|
||||||
|
* @task load
|
||||||
|
*/
|
||||||
|
private static function loadProductionEngines() {
|
||||||
$engines = self::loadAllEngines();
|
$engines = self::loadAllEngines();
|
||||||
|
|
||||||
$writable = array();
|
$active = array();
|
||||||
foreach ($engines as $key => $engine) {
|
foreach ($engines as $key => $engine) {
|
||||||
if ($engine->isTestEngine()) {
|
if ($engine->isTestEngine()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$active[$key] = $engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $active;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task load
|
||||||
|
*/
|
||||||
|
public static function loadWritableEngines() {
|
||||||
|
$engines = self::loadProductionEngines();
|
||||||
|
|
||||||
|
$writable = array();
|
||||||
|
foreach ($engines as $key => $engine) {
|
||||||
if (!$engine->canWriteFiles()) {
|
if (!$engine->canWriteFiles()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($engine->isChunkEngine()) {
|
||||||
|
// Don't select chunk engines as writable.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
$writable[$key] = $engine;
|
$writable[$key] = $engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $writable;
|
return $writable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @task load
|
||||||
|
*/
|
||||||
|
public static function loadWritableChunkEngines() {
|
||||||
|
$engines = self::loadProductionEngines();
|
||||||
|
|
||||||
|
$chunk = array();
|
||||||
|
foreach ($engines as $key => $engine) {
|
||||||
|
if (!$engine->canWriteFiles()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!$engine->isChunkEngine()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$chunk[$key] = $engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the largest file size which can be uploaded without chunking.
|
* Return the largest file size which can not be uploaded in chunks.
|
||||||
*
|
*
|
||||||
* Files smaller than this will always upload in one request, so clients
|
* Files smaller than this will always upload in one request, so clients
|
||||||
* can safely skip the allocation step.
|
* can safely skip the allocation step.
|
||||||
|
@ -275,14 +329,10 @@ abstract class PhabricatorFileStorageEngine {
|
||||||
* @return int|null Byte size, or `null` if there is no chunk support.
|
* @return int|null Byte size, or `null` if there is no chunk support.
|
||||||
*/
|
*/
|
||||||
public static function getChunkThreshold() {
|
public static function getChunkThreshold() {
|
||||||
$engines = self::loadWritableEngines();
|
$engines = self::loadWritableChunkEngines();
|
||||||
|
|
||||||
$min = null;
|
$min = null;
|
||||||
foreach ($engines as $engine) {
|
foreach ($engines as $engine) {
|
||||||
if (!$engine->isChunkEngine()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$min) {
|
if (!$min) {
|
||||||
$min = $engine;
|
$min = $engine;
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in a new issue