diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp
index 8078e285195e49fc055908bf8f3089fd5d700c86..2157c4853d687434849aeacd8b122f81ba1d63c4 100644
--- a/catalogue/Catalogue.hpp
+++ b/catalogue/Catalogue.hpp
@@ -46,6 +46,7 @@
 #include "common/dataStructures/RepackInfo.hpp"
 #include "common/dataStructures/RepackType.hpp"
 #include "common/dataStructures/Requester.hpp"
+#include "common/dataStructures/RetrieveFileQueueCriteria.hpp"
 #include "common/dataStructures/RetrieveJob.hpp"
 #include "common/dataStructures/RetrieveRequest.hpp"
 #include "common/dataStructures/SecurityIdentity.hpp"
@@ -210,9 +211,9 @@ public:
    * archiving the file.
    * @return The information required to queue the associated archive request.
    */
-  virtual common::dataStructures::ArchiveFileQueueCriteria
-    prepareForNewFile(const std::string &storageClass, const common::dataStructures::UserIdentity &user)
-    = 0;
+  virtual common::dataStructures::ArchiveFileQueueCriteria prepareForNewFile(
+    const std::string &storageClass,
+    const common::dataStructures::UserIdentity &user) = 0;
 
   /**
    * Notifies the catalogue that a file has been written to tape.
@@ -221,6 +222,22 @@ public:
    */
   virtual void fileWrittenToTape(const TapeFileWritten &event) = 0;
 
