summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2018-09-09 20:09:44 +0200
committerFlorian Pritz <bluewind@xinu.at>2018-09-09 20:09:44 +0200
commit2e6bbd753f2fa0a4727b67fd5278fd4f0e0cee39 (patch)
tree38de6b366eea7f37e47b6b02790835a388e923e3
parentd361bb7806791b63702e55e3c86523c93436062f (diff)
downloadApp-BorgRestore-2e6bbd753f2fa0a4727b67fd5278fd4f0e0cee39.tar.gz
App-BorgRestore-2e6bbd753f2fa0a4727b67fd5278fd4f0e0cee39.tar.xz
PathTimeTable/DB: Use cache as kind of stack and only write to DB when removing an item from the stack
Signed-off-by: Florian Pritz <bluewind@xinu.at>
-rw-r--r--lib/App/BorgRestore/PathTimeTable/DB.pm43
1 files changed, 25 insertions, 18 deletions
diff --git a/lib/App/BorgRestore/PathTimeTable/DB.pm b/lib/App/BorgRestore/PathTimeTable/DB.pm
index d514f0c..de0b861 100644
--- a/lib/App/BorgRestore/PathTimeTable/DB.pm
+++ b/lib/App/BorgRestore/PathTimeTable/DB.pm
@@ -14,11 +14,11 @@ This is used by L<App::BorgRestore> to add new archive data into the database.
Data is written to the database directly and existing data is updated where necessary.
For performance reasons this class keeps an internal cache so that the database
-is only contacted when necessary. Depending on the distribution of modification
-times of files and directories, the effectiveness of this cache can vary. The
-cache also assumes that the path are sorted so that all files from one
-directory are added, before files from another. If a path from a different
-directory is added, the previous cache is invalidated.
+is only contacted when necessary. The cache assumes that the path are sorted so
+that all files from one directory are added, before files from another. If a
+path from a different directory is added, the previous cache is invalidated.
+Upon invalidation the time stamp is written to the database. If paths are
+properly sorted, this results in only a single database write for each path.
=cut
@@ -53,24 +53,23 @@ method add_path($path, $time) {
# keep the cache content for the part of the path that stays the same
last;
}
- delete $self->{cache}->{$old_cache_path};
+ my $removed_time = delete $self->{cache}->{$old_cache_path};
+ $self->_add_path_to_db($self->{archive_id}, $old_cache_path, $removed_time);
# strip last part of path
$old_cache_path = substr($old_cache_path, 0, $slash_index);
}
my $full_path = $path;
while ((my $slash_index = rindex($path, "/")) != -1) {
- $self->_add_path_to_db($self->{archive_id}, $path, $time);
my $cached = $self->{cache}->{$path};
- if ($path ne $full_path && (!defined $cached || $cached < $time)) {
+ if (!defined $cached || $cached < $time) {
$log->tracef("Setting cache time for path '%s' to %d", $path, $time) if TRACE;
$self->{cache}->{$path} = $time;
}
$path = substr($path, 0, $slash_index);
}
- $self->_add_path_to_db($self->{archive_id}, $path, $time) unless $path eq ".";
my $cached = $self->{cache}->{$path};
- if ($path ne $full_path && (!defined $cached || $cached < $time)) {
+ if (!defined $cached || $cached < $time) {
$log->tracef("Setting cache time for path '%s' to %d", $path, $time) if TRACE;
$self->{cache}->{$path} = $time;
}
@@ -80,21 +79,29 @@ method add_path($path, $time) {
method _add_path_to_db($archive_id, $path,$time) {
my $cached = $self->{cache}->{$path};
$self->{stats}->{total_potential_calls_to_db_class}++;
- if (!defined $cached || $cached < $time) {
- $log->tracef("Updating DB for path '%s' with time %d", $path, $time) if TRACE;
- $self->{stats}->{real_calls_to_db_class}++;
- $self->{deps}->{db}->update_path_if_greater($archive_id, $path, $time);
- } else {
- $log->tracef("Skipping DB update for path '%s' because (cached) DB time is %d and file time is %d which is lower", $path, $cached, $time) if TRACE;
- }
+ $log->tracef("Updating DB for path '%s' with time %d", $path, $time) if TRACE;
+ $self->{stats}->{real_calls_to_db_class}++;
+ $self->{deps}->{db}->update_path_if_greater($archive_id, $path, $time);
}
method save_nodes() {
+ # flush remaining paths to the DB
+ my $old_cache_path = $self->{current_path_in_cache};
+ $log->debugf("cache content %s", $old_cache_path);
+ while ((my $slash_index = rindex($old_cache_path, "/")) != -1) {
+ $self->{stats}->{cache_invalidation_loop_iterations}++;
+ my $removed_time = delete $self->{cache}->{$old_cache_path};
+ $self->_add_path_to_db($self->{archive_id}, $old_cache_path, $removed_time);
+ # strip last part of path
+ $old_cache_path = substr($old_cache_path, 0, $slash_index);
+ }
+ # ensure that top level directory is also written
+ $self->_add_path_to_db($self->{archive_id}, $old_cache_path, $self->{cache}->{$old_cache_path});
+
for my $key (keys %{$self->{stats}}) {
$log->debugf("Performance counter %s = %s", $key, $self->{stats}->{$key});
}
- # do nothing because we already write everything to the DB directly
}
1;