- Timestamp:
- May 3, 2010, 8:45:22 AM (16 years ago)
- Location:
- branches/simmosaic_branches
- Files:
-
- 2 edited
-
. (modified) (1 prop)
-
Nebulous-Server/lib/Nebulous/Server.pm (modified) (33 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/simmosaic_branches
- Property svn:mergeinfo changed
-
branches/simmosaic_branches/Nebulous-Server/lib/Nebulous/Server.pm
r24637 r27839 36 36 use constant TRANS_RETRY_WAIT => 1; 37 37 38 # This is the umask hack. 39 umask(0002); 40 41 # This determines how many entries from the list of volumes sorted by free space are randomized. 42 my $topfew_count = 15; 43 my $max_used_space = 0.98; 38 44 # transaction restart/retry regex 39 45 my $trans_regex = qr/Deadlock Found|Lock wait timeout exceeded|try restarting transaction|Can't connect to MySQL server/i; … … 696 702 $log->debug("entered - @_"); 697 703 698 my ($key, $ vol_name) = validate_pos(@_,704 my ($key, $dest_vol_name) = validate_pos(@_, 699 705 { 700 706 type => SCALAR, … … 726 732 # instance on it. If all avilable volume already have an instance on them 727 733 # then we should throw an error 728 729 # vol_name overrides the key implied volume 730 eval { 731 $key = parse_neb_key($key, $vol_name); 734 # volume names implied as part of the key are *IGNORED* as the source and 735 # *SHOULD NOT* be used as the destination either 736 737 eval { 738 $key = parse_neb_key($key); 732 739 }; 733 740 $log->logdie("$@") if $@; 734 $vol_name = $key->volume;735 741 736 742 my $db = $self->db($key); 737 743 738 if (defined $vol_name 744 # puke if the source volume is bogus, we may want to actually use this as 745 # the instance to be copied later 746 if (defined $key->volume 739 747 and not $self->_is_valid_volume_name($key, $key->volume)) { 740 748 unless ($key->hard_volume) { 741 $log->warn( "$vol_name is not a known volume name" ); 742 $vol_name = undef; 749 $log->warn($key->volume . " not a known volume name"); 743 750 } else { 744 $log->logdie("$vol_name is not a valid volume name"); 745 } 751 $log->logdie("$key is not a valid volume name"); 752 } 753 } 754 # puke if the source volume is bogus, we may want to actually use this as 755 # the instance to be copied later 756 if (defined $dest_vol_name 757 and not $self->_is_valid_volume_name($key, $dest_vol_name)) { 758 $log->logdie($key->volume . " is not a valid volume name"); 746 759 } 747 760 748 761 my ($vol_id, $vol_host, $vol_path, $vol_xattr); 749 if (defined $ vol_name) {762 if (defined $dest_vol_name) { 750 763 ($vol_id, $vol_host, $vol_path, $vol_xattr) 751 = $self->_get_storage_volume($key, $ vol_name);764 = $self->_get_storage_volume($key, $dest_vol_name); 752 765 } else { 753 766 ($vol_id, $vol_host, $vol_path, $vol_xattr) … … 810 823 $db->rollback; 811 824 # handle soft volumes 812 if (defined $ vol_name and not defined $key->hard_volume) {825 if (defined $dest_vol_name and not defined $key->hard_volume) { 813 826 $log->debug("retrying with 'any' volume"); 814 827 return $self->replicate_object($key->path, 'any'); … … 844 857 845 858 846 sub lock_object847 { 848 my $self = shift; 849 850 my $log = $self->log; 851 $log->debug( "entered - @_");852 853 my ( $key, $type ) = validate_pos(@_,859 sub prune_object 860 { 861 my $self = shift; 862 863 my $log = $self->log; 864 $log->debug("entered - @_"); 865 866 my ($key) = validate_pos(@_, 854 867 { 855 868 type => SCALAR, 856 869 callbacks => { 857 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) }, 858 }, 859 }, 860 { 861 type => SCALAR, 862 callbacks => { 863 'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ }, 870 'is valid object key' 871 => sub { $self->_is_valid_object_key($_[0]) }, 864 872 }, 865 873 }, … … 868 876 my $sql = $self->sql; 869 877 870 # ignore volume871 878 eval { 872 879 $key = parse_neb_key($key); … … 876 883 my $db = $self->db($key); 877 884 878 my $so_id; 879 my $read_lock; 880 my $write_lock; 881 885 my $rows_removed = 0; 882 886 TRANS: while (1) { 883 887 eval { 888 # remove key from cache 889 $self->cache->delete($key->path) if defined $self->cache; 890 891 my $so_id; 884 892 { 885 # this will set update locks 886 my $query = $db->prepare_cached( $sql->get_object_locks ); 887 my $rows = $query->execute( $key->path ); 888 unless ( $rows == 1 ) { 889 $query->finish; 890 die( "storage object does not exist" ); 891 } 892 893 my $row = $query->fetchrow_hashref; 893 my $query = $db->prepare_cached( $sql->find_object_by_ext_id ); 894 $query->execute( $key->path ); 895 $so_id = $query->fetchrow_hashref->{'so_id'}; 894 896 $query->finish; 895 896 $so_id = $row->{ 'so_id' }; 897 $read_lock = $row->{ 'read_lock' }; 898 $write_lock = $row->{ 'write_lock' }; 899 } 900 901 if ($type eq 'write') { 902 # can't set a write lock twice and 903 # can't set a write lock if there are read locks 904 if ($write_lock) { 905 die("can not write lock twice -- retry"); 906 } 907 908 if ($read_lock > 0) { 909 die("can not write lock after read lock -- retry"); 910 } 911 912 { 913 my $query = $db->prepare_cached( $sql->set_write_lock ); 914 my $rows = $query->execute($key->path); 915 916 # if we affected more then one row something very bad has happened. 917 unless ($rows == 1) { 918 die("affected row count is $rows instead of 1"); 919 } 920 921 } 922 } elsif ($type eq 'read') { 923 # can't set a read lock if there's a write lock 924 if ($write_lock) { 925 die("can not read lock after write lock -- retry"); 926 } 927 928 { 929 my $query = $db->prepare_cached( $sql->increment_read_lock ); 930 my $rows = $query->execute($key->path); 931 932 # if we affected more then one row something very bad has happened. 933 unless ($rows == 1) { 934 die("affected row count is $rows instead of 1"); 935 } 936 } 937 } 938 897 } 898 899 # record the path of the innaccesible files for deferred 900 # deletion 901 my $rows_copied; 902 { 903 my $query = $db->prepare_cached( $sql->copy_dead_instances_to_deleted ); 904 $rows_copied = $query->execute( $so_id ); 905 } 906 907 # check to see if there is anything to be done 908 unless ($rows_copied > 0) { 909 $db->rollback; 910 return; 911 } 912 913 # In MySQL you can't select from a table you're deleting rows from so 914 # we first have to get a list of instances to be removed, and then 915 # remove them. 916 my $rows_found; 917 { 918 my $query = $db->prepare_cached( $sql->find_dead_instances_by_so_id ); 919 $rows_found = $query->execute( $so_id ); 920 my $i = 0; 921 while (my $row = $query->fetchrow_hashref) { 922 # remove dead instances 923 # $log->warn("copied: $rows_copied found: $rows_found removed: $rows_removed"); 924 my $query = $db->prepare_cached( $sql->delete_instance_by_ins_id); 925 $rows_removed += $query->execute( $row->{ins_id} ); 926 } 927 $query->finish; 928 } 929 # $log->warn("copied: $rows_copied found: $rows_found removed: $rows_removed"); 930 # sanity check 931 die("instances inaccessible ($rows_copied) != instances removed ($rows_removed)") 932 unless $rows_copied == $rows_removed; 933 939 934 $db->commit; 940 935 $log->debug("commit"); … … 955 950 $log->debug("leaving"); 956 951 957 return 1;958 } 959 960 961 sub unlock_object952 return $rows_removed; 953 } 954 955 956 sub lock_object 962 957 { 963 958 my $self = shift; … … 1000 995 # this will set update locks 1001 996 my $query = $db->prepare_cached( $sql->get_object_locks ); 1002 my $rows = $query->execute( $key->path);1003 unless ( $rows == 1) {997 my $rows = $query->execute( $key->path ); 998 unless ( $rows == 1 ) { 1004 999 $query->finish; 1005 die( "storage object does not exist");1000 die( "storage object does not exist" ); 1006 1001 } 1007 1002 … … 1015 1010 1016 1011 if ($type eq 'write') { 1017 # can't remove a write lock if it doesn't exist 1018 if ($read_lock) { 1019 die("can not have a write lock under a read lock"); 1020 } 1021 1022 unless ($write_lock) { 1023 die("can not remove non-existant write lock"); 1012 # can't set a write lock twice and 1013 # can't set a write lock if there are read locks 1014 if ($write_lock) { 1015 die("can not write lock twice -- retry"); 1016 } 1017 1018 if ($read_lock > 0) { 1019 die("can not write lock after read lock -- retry"); 1024 1020 } 1025 1021 1026 1022 { 1027 my $query = $db->prepare_cached( $sql-> delete_write_lock );1023 my $query = $db->prepare_cached( $sql->set_write_lock ); 1028 1024 my $rows = $query->execute($key->path); 1029 1025 … … 1032 1028 die("affected row count is $rows instead of 1"); 1033 1029 } 1030 1034 1031 } 1035 1032 } elsif ($type eq 'read') { 1036 # can't remove a read lock if there's a write lock and 1037 # can't remove a read lock if there aren't any 1033 # can't set a read lock if there's a write lock 1038 1034 if ($write_lock) { 1039 die("can not have a read lock under a write lock"); 1040 } 1041 1042 if ($read_lock == 0) { 1043 die("can not remove non-existant read lock"); 1035 die("can not read lock after write lock -- retry"); 1044 1036 } 1045 1037 1046 1038 { 1047 my $query = $db->prepare_cached( $sql-> decrement_read_lock );1039 my $query = $db->prepare_cached( $sql->increment_read_lock ); 1048 1040 my $rows = $query->execute($key->path); 1049 1041 … … 1052 1044 die("affected row count is $rows instead of 1"); 1053 1045 } 1054 1055 }1056 } 1046 } 1047 } 1048 1057 1049 $db->commit; 1058 1050 $log->debug("commit"); … … 1071 1063 } 1072 1064 1073 $log->debug( "leaving");1065 $log->debug("leaving"); 1074 1066 1075 1067 return 1; … … 1077 1069 1078 1070 1079 sub setxattr_object1080 { 1081 my $self = shift; 1082 1083 my $log = $self->log; 1084 $log->debug( "entered - @_");1085 1086 my ( $key, $name, $value, $flags) = validate_pos(@_,1071 sub unlock_object 1072 { 1073 my $self = shift; 1074 1075 my $log = $self->log; 1076 $log->debug( "entered - @_" ); 1077 1078 my ( $key, $type ) = validate_pos( @_, 1087 1079 { 1088 1080 type => SCALAR, … … 1094 1086 type => SCALAR, 1095 1087 callbacks => { 1096 'xattr is in user. namespace' 1097 => sub { ($_[0]) =~ qr/^user\./ }, 1098 }, 1099 }, 1100 { 1101 type => SCALAR, 1102 }, 1103 { 1104 type => SCALAR, 1105 callbacks => { 1106 'is read or write' => sub { $_[0] =~ /^(?:create|replace)$/i }, 1088 'is read or write' => sub { $_[0] =~ /^(?:read|write)$/ }, 1107 1089 }, 1108 1090 }, … … 1118 1100 1119 1101 my $db = $self->db($key); 1102 1103 my $so_id; 1104 my $read_lock; 1105 my $write_lock; 1120 1106 1121 1107 TRANS: while (1) { 1122 1108 eval { 1123 my $query; 1124 1125 if ($flags eq 'create') { 1126 $query = $db->prepare_cached( $sql->new_object_xattr ); 1127 } else { 1128 # replace 1129 $query = $db->prepare_cached( $sql->replace_object_xattr ); 1130 } 1131 1132 # name, value, ext_id 1133 my $rows = $query->execute($name, $value, $key->path); 1134 $query->finish; 1135 1136 # if we affected more then one row something very bad has happened. 1137 if ($flags eq 'create') { 1109 { 1110 # this will set update locks 1111 my $query = $db->prepare_cached( $sql->get_object_locks ); 1112 my $rows = $query->execute($key->path); 1138 1113 unless ($rows == 1) { 1139 die( "affected row count is $rows instead of 1" ); 1140 } 1141 } else { 1142 # replace_object_xattr can effect either 1 or 2 rows. 2 rows in 1143 # the case of a replace and 1 if the xattr didn't already exist. 1144 unless ($rows == 1 or $rows == 2) { 1145 die( "affected row count is $rows instead of 2" ); 1146 } 1147 } 1148 1114 $query->finish; 1115 die("storage object does not exist"); 1116 } 1117 1118 my $row = $query->fetchrow_hashref; 1119 $query->finish; 1120 1121 $so_id = $row->{ 'so_id' }; 1122 $read_lock = $row->{ 'read_lock' }; 1123 $write_lock = $row->{ 'write_lock' }; 1124 } 1125 1126 if ($type eq 'write') { 1127 # can't remove a write lock if it doesn't exist 1128 if ($read_lock) { 1129 die("can not have a write lock under a read lock"); 1130 } 1131 1132 unless ($write_lock) { 1133 die("can not remove non-existant write lock"); 1134 } 1135 1136 { 1137 my $query = $db->prepare_cached( $sql->delete_write_lock ); 1138 my $rows = $query->execute($key->path); 1139 1140 # if we affected more then one row something very bad has happened. 1141 unless ($rows == 1) { 1142 die("affected row count is $rows instead of 1"); 1143 } 1144 } 1145 } elsif ($type eq 'read') { 1146 # can't remove a read lock if there's a write lock and 1147 # can't remove a read lock if there aren't any 1148 if ($write_lock) { 1149 die("can not have a read lock under a write lock"); 1150 } 1151 1152 if ($read_lock == 0) { 1153 die("can not remove non-existant read lock"); 1154 } 1155 1156 { 1157 my $query = $db->prepare_cached( $sql->decrement_read_lock ); 1158 my $rows = $query->execute($key->path); 1159 1160 # if we affected more then one row something very bad has happened. 1161 unless ($rows == 1) { 1162 die("affected row count is $rows instead of 1"); 1163 } 1164 1165 } 1166 } 1149 1167 $db->commit; 1150 1168 $log->debug("commit"); … … 1158 1176 redo TRANS; 1159 1177 } 1160 $log->logdie(" databaseerror: $@");1178 $log->logdie("error: $@"); 1161 1179 } 1162 1180 last; 1163 1181 } 1164 1182 1165 $log->debug( "leaving");1183 $log->debug( "leaving" ); 1166 1184 1167 1185 return 1; … … 1169 1187 1170 1188 1171 sub getxattr_object1189 sub setxattr_object 1172 1190 { 1173 1191 my $self = shift; … … 1176 1194 $log->debug("entered - @_"); 1177 1195 1178 my ($key, $name ) = validate_pos(@_,1196 my ($key, $name, $value, $flags) = validate_pos(@_, 1179 1197 { 1180 1198 type => SCALAR, … … 1190 1208 }, 1191 1209 }, 1192 ); 1193 1194 my $sql = $self->sql; 1195 1196 # ignore volume 1197 eval { 1198 $key = parse_neb_key($key); 1199 }; 1200 $log->logdie("$@") if $@; 1201 1202 my $db = $self->db($key); 1203 1204 my $value; 1205 eval { 1206 my $query = $db->prepare_cached( $sql->get_object_xattr ); 1207 # ext_id, name 1208 my $rows = $query->execute($key->path, $name); 1209 1210 # no rows returned means that the xattr does not exist 1211 if ($rows == 0) { 1212 $query->finish; 1213 die( "xattr $key:$name does not exist" ); 1214 } 1215 # if we go more then one row bad something very bad has happened. 1216 unless ($rows == 1) { 1217 $query->finish; 1218 die( "affected row count is $rows instead of 1" ); 1219 } 1220 1221 my $row = $query->fetchrow_hashref; 1222 # XXX: DBI bug? ->finish is needed here even though $query is going out 1223 # of scope 1224 $query->finish; 1225 $value = $row->{ 'value' }; 1226 }; 1227 if ($@) { 1228 if ($@ =~ /user\..*? does not exist/) { 1229 # do not log xattr does not exist messages 1230 die $@; 1231 } 1232 $log->logdie("database error: $@") if $@; 1233 } 1234 1235 $log->debug("leaving"); 1236 1237 return $value; 1238 } 1239 1240 1241 sub listxattr_object 1242 { 1243 my $self = shift; 1244 1245 my $log = $self->log; 1246 $log->debug("entered - @_"); 1247 1248 my ($key) = validate_pos(@_, 1210 { 1211 type => SCALAR, 1212 }, 1249 1213 { 1250 1214 type => SCALAR, 1251 1215 callbacks => { 1252 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) }, 1253 }, 1254 }, 1255 ); 1256 1257 my $sql = $self->sql; 1258 1259 # ignore volume 1260 eval { 1261 $key = parse_neb_key($key); 1262 }; 1263 $log->logdie("$@") if $@; 1264 1265 my $db = $self->db($key); 1266 1267 my @xattrs; 1268 eval { 1269 my $query = $db->prepare_cached( $sql->list_object_xattr ); 1270 # ext_id 1271 my $rows = $query->execute($key->path); 1272 1273 while (my $row = $query->fetchrow_hashref) { 1274 push @xattrs, $row->{ 'name' }; 1275 } 1276 }; 1277 $log->logdie("database error: $@") if $@; 1278 1279 $log->debug("leaving"); 1280 1281 return \@xattrs; 1282 } 1283 1284 1285 sub removexattr_object 1286 { 1287 my $self = shift; 1288 1289 my $log = $self->log; 1290 $log->debug("entered - @_"); 1291 1292 my ($key, $name) = validate_pos(@_, 1293 { 1294 type => SCALAR, 1295 callbacks => { 1296 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) }, 1297 }, 1298 }, 1299 { 1300 type => SCALAR, 1301 callbacks => { 1302 'xattr is in user. namespace' 1303 => sub { ($_[0]) =~ qr/^user\./ }, 1216 'is read or write' => sub { $_[0] =~ /^(?:create|replace)$/i }, 1304 1217 }, 1305 1218 }, … … 1318 1231 TRANS: while (1) { 1319 1232 eval { 1320 my $query = $db->prepare_cached( $sql->remove_object_xattr ); 1321 # ext_id, name 1322 my $rows = $query->execute($key->path, $name); 1233 my $query; 1234 1235 if ($flags eq 'create') { 1236 $query = $db->prepare_cached( $sql->new_object_xattr ); 1237 } else { 1238 # replace 1239 $query = $db->prepare_cached( $sql->replace_object_xattr ); 1240 } 1241 1242 # name, value, ext_id 1243 my $rows = $query->execute($name, $value, $key->path); 1323 1244 $query->finish; 1324 1245 1325 # no rows affected means the xattr did not exist1326 if ($rows == 0) {1327 die( "xattr $key:$name does not exist" );1328 }1329 1330 1246 # if we affected more then one row something very bad has happened. 1331 if ($rows > 1) { 1332 die( "affected row count is $rows instead of 1" ); 1247 if ($flags eq 'create') { 1248 unless ($rows == 1) { 1249 die( "affected row count is $rows instead of 1" ); 1250 } 1251 } else { 1252 # replace_object_xattr can effect either 1 or 2 rows. 2 rows in 1253 # the case of a replace and 1 if the xattr didn't already exist. 1254 unless ($rows == 1 or $rows == 2) { 1255 die( "affected row count is $rows instead of 2" ); 1256 } 1333 1257 } 1334 1258 … … 1347 1271 } 1348 1272 last; 1273 } 1274 1275 $log->debug("leaving"); 1276 1277 return 1; 1278 } 1279 1280 1281 sub getxattr_object 1282 { 1283 my $self = shift; 1284 1285 my $log = $self->log; 1286 $log->debug("entered - @_"); 1287 1288 my ($key, $name) = validate_pos(@_, 1289 { 1290 type => SCALAR, 1291 callbacks => { 1292 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) }, 1293 }, 1294 }, 1295 { 1296 type => SCALAR, 1297 callbacks => { 1298 'xattr is in user. namespace' 1299 => sub { ($_[0]) =~ qr/^user\./ }, 1300 }, 1301 }, 1302 ); 1303 1304 my $sql = $self->sql; 1305 1306 # ignore volume 1307 eval { 1308 $key = parse_neb_key($key); 1309 }; 1310 $log->logdie("$@") if $@; 1311 1312 my $db = $self->db($key); 1313 1314 my $value; 1315 eval { 1316 my $query = $db->prepare_cached( $sql->get_object_xattr ); 1317 # ext_id, name 1318 my $rows = $query->execute($key->path, $name); 1319 1320 # no rows returned means that the xattr does not exist 1321 if ($rows == 0) { 1322 $query->finish; 1323 die( "xattr $key:$name does not exist" ); 1324 } 1325 # if we go more then one row bad something very bad has happened. 1326 unless ($rows == 1) { 1327 $query->finish; 1328 die( "affected row count is $rows instead of 1" ); 1329 } 1330 1331 my $row = $query->fetchrow_hashref; 1332 # XXX: DBI bug? ->finish is needed here even though $query is going out 1333 # of scope 1334 $query->finish; 1335 $value = $row->{ 'value' }; 1336 }; 1337 if ($@) { 1338 if ($@ =~ /user\..*? does not exist/) { 1339 # do not log xattr does not exist messages 1340 die $@; 1341 } 1342 $log->logdie("database error: $@") if $@; 1343 } 1344 1345 $log->debug("leaving"); 1346 1347 return $value; 1348 } 1349 1350 1351 sub listxattr_object 1352 { 1353 my $self = shift; 1354 1355 my $log = $self->log; 1356 $log->debug("entered - @_"); 1357 1358 my ($key) = validate_pos(@_, 1359 { 1360 type => SCALAR, 1361 callbacks => { 1362 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) }, 1363 }, 1364 }, 1365 ); 1366 1367 my $sql = $self->sql; 1368 1369 # ignore volume 1370 eval { 1371 $key = parse_neb_key($key); 1372 }; 1373 $log->logdie("$@") if $@; 1374 1375 my $db = $self->db($key); 1376 1377 my @xattrs; 1378 eval { 1379 my $query = $db->prepare_cached( $sql->list_object_xattr ); 1380 # ext_id 1381 my $rows = $query->execute($key->path); 1382 1383 while (my $row = $query->fetchrow_hashref) { 1384 push @xattrs, $row->{ 'name' }; 1385 } 1386 }; 1387 $log->logdie("database error: $@") if $@; 1388 1389 $log->debug("leaving"); 1390 1391 return \@xattrs; 1392 } 1393 1394 1395 sub removexattr_object 1396 { 1397 my $self = shift; 1398 1399 my $log = $self->log; 1400 $log->debug("entered - @_"); 1401 1402 my ($key, $name) = validate_pos(@_, 1403 { 1404 type => SCALAR, 1405 callbacks => { 1406 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) }, 1407 }, 1408 }, 1409 { 1410 type => SCALAR, 1411 callbacks => { 1412 'xattr is in user. namespace' 1413 => sub { ($_[0]) =~ qr/^user\./ }, 1414 }, 1415 }, 1416 ); 1417 1418 my $sql = $self->sql; 1419 1420 # ignore volume 1421 eval { 1422 $key = parse_neb_key($key); 1423 }; 1424 $log->logdie("$@") if $@; 1425 1426 my $db = $self->db($key); 1427 1428 TRANS: while (1) { 1429 eval { 1430 my $query = $db->prepare_cached( $sql->remove_object_xattr ); 1431 # ext_id, name 1432 my $rows = $query->execute($key->path, $name); 1433 $query->finish; 1434 1435 # no rows affected means the xattr did not exist 1436 if ($rows == 0) { 1437 die( "xattr $key:$name does not exist" ); 1438 } 1439 1440 # if we affected more then one row something very bad has happened. 1441 if ($rows > 1) { 1442 die( "affected row count is $rows instead of 1" ); 1443 } 1444 1445 $db->commit; 1446 $log->debug("commit"); 1447 }; 1448 if ($@) { 1449 $db->rollback; 1450 $log->debug("rollback"); 1451 if ($@ =~ $trans_regex) { 1452 $log->warn("database error, retrying transaction: $@"); 1453 sleep TRANS_RETRY_WAIT; 1454 redo TRANS; 1455 } 1456 $log->logdie("database error: $@"); 1457 } 1458 last; 1349 1459 } 1350 1460 … … 1496 1606 $log->debug("entered - @_"); 1497 1607 1498 my ($key, $vol_name ) = validate_pos(@_,1608 my ($key, $vol_name, $find_invalid) = validate_pos(@_, 1499 1609 { 1500 1610 type => SCALAR, … … 1514 1624 optional => 1, 1515 1625 }, 1626 { 1627 # find_invalid 1628 type => SCALAR|UNDEF, 1629 optional => 1, 1630 }, 1516 1631 ); 1517 1632 … … 1557 1672 } else { 1558 1673 $query = $db->prepare_cached( $sql->get_object_instances ); 1674 my $rows; 1675 # ext_id, available 1676 if (defined($find_invalid)) { 1677 $rows = $query->execute($key->path, 0); 1678 } 1679 else { 1680 $rows = $query->execute($key->path, 1); 1681 } 1682 unless ($rows > 0) { 1683 $query->finish; 1684 die("no instances available for key: $key"); 1685 } 1686 } 1687 1688 while (my $row = $query->fetchrow_hashref) { 1689 my $instance = $row->{ 'uri' }; 1690 push @locations, $instance if $instance; 1691 } 1692 }; 1693 if ($@) { 1694 $db->rollback; 1695 # handle soft volumes 1696 if (defined $vol_name and not defined $key->hard_volume) { 1697 $log->debug("retrying with 'any' volume"); 1698 return $self->find_instances($key->path, 'any'); 1699 } 1700 $log->logdie("database error: $@"); 1701 } 1702 1703 # XXX remove this? 1704 $log->logdie("no instances found") unless (scalar @locations); 1705 1706 $log->debug("found: @locations"); 1707 1708 $log->debug("leaving"); 1709 1710 return \@locations; 1711 } 1712 1713 sub find_instances_for_cull 1714 { 1715 my $self = shift; 1716 1717 my $log = $self->log; 1718 $log->debug("entered - @_"); 1719 1720 my ($key, $vol_name) = validate_pos(@_, 1721 { 1722 type => SCALAR, 1723 callbacks => { 1724 'is valid object key' => sub { $self->_is_valid_object_key($_[0]) }, 1725 }, 1726 }, 1727 { 1728 type => SCALAR|UNDEF, 1729 # callbacks => { 1730 # # check that the volume name requested is valid 1731 # 'is valid volume name' => sub { 1732 # return 1 if not defined $_[0]; 1733 # $self->_is_valid_volume_name($_[0]) 1734 # }, 1735 # }, 1736 optional => 1, 1737 }, 1738 ); 1739 1740 my $sql = $self->sql; 1741 1742 # unless ($key) { 1743 # $log->warn("key was undefined after validate_pos(), trying again..."); 1744 # return $self->find_instances(@_); 1745 # } 1746 1747 # vol_name overrides the key implied volume 1748 eval { 1749 $key = parse_neb_key($key, $vol_name); 1750 }; 1751 $log->logdie("$@") if $@; 1752 $vol_name = $key->volume; 1753 1754 my $db = $self->db($key); 1755 1756 # the key's volume can't be validiated on input for this method so we have 1757 # to check it after parsing the key 1758 if (defined $vol_name 1759 and not $self->_is_valid_volume_name($key, $key->volume)) { 1760 if ($key->hard_volume) { 1761 $log->logdie("$vol_name is not a valid volume name"); 1762 } else { 1763 $log->warn( "$vol_name is not a known volume name" ); 1764 $vol_name = undef; 1765 } 1766 } 1767 1768 my @locations; 1769 eval { 1770 my $query; 1771 if ($vol_name) { 1772 $query = $db->prepare_cached( $sql->get_object_instances_by_vol_name ); 1773 # ext_id, name, available 1774 my $rows = $query->execute($key->path, $vol_name, 1); 1775 unless ($rows > 0) { 1776 $query->finish; 1777 die("no instances on storage volume or volume is not avaiable for key: $key volume: $vol_name"); 1778 } 1779 } else { 1780 $query = $db->prepare_cached( $sql->get_object_instances ); 1559 1781 # ext_id, available 1560 1782 my $rows = $query->execute($key->path, 1); … … 1564 1786 } 1565 1787 } 1566 1788 1567 1789 while (my $row = $query->fetchrow_hashref) { 1568 my $instance = $row->{ 'uri' }; 1569 push @locations, $instance if $instance; 1790 # my $instance_hash = { uri => $row->{ 'uri' }, 1791 # vol_id => $row->{ 'vol_id' }, 1792 # cab_id => $row->{ 'cab_id'} }; 1793 my $instance = $row->{ 'uri' }; 1794 push @locations, $row if $instance; 1570 1795 } 1571 1796 }; … … 1674 1899 # remove key from cache 1675 1900 $self->cache->delete($key->path) if defined $self->cache; 1676 1677 # record the path of the innaccesible files for deferred 1678 # deletion 1679 { 1680 my $query = $db->prepare_cached( $sql->copy_instances_to_deleted ); 1681 $query->execute( $so_id ); 1682 } 1683 # remove all instances... not strictly nessicary as the delete 1684 # from storage_object should cascade but the fkey was specified 1685 # without the cascade 1686 { 1687 my $query = $db->prepare_cached( $sql->delete_instance_by_so_id ); 1688 $query->execute( $so_id ); 1901 1902 if ($total > $available) { 1903 $self->prune_object("$key"); 1689 1904 } 1690 1905 … … 1892 2107 1893 2108 my ($key, $name, $hard_volume) = @_; 1894 2109 2110 # $log->warn("_g_s_v: key:>$key< name:>$name< hard_vol:>$hard_volume<"); 1895 2111 my $sql = $self->sql; 1896 2112 my $db = $self->db($key); … … 1903 2119 $query = $db->prepare_cached( $sql->get_storage_volume_by_name ); 1904 2120 # %free, name, avaiable, allocate 1905 $rows = $query->execute( 0.95, $name, 1, 1);1906 # XXX destinguish between non-existant and unav iable2121 $rows = $query->execute($max_used_space, $name, 1, 1); 2122 # XXX destinguish between non-existant and unavailable 1907 2123 unless ($rows > 0) { 1908 2124 $query->finish; … … 1924 2140 $query = $db->prepare_cached( $sql->get_storage_volume ); 1925 2141 # %free, avaiable, allocate 1926 $rows = $query->execute(0.95, 1, 1); 2142 $rows = $query->execute($max_used_space, 1, 1, $topfew_count); 2143 # $log->warn("Storage_volume: $rows $topfew_count"); 1927 2144 # there has to be atleast one storage volume 1928 2145 unless ($rows > 0) { … … 1970 2187 my $db = $self->db($key); 1971 2188 1972 my ($vol_id, $vol_host, $vol_path, $xattr );2189 my ($vol_id, $vol_host, $vol_path, $xattr, $forbidden_cabinet); 1973 2190 eval { 1974 2191 my $rows; 1975 my $query = $db->prepare_cached( $sql->get_replication_volume_for_ext_id ); 2192 2193 my $query = $db->prepare_cached( $sql->get_cabinets_for_ext_id ); 2194 $rows = $query->execute($key->path); 2195 unless ($rows > 0) { 2196 $query->finish; 2197 die("Requested key $key does not exist"); 2198 } 2199 if ($rows == 1) { 2200 ($forbidden_cabinet) = $query->fetchrow_array; 2201 unless (defined($forbidden_cabinet)) { 2202 $forbidden_cabinet = 0; 2203 } 2204 $query->finish; 2205 } 2206 else { 2207 $forbidden_cabinet = 0; 2208 $query->finish; 2209 } 2210 2211 2212 $query = $db->prepare_cached( $sql->get_replication_volume_for_ext_id ); 1976 2213 # ext_id, %free, avaiable, allocate 1977 $rows = $query->execute($key->path, 0.95, 1, 1);2214 $rows = $query->execute($key->path, $max_used_space, 1, 1, $forbidden_cabinet, $topfew_count); 1978 2215 # XXX destinguish between non-existant and unaviable 1979 2216 unless ($rows > 0) { … … 2083 2320 2084 2321 # handle "any" volume 2085 if ( $vol_name eq 'any') {2322 if (($vol_name eq 'any')||($vol_name eq 'any.0')) { 2086 2323 $log->debug( "found volume name $vol_name" ); 2087 2324 $log->debug( "leaving" ); … … 2108 2345 $log->debug( "leaving" ); 2109 2346 2110 return ;2347 return 0; 2111 2348 } 2112 2349
Note:
See TracChangeset
for help on using the changeset viewer.