+  /**
+   * Prepares for a file retrieval by returning the information required to
+   * queue the associated retrieve request(s).
+   *
+   * @param archiveFileId The unique identifier of the archived file that is
+   * to be retrieved.
+   * @param user The user for whom the file is to be retrieved.  This will be
+   * used by the Catalogue to determine the mount policy to be used when
+   * retrieving the file.
+   *
+   * @return The information required to queue the associated retrieve request(s).
+   */
+  virtual common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFile(
+    const uint64_t archiveFileId,
+    common::dataStructures::UserIdentity &user) = 0;
+
   virtual common::dataStructures::TapeCopyToPoolMap getTapeCopyToPoolMap(const std::string &storageClass) const = 0;
 
   /**
diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp
index e580d7cc2e0c0954b948e5c5fcc7b1cbc48918c1..cb9a1f96be0be31bfcd739e443df21952b73875c 100644
--- a/catalogue/RdbmsCatalogue.cpp
+++ b/catalogue/RdbmsCatalogue.cpp
@@ -1895,106 +1895,6 @@ void RdbmsCatalogue::setDriveStatus(const common::dataStructures::SecurityIdenti
   throw exception::Exception(std::string(__FUNCTION__) + " not implemented");
 }
 
-//------------------------------------------------------------------------------
-// fileWrittenToTape
-//------------------------------------------------------------------------------
-void RdbmsCatalogue::fileWrittenToTape(const TapeFileWritten &event) {
-  try {
-    const time_t now = time(NULL);
-    std::lock_guard<std::mutex> m_lock(m_mutex);
-
-    std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile = getArchiveFile(event.archiveFileId);
-
-    // If the archive file does not already exist
-    if(NULL == archiveFile.get()) {
-      // Create one
-      ArchiveFileRow row;
-      row.archiveFileId = event.archiveFileId;
-      row.diskFileId = event.diskFileId;
-      row.diskInstance = event.diskInstance;
-      row.size = event.size;
-      row.storageClassName = event.storageClassName;
-      row.diskFilePath = event.diskFilePath;
-      row.diskFileUser = event.diskFileUser;
-      row.diskFileGroup = event.diskFileGroup;
-      row.diskFileRecoveryBlob = event.diskFileRecoveryBlob;
-      insertArchiveFile(row);
-    } else {
-      throwIfCommonEventDataMismatch(*archiveFile, event);
-    }
-
-    // Create the tape file
-    common::dataStructures::TapeFile tapeFile;
-    tapeFile.vid            = event.vid;
-    tapeFile.fSeq           = event.fSeq;
-    tapeFile.blockId        = event.blockId;
-    tapeFile.compressedSize = event.compressedSize;
-    tapeFile.copyNb         = event.copyNb;
-    tapeFile.creationTime   = now;
-    createTapeFile(tapeFile, event.archiveFileId);
-  } catch(exception::Exception &ex) {
-    exception::Exception ex;
-    ex.getMessage() << __FUNCTION__ << " failed: " << ex.getMessage().str();
-    throw ex;
-  }
-}
-
-//------------------------------------------------------------------------------
-// throwIfCommonEventDataMismatch
-//------------------------------------------------------------------------------
-void RdbmsCatalogue::throwIfCommonEventDataMismatch(const common::dataStructures::ArchiveFile &expected,
-  const TapeFileWritten &actual) const {
-  // Throw an exception if the common disk information of this tape file
-  // written event does not match the previous
-  if(expected.diskFileID != actual.diskFileId) {
-    exception::Exception ex;
-    ex.getMessage() << "Disk file ID mismatch: expected=" << expected.diskFileID << " actual=" <<
-    actual.diskFileId;
-    throw ex;
-  }
-  if(expected.fileSize != actual.size) {
-    exception::Exception ex;
-    ex.getMessage() << "File size mismatch: expected=" << expected.fileSize << " actual=" << actual.size;
-    throw ex;
-  }
-  if(expected.storageClass != actual.storageClassName) {
-    exception::Exception ex;
-    ex.getMessage() << "Storage class mismatch: expected=" << expected.storageClass << " actual=" <<
-    actual.storageClassName;
-    throw ex;
-  }
-  if(expected.diskInstance != actual.diskInstance) {
-    exception::Exception ex;
-    ex.getMessage() << "Disk instance mismatch: expected=" << expected.diskInstance << " actual=" <<
-    actual.diskInstance;
-    throw ex;
-  }
-  if(expected.drData.drPath != actual.diskFilePath) {
-    exception::Exception ex;
-    ex.getMessage() << "Disk file path mismatch: expected=" << expected.drData.drPath << " actual=" <<
-    actual.diskFilePath;
-    throw ex;
-  }
-  if(expected.drData.drOwner != actual.diskFileUser) {
-    exception::Exception ex;
-    ex.getMessage() << "Disk file user mismatch: expected=" << expected.drData.drOwner << " actual=" <<
-    actual.diskFileUser;
-    throw ex;
-  }
-  if(expected.drData.drGroup != actual.diskFileGroup) {
-    exception::Exception ex;
-    ex.getMessage() << "Disk file group mismatch: expected=" << expected.drData.drGroup << " actual=" <<
-    actual.diskFileGroup;
-    throw ex;
-  }
-  if(expected.drData.drGroup != actual.diskFileGroup) {
-    exception::Exception ex;
-    ex.getMessage() << "Disk recovery blob mismatch";
-    throw ex;
-  }
-
-}
-
 //------------------------------------------------------------------------------
 // prepareForNewFile
 //------------------------------------------------------------------------------
@@ -2161,6 +2061,115 @@ common::dataStructures::MountPolicy RdbmsCatalogue::
   }
 }
 
+//------------------------------------------------------------------------------
+// fileWrittenToTape
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::fileWrittenToTape(const TapeFileWritten &event) {
+  try {
+    const time_t now = time(NULL);
+    std::lock_guard<std::mutex> m_lock(m_mutex);
+
+    std::unique_ptr<common::dataStructures::ArchiveFile> archiveFile = getArchiveFile(event.archiveFileId);
+
+    // If the archive file does not already exist
+    if(NULL == archiveFile.get()) {
+      // Create one
+      ArchiveFileRow row;
+      row.archiveFileId = event.archiveFileId;
+      row.diskFileId = event.diskFileId;
+      row.diskInstance = event.diskInstance;
+      row.size = event.size;
+      row.storageClassName = event.storageClassName;
+      row.diskFilePath = event.diskFilePath;
+      row.diskFileUser = event.diskFileUser;
+      row.diskFileGroup = event.diskFileGroup;
+      row.diskFileRecoveryBlob = event.diskFileRecoveryBlob;
+      insertArchiveFile(row);
+    } else {
+      throwIfCommonEventDataMismatch(*archiveFile, event);
+    }
+
+    // Create the tape file
+    common::dataStructures::TapeFile tapeFile;
+    tapeFile.vid            = event.vid;
+    tapeFile.fSeq           = event.fSeq;
+    tapeFile.blockId        = event.blockId;
+    tapeFile.compressedSize = event.compressedSize;
+    tapeFile.copyNb         = event.copyNb;
+    tapeFile.creationTime   = now;
+    createTapeFile(tapeFile, event.archiveFileId);
+  } catch(exception::Exception &ex) {
+    exception::Exception ex;
+    ex.getMessage() << __FUNCTION__ << " failed: " << ex.getMessage().str();
+    throw ex;
+  }
+}
+
+//------------------------------------------------------------------------------
+// throwIfCommonEventDataMismatch
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::throwIfCommonEventDataMismatch(const common::dataStructures::ArchiveFile &expected,
+                                                    const TapeFileWritten &actual) const {
+  // Throw an exception if the common disk information of this tape file
+  // written event does not match the previous
+  if(expected.diskFileID != actual.diskFileId) {
+    exception::Exception ex;
+    ex.getMessage() << "Disk file ID mismatch: expected=" << expected.diskFileID << " actual=" <<
+    actual.diskFileId;
+    throw ex;
+  }
+  if(expected.fileSize != actual.size) {
+    exception::Exception ex;
+    ex.getMessage() << "File size mismatch: expected=" << expected.fileSize << " actual=" << actual.size;
+    throw ex;
+  }
+  if(expected.storageClass != actual.storageClassName) {
+    exception::Exception ex;
+    ex.getMessage() << "Storage class mismatch: expected=" << expected.storageClass << " actual=" <<
+    actual.storageClassName;
+    throw ex;
+  }
+  if(expected.diskInstance != actual.diskInstance) {
+    exception::Exception ex;
+    ex.getMessage() << "Disk instance mismatch: expected=" << expected.diskInstance << " actual=" <<
+    actual.diskInstance;
+    throw ex;
+  }
+  if(expected.drData.drPath != actual.diskFilePath) {
+    exception::Exception ex;
+    ex.getMessage() << "Disk file path mismatch: expected=" << expected.drData.drPath << " actual=" <<
+    actual.diskFilePath;
+    throw ex;
+  }
+  if(expected.drData.drOwner != actual.diskFileUser) {
+    exception::Exception ex;
+    ex.getMessage() << "Disk file user mismatch: expected=" << expected.drData.drOwner << " actual=" <<
+    actual.diskFileUser;
+    throw ex;
+  }
+  if(expected.drData.drGroup != actual.diskFileGroup) {
+    exception::Exception ex;
+    ex.getMessage() << "Disk file group mismatch: expected=" << expected.drData.drGroup << " actual=" <<
+    actual.diskFileGroup;
+    throw ex;
+  }
+  if(expected.drData.drGroup != actual.diskFileGroup) {
+    exception::Exception ex;
+    ex.getMessage() << "Disk recovery blob mismatch";
+    throw ex;
+  }
+
+}
+
+//------------------------------------------------------------------------------
+// prepareToRetreiveFile
+//------------------------------------------------------------------------------
+common::dataStructures::RetrieveFileQueueCriteria RdbmsCatalogue::prepareToRetrieveFile(
+  const uint64_t archiveFileId,
+  common::dataStructures::UserIdentity &user) {
+  throw exception::Exception(std::string(__FUNCTION__) + " not implemented");
+}
+
 //------------------------------------------------------------------------------
 // isAdmin
 //------------------------------------------------------------------------------
diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp
index 8d42907b11f80adeb2d930156c1c1fd9a6c3ece1..38279046747b1a00ca7b91a31e27704e978ece2d 100644
--- a/catalogue/RdbmsCatalogue.hpp
+++ b/catalogue/RdbmsCatalogue.hpp
@@ -176,14 +176,6 @@ public:
   virtual common::dataStructures::ArchiveFile getArchiveFileById(const uint64_t id);
   
   virtual void setDriveStatus(const common::dataStructures::SecurityIdentity &cliIdentity, const std::string &driveName, const bool up, const bool force);
-
-  /**
-   * Notifies the catalogue that a file has been written to tape.
-   *
-   * @param event The tape file written event.
-   */
-  virtual void fileWrittenToTape(const TapeFileWritten &event);
-
   /**
    * Prepares the catalogue for a new archive file and returns the information
    * required to queue the associated archive request.
@@ -196,8 +188,32 @@ public:
    * archiving the file.
    * @return The information required to queue the associated archive request.
    */
-  virtual common::dataStructures::ArchiveFileQueueCriteria
-    prepareForNewFile(const std::string &storageClass, const common::dataStructures::UserIdentity &user);
+  virtual common::dataStructures::ArchiveFileQueueCriteria prepareForNewFile(
+    const std::string &storageClass,
+    const common::dataStructures::UserIdentity &user);
+
+  /**
+   * Notifies the catalogue that a file has been written to tape.
+   *
+   * @param event The tape file written event.
+   */
+  virtual void fileWrittenToTape(const TapeFileWritten &event);
+
+  /**
+   * Prepares for a file retrieval by returning the information required to
+   * queue the associated retrieve request(s).
+   *
+   * @param archiveFileId The unique identifier of the archived file that is
+   * to be retrieved.
+   * @param user The user for whom the file is to be retrieved.  This will be
+   * used by the Catalogue to determine the mount policy to be used when
+   * retrieving the file.
+   *
+   * @return The information required to queue the associated retrieve request(s).
+   */
+  virtual common::dataStructures::RetrieveFileQueueCriteria prepareToRetrieveFile(
+    const uint64_t archiveFileId,
+    common::dataStructures::UserIdentity &user);
 
   virtual common::dataStructures::TapeCopyToPoolMap getTapeCopyToPoolMap(const std::string &storageClass) const;
 
diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt
index 42d49912e812e6987cbdee9c05223d88d464f5fa..562576cfbd96c0a332fee7e13773762097a8f96c 100644
--- a/common/CMakeLists.txt
+++ b/common/CMakeLists.txt
@@ -46,6 +46,7 @@ set (COMMON_LIB_SRC_FILES
   dataStructures/RepackInfo.cpp
   dataStructures/RepackType.cpp
   dataStructures/Requester.cpp
+  dataStructures/RetrieveFileQueueCriteria.cpp
   dataStructures/RetrieveJob.cpp
   dataStructures/RetrieveRequest.cpp
   dataStructures/SecurityIdentity.cpp