I have another patchset here which refactors a little code and adds two
hooks for the ordering of devices for results to the create_open and
get_paths commands.
The 5th patch in this set shows the goal I'm moving towards, a plugin
that prioritizes local storage nodes (defined by the network zones
provided by the MogileFS::Network module(1))
Any comments on this design?
--hachi
(1) The MogileFS::Network module is originally from Andy McFarland on
this list October 3, 2007. Slightly modified now.
>From 04db156d1d1afb021f6c436843ae972cdfbd9d9c Mon Sep 17 00:00:00 2001
From: Jonathan Steinert <[EMAIL PROTECTED]>
Date: Tue, 11 Mar 2008 16:45:39 -0700
Subject: [PATCH] Switch to passing device objects around instead of device id's. This is a lead-in to a hook being able to handle the list.
---
server/lib/MogileFS/Worker/Query.pm | 14 +++++++-------
1 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/server/lib/MogileFS/Worker/Query.pm b/server/lib/MogileFS/Worker/Query.pm
index 1bb6884..f77445f 100644
--- a/server/lib/MogileFS/Worker/Query.pm
+++ b/server/lib/MogileFS/Worker/Query.pm
@@ -861,8 +861,6 @@ sub cmd_get_paths {
paths => 0,
};
- my @devices_with_weights;
-
# find devids that FID is on in memcache or db.
my @fid_devids;
my $need_devids_in_memcache = 0;
@@ -881,10 +879,13 @@ sub cmd_get_paths {
$memc->add($devid_memkey, [EMAIL PROTECTED], 3600) if $need_devids_in_memcache;
}
+ my @devices = map { $dmap->{$_} } @fid_devids;
+
+ my @devices_with_weights;
+
# is this fid still owned by this key?
- foreach my $devid (@fid_devids) {
+ foreach my $dev (@devices) {
my $weight;
- my $dev = $dmap->{$devid};
my $util = $dev->observed_utilization;
if (defined($util) and $util =~ /\A\d+\Z/) {
@@ -894,7 +895,7 @@ sub cmd_get_paths {
$weight = $dev->weight;
$weight ||= 100;
}
- push @devices_with_weights, [$devid, $weight];
+ push @devices_with_weights, [$dev, $weight];
}
# randomly weight the devices
@@ -904,8 +905,7 @@ sub cmd_get_paths {
my $backup_path;
# construct result paths
- foreach my $devid (@list) {
- my $dev = $dmap->{$devid};
+ foreach my $dev (@list) {
next unless $dev && ($dev->can_read_from);
my $host = $dev->host;
--
1.5.4.3
>From 0efe46cfd82f3ca78b8e7643e5bd2fe2092996b4 Mon Sep 17 00:00:00 2001
From: Jonathan Steinert <[EMAIL PROTECTED]>
Date: Tue, 11 Mar 2008 16:53:23 -0700
Subject: [PATCH] Move the sorting of devices by utilization into a seperate subroutine.
---
server/lib/MogileFS/Worker/Query.pm | 46 +++++++++++++++++++---------------
1 files changed, 26 insertions(+), 20 deletions(-)
diff --git a/server/lib/MogileFS/Worker/Query.pm b/server/lib/MogileFS/Worker/Query.pm
index f77445f..4f3da98 100644
--- a/server/lib/MogileFS/Worker/Query.pm
+++ b/server/lib/MogileFS/Worker/Query.pm
@@ -881,31 +881,13 @@ sub cmd_get_paths {
my @devices = map { $dmap->{$_} } @fid_devids;
- my @devices_with_weights;
-
- # is this fid still owned by this key?
- foreach my $dev (@devices) {
- my $weight;
- my $util = $dev->observed_utilization;
-
- if (defined($util) and $util =~ /\A\d+\Z/) {
- $weight = 102 - $util;
- $weight ||= 100;
- } else {
- $weight = $dev->weight;
- $weight ||= 100;
- }
- push @devices_with_weights, [$dev, $weight];
- }
-
- # randomly weight the devices
- my @list = MogileFS::Util::weighted_list(@devices_with_weights);
+ my @sorted_devs = sort_devs_by_utilization(@devices);
# keep one partially-bogus path around just in case we have nothing else to send.
my $backup_path;
# construct result paths
- foreach my $dev (@list) {
+ foreach my $dev (@sorted_devs) {
next unless $dev && ($dev->can_read_from);
my $host = $dev->host;
@@ -940,6 +922,30 @@ sub cmd_get_paths {
return $self->ok_line($ret);
}
+sub sort_devs_by_utilization {
+ my @devices_with_weights;
+
+ # is this fid still owned by this key?
+ foreach my $dev (@_) {
+ my $weight;
+ my $util = $dev->observed_utilization;
+
+ if (defined($util) and $util =~ /\A\d+\Z/) {
+ $weight = 102 - $util;
+ $weight ||= 100;
+ } else {
+ $weight = $dev->weight;
+ $weight ||= 100;
+ }
+ push @devices_with_weights, [$dev, $weight];
+ }
+
+ # randomly weight the devices
+ my @list = MogileFS::Util::weighted_list(@devices_with_weights);
+
+ return @list;
+}
+
# ------------------------------------------------------------
#
# NOTE: cmd_edit_file is EXPERIMENTAL. Please see the documentation
--
1.5.4.3
>From 80cacb5c0f12f381ffb05f18142fc5792fcc43d5 Mon Sep 17 00:00:00 2001
From: Jonathan Steinert <[EMAIL PROTECTED]>
Date: Tue, 11 Mar 2008 17:00:46 -0700
Subject: [PATCH] Add global hook for taking care of the ordering of devices at get_paths time.
---
server/lib/MogileFS/Worker/Query.pm | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/server/lib/MogileFS/Worker/Query.pm b/server/lib/MogileFS/Worker/Query.pm
index 4f3da98..5348942 100644
--- a/server/lib/MogileFS/Worker/Query.pm
+++ b/server/lib/MogileFS/Worker/Query.pm
@@ -881,7 +881,10 @@ sub cmd_get_paths {
my @devices = map { $dmap->{$_} } @fid_devids;
- my @sorted_devs = sort_devs_by_utilization(@devices);
+ my @sorted_devs;
+ unless (MogileFS::run_global_hook('cmd_get_paths_order_devices', [EMAIL PROTECTED], [EMAIL PROTECTED])) {
+ @sorted_devs = sort_devs_by_utilization(@devices);
+ }
# keep one partially-bogus path around just in case we have nothing else to send.
my $backup_path;
--
1.5.4.3
>From d2b07d00276825cce166e20470aa858bfa24ba35 Mon Sep 17 00:00:00 2001
From: Jonathan Steinert <[EMAIL PROTECTED]>
Date: Tue, 1 Apr 2008 18:09:41 -0700
Subject: [PATCH] Refactor cmd_create_open to call into sort_devs_by_freespace and also call a hook to let a plugin override this sort order.
---
server/lib/MogileFS/Worker/Query.pm | 36 ++++++++++++++++++++++++++--------
1 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/server/lib/MogileFS/Worker/Query.pm b/server/lib/MogileFS/Worker/Query.pm
index 5348942..d0eb9e8 100644
--- a/server/lib/MogileFS/Worker/Query.pm
+++ b/server/lib/MogileFS/Worker/Query.pm
@@ -241,21 +241,24 @@ sub cmd_create_open {
$profstart->("wait_monitor");
$self->wait_for_monitor;
+ $profstart->("find_deviceid");
+
+ my @devices;
+
+ unless (MogileFS::run_global_hook('cmd_create_open_order_devices', [MogileFS::Device->devices], [EMAIL PROTECTED])) {
+ @devices = sort_devs_by_freespace(MogileFS::Device->devices);
+ }
+
# find suitable device(s) to put this file on.
my @dests; # MogileFS::Device objects which are suitabke
- $profstart->("find_deviceid");
while (scalar(@dests) < ($multi ? 3 : 1)) {
- my $ddev = first {
- $_->should_get_new_files &&
- $_->not_on_hosts(map { $_->host } @dests)
- } weighted_list map {
- [$_, 100 * $_->percent_free]
- } grep {
- $_->exists
- } MogileFS::Device->devices;
+ my $ddev = shift @devices;
last unless $ddev;
+ next unless $ddev->should_get_new_files;
+ next unless $ddev->not_on_hosts(map { $_->host } @dests);
+
push @dests, $ddev;
}
return $self->err_line("no_devices") unless @dests;
@@ -319,6 +322,21 @@ sub cmd_create_open {
return $self->ok_line($res);
}
+sub sort_devs_by_freespace {
+ my @devices_with_weights;
+
+ foreach my $dev (@_) {
+ next unless $dev->exists;
+
+ my $weight = 100 * $dev->percent_free;
+ push @devices_with_weights, [$dev, $weight];
+ }
+
+ my @list = MogileFS::Util::weighted_list(@devices_with_weights);
+
+ return @list;
+}
+
sub cmd_create_close {
my MogileFS::Worker::Query $self = shift;
my $args = shift;
--
1.5.4.3
>From 4eab87c129139ef8ee340068241834208111acad Mon Sep 17 00:00:00 2001
From: Jonathan Steinert <[EMAIL PROTECTED]>
Date: Wed, 2 Apr 2008 23:52:50 -0700
Subject: [PATCH] Add ZoneLocal plugin which hooks in using new hooks to reorder devices for create_open and get_paths results.
---
.../lib/MogileFS/Plugin/ZoneLocal.pm | 66 ++++++++++++++++++++
1 files changed, 66 insertions(+), 0 deletions(-)
create mode 100644 server-plugins/MogileFS-Plugin-ZoneLocal/lib/MogileFS/Plugin/ZoneLocal.pm
diff --git a/server-plugins/MogileFS-Plugin-ZoneLocal/lib/MogileFS/Plugin/ZoneLocal.pm b/server-plugins/MogileFS-Plugin-ZoneLocal/lib/MogileFS/Plugin/ZoneLocal.pm
new file mode 100644
index 0000000..0cb5fe0
--- /dev/null
+++ b/server-plugins/MogileFS-Plugin-ZoneLocal/lib/MogileFS/Plugin/ZoneLocal.pm
@@ -0,0 +1,66 @@
+# FilePaths plugin for MogileFS, by hachi
+
+package MogileFS::Plugin::ZoneLocal;
+
+use strict;
+use warnings;
+
+our $VERSION = '0.01';
+$VERSION = eval $VERSION;
+
+use MogileFS::Worker::Query;
+use MogileFS::Network;
+
+sub prioritize_devs_current_zone;
+
+sub load {
+ MogileFS::register_global_hook( 'cmd_get_paths_order_devices', sub {
+ my $devices = shift;
+ my $sorted_devs = shift;
+
+ @$sorted_devs = prioritize_devs_current_zone
+ MogileFS::Worker::Query::sort_devs_by_utilization(@$devices);
+
+ return 1;
+ });
+
+ MogileFS::register_global_hook( 'cmd_create_open_order_devices', sub {
+ my $devices = shift;
+ my $sorted_devs = shift;
+
+ @$sorted_devs = prioritize_devs_current_zone
+ MogileFS::Worker::Query::sort_devs_by_freespace(@$devices);
+
+ return 1;
+ });
+
+ return 1;
+}
+
+sub unload {
+ # remove our hooks
+ MogileFS::unregister_global_hook( 'cmd_get_paths_order_devices' );
+
+ return 1;
+}
+
+sub prioritize_devs_current_zone {
+ my $current_zone = MogileFS::Network->zone_for_ip($MogileFS::REQ_client_ip);
+ my (@this_zone, @other_zone);
+
+ foreach my $dev (@_) {
+ my $ip = $dev->host->ip;
+ my $host_id = $dev->host->id;
+ my $zone = MogileFS::Network->zone_for_ip($ip);
+
+ if ($current_zone eq $zone) {
+ push @this_zone, $dev;
+ } else {
+ push @other_zone, $dev;
+ }
+ }
+
+ return @this_zone, @other_zone;
+}
+
+1;
--
1.5.4.3