Skip to content

Commit b0fac08

Browse files
committed
More code refactoring; too many to list
1 parent 41c54e1 commit b0fac08

23 files changed

+1187
-1139
lines changed

greyhole

-996
Large diffs are not rendered by default.

includes/CLI/BalanceStatusCliRunner.php

+11-15
Original file line numberDiff line numberDiff line change
@@ -45,39 +45,35 @@ public function output() {
4545
$max_storage_pool_strlen = max(array_map('mb_strlen', Config::storagePoolDrives()));
4646
$cols -= $max_storage_pool_strlen + 14;
4747

48-
$sorted_pool_drives = sort_storage_drives_available_space();
49-
$pool_drives_avail_space = array();
50-
foreach ($sorted_pool_drives as $available_space => $drive) {
51-
$pool_drives_avail_space[$drive] = $available_space;
52-
}
48+
$pool_drives_avail_space = StoragePool::get_drives_available_space();
5349
$target_avail_space = array_sum($pool_drives_avail_space) / count($pool_drives_avail_space);
5450

5551
printf("\n%$max_storage_pool_strlen"."s %s", "", "Target free space in all storage pool drives: " . bytes_to_human($target_avail_space*1024, FALSE) . "\n");
56-
$num_lines+=2;
52+
$num_lines += 2;
5753

58-
$dfs = get_free_space_in_storage_pool_drives();
5954
foreach (Config::storagePoolDrives() as $sp_drive) {
60-
if (!isset($dfs[$sp_drive])) {
55+
$df = StoragePool::get_free_space($sp_drive);
56+
if (!$df) {
6157
continue;
6258
}
6359

64-
$dfs[$sp_drive]['free'] -= (float) Config::get(CONFIG_MIN_FREE_SPACE_POOL_DRIVE, $sp_drive);
60+
$df['free'] -= (float) Config::get(CONFIG_MIN_FREE_SPACE_POOL_DRIVE, $sp_drive);
6561

66-
$percent_free = $dfs[$sp_drive]['free'] / ($dfs[$sp_drive]['free'] + $dfs[$sp_drive]['used']);
62+
$percent_free = $df['free'] / ($df['free'] + $df['used']);
6763
$cols_free = ceil($cols * $percent_free);
6864
$cols_used = $cols - abs($cols_free);
6965

7066
$suffix = "\033[0m";
71-
if ($dfs[$sp_drive]['free'] < $target_avail_space) {
72-
$diff = $target_avail_space - $dfs[$sp_drive]['free'];
73-
$percent_diff = $diff / ($dfs[$sp_drive]['free'] + $dfs[$sp_drive]['used']);
67+
if ($df['free'] < $target_avail_space) {
68+
$diff = $target_avail_space - $df['free'];
69+
$percent_diff = $diff / ($df['free'] + $df['used']);
7470
$cols_diff = round($cols * $percent_diff);
7571
$cols_used -= $cols_diff;
7672
$prefix = "\033[31m";
7773
$sign = '-';
7874
} else {
79-
$diff = $dfs[$sp_drive]['free'] - $target_avail_space;
80-
$percent_diff = $diff / ($dfs[$sp_drive]['free'] + $dfs[$sp_drive]['used']);
75+
$diff = $df['free'] - $target_avail_space;
76+
$percent_diff = $diff / ($df['free'] + $df['used']);
8177
$cols_diff = round($cols * $percent_diff);
8278
$cols_free -= $cols_diff;
8379
$prefix = "\033[32m";

includes/CLI/CommandLineHelper.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ private function getRunner() {
157157
} else {
158158
if ($this->actionCmd->getLongOpt() != 'test-config') {
159159
// Those will be tested in TestCliRunner
160-
process_config();
160+
ConfigHelper::test();
161161
$retry_until_successful = ( $this->actionCmd->getLongOpt() == 'boot-init' );
162162
DB::connect($retry_until_successful);
163163
}

includes/CLI/GoneCliRunner.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ private function isGoing() {
4141

4242
public function run() {
4343
// Removing this drive here will insure it won't be used for new files while we're moving files away, and that it can later be replaced.
44-
remove_drive_definition($this->drive);
44+
StoragePool::remove_drive($this->drive);
4545

4646
if ($this->isGoing()) {
4747
file_put_contents($this->drive . "/.greyhole_used_this", "Flag to prevent Greyhole from thinking this drive disappeared for no reason...");
@@ -132,7 +132,7 @@ protected static function check_going_dir($path, $share, $going_drive) {
132132
} else {
133133
$file_path = trim(mb_substr($path, mb_strlen("$going_drive/$share")+1), '/');
134134
$file_metafiles = array();
135-
$file_copies_inodes = get_file_inodes($share, $file_path, $filename, $file_metafiles, TRUE);
135+
$file_copies_inodes = StoragePool::get_file_copies_inodes($share, $file_path, $filename, $file_metafiles, TRUE);
136136
if (count($file_copies_inodes) == 0) {
137137
Log::debug("Found a file, $full_path, that has no other copies on other drives. Removing $going_drive would make that file disappear! Will create extra copies now.");
138138
echo ".";

includes/CLI/ReplaceCliRunner.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
class ReplaceCliRunner extends AbstractPoolDriveCliRunner {
2424
public function run() {
25-
remove_drive_definition($this->drive);
25+
StoragePool::remove_drive($this->drive);
2626

2727
Log::info("Storage pool drive $this->drive has been marked replaced. The Greyhole daemon will now be restarted to allow it to use this new drive.");
2828
$this->log("Storage pool drive $this->drive has been marked replaced. The Greyhole daemon will now be restarted to allow it to use this new drive.");

includes/CLI/StatsCliRunner.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ public function run() {
3838
'potential_available_space' => 0
3939
);
4040

41-
$dfs = get_free_space_in_storage_pool_drives();
4241
$stats = array();
4342
foreach (Config::storagePoolDrives() as $sp_drive) {
44-
if (!isset($dfs[$sp_drive]) || !file_exists($sp_drive)) {
43+
$df = StoragePool::get_free_space($sp_drive);
44+
if (!$df || !file_exists($sp_drive)) {
4545
$stats[$sp_drive] = (object) array();
4646
continue;
4747
}
@@ -63,7 +63,7 @@ public function run() {
6363
}
6464
}
6565

66-
$free_space = $dfs[$sp_drive]['free'];
66+
$free_space = $df['free'];
6767

6868
$trash_path = clean_dir("$sp_drive/.gh_trash");
6969
if (!file_exists($trash_path)) {

includes/CLI/TestCliRunner.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
class TestCliRunner extends AbstractCliRunner {
2424
public function run() {
25-
process_config();
25+
ConfigHelper::test();
2626
DB::connect();
2727
DB::repairTables();
2828
MigrationHelper::convertStoragePoolDrivesTagFiles();

includes/ConfigHelper.php

+72
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,22 @@ private static function assert($check, $error_message, $event_code) {
563563
Log::critical($error_message, $event_code);
564564
}
565565
}
566+
567+
public static function test() {
568+
while (!ConfigHelper::parse()) {
569+
// Invalid config file; either it's missing storage_pool_drive, or it contains a share that isn't in smb.conf
570+
if (SystemHelper::is_amahi() && Log::actionIs(ACTION_DAEMON)) {
571+
// If running on Amahi, loop until the config works.
572+
// User might configure Greyhole later, and they don't want to show Greyhole 'offline' until then. Those users are easy to confuse! ;)
573+
sleep(600); // 10 minutes
574+
} else {
575+
// Otherwise, die.
576+
Log::critical("Config file parsing failed. Exiting.", Log::EVENT_CODE_CONFIG_FILE_PARSING_FAILED);
577+
}
578+
}
579+
// Config is OK; go on!
580+
}
581+
566582
}
567583

568584
final class Config {
@@ -694,6 +710,62 @@ public static function add($share, $name, $value, $index=NULL) {
694710
}
695711
self::$shares_config[$share] = $config;
696712
}
713+
714+
public static function getNumCopies($share) {
715+
$num_copies = static::get($share, CONFIG_NUM_COPIES);
716+
if (!$num_copies) {
717+
Log::warn("Found a task on a share ($share) that disappeared from " . ConfigHelper::$config_file . ". Skipping.", Log::EVENT_CODE_TASK_FOR_UNKNOWN_SHARE);
718+
return -1;
719+
}
720+
if ($num_copies < 1) {
721+
$num_copies = 1;
722+
}
723+
$max_copies = 0;
724+
foreach (Config::storagePoolDrives() as $sp_drive) {
725+
if (StoragePool::is_pool_drive($sp_drive)) {
726+
$max_copies++;
727+
}
728+
}
729+
if ($num_copies > $max_copies) {
730+
$num_copies = $max_copies;
731+
}
732+
return $num_copies;
733+
}
734+
735+
public static function getShareOptions($full_path) {
736+
$share = FALSE;
737+
$landing_zone = '';
738+
foreach (SharesConfig::getShares() as $share_name => $share_options) {
739+
$lz = $share_options[CONFIG_LANDING_ZONE];
740+
if (string_starts_with($full_path, $lz) && mb_strlen($lz) > mb_strlen($landing_zone)) {
741+
$landing_zone = $lz;
742+
$share = $share_options;
743+
}
744+
}
745+
return $share;
746+
}
747+
748+
function getShareOptionsFromDrive($full_path, $sp_drive) {
749+
$landing_zone = '';
750+
$share = FALSE;
751+
foreach (SharesConfig::getShares() as $share_name => $share_options) {
752+
$lz = $share_options[CONFIG_LANDING_ZONE];
753+
$metastore = Metastores::get_metastore_from_path($full_path);
754+
if ($metastore !== FALSE) {
755+
if (string_starts_with($full_path, "$metastore/$share_name") && mb_strlen($lz) > mb_strlen($landing_zone)) {
756+
$landing_zone = $lz;
757+
$share = $share_options;
758+
}
759+
} else {
760+
if (string_starts_with($full_path, "$sp_drive/$share_name") && mb_strlen($lz) > mb_strlen($landing_zone)) {
761+
$landing_zone = $lz;
762+
$share = $share_options;
763+
}
764+
}
765+
}
766+
return $share;
767+
}
768+
697769
}
698770

699771
?>

includes/DBSpool.php

+45-8
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,53 @@ public static function setNextTask($task) {
118118
array_unshift(static::getInstance()->next_tasks, $task);
119119
}
120120

121-
public static function lockFile($idx, $locked_by) {
122-
static::getInstance()->locked_files[$idx] = $locked_by;
121+
private function lockFile($idx, $locked_by) {
122+
$this->locked_files[$idx] = $locked_by;
123123
}
124124

125-
public static function isFileLocked($full_path) {
125+
public static function isFileLocked($share, $full_path) {
126126
$db_spool = static::getInstance();
127-
if (isset($db_spool->locked_files[$full_path])) {
128-
return $db_spool->locked_files[$full_path];
127+
$idx = clean_dir("$share/$full_path");
128+
if (isset($db_spool->locked_files[$idx])) {
129+
return $db_spool->locked_files[$idx];
129130
}
130-
return FALSE;
131+
132+
if (Config::get(CONFIG_CHECK_FOR_OPEN_FILES) === FALSE) {
133+
Log::debug(" Skipping open file (lock) check.");
134+
return FALSE;
135+
}
136+
137+
$landing_zone = get_share_landing_zone($share);
138+
if (!$landing_zone) {
139+
return FALSE;
140+
}
141+
142+
$real_fullpath = "$landing_zone/$full_path";
143+
144+
$result = gh_is_file_locked($real_fullpath);
145+
if ($result !== FALSE) {
146+
$db_spool->lockFile($idx, $result);
147+
return $result;
148+
}
149+
150+
$query = "SELECT * FROM tasks WHERE complete = 'no' AND action = 'write' AND share = :share AND full_path = :full_path LIMIT 1";
151+
$params = array('share' => $share, 'full_path' => $full_path);
152+
$row = DB::getFirst($query, $params);
153+
if ($row === FALSE) {
154+
return FALSE;
155+
}
156+
157+
// Locked, according to DB... But maybe it's not really locked?
158+
if (!gh_file_exists($real_fullpath)) {
159+
// File doesn't exists anymore... It can't be really locked... Let's assume this is just Samba that 'forgot' to close the file handle.
160+
$query = "UPDATE tasks SET complete = 'yes' WHERE complete = 'no' AND action = 'write' AND share = :share AND full_path = :full_path";
161+
DB::execute($query, $params);
162+
return FALSE;
163+
}
164+
165+
$result = 'samba-vfs-writer';
166+
$db_spool->lockFile($idx, $result);
167+
return $result;
131168
}
132169

133170
public function execute_next_task() {
@@ -200,7 +237,7 @@ public function execute_next_task() {
200237
}
201238

202239
if ($task->complete == 'written') {
203-
if (should_ignore_file($task->share, $task->full_path)) {
240+
if ($task->should_ignore_file()) {
204241
$this->archive_task($task->id);
205242
return;
206243
}
@@ -224,7 +261,7 @@ public function execute_next_task() {
224261

225262
if (!empty($this->written_files[clean_dir("$task->share/$task->full_path")])) {
226263
Log::debug(" File is still being written to (" . bytes_to_human($filesize, FALSE) . "). Postponing.");
227-
static::lockFile(clean_dir("$task->share/$task->full_path"), 'samba-bytes-writer');
264+
$this->lockFile(clean_dir("$task->share/$task->full_path"), 'samba-bytes-writer');
228265
$this->locked_shares[$task->share] = TRUE;
229266
return;
230267
}

includes/DaemonRunner.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
class DaemonRunner extends AbstractRunner {
2222

2323
public static $was_idle = TRUE;
24-
24+
2525
public function run() {
2626
// Prevent multiple daemons from running simultaneously
2727
if (self::isRunning()) {
@@ -57,14 +57,14 @@ private static function isRunning() {
5757
private static function getPID() {
5858
return exec('ps ax | grep "greyhole --daemon\|greyhole -D" | grep -v grep | grep -v bash | grep -v "sudo" | grep -v ' . getmypid() . ' | awk "{print \$1}"');
5959
}
60-
60+
6161
private function initialize() {
6262
// Check the database tables, and repair them if needed.
6363
DB::repairTables();
64-
64+
6565
// Creates a GUID (if one doesn't exist); will be used to uniquely identify this Greyhole install, when reporting anonymous usage to greyhole.net
6666
GetGUIDCliRunner::setUniqID();
67-
67+
6868
// Terminology changed (attic > trash, graveyard > metadata store, tombstones > metadata files); this requires filesystem & database changes.
6969
MigrationHelper::terminologyConversion();
7070

@@ -73,20 +73,20 @@ private function initialize() {
7373

7474
// We backup the database settings to disk, in order to be able to restore them if the database is lost.
7575
Settings::backup();
76-
76+
7777
// Check that the Greyhole VFS module used by Samba is the correct one for the current Samba version. This is needed when Samba is updated to a new major version after Greyhole is installed.
7878
SambaUtils::samba_check_vfs();
7979

8080
// Check if the in-memory spool folder exists, and if no, create it and mount a tmpfs there. VFS will write there recvfile (etc.) operations.
8181
SambaSpool::create_mem_spool();
82-
82+
8383
// Process the spool directory, and insert each task found there into the database.
8484
SambaSpool::parse_samba_spool();
85-
85+
8686
// Create the dfree cache folder, if it doesn't exist
87-
gh_mkdir('/var/cache/greyhole-dfree', (object) array('fileowner' => 0, 'filegroup' => 0, 'fileperms' => (int) base_convert("0777", 8, 10)));
87+
gh_mkdir('/var/cache/greyhole-dfree', NULL, (object) array('fileowner' => 0, 'filegroup' => 0, 'fileperms' => (int) base_convert("0777", 8, 10)));
8888
}
89-
89+
9090
public function finish($returnValue = 0) {
9191
// The daemon should never finish; it will be killed by the init script.
9292
// Not that it can reach finish() anyway, since it's in an infinite while(TRUE) loop in run()... :)

includes/Metastores.php

+9-9
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public static function get_metastore_from_path($path) {
149149
public static function get_metastores_from_storage_volume($storage_volume) {
150150
$volume_metastores = array();
151151
foreach (static::get_metastores() as $metastore) {
152-
if (get_storage_volume_from_path($metastore) == $storage_volume) {
152+
if (StoragePool::getDriveFromPath($metastore) == $storage_volume) {
153153
$volume_metastores[] = $metastore;
154154
}
155155
}
@@ -243,7 +243,7 @@ public static function get_metafiles_for_file($share, $path, $filename=NULL, $lo
243243
foreach ($metafiles as $key => $metafile) {
244244
$valid_path = FALSE;
245245

246-
$drive = get_storage_volume_from_path($metafile->path);
246+
$drive = StoragePool::getDriveFromPath($metafile->path);
247247
if ($drive !== FALSE) {
248248
$valid_path = TRUE;
249249
}
@@ -287,11 +287,11 @@ public static function create_metafiles($share, $full_path, $num_copies_required
287287
}
288288

289289
// Check free space!
290-
$dfs = get_free_space_in_storage_pool_drives();
291-
if (!isset($dfs[$sp_drive])) {
290+
$df = StoragePool::get_free_space($sp_drive);
291+
if (!$df) {
292292
$free_space = 0;
293293
} else {
294-
$free_space = $dfs[$sp_drive]['free'];
294+
$free_space = $df['free'];
295295
}
296296
if ($free_space <= $filesize/1024) {
297297
$metafile->state = Metafile::STATE_GONE;
@@ -312,11 +312,11 @@ public static function create_metafiles($share, $full_path, $num_copies_required
312312

313313
// Select drives that have enough free space for this file
314314
if ($num_ok < $num_copies_required) {
315-
$local_target_drives = order_target_drives($filesize/1024, FALSE, $share, $path, ' ');
315+
$target_drives = StoragePool::choose_target_drives($filesize/1024, FALSE, $share, $path, ' ');
316316
}
317317
/** @noinspection PhpUndefinedVariableInspection */
318-
while ($num_ok < $num_copies_required && count($local_target_drives) > 0) {
319-
$sp_drive = array_shift($local_target_drives);
318+
while ($num_ok < $num_copies_required && count($target_drives) > 0) {
319+
$sp_drive = array_shift($target_drives);
320320
$clean_target_full_path = clean_dir("$sp_drive/$share/$full_path");
321321
// Don't use drives that already have a copy
322322
if (isset($metafiles[$clean_target_full_path])) {
@@ -360,7 +360,7 @@ public static function save_metafiles($share, $path, $filename, $metafiles) {
360360
$data_filepath = clean_dir("$metastore/$share/$path");
361361
$has_metafile = FALSE;
362362
foreach ($metafiles as $metafile) {
363-
if (get_storage_volume_from_path($metafile->path) == $sp_drive && StoragePool::is_pool_drive($sp_drive)) {
363+
if (StoragePool::getDriveFromPath($metafile->path) == $sp_drive && StoragePool::is_pool_drive($sp_drive)) {
364364
gh_mkdir($data_filepath, get_share_landing_zone($share) . "/$path");
365365
Log::debug(" Saving metadata in " . clean_dir("$data_filepath/$filename"));
366366
if (is_dir("$data_filepath/$filename")) {

0 commit comments

Comments
 (0)