diff --git a/Anvil/Tools/Database.pm b/Anvil/Tools/Database.pm
index 6f57b377..6c80f9a8 100644
--- a/Anvil/Tools/Database.pm
+++ b/Anvil/Tools/Database.pm
@@ -404,8 +404,6 @@ sub check_file_locations
# Get all the Anvil! systems we know of.
$anvil->Database->get_hosts({debug => $debug});
- #$anvil->Database->get_files({debug => $debug});
- #$anvil->Database->get_file_locations({debug => $debug});
foreach my $host_name (sort {$a cmp $b} keys %{$anvil->data->{hosts}{host_name}})
{
@@ -3705,23 +3703,26 @@ WHERE
}});
foreach my $row (@{$results})
{
- my $file_uuid = $row->[0];
- my $file_name = $row->[1];
- my $file_directory = $row->[2];
- my $file_size = $row->[3];
- my $file_md5sum = $row->[4];
- my $file_type = $row->[5];
- my $file_mtime = $row->[6];
- my $modified_date = $row->[7];
+ my $file_uuid = $row->[0];
+ my $file_name = $row->[1];
+ my $file_directory = $row->[2];
+ my $file_size = $row->[3];
+ my $file_md5sum = $row->[4];
+ my $file_type = $row->[5];
+ my $file_mtime = $row->[6];
+ my $modified_date = $row->[7];
+ my $full_path = $file_directory."/".$file_name;
+ $full_path =~ s/\/\//\//g;
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
file_uuid => $file_uuid,
file_name => $file_name,
file_directory => $file_directory,
- file_size => $file_size,
+ file_size => $file_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $file_size}).")",
file_md5sum => $file_md5sum,
file_type => $file_type,
file_mtime => $file_mtime,
modified_date => $modified_date,
+ full_path => $full_path,
}});
# Record the data in the hash, too.
@@ -3735,13 +3736,148 @@ WHERE
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"files::file_uuid::${file_uuid}::file_name" => $anvil->data->{files}{file_uuid}{$file_uuid}{file_name},
"files::file_uuid::${file_uuid}::file_directory" => $anvil->data->{files}{file_uuid}{$file_uuid}{file_directory},
- "files::file_uuid::${file_uuid}::file_size" => $anvil->data->{files}{file_uuid}{$file_uuid}{file_size},
+ "files::file_uuid::${file_uuid}::file_size" => $anvil->data->{files}{file_uuid}{$file_uuid}{file_size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{files}{file_uuid}{$file_uuid}{file_size}}).")",
"files::file_uuid::${file_uuid}::file_md5sum" => $anvil->data->{files}{file_uuid}{$file_uuid}{file_md5sum},
"files::file_uuid::${file_uuid}::file_type" => $anvil->data->{files}{file_uuid}{$file_uuid}{file_type},
"files::file_uuid::${file_uuid}::file_mtime" => $anvil->data->{files}{file_uuid}{$file_uuid}{file_mtime},
"files::file_uuid::${file_uuid}::modified_date" => $anvil->data->{files}{file_uuid}{$file_uuid}{modified_date},
}});
+ # Is this a duplicate?
+ if (exists $anvil->data->{files}{full_path}{$full_path})
+ {
+ # Duplicate! How many file_locations are linked to the duplicates?
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0812", variables => { full_path => $full_path }});
+
+ $anvil->Database->get_file_locations({debug => $debug});
+ my $other_file_uuid = $anvil->data->{files}{full_path}{$full_path}{file_uuid};
+ my $other_file_size = $anvil->data->{files}{file_uuid}{$other_file_uuid}{file_size};
+ my $other_file_md5sum = $anvil->data->{files}{file_uuid}{$file_uuid}{file_md5sum};
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ other_file_uuid => $other_file_uuid,
+ other_file_size => $other_file_size." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $other_file_size}).")",
+ other_file_md5sum => $other_file_md5sum,
+ }});
+
+ my $delete_file_uuid = "";
+
+ # How many linked file_locations are there?
+ my $query = "SELECT COUNT(*) FROM file_locations WHERE file_location_file_uuid = ".$anvil->Database->quote($file_uuid).";";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
+
+ my $file_location_count = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { file_location_count => $file_location_count }});
+
+ $query = "SELECT COUNT(*) FROM file_locations WHERE file_location_file_uuid = ".$anvil->Database->quote($other_file_uuid).";";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { query => $query }});
+
+ my $other_file_location_count = $anvil->Database->query({query => $query, source => $THIS_FILE, line => __LINE__})->[0]->[0];
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { other_file_location_count => $other_file_location_count }});
+
+ # This could happen just after peering a striker, so both could have no
+ # file_locations yet. If so, delete this one.
+ if (not $file_location_count)
+ {
+ $delete_file_uuid = $file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_file_uuid => $delete_file_uuid }});
+ }
+ elsif (not $other_file_location_count)
+ {
+ # Choose the other
+ $delete_file_uuid = $other_file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_file_uuid => $delete_file_uuid }});
+ }
+ else
+ {
+ # Pick the one with the largest file, if there's a difference.
+ if ($file_size != $other_file_size)
+ {
+ if ($file_size > $other_file_size)
+ {
+ # This one is bigger, delete the other
+ $delete_file_uuid = $other_file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_file_uuid => $delete_file_uuid }});
+ }
+ else
+ {
+ # The other is bigger, delete this one.
+ $delete_file_uuid = $file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_file_uuid => $delete_file_uuid }});
+ }
+ }
+ else
+ {
+ # Sizes are the same. Does one have more file_location references?
+ if ($file_location_count != $other_file_location_count)
+ {
+ if ($file_location_count > $other_file_location_count)
+ {
+ # This one has more references
+ $delete_file_uuid = $other_file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_file_uuid => $delete_file_uuid }});
+ }
+ else
+ {
+ # The other one has more references.
+ $delete_file_uuid = $file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_file_uuid => $delete_file_uuid }});
+ }
+ }
+ else
+ {
+ # No difference, delete this one.
+ $delete_file_uuid = $file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { delete_file_uuid => $delete_file_uuid }});
+ }
+ }
+ }
+
+ if ($delete_file_uuid)
+ {
+ # Log which we're deleting
+ $anvil->Log->entry({source => $THIS_FILE, line => __LINE__, level => 1, key => "log_0813", variables => { full_uuid => $delete_file_uuid }});
+
+ # As we delete file_locations, we need to make sure that there are
+ # file_location_file_uuid entries for the other file.
+ my $keep_file_uuid = $file_uuid eq $delete_file_uuid ? $other_file_uuid : $file_uuid;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { keep_file_uuid => $keep_file_uuid }});
+
+ my $query = "DELETE FROM history.file_locations WHERE file_location_file_uuid = ".$anvil->Database->quote($delete_file_uuid).";";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
+ $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
+
+ $query = "DELETE FROM file_locations WHERE file_location_file_uuid = ".$anvil->Database->quote($delete_file_uuid).";";
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => 2, list => { query => $query }});
+ $anvil->Database->write({query => $query, source => $THIS_FILE, line => __LINE__});
+
+ delete $anvil->data->{files}{file_uuid}{$delete_file_uuid};
+ next;
+ }
+ }
+ else
+ {
+ $anvil->data->{files}{full_path}{$full_path}{file_uuid} = $file_uuid;
+ $anvil->data->{files}{full_path}{$full_path}{file_name} = $file_name;
+ $anvil->data->{files}{full_path}{$full_path}{file_directory} = $file_directory;
+ $anvil->data->{files}{full_path}{$full_path}{file_size} = $file_size;
+ $anvil->data->{files}{full_path}{$full_path}{file_md5sum} = $file_md5sum;
+ $anvil->data->{files}{full_path}{$full_path}{file_type} = $file_type;
+ $anvil->data->{files}{full_path}{$full_path}{file_mtime} = $file_mtime;
+ $anvil->data->{files}{full_path}{$full_path}{modified_date} = $modified_date;
+ $anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
+ "files::full_path::${full_path}::file_uuid" => $anvil->data->{files}{full_path}{$full_path}{file_uuid},
+ "files::full_path::${full_path}::file_name" => $anvil->data->{files}{full_path}{$full_path}{file_name},
+ "files::full_path::${full_path}::file_directory" => $anvil->data->{files}{full_path}{$full_path}{file_directory},
+ "files::full_path::${full_path}::file_size" => $anvil->data->{files}{full_path}{$full_path}{file_size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{files}{full_path}{$full_path}{file_size}}).")",
+ "files::full_path::${full_path}::file_md5sum" => $anvil->data->{files}{full_path}{$full_path}{file_md5sum},
+ "files::full_path::${full_path}::file_type" => $anvil->data->{files}{full_path}{$full_path}{file_type},
+ "files::full_path::${full_path}::file_mtime" => $anvil->data->{files}{full_path}{$full_path}{file_mtime},
+ "files::full_path::${full_path}::modified_date" => $anvil->data->{files}{full_path}{$full_path}{modified_date},
+ }});
+ }
+
+ ### NOTE: This is the old way, which didn't allow two files with the same name in different
+ ### directories. This needs to be retired.
$anvil->data->{files}{file_name}{$file_name}{file_uuid} = $file_uuid;
$anvil->data->{files}{file_name}{$file_name}{file_directory} = $file_directory;
$anvil->data->{files}{file_name}{$file_name}{file_size} = $file_size;
@@ -3752,7 +3888,7 @@ WHERE
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => {
"files::file_name::${file_name}::file_uuid" => $anvil->data->{files}{file_name}{$file_name}{file_uuid},
"files::file_name::${file_name}::file_directory" => $anvil->data->{files}{file_name}{$file_name}{file_directory},
- "files::file_name::${file_name}::file_size" => $anvil->data->{files}{file_name}{$file_name}{file_size},
+ "files::file_name::${file_name}::file_size" => $anvil->data->{files}{file_name}{$file_name}{file_size}." (".$anvil->Convert->bytes_to_human_readable({'bytes' => $anvil->data->{files}{file_name}{$file_name}{file_size}}).")",
"files::file_name::${file_name}::file_md5sum" => $anvil->data->{files}{file_name}{$file_name}{file_md5sum},
"files::file_name::${file_name}::file_type" => $anvil->data->{files}{file_name}{$file_name}{file_type},
"files::file_name::${file_name}::file_mtime" => $anvil->data->{files}{file_name}{$file_name}{file_mtime},
diff --git a/Anvil/Tools/Storage.pm b/Anvil/Tools/Storage.pm
index b2d3232a..40fc9d82 100644
--- a/Anvil/Tools/Storage.pm
+++ b/Anvil/Tools/Storage.pm
@@ -611,6 +611,7 @@ sub check_files
my $host_type = $anvil->Get->host_type();
$anvil->Log->variables({source => $THIS_FILE, line => __LINE__, level => $debug, list => { host_type => $host_type }});
+ # Look for files on this computer not yet on the system
if ($host_type ne "striker")
{
my $reload = 0;
diff --git a/share/words.xml b/share/words.xml
index 8da7a104..8b851e10 100644
--- a/share/words.xml
+++ b/share/words.xml
@@ -2611,6 +2611,8 @@ The file: [#!variable!file!#] needs to be updated. The difference is:
- Deleting the server: [#!variable!server_name!#]'s screenshot: [#!variable!file!#].
- No access to: [#!variable!host_name!#] found.
- The host: [#!variable!host_name!#] is not configured, skipping it.
+ The file: [#!variable!full_path!#] is in the database multiple times. This could be an artifact from peering Strikers. Selecting an entry to remove...
+ Deleting the 'files' database entry for the file uuid: [#!variable!file_uuid!#].
The host name: [#!variable!target!#] does not resolve to an IP address.