1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-01-24 13:38:19 +01:00

Make storage.mysql-engine.max-size independent on max_allowed_packet

Summary:
I like systems that just work. It is possible to store files larger than max_allowed_packet in MySQL and we shouldn't demand it.

It also fixes a problem when file was smaller than `storage.mysql-engine.max-size` but its escaped version was larger than `max_allowed_packet`.

Test Plan: Reduced the size to 5e4, uploaded 90 kB file, checked the queries in DarkConsole, downloaded the file.

Reviewers: epriestley

Reviewed By: epriestley

CC: aran, Korvin

Differential Revision: https://secure.phabricator.com/D3392
This commit is contained in:
vrana 2012-08-27 15:40:28 -07:00
parent c4efeb3c97
commit 5f3dc3b7ae
5 changed files with 39 additions and 27 deletions

View file

@ -873,10 +873,8 @@ return array(
// The largest filesize Phabricator will store in the MySQL BLOB storage // The largest filesize Phabricator will store in the MySQL BLOB storage
// engine, which just uses a database table to store files. While this isn't a // engine, which just uses a database table to store files. While this isn't a
// best practice, it's really easy to set up. This is hard-limited by the // best practice, it's really easy to set up. Set this to 0 to disable use of
// value of 'max_allowed_packet' in MySQL (since this often defaults to 1MB, // the MySQL blob engine.
// the default here is slightly smaller than 1MB). Set this to 0 to disable
// use of the MySQL blob engine.
'storage.mysql-engine.max-size' => 1000000, 'storage.mysql-engine.max-size' => 1000000,
// Phabricator provides a local disk storage engine, which just writes files // Phabricator provides a local disk storage engine, which just writes files

View file

@ -22,7 +22,42 @@
* @group filestorage * @group filestorage
*/ */
final class PhabricatorFileStorageBlob extends PhabricatorFileDAO { final class PhabricatorFileStorageBlob extends PhabricatorFileDAO {
// max_allowed_packet defaults to 1 MiB, escaping can make the data twice
// longer, query fits in the rest.
const CHUNK_SIZE = 5e5;
protected $data; protected $data;
private $fullData;
protected function willWriteData(array &$data) {
parent::willWriteData($data);
$this->fullData = $data['data'];
if (strlen($data['data']) > self::CHUNK_SIZE) {
$data['data'] = substr($data['data'], 0, self::CHUNK_SIZE);
$this->openTransaction();
}
}
protected function didWriteData() {
$size = self::CHUNK_SIZE;
$length = strlen($this->fullData);
if ($length > $size) {
$conn = $this->establishConnection('w');
for ($offset = $size; $offset < $length; $offset += $size) {
queryfx(
$conn,
'UPDATE %T SET data = CONCAT(data, %s) WHERE %C = %d',
$this->getTableName(),
substr($this->fullData, $offset, $size),
$this->getIDKeyForUse(),
$this->getID());
}
$this->saveTransaction();
}
parent::didWriteData();
}
} }

View file

@ -41,8 +41,7 @@ Builtin storage engines and information on how to configure them.
MySQL storage is configured by default, for files up to (just under) 1MB. You MySQL storage is configured by default, for files up to (just under) 1MB. You
can configure it with these keys: can configure it with these keys:
- ##storage.mysql-engine.max-size##: Change the filesize limit. Note that - ##storage.mysql-engine.max-size##: Change the filesize limit. Set to 0
this must be smaller than 'max_allowed_packet' on the server. Set to 0
to disable. to disable.
For most installs, it is recommended you configure local disk storage below, For most installs, it is recommended you configure local disk storage below,

View file

@ -41,8 +41,7 @@ limit uploads are:
configured storage engine which can accept it. Phabricator should give you configured storage engine which can accept it. Phabricator should give you
useful errors if any of these fail. useful errors if any of these fail.
- **MySQL Engine**: Upload size is limited by the Phabricator setting - **MySQL Engine**: Upload size is limited by the Phabricator setting
`storage.mysql-engine.max-size`, which is in turn limited by the MySQL `storage.mysql-engine.max-size`.
setting `max_allowed_packet`. This often defaults to `1M`.
- **Amazon S3**: Upload size is limited by Phabricator's implementation to - **Amazon S3**: Upload size is limited by Phabricator's implementation to
`5G`. `5G`.
- **Local Disk**: Upload size is limited only by free disk space. - **Local Disk**: Upload size is limited only by free disk space.

View file

@ -564,25 +564,6 @@ final class PhabricatorSetup {
self::write(" okay max_allowed_packet = {$max_allowed_packet}.\n"); self::write(" okay max_allowed_packet = {$max_allowed_packet}.\n");
} }
$mysql_key = 'storage.mysql-engine.max-size';
$mysql_limit = PhabricatorEnv::getEnvConfig($mysql_key);
if ($mysql_limit && ($mysql_limit + 8192) > $max_allowed_packet) {
self::writeFailure();
self::write(
"Setup failure! Your Phabricator 'storage.mysql-engine.max-size' ".
"configuration ('{$mysql_limit}') must be at least 8KB smaller ".
"than your MySQL 'max_allowed_packet' configuration ".
"('{$max_allowed_packet}'). Raise the 'max_allowed_packet' in your ".
"MySQL configuration, or reduce the maximum file size allowed by ".
"the Phabricator configuration.\n");
return;
} else if (!$mysql_limit) {
self::write(" skip MySQL file storage engine not configured.\n");
} else {
self::write(" okay MySQL file storage engine configuration okay.\n");
}
$local_key = 'storage.local-disk.path'; $local_key = 'storage.local-disk.path';
$local_path = PhabricatorEnv::getEnvConfig($local_key); $local_path = PhabricatorEnv::getEnvConfig($local_key);
if ($local_path) { if ($local_path) {