Imported Upstream version 3.3.2
[debian/amanda] / device-src / xfer-source-recovery.c
index da2813473ebbdc9f3bb3efeae70c3b141f71b8ac..f305f0cb7f1e23fd91b2a5f99a6416d78563bcf1 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 2009, 2010 Zmanda, Inc.  All Rights Reserved.
+ * Copyright (c) 2009-2012 Zmanda, Inc.  All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 as published
@@ -76,12 +76,17 @@ typedef struct XferSourceRecovery {
      * part) */
     size_t block_size;
 
+    /* bytes read for this image */
+    guint64 bytes_read;
+
     /* part size (potentially including any zero-padding from the
      * device) */
     guint64 part_size;
 
     /* timer for the duration; NULL while paused or cancelled */
     GTimer *part_timer;
+
+    gint64   size;
 } XferSourceRecovery;
 
 /*
@@ -113,7 +118,7 @@ _xsr_dbg(const char *fmt, ...)
     arglist_start(argp, fmt);
     g_vsnprintf(msg, sizeof(msg), fmt, argp);
     arglist_end(argp);
-    g_debug("XSR thd-%p: %s", g_thread_self(), msg);
+    g_debug("XSR: %s", msg);
 }
 
 /*
@@ -405,8 +410,9 @@ pull_buffer_impl(
                    _("error reading from %s: %s"),
                    self->device->device_name,
                    device_error_or_status(self->device));
+               g_mutex_unlock(self->start_part_mutex);
                wait_until_xfer_cancelled(elt->xfer);
-                goto error;
+                goto error_unlocked;
            }
 
            /* the device has signalled EOF (really end-of-part), so clean up instance
@@ -423,6 +429,7 @@ pull_buffer_impl(
            self->paused = TRUE;
            g_object_unref(self->device);
            self->device = NULL;
+           self->bytes_read += self->part_size;
            self->part_size = 0;
            self->block_size = 0;
            if (self->part_timer) {
@@ -438,9 +445,30 @@ pull_buffer_impl(
 
     g_mutex_unlock(self->start_part_mutex);
 
+    if (elt->size > 0) {
+       /* initialize on first pass */
+       if (self->size == 0)
+           self->size = elt->size;
+       
+       if (self->size == -1) {
+           *size = 0;
+           amfree(buf);
+           return NULL;
+       }
+
+       if (*size > (guint64)self->size) {
+           /* return only self->size bytes */
+           *size = self->size;
+           self->size = -1;
+       } else {
+           self->size -= *size;
+       }
+    }
+
     return buf;
 error:
     g_mutex_unlock(self->start_part_mutex);
+error_unlocked:
     *size = 0;
     return NULL;
 }
@@ -676,3 +704,17 @@ xfer_source_recovery_use_device(
     klass = XFER_SOURCE_RECOVERY_GET_CLASS(elt);
     klass->use_device(XFER_SOURCE_RECOVERY(elt), device);
 }
+
+guint64
+xfer_source_recovery_get_bytes_read(
+    XferElement *elt)
+{
+    XferSourceRecovery *self = XFER_SOURCE_RECOVERY(elt);
+    guint64 bytes_read = self->bytes_read;
+
+    if (self->device)
+       bytes_read += device_get_bytes_read(self->device);
+
+    return bytes_read;
+}
+