diff --git a/ReleaseNotes.md b/ReleaseNotes.md
index c9a48cd57bff2039da821ee5c64fe11f3bca137e..de748a59cc0c46c2d8795d9c099300b4a17db73d 100644
--- a/ReleaseNotes.md
+++ b/ReleaseNotes.md
@@ -3,8 +3,25 @@
 ## Summary
 
 ### Features
- - cta/CTA#1016 New options for filtering deleted files using `cta-admin rtf ls` command.
- - cta/CTA#983 Add cta-release package for public binary rpm distribution.
+
+# v4.2-1
+
+## Summary
+
+### Features
+- cta/CTA#1001 Maximum file size is now defined by VO instead of globally.
+- cta/CTA#1019 New command `cta-readtp` allows reading files from tape and verifying their checksum
+
+# v4.1-1
+
+## Summary
+
+### Features
+- cta/CTA#1016 New options for filtering deleted files using `cta-admin rtf ls` command.
+- cta/CTA#983 Add cta-release package for public binary rpm distribution.
+- cta/CTA#980 Add external encryption script option
+- cta/CTA#976 Define a new table in the DB schema to contain the drive status.
+- cta/CTA#834 New command "recycletf restore" allows undeleting a copy of a file from tape deleted using tapefile rm
 
 - [frontend] New command "tapefile rm" allows deleting a copy of a file from tape
 
diff --git a/catalogue/4.2/mysql_catalogue_schema.sql b/catalogue/4.2/mysql_catalogue_schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..e88ac3e28dc852cb88be5973bd65270f75c1308c
--- /dev/null
+++ b/catalogue/4.2/mysql_catalogue_schema.sql
@@ -0,0 +1,422 @@
+CREATE TABLE ARCHIVE_FILE_ID(
+  ID BIGINT UNSIGNED,
+  CONSTRAINT ARCHIVE_FILE_ID_PK PRIMARY KEY(ID)
+);
+INSERT INTO ARCHIVE_FILE_ID(ID) VALUES(1);
+CREATE TABLE LOGICAL_LIBRARY_ID(
+  ID BIGINT UNSIGNED,
+  CONSTRAINT LOGICAL_LIBRARY_ID_PK PRIMARY KEY(ID)
+);
+INSERT INTO LOGICAL_LIBRARY_ID(ID) VALUES(1);
+CREATE TABLE MEDIA_TYPE_ID(
+  ID BIGINT UNSIGNED,
+  CONSTRAINT MEDIA_TYPE_ID_PK PRIMARY KEY(ID)
+);
+INSERT INTO MEDIA_TYPE_ID(ID) VALUES(1);
+CREATE TABLE STORAGE_CLASS_ID(
+  ID BIGINT UNSIGNED,
+  CONSTRAINT STORAGE_CLASS_ID_PK PRIMARY KEY(ID)
+);
+INSERT INTO STORAGE_CLASS_ID(ID) VALUES(1);
+CREATE TABLE TAPE_POOL_ID(
+  ID BIGINT UNSIGNED,
+  CONSTRAINT TAPE_POOL_ID_PK PRIMARY KEY(ID)
+);
+INSERT INTO TAPE_POOL_ID(ID) VALUES(1);
+CREATE TABLE VIRTUAL_ORGANIZATION_ID(
+  ID BIGINT UNSIGNED,
+  CONSTRAINT VIRTUAL_ORGANIZATION_ID_PK PRIMARY KEY(ID)
+);
+INSERT INTO VIRTUAL_ORGANIZATION_ID(ID) VALUES(1);
+CREATE TABLE FILE_RECYCLE_LOG_ID(
+  ID BIGINT UNSIGNED,
+  CONSTRAINT FILE_RECYCLE_LOG_ID PRIMARY KEY(ID)
+);
+INSERT INTO FILE_RECYCLE_LOG_ID(ID) VALUES (1);
+CREATE TABLE CTA_CATALOGUE(
+  SCHEMA_VERSION_MAJOR    BIGINT UNSIGNED      CONSTRAINT CTA_CATALOGUE_SVM1_NN NOT NULL,
+  SCHEMA_VERSION_MINOR    BIGINT UNSIGNED      CONSTRAINT CTA_CATALOGUE_SVM2_NN NOT NULL,
+  NEXT_SCHEMA_VERSION_MAJOR BIGINT UNSIGNED,
+  NEXT_SCHEMA_VERSION_MINOR BIGINT UNSIGNED,
+  STATUS                  VARCHAR(100),
+  IS_PRODUCTION           CHAR(1)         DEFAULT '0' CONSTRAINT CTA_CATALOGUE_IP_NN NOT NULL,
+  CONSTRAINT CTA_CATALOGUE_IP_BOOL_CK     CHECK(IS_PRODUCTION IN ('0','1'))
+);
+CREATE TABLE ADMIN_USER(
+  ADMIN_USER_NAME         VARCHAR(100)    CONSTRAINT ADMIN_USER_AUN_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ADMIN_USER_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT ADMIN_USER_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,
+  CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)
+);
+CREATE TABLE DISK_SYSTEM(
+  DISK_SYSTEM_NAME        VARCHAR(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,
+  FILE_REGEXP             VARCHAR(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,
+  FREE_SPACE_QUERY_URL    VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,
+  REFRESH_INTERVAL        BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,
+  TARGETED_FREE_SPACE     BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,
+  SLEEP_TIME              BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_ST_NN   NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,
+  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)
+);
+CREATE TABLE VIRTUAL_ORGANIZATION(
+  VIRTUAL_ORGANIZATION_ID BIGINT UNSIGNED      CONSTRAINT VIRTUAL_ORGANIZATION_VOI_NN  NOT NULL,
+  VIRTUAL_ORGANIZATION_NAME VARCHAR(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,
+  READ_MAX_DRIVES BIGINT UNSIGNED              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,
+  WRITE_MAX_DRIVES BIGINT UNSIGNED             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,
+  MAX_FILE_SIZE BIGINT UNSIGNED                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT VIRTUAL_ORGANIZATION_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT VIRTUAL_ORGANIZATION_LUT_NN  NOT NULL,
+  CONSTRAINT VIRTUAL_ORGANIZATION_PK PRIMARY KEY(VIRTUAL_ORGANIZATION_ID),
+  CONSTRAINT VIRTUAL_ORGANIZATION_VON_UN UNIQUE(VIRTUAL_ORGANIZATION_NAME)
+);
+CREATE TABLE STORAGE_CLASS(
+  STORAGE_CLASS_ID        BIGINT UNSIGNED      CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,
+  STORAGE_CLASS_NAME      VARCHAR(100)    CONSTRAINT STORAGE_CLASS_SCN_NN  NOT NULL,
+  NB_COPIES               TINYINT UNSIGNED       CONSTRAINT STORAGE_CLASS_NC_NN   NOT NULL,
+  VIRTUAL_ORGANIZATION_ID BIGINT UNSIGNED      CONSTRAINT STORAGE_CLASS_VOI_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT STORAGE_CLASS_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT STORAGE_CLASS_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT STORAGE_CLASS_LUT_NN  NOT NULL,
+  CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),
+  CONSTRAINT STORAGE_CLASS_SCN_UN UNIQUE(STORAGE_CLASS_NAME),
+  CONSTRAINT STORAGE_CLASS_VOI_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)
+);
+CREATE TABLE TAPE_POOL(
+  TAPE_POOL_ID            BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_TPI_NN  NOT NULL,
+  TAPE_POOL_NAME          VARCHAR(100)    CONSTRAINT TAPE_POOL_TPN_NN  NOT NULL,
+  VIRTUAL_ORGANIZATION_ID BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_VOI_NN  NOT NULL,
+  NB_PARTIAL_TAPES        BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_NPT_NN  NOT NULL,
+  IS_ENCRYPTED            CHAR(1)         CONSTRAINT TAPE_POOL_IE_NN   NOT NULL,
+  SUPPLY                  VARCHAR(100),
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT TAPE_POOL_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_LUT_NN  NOT NULL,
+  CONSTRAINT TAPE_POOL_PK PRIMARY KEY(TAPE_POOL_ID),
+  CONSTRAINT TAPE_POOL_TPN_UN UNIQUE(TAPE_POOL_NAME),
+  CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN ('0', '1')),
+  CONSTRAINT TAPE_POOL_VO_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)
+);
+CREATE TABLE ARCHIVE_ROUTE(
+  STORAGE_CLASS_ID        BIGINT UNSIGNED      CONSTRAINT ARCHIVE_ROUTE_SCI_NN  NOT NULL,
+  COPY_NB                 TINYINT UNSIGNED       CONSTRAINT ARCHIVE_ROUTE_CN_NN   NOT NULL,
+  TAPE_POOL_ID            BIGINT UNSIGNED      CONSTRAINT ARCHIVE_ROUTE_TPI_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ARCHIVE_ROUTE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT ARCHIVE_ROUTE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT ARCHIVE_ROUTE_LUT_NN  NOT NULL,
+  CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(STORAGE_CLASS_ID, COPY_NB),
+  CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
+  CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),
+  CONSTRAINT ARCHIVE_ROUTE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0),
+  CONSTRAINT ARCHIVE_ROUTE_SCI_TPI_UN UNIQUE(STORAGE_CLASS_ID, TAPE_POOL_ID)
+);
+CREATE TABLE MEDIA_TYPE(
+  MEDIA_TYPE_ID          BIGINT UNSIGNED    CONSTRAINT MEDIA_TYPE_MTI_NN  NOT NULL,
+  MEDIA_TYPE_NAME        VARCHAR(100)  CONSTRAINT MEDIA_TYPE_MTN_NN  NOT NULL,
+  CARTRIDGE              VARCHAR(100)  CONSTRAINT MEDIA_TYPE_C_NN    NOT NULL,
+  CAPACITY_IN_BYTES      BIGINT UNSIGNED    CONSTRAINT MEDIA_TYPE_CIB_NN  NOT NULL,
+  PRIMARY_DENSITY_CODE   TINYINT UNSIGNED,
+  SECONDARY_DENSITY_CODE TINYINT UNSIGNED,
+  NB_WRAPS               INT UNSIGNED,
+  MIN_LPOS               BIGINT UNSIGNED,
+  MAX_LPOS               BIGINT UNSIGNED,
+  USER_COMMENT           VARCHAR(1000) CONSTRAINT MEDIA_TYPE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      BIGINT UNSIGNED    CONSTRAINT MEDIA_TYPE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       BIGINT UNSIGNED    CONSTRAINT MEDIA_TYPE_LUT_NN  NOT NULL,
+  CONSTRAINT MEDIA_TYPE_PK PRIMARY KEY(MEDIA_TYPE_ID),
+  CONSTRAINT MEDIA_TYPE_MTN_UN UNIQUE(MEDIA_TYPE_NAME)
+);
+CREATE TABLE LOGICAL_LIBRARY(
+  LOGICAL_LIBRARY_ID      BIGINT UNSIGNED      CONSTRAINT LOGICAL_LIBRARY_LLI_NN  NOT NULL,
+  LOGICAL_LIBRARY_NAME    VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LLN_NN  NOT NULL,
+  IS_DISABLED             CHAR(1)         DEFAULT '0' CONSTRAINT LOGICAL_LIBRARY_ID_NN NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT LOGICAL_LIBRARY_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT LOGICAL_LIBRARY_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT LOGICAL_LIBRARY_LUT_NN  NOT NULL,
+  CONSTRAINT LOGICAL_LIBRARY_PK PRIMARY KEY(LOGICAL_LIBRARY_ID),
+  CONSTRAINT LOGICAL_LIBRARY_LLN_UN UNIQUE(LOGICAL_LIBRARY_NAME),
+  CONSTRAINT LOGICAL_LIBRARY_ID_BOOL_CK CHECK(IS_DISABLED IN ('0', '1'))
+);
+CREATE TABLE TAPE(
+  VID                     VARCHAR(100)    CONSTRAINT TAPE_V_NN    NOT NULL,
+  MEDIA_TYPE_ID           BIGINT UNSIGNED      CONSTRAINT TAPE_MTID_NN   NOT NULL,
+  VENDOR                  VARCHAR(100)    CONSTRAINT TAPE_V2_NN   NOT NULL,
+  LOGICAL_LIBRARY_ID      BIGINT UNSIGNED      CONSTRAINT TAPE_LLI_NN  NOT NULL,
+  TAPE_POOL_ID            BIGINT UNSIGNED      CONSTRAINT TAPE_TPI_NN  NOT NULL,
+  ENCRYPTION_KEY_NAME     VARCHAR(100),
+  DATA_IN_BYTES           BIGINT UNSIGNED      CONSTRAINT TAPE_DIB_NN  NOT NULL,
+  LAST_FSEQ               BIGINT UNSIGNED      CONSTRAINT TAPE_LF_NN   NOT NULL,
+  NB_MASTER_FILES         BIGINT UNSIGNED      DEFAULT 0 CONSTRAINT TAPE_NB_MASTER_FILES_NN NOT NULL,
+  MASTER_DATA_IN_BYTES    BIGINT UNSIGNED      DEFAULT 0 CONSTRAINT TAPE_MASTER_DATA_IN_BYTES_NN NOT NULL,
+  IS_FULL                 CHAR(1)         CONSTRAINT TAPE_IF_NN   NOT NULL,
+  IS_FROM_CASTOR          CHAR(1)         CONSTRAINT TAPE_IFC_NN  NOT NULL,
+  DIRTY                   CHAR(1)         DEFAULT '1' CONSTRAINT TAPE_DIRTY_NN NOT NULL,
+  NB_COPY_NB_1            BIGINT UNSIGNED     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_1_NN NOT NULL,
+  COPY_NB_1_IN_BYTES      BIGINT UNSIGNED     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_1_IN_BYTES_NN NOT NULL,
+  NB_COPY_NB_GT_1         BIGINT UNSIGNED     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_GT_1_NN NOT NULL,
+  COPY_NB_GT_1_IN_BYTES   BIGINT UNSIGNED     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_GT_1_IN_BYTES_NN NOT NULL,
+  LABEL_DRIVE             VARCHAR(100),
+  LABEL_TIME              BIGINT UNSIGNED    ,
+  LAST_READ_DRIVE         VARCHAR(100),
+  LAST_READ_TIME          BIGINT UNSIGNED    ,
+  LAST_WRITE_DRIVE        VARCHAR(100),
+  LAST_WRITE_TIME         BIGINT UNSIGNED    ,
+  READ_MOUNT_COUNT        BIGINT UNSIGNED      DEFAULT 0 CONSTRAINT TAPE_RMC_NN NOT NULL,
+  WRITE_MOUNT_COUNT       BIGINT UNSIGNED      DEFAULT 0 CONSTRAINT TAPE_WMC_NN NOT NULL,
+  USER_COMMENT            VARCHAR(1000),
+  TAPE_STATE              VARCHAR(100)    CONSTRAINT TAPE_TS_NN NOT NULL,
+  STATE_REASON            VARCHAR(1000),
+  STATE_UPDATE_TIME       BIGINT UNSIGNED      CONSTRAINT TAPE_SUT_NN NOT NULL,
+  STATE_MODIFIED_BY       VARCHAR(100)    CONSTRAINT TAPE_SMB_NN NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT TAPE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT TAPE_LUT_NN  NOT NULL,
+  CONSTRAINT TAPE_PK PRIMARY KEY(VID),
+  CONSTRAINT TAPE_LOGICAL_LIBRARY_FK FOREIGN KEY(LOGICAL_LIBRARY_ID) REFERENCES LOGICAL_LIBRARY(LOGICAL_LIBRARY_ID),
+  CONSTRAINT TAPE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),
+  CONSTRAINT TAPE_IS_FULL_BOOL_CK CHECK(IS_FULL IN ('0', '1')),
+  CONSTRAINT TAPE_IS_FROM_CASTOR_BOOL_CK CHECK(IS_FROM_CASTOR IN ('0', '1')),
+  CONSTRAINT TAPE_DIRTY_BOOL_CK CHECK(DIRTY IN ('0','1')),
+  CONSTRAINT TAPE_STATE_CK CHECK(TAPE_STATE IN ('ACTIVE', 'DISABLED', 'BROKEN')),
+  CONSTRAINT TAPE_MEDIA_TYPE_FK FOREIGN KEY(MEDIA_TYPE_ID) REFERENCES MEDIA_TYPE(MEDIA_TYPE_ID)
+);
+CREATE INDEX TAPE_TAPE_POOL_ID_IDX ON TAPE(TAPE_POOL_ID);
+CREATE INDEX TAPE_STATE_IDX ON TAPE(TAPE_STATE);
+CREATE TABLE MOUNT_POLICY(
+  MOUNT_POLICY_NAME          VARCHAR(100)    CONSTRAINT MOUNT_POLICY_MPN_NN  NOT NULL,
+  ARCHIVE_PRIORITY           BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_AP_NN   NOT NULL,
+  ARCHIVE_MIN_REQUEST_AGE    BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_AMRA_NN NOT NULL,
+  RETRIEVE_PRIORITY          BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_RP_NN   NOT NULL,
+  RETRIEVE_MIN_REQUEST_AGE   BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_RMRA_NN NOT NULL,
+  USER_COMMENT               VARCHAR(1000)   CONSTRAINT MOUNT_POLICY_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME          BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME           BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_LUT_NN  NOT NULL,
+  CONSTRAINT MOUNT_POLICY_PK PRIMARY KEY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE REQUESTER_MOUNT_RULE(
+  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_RULE_DIN_NN  NOT NULL,
+  REQUESTER_NAME         VARCHAR(100)    CONSTRAINT RQSTER_RULE_RN_NN   NOT NULL,
+  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_RULE_MPN_NN  NOT NULL,
+  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_RULE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      BIGINT UNSIGNED      CONSTRAINT RQSTER_RULE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       BIGINT UNSIGNED      CONSTRAINT RQSTER_RULE_LUT_NN  NOT NULL,
+  CONSTRAINT RQSTER_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_NAME),
+  CONSTRAINT RQSTER_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)
+    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE REQUESTER_GROUP_MOUNT_RULE(
+  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_DIN_NN  NOT NULL,
+  REQUESTER_GROUP_NAME   VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_RGN_NN  NOT NULL,
+  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_MPN_NN  NOT NULL,
+  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_GRP_RULE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      BIGINT UNSIGNED      CONSTRAINT RQSTER_GRP_RULE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       BIGINT UNSIGNED      CONSTRAINT RQSTER_GRP_RULE_LUT_NN  NOT NULL,
+  CONSTRAINT RQSTER_GRP_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME),
+  CONSTRAINT RQSTER_GRP_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)
+    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE ARCHIVE_FILE(
+  ARCHIVE_FILE_ID         BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_AFI_NN  NOT NULL,
+  DISK_INSTANCE_NAME      VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DIN_NN  NOT NULL,
+  DISK_FILE_ID            VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DFI_NN  NOT NULL,
+  DISK_FILE_UID           INT UNSIGNED      CONSTRAINT ARCHIVE_FILE_DFUID_NN  NOT NULL,
+  DISK_FILE_GID           INT UNSIGNED      CONSTRAINT ARCHIVE_FILE_DFGID_NN  NOT NULL,
+  SIZE_IN_BYTES           BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_SIB_NN  NOT NULL,
+  CHECKSUM_BLOB           VARBINARY(200),
+  CHECKSUM_ADLER32        INT UNSIGNED      CONSTRAINT ARCHIVE_FILE_CB2_NN  NOT NULL,
+  STORAGE_CLASS_ID        BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_SCI_NN  NOT NULL,
+  CREATION_TIME           BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_CT2_NN  NOT NULL,
+  RECONCILIATION_TIME     BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_RT_NN   NOT NULL,
+  IS_DELETED              CHAR(1)         DEFAULT '0' CONSTRAINT ARCHIVE_FILE_ID_NN NOT NULL,
+  COLLOCATION_HINT        VARCHAR(100),
+  CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),
+  CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
+  CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID),
+  CONSTRAINT ARCHIVE_FILE_ID_BOOL_CK CHECK(IS_DELETED IN ('0', '1'))
+);
+CREATE INDEX ARCHIVE_FILE_DIN_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME);
+CREATE INDEX ARCHIVE_FILE_DFI_IDX ON ARCHIVE_FILE(DISK_FILE_ID);
+CREATE TABLE TAPE_FILE(
+  VID                      VARCHAR(100)   CONSTRAINT TAPE_FILE_V_NN    NOT NULL,
+  FSEQ                     BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_F_NN    NOT NULL,
+  BLOCK_ID                 BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_BI_NN   NOT NULL,
+  LOGICAL_SIZE_IN_BYTES    BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_CSIB_NN NOT NULL,
+  COPY_NB                  TINYINT UNSIGNED      CONSTRAINT TAPE_FILE_CN_NN   NOT NULL,
+  CREATION_TIME            BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_CT_NN   NOT NULL,
+  ARCHIVE_FILE_ID          BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_AFI_NN  NOT NULL,
+  CONSTRAINT TAPE_FILE_PK PRIMARY KEY(VID, FSEQ),
+  CONSTRAINT TAPE_FILE_TAPE_FK FOREIGN KEY(VID)
+    REFERENCES TAPE(VID),
+  CONSTRAINT TAPE_FILE_ARCHIVE_FILE_FK FOREIGN KEY(ARCHIVE_FILE_ID)
+    REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),
+  CONSTRAINT TAPE_FILE_VID_BLOCK_ID_UN UNIQUE(VID, BLOCK_ID),
+  CONSTRAINT TAPE_FILE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0)
+);
+CREATE INDEX TAPE_FILE_VID_IDX ON TAPE_FILE(VID);
+CREATE INDEX TAPE_FILE_ARCHIVE_FILE_ID_IDX ON TAPE_FILE(ARCHIVE_FILE_ID);
+CREATE TABLE ACTIVITIES_WEIGHTS (
+  DISK_INSTANCE_NAME       VARCHAR(100),
+  ACTIVITY                 VARCHAR(100),
+  WEIGHT                   VARCHAR(100),
+  USER_COMMENT             VARCHAR(1000)   CONSTRAINT ACTIV_WEIGHTS_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME        BIGINT UNSIGNED      CONSTRAINT ACTIV_WEIGHTS_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME         BIGINT UNSIGNED      CONSTRAINT ACTIV_WEIGHTS_LUT_NN  NOT NULL
+);
+CREATE TABLE FILE_RECYCLE_LOG(
+  FILE_RECYCLE_LOG_ID        BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_ID_NN NOT NULL,
+  VID                        VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_VID_NN NOT NULL,
+  FSEQ                       BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_FSEQ_NN NOT NULL,
+  BLOCK_ID                   BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_BID_NN NOT NULL,
+  COPY_NB                    TINYINT UNSIGNED           CONSTRAINT FILE_RECYCLE_LOG_COPY_NB_NN NOT NULL,
+  TAPE_FILE_CREATION_TIME    BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_TFCT_NN NOT NULL,
+  ARCHIVE_FILE_ID            BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_AFI_NN NOT NULL,
+  DISK_INSTANCE_NAME         VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DIN_NN NOT NULL,
+  DISK_FILE_ID               VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFI_NN NOT NULL,
+  DISK_FILE_ID_WHEN_DELETED  VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFIWD_NN NOT NULL,
+  DISK_FILE_UID              BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_DFU_NN NOT NULL,
+  DISK_FILE_GID              BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_DFG_NN NOT NULL,
+  SIZE_IN_BYTES              BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_SIB_NN NOT NULL,
+  CHECKSUM_BLOB              VARBINARY(200),
+  CHECKSUM_ADLER32           INT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_CA_NN NOT NULL,
+  STORAGE_CLASS_ID           BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_SCI_NN NOT NULL,
+  ARCHIVE_FILE_CREATION_TIME BIGINT UNSIGNED          CONSTRAINT FILE_RECYLE_LOG_CT_NN NOT NULL,
+  RECONCILIATION_TIME        BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_RT_NN NOT NULL,
+  COLLOCATION_HINT           VARCHAR(100),
+  DISK_FILE_PATH             VARCHAR(2000),
+  REASON_LOG                 VARCHAR(1000)       CONSTRAINT FILE_RECYCLE_LOG_RL_NN NOT NULL,
+  RECYCLE_LOG_TIME           BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_RLT_NN NOT NULL,
+  CONSTRAINT FILE_RECYCLE_LOG_PK PRIMARY KEY(FILE_RECYCLE_LOG_ID),
+  CONSTRAINT FILE_RECYCLE_LOG_VID_FK FOREIGN KEY(VID) REFERENCES TAPE(VID),
+  CONSTRAINT FILE_RECYCLE_LOG_SC_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID)
+);
+CREATE INDEX FILE_RECYCLE_LOG_DFI_IDX ON FILE_RECYCLE_LOG(DISK_FILE_ID);
+
+CREATE TABLE DRIVE_CONFIG (
+  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_DN_NN  NOT NULL,
+  CATEGORY                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_C_NN   NOT NULL,
+  KEY_NAME                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_KN_NN  NOT NULL,
+  VALUE                       VARCHAR(1000)      CONSTRAINT DRIVE_CONFIG_V_NN   NOT NULL,
+  SOURCE                      VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_S_NN   NOT NULL,
+  CONSTRAINT DRIVE_CONFIG_DN_PK PRIMARY KEY(KEY_NAME, DRIVE_NAME)
+);
+
+CREATE TABLE TAPE_DRIVE (
+  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_STATE_DN_NN NOT NULL,
+  HOST                        VARCHAR(100)       CONSTRAINT DRIVE_STATE_H_NN  NOT NULL,
+  LOGICAL_LIBRARY             VARCHAR(100)       CONSTRAINT DRIVE_STATE_LL_NN NOT NULL,
+  SESSION_ID                  BIGINT UNSIGNED,
+  BYTES_TRANSFERED_IN_SESSION BIGINT UNSIGNED,
+  FILES_TRANSFERED_IN_SESSION BIGINT UNSIGNED,
+  LATEST_BANDWIDTH            VARCHAR(100),
+  SESSION_START_TIME          BIGINT UNSIGNED,
+  MOUNT_START_TIME            BIGINT UNSIGNED,
+  TRANSFER_START_TIME         BIGINT UNSIGNED,
+  UNLOAD_START_TIME           BIGINT UNSIGNED,
+  UNMOUNT_START_TIME          BIGINT UNSIGNED,
+  DRAINING_START_TIME         BIGINT UNSIGNED,
+  DOWN_OR_UP_START_TIME       BIGINT UNSIGNED,
+  PROBE_START_TIME            BIGINT UNSIGNED,
+  CLEANUP_START_TIME          BIGINT UNSIGNED,
+  START_START_TIME            BIGINT UNSIGNED,
+  SHUTDOWN_TIME               BIGINT UNSIGNED,
+  MOUNT_TYPE                  INT UNSIGNED      CONSTRAINT DRIVE_STATE_MT_NN NOT NULL,
+  DRIVE_STATUS                VARCHAR(100)    DEFAULT 'UNKNOWN' CONSTRAINT DRIVE_STATE_DS_NN NOT NULL,
+  DESIRED_UP                  CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DU_NN  NOT NULL,
+  DESIRED_FORCE_DOWN          CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DFD_NN NOT NULL,
+  REASON_UP_DOWN              VARCHAR(1000),
+  CURRENT_VID                 VARCHAR(100),
+  CTA_VERSION                 VARCHAR(100),
+  CURRENT_PRIORITY            BIGINT UNSIGNED,
+  CURRENT_ACTIVITY            VARCHAR(100),
+  CURRENT_ACTIVITY_WEIGHT     VARCHAR(100),
+  CURRENT_TAPE_POOL           VARCHAR(100),
+  NEXT_MOUNT_TYPE             INT UNSIGNED,
+  NEXT_VID                    VARCHAR(100),
+  NEXT_TAPE_POOL              VARCHAR(100),
+  NEXT_PRIORITY               BIGINT UNSIGNED,
+  NEXT_ACTIVITY               VARCHAR(100),
+  NEXT_ACTIVITY_WEIGHT        VARCHAR(100),
+  DEV_FILE_NAME               VARCHAR(100),
+  RAW_LIBRARY_SLOT            VARCHAR(100),
+  CURRENT_VO                  VARCHAR(100),
+  NEXT_VO                     VARCHAR(100),
+  USER_COMMENT                VARCHAR(1000),
+  CREATION_LOG_USER_NAME      VARCHAR(100),
+  CREATION_LOG_HOST_NAME      VARCHAR(100),
+  CREATION_LOG_TIME           BIGINT UNSIGNED,
+  LAST_UPDATE_USER_NAME       VARCHAR(100),
+  LAST_UPDATE_HOST_NAME       VARCHAR(100),
+  LAST_UPDATE_TIME            BIGINT UNSIGNED,
+  DISK_SYSTEM_NAME            VARCHAR(100)       CONSTRAINT DRIVE_STATE_DSN_NN NOT NULL,
+  RESERVED_BYTES              BIGINT UNSIGNED         CONSTRAINT DRIVE_STATE_RB_NN  NOT NULL,
+  CONSTRAINT DRIVE_STATE_DN_PK PRIMARY KEY(DRIVE_NAME),
+  CONSTRAINT DRIVE_STATE_DU_BOOL_CK CHECK(DESIRED_UP IN ('0', '1')),
+  CONSTRAINT DRIVE_STATE_DFD_BOOL_CK CHECK(DESIRED_FORCE_DOWN IN ('0', '1')),
+  CONSTRAINT DRIVE_STATE_DS_STRING_CK CHECK(DRIVE_STATUS IN ('DOWN', 'UP', 'PROBING', 'STARTING',
+  'MOUNTING', 'TRANSFERING', 'UNLOADING', 'UNMOUNTING', 'DRAININGTODISK', 'CLEANINGUP', 'SHUTDOWN',
+  'UNKNOWN'))
+);
+INSERT INTO CTA_CATALOGUE(
+  SCHEMA_VERSION_MAJOR,
+  SCHEMA_VERSION_MINOR,
+  STATUS)
+VALUES(
+  4,
+  2,
+  'PRODUCTION');
+ALTER TABLE CTA_CATALOGUE ADD CONSTRAINT
+  CATALOGUE_STATUS_CONTENT_CK CHECK((NEXT_SCHEMA_VERSION_MAJOR IS NULL AND NEXT_SCHEMA_VERSION_MINOR IS NULL AND STATUS='PRODUCTION') OR (STATUS='UPGRADING'));
diff --git a/catalogue/4.2/oracle_catalogue_schema.sql b/catalogue/4.2/oracle_catalogue_schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..279281b840908aab7a79b27636aef9c5de4f058c
--- /dev/null
+++ b/catalogue/4.2/oracle_catalogue_schema.sql
@@ -0,0 +1,455 @@
+CREATE SEQUENCE ARCHIVE_FILE_ID_SEQ
+  INCREMENT BY 1
+  START WITH 4294967296
+  NOMAXVALUE
+  MINVALUE 1
+  NOCYCLE
+  CACHE 20
+  NOORDER;
+CREATE SEQUENCE LOGICAL_LIBRARY_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NOMAXVALUE
+  MINVALUE 1
+  NOCYCLE
+  CACHE 20
+  NOORDER;
+CREATE SEQUENCE MEDIA_TYPE_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NOMAXVALUE
+  MINVALUE 1
+  NOCYCLE
+  CACHE 20
+  NOORDER;
+CREATE SEQUENCE STORAGE_CLASS_ID_SEQ
+  INCREMENT BY 1
+  START WITH 10000
+  NOMAXVALUE
+  MINVALUE 1
+  NOCYCLE
+  CACHE 20
+  NOORDER;
+CREATE SEQUENCE TAPE_POOL_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NOMAXVALUE
+  MINVALUE 1
+  NOCYCLE
+  CACHE 20
+  NOORDER;
+CREATE SEQUENCE VIRTUAL_ORGANIZATION_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NOMAXVALUE
+  MINVALUE 1
+  NOCYCLE
+  CACHE 20
+  NOORDER;
+CREATE SEQUENCE FILE_RECYCLE_LOG_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NOMAXVALUE
+  MINVALUE 1
+  NOCYCLE
+  CACHE 20
+  NOORDER;
+CREATE GLOBAL TEMPORARY TABLE TEMP_TAPE_FILE_INSERTION_BATCH(
+  VID                   VARCHAR2(100),
+  FSEQ                  NUMERIC(20, 0)  ,
+  BLOCK_ID              NUMERIC(20, 0)  ,
+  LOGICAL_SIZE_IN_BYTES NUMERIC(20, 0)  ,
+  COPY_NB               NUMERIC(3, 0)   ,
+  CREATION_TIME         NUMERIC(20, 0)  ,
+  ARCHIVE_FILE_ID       NUMERIC(20, 0)
+)
+ON COMMIT DELETE ROWS;
+CREATE INDEX TEMP_T_F_I_B_AFI_IDX ON TEMP_TAPE_FILE_INSERTION_BATCH(ARCHIVE_FILE_ID);
+CREATE TABLE CTA_CATALOGUE(
+  SCHEMA_VERSION_MAJOR    NUMERIC(20, 0)      CONSTRAINT CTA_CATALOGUE_SVM1_NN NOT NULL,
+  SCHEMA_VERSION_MINOR    NUMERIC(20, 0)      CONSTRAINT CTA_CATALOGUE_SVM2_NN NOT NULL,
+  NEXT_SCHEMA_VERSION_MAJOR NUMERIC(20, 0),
+  NEXT_SCHEMA_VERSION_MINOR NUMERIC(20, 0),
+  STATUS                  VARCHAR2(100),
+  IS_PRODUCTION           CHAR(1)         DEFAULT '0' CONSTRAINT CTA_CATALOGUE_IP_NN NOT NULL,
+  CONSTRAINT CTA_CATALOGUE_IP_BOOL_CK     CHECK(IS_PRODUCTION IN ('0','1'))
+);
+CREATE TABLE ADMIN_USER(
+  ADMIN_USER_NAME         VARCHAR2(100)    CONSTRAINT ADMIN_USER_AUN_NN  NOT NULL,
+  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT ADMIN_USER_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT ADMIN_USER_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT ADMIN_USER_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT ADMIN_USER_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT ADMIN_USER_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT ADMIN_USER_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,
+  CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)
+);
+CREATE TABLE DISK_SYSTEM(
+  DISK_SYSTEM_NAME        VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,
+  FILE_REGEXP             VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,
+  FREE_SPACE_QUERY_URL    VARCHAR2(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,
+  REFRESH_INTERVAL        NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,
+  TARGETED_FREE_SPACE     NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,
+  SLEEP_TIME              NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_ST_NN   NOT NULL,
+  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,
+  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)
+);
+CREATE TABLE VIRTUAL_ORGANIZATION(
+  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_VOI_NN  NOT NULL,
+  VIRTUAL_ORGANIZATION_NAME VARCHAR2(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,
+  READ_MAX_DRIVES NUMERIC(20, 0)              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,
+  WRITE_MAX_DRIVES NUMERIC(20, 0)             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,
+  MAX_FILE_SIZE NUMERIC(20, 0)                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,
+  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_LUT_NN  NOT NULL,
+  CONSTRAINT VIRTUAL_ORGANIZATION_PK PRIMARY KEY(VIRTUAL_ORGANIZATION_ID),
+  CONSTRAINT VIRTUAL_ORGANIZATION_VON_UN UNIQUE(VIRTUAL_ORGANIZATION_NAME)
+);
+CREATE TABLE STORAGE_CLASS(
+  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,
+  STORAGE_CLASS_NAME      VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_SCN_NN  NOT NULL,
+  NB_COPIES               NUMERIC(3, 0)       CONSTRAINT STORAGE_CLASS_NC_NN   NOT NULL,
+  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_VOI_NN  NOT NULL,
+  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT STORAGE_CLASS_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_LUT_NN  NOT NULL,
+  CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),
+  CONSTRAINT STORAGE_CLASS_SCN_UN UNIQUE(STORAGE_CLASS_NAME),
+  CONSTRAINT STORAGE_CLASS_VOI_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)
+);
+CREATE TABLE TAPE_POOL(
+  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_TPI_NN  NOT NULL,
+  TAPE_POOL_NAME          VARCHAR2(100)    CONSTRAINT TAPE_POOL_TPN_NN  NOT NULL,
+  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_VOI_NN  NOT NULL,
+  NB_PARTIAL_TAPES        NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_NPT_NN  NOT NULL,
+  IS_ENCRYPTED            CHAR(1)         CONSTRAINT TAPE_POOL_IE_NN   NOT NULL,
+  SUPPLY                  VARCHAR2(100),
+  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT TAPE_POOL_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT TAPE_POOL_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT TAPE_POOL_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT TAPE_POOL_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT TAPE_POOL_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_LUT_NN  NOT NULL,
+  CONSTRAINT TAPE_POOL_PK PRIMARY KEY(TAPE_POOL_ID),
+  CONSTRAINT TAPE_POOL_TPN_UN UNIQUE(TAPE_POOL_NAME),
+  CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN ('0', '1')),
+  CONSTRAINT TAPE_POOL_VO_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)
+);
+CREATE TABLE ARCHIVE_ROUTE(
+  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_SCI_NN  NOT NULL,
+  COPY_NB                 NUMERIC(3, 0)       CONSTRAINT ARCHIVE_ROUTE_CN_NN   NOT NULL,
+  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_TPI_NN  NOT NULL,
+  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT ARCHIVE_ROUTE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT ARCHIVE_ROUTE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT ARCHIVE_ROUTE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT ARCHIVE_ROUTE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_LUT_NN  NOT NULL,
+  CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(STORAGE_CLASS_ID, COPY_NB),
+  CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
+  CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),
+  CONSTRAINT ARCHIVE_ROUTE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0),
+  CONSTRAINT ARCHIVE_ROUTE_SCI_TPI_UN UNIQUE(STORAGE_CLASS_ID, TAPE_POOL_ID)
+);
+CREATE TABLE MEDIA_TYPE(
+  MEDIA_TYPE_ID          NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_MTI_NN  NOT NULL,
+  MEDIA_TYPE_NAME        VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_MTN_NN  NOT NULL,
+  CARTRIDGE              VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_C_NN    NOT NULL,
+  CAPACITY_IN_BYTES      NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_CIB_NN  NOT NULL,
+  PRIMARY_DENSITY_CODE   NUMERIC(3, 0),
+  SECONDARY_DENSITY_CODE NUMERIC(3, 0),
+  NB_WRAPS               NUMERIC(10, 0),
+  MIN_LPOS               NUMERIC(20, 0),
+  MAX_LPOS               NUMERIC(20, 0),
+  USER_COMMENT           VARCHAR2(1000) CONSTRAINT MEDIA_TYPE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_LUT_NN  NOT NULL,
+  CONSTRAINT MEDIA_TYPE_PK PRIMARY KEY(MEDIA_TYPE_ID),
+  CONSTRAINT MEDIA_TYPE_MTN_UN UNIQUE(MEDIA_TYPE_NAME)
+);
+CREATE TABLE LOGICAL_LIBRARY(
+  LOGICAL_LIBRARY_ID      NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_LLI_NN  NOT NULL,
+  LOGICAL_LIBRARY_NAME    VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_LLN_NN  NOT NULL,
+  IS_DISABLED             CHAR(1)         DEFAULT '0' CONSTRAINT LOGICAL_LIBRARY_ID_NN NOT NULL,
+  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT LOGICAL_LIBRARY_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_LUT_NN  NOT NULL,
+  CONSTRAINT LOGICAL_LIBRARY_PK PRIMARY KEY(LOGICAL_LIBRARY_ID),
+  CONSTRAINT LOGICAL_LIBRARY_LLN_UN UNIQUE(LOGICAL_LIBRARY_NAME),
+  CONSTRAINT LOGICAL_LIBRARY_ID_BOOL_CK CHECK(IS_DISABLED IN ('0', '1'))
+);
+CREATE TABLE TAPE(
+  VID                     VARCHAR2(100)    CONSTRAINT TAPE_V_NN    NOT NULL,
+  MEDIA_TYPE_ID           NUMERIC(20, 0)      CONSTRAINT TAPE_MTID_NN   NOT NULL,
+  VENDOR                  VARCHAR2(100)    CONSTRAINT TAPE_V2_NN   NOT NULL,
+  LOGICAL_LIBRARY_ID      NUMERIC(20, 0)      CONSTRAINT TAPE_LLI_NN  NOT NULL,
+  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT TAPE_TPI_NN  NOT NULL,
+  ENCRYPTION_KEY_NAME     VARCHAR2(100),
+  DATA_IN_BYTES           NUMERIC(20, 0)      CONSTRAINT TAPE_DIB_NN  NOT NULL,
+  LAST_FSEQ               NUMERIC(20, 0)      CONSTRAINT TAPE_LF_NN   NOT NULL,
+  NB_MASTER_FILES         NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_NB_MASTER_FILES_NN NOT NULL,
+  MASTER_DATA_IN_BYTES    NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_MASTER_DATA_IN_BYTES_NN NOT NULL,
+  IS_FULL                 CHAR(1)         CONSTRAINT TAPE_IF_NN   NOT NULL,
+  IS_FROM_CASTOR          CHAR(1)         CONSTRAINT TAPE_IFC_NN  NOT NULL,
+  DIRTY                   CHAR(1)         DEFAULT '1' CONSTRAINT TAPE_DIRTY_NN NOT NULL,
+  NB_COPY_NB_1            NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_1_NN NOT NULL,
+  COPY_NB_1_IN_BYTES      NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_1_IN_BYTES_NN NOT NULL,
+  NB_COPY_NB_GT_1         NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_GT_1_NN NOT NULL,
+  COPY_NB_GT_1_IN_BYTES   NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_GT_1_IN_BYTES_NN NOT NULL,
+  LABEL_DRIVE             VARCHAR2(100),
+  LABEL_TIME              NUMERIC(20, 0)    ,
+  LAST_READ_DRIVE         VARCHAR2(100),
+  LAST_READ_TIME          NUMERIC(20, 0)    ,
+  LAST_WRITE_DRIVE        VARCHAR2(100),
+  LAST_WRITE_TIME         NUMERIC(20, 0)    ,
+  READ_MOUNT_COUNT        NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_RMC_NN NOT NULL,
+  WRITE_MOUNT_COUNT       NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_WMC_NN NOT NULL,
+  USER_COMMENT            VARCHAR2(1000),
+  TAPE_STATE              VARCHAR2(100)    CONSTRAINT TAPE_TS_NN NOT NULL,
+  STATE_REASON            VARCHAR2(1000),
+  STATE_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_SUT_NN NOT NULL,
+  STATE_MODIFIED_BY       VARCHAR2(100)    CONSTRAINT TAPE_SMB_NN NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT TAPE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT TAPE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT TAPE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT TAPE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT TAPE_LUT_NN  NOT NULL,
+  CONSTRAINT TAPE_PK PRIMARY KEY(VID),
+  CONSTRAINT TAPE_LOGICAL_LIBRARY_FK FOREIGN KEY(LOGICAL_LIBRARY_ID) REFERENCES LOGICAL_LIBRARY(LOGICAL_LIBRARY_ID),
+  CONSTRAINT TAPE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),
+  CONSTRAINT TAPE_IS_FULL_BOOL_CK CHECK(IS_FULL IN ('0', '1')),
+  CONSTRAINT TAPE_IS_FROM_CASTOR_BOOL_CK CHECK(IS_FROM_CASTOR IN ('0', '1')),
+  CONSTRAINT TAPE_DIRTY_BOOL_CK CHECK(DIRTY IN ('0','1')),
+  CONSTRAINT TAPE_STATE_CK CHECK(TAPE_STATE IN ('ACTIVE', 'DISABLED', 'BROKEN')),
+  CONSTRAINT TAPE_MEDIA_TYPE_FK FOREIGN KEY(MEDIA_TYPE_ID) REFERENCES MEDIA_TYPE(MEDIA_TYPE_ID)
+);
+CREATE INDEX TAPE_TAPE_POOL_ID_IDX ON TAPE(TAPE_POOL_ID);
+CREATE INDEX TAPE_STATE_IDX ON TAPE(TAPE_STATE);
+CREATE TABLE MOUNT_POLICY(
+  MOUNT_POLICY_NAME          VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_MPN_NN  NOT NULL,
+  ARCHIVE_PRIORITY           NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_AP_NN   NOT NULL,
+  ARCHIVE_MIN_REQUEST_AGE    NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_AMRA_NN NOT NULL,
+  RETRIEVE_PRIORITY          NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_RP_NN   NOT NULL,
+  RETRIEVE_MIN_REQUEST_AGE   NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_RMRA_NN NOT NULL,
+  USER_COMMENT               VARCHAR2(1000)   CONSTRAINT MOUNT_POLICY_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME     VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME     VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME          NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME      VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME      VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME           NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_LUT_NN  NOT NULL,
+  CONSTRAINT MOUNT_POLICY_PK PRIMARY KEY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE REQUESTER_MOUNT_RULE(
+  DISK_INSTANCE_NAME     VARCHAR2(100)    CONSTRAINT RQSTER_RULE_DIN_NN  NOT NULL,
+  REQUESTER_NAME         VARCHAR2(100)    CONSTRAINT RQSTER_RULE_RN_NN   NOT NULL,
+  MOUNT_POLICY_NAME      VARCHAR2(100)    CONSTRAINT RQSTER_RULE_MPN_NN  NOT NULL,
+  USER_COMMENT           VARCHAR2(1000)   CONSTRAINT RQSTER_RULE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR2(100)    CONSTRAINT RQSTER_RULE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR2(100)    CONSTRAINT RQSTER_RULE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      NUMERIC(20, 0)      CONSTRAINT RQSTER_RULE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR2(100)    CONSTRAINT RQSTER_RULE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR2(100)    CONSTRAINT RQSTER_RULE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT RQSTER_RULE_LUT_NN  NOT NULL,
+  CONSTRAINT RQSTER_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_NAME),
+  CONSTRAINT RQSTER_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)
+    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE REQUESTER_GROUP_MOUNT_RULE(
+  DISK_INSTANCE_NAME     VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_DIN_NN  NOT NULL,
+  REQUESTER_GROUP_NAME   VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_RGN_NN  NOT NULL,
+  MOUNT_POLICY_NAME      VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_MPN_NN  NOT NULL,
+  USER_COMMENT           VARCHAR2(1000)   CONSTRAINT RQSTER_GRP_RULE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      NUMERIC(20, 0)      CONSTRAINT RQSTER_GRP_RULE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT RQSTER_GRP_RULE_LUT_NN  NOT NULL,
+  CONSTRAINT RQSTER_GRP_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME),
+  CONSTRAINT RQSTER_GRP_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)
+    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE ARCHIVE_FILE(
+  ARCHIVE_FILE_ID         NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_AFI_NN  NOT NULL,
+  DISK_INSTANCE_NAME      VARCHAR2(100)    CONSTRAINT ARCHIVE_FILE_DIN_NN  NOT NULL,
+  DISK_FILE_ID            VARCHAR2(100)    CONSTRAINT ARCHIVE_FILE_DFI_NN  NOT NULL,
+  DISK_FILE_UID           NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_DFUID_NN  NOT NULL,
+  DISK_FILE_GID           NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_DFGID_NN  NOT NULL,
+  SIZE_IN_BYTES           NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_SIB_NN  NOT NULL,
+  CHECKSUM_BLOB           RAW(200),
+  CHECKSUM_ADLER32        NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_CB2_NN  NOT NULL,
+  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_SCI_NN  NOT NULL,
+  CREATION_TIME           NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_CT2_NN  NOT NULL,
+  RECONCILIATION_TIME     NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_RT_NN   NOT NULL,
+  IS_DELETED              CHAR(1)         DEFAULT '0' CONSTRAINT ARCHIVE_FILE_ID_NN NOT NULL,
+  COLLOCATION_HINT        VARCHAR2(100),
+  CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),
+  CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
+  CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID),
+  CONSTRAINT ARCHIVE_FILE_ID_BOOL_CK CHECK(IS_DELETED IN ('0', '1'))
+);
+CREATE INDEX ARCHIVE_FILE_DIN_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME);
+CREATE INDEX ARCHIVE_FILE_DFI_IDX ON ARCHIVE_FILE(DISK_FILE_ID);
+CREATE TABLE TAPE_FILE(
+  VID                      VARCHAR2(100)   CONSTRAINT TAPE_FILE_V_NN    NOT NULL,
+  FSEQ                     NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_F_NN    NOT NULL,
+  BLOCK_ID                 NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_BI_NN   NOT NULL,
+  LOGICAL_SIZE_IN_BYTES    NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_CSIB_NN NOT NULL,
+  COPY_NB                  NUMERIC(3, 0)      CONSTRAINT TAPE_FILE_CN_NN   NOT NULL,
+  CREATION_TIME            NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_CT_NN   NOT NULL,
+  ARCHIVE_FILE_ID          NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_AFI_NN  NOT NULL,
+  CONSTRAINT TAPE_FILE_PK PRIMARY KEY(VID, FSEQ),
+  CONSTRAINT TAPE_FILE_TAPE_FK FOREIGN KEY(VID)
+    REFERENCES TAPE(VID),
+  CONSTRAINT TAPE_FILE_ARCHIVE_FILE_FK FOREIGN KEY(ARCHIVE_FILE_ID)
+    REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),
+  CONSTRAINT TAPE_FILE_VID_BLOCK_ID_UN UNIQUE(VID, BLOCK_ID),
+  CONSTRAINT TAPE_FILE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0)
+);
+CREATE INDEX TAPE_FILE_VID_IDX ON TAPE_FILE(VID);
+CREATE INDEX TAPE_FILE_ARCHIVE_FILE_ID_IDX ON TAPE_FILE(ARCHIVE_FILE_ID);
+CREATE TABLE ACTIVITIES_WEIGHTS (
+  DISK_INSTANCE_NAME       VARCHAR2(100),
+  ACTIVITY                 VARCHAR2(100),
+  WEIGHT                   VARCHAR2(100),
+  USER_COMMENT             VARCHAR2(1000)   CONSTRAINT ACTIV_WEIGHTS_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME   VARCHAR2(100)    CONSTRAINT ACTIV_WEIGHTS_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME   VARCHAR2(100)    CONSTRAINT ACTIV_WEIGHTS_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME        NUMERIC(20, 0)      CONSTRAINT ACTIV_WEIGHTS_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME    VARCHAR2(100)    CONSTRAINT ACTIV_WEIGHTS_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME    VARCHAR2(100)    CONSTRAINT ACTIV_WEIGHTS_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME         NUMERIC(20, 0)      CONSTRAINT ACTIV_WEIGHTS_LUT_NN  NOT NULL
+);
+CREATE TABLE FILE_RECYCLE_LOG(
+  FILE_RECYCLE_LOG_ID        NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_ID_NN NOT NULL,
+  VID                        VARCHAR2(100)        CONSTRAINT FILE_RECYCLE_LOG_VID_NN NOT NULL,
+  FSEQ                       NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_FSEQ_NN NOT NULL,
+  BLOCK_ID                   NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_BID_NN NOT NULL,
+  COPY_NB                    NUMERIC(3, 0)           CONSTRAINT FILE_RECYCLE_LOG_COPY_NB_NN NOT NULL,
+  TAPE_FILE_CREATION_TIME    NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_TFCT_NN NOT NULL,
+  ARCHIVE_FILE_ID            NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_AFI_NN NOT NULL,
+  DISK_INSTANCE_NAME         VARCHAR2(100)        CONSTRAINT FILE_RECYCLE_LOG_DIN_NN NOT NULL,
+  DISK_FILE_ID               VARCHAR2(100)        CONSTRAINT FILE_RECYCLE_LOG_DFI_NN NOT NULL,
+  DISK_FILE_ID_WHEN_DELETED  VARCHAR2(100)        CONSTRAINT FILE_RECYCLE_LOG_DFIWD_NN NOT NULL,
+  DISK_FILE_UID              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_DFU_NN NOT NULL,
+  DISK_FILE_GID              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_DFG_NN NOT NULL,
+  SIZE_IN_BYTES              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_SIB_NN NOT NULL,
+  CHECKSUM_BLOB              RAW(200),
+  CHECKSUM_ADLER32           NUMERIC(10, 0)          CONSTRAINT FILE_RECYCLE_LOG_CA_NN NOT NULL,
+  STORAGE_CLASS_ID           NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_SCI_NN NOT NULL,
+  ARCHIVE_FILE_CREATION_TIME NUMERIC(20, 0)          CONSTRAINT FILE_RECYLE_LOG_CT_NN NOT NULL,
+  RECONCILIATION_TIME        NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_RT_NN NOT NULL,
+  COLLOCATION_HINT           VARCHAR2(100),
+  DISK_FILE_PATH             VARCHAR2(2000),
+  REASON_LOG                 VARCHAR2(1000)       CONSTRAINT FILE_RECYCLE_LOG_RL_NN NOT NULL,
+  RECYCLE_LOG_TIME           NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_RLT_NN NOT NULL,
+  CONSTRAINT FILE_RECYCLE_LOG_PK PRIMARY KEY(FILE_RECYCLE_LOG_ID),
+  CONSTRAINT FILE_RECYCLE_LOG_VID_FK FOREIGN KEY(VID) REFERENCES TAPE(VID),
+  CONSTRAINT FILE_RECYCLE_LOG_SC_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID)
+);
+CREATE INDEX FILE_RECYCLE_LOG_DFI_IDX ON FILE_RECYCLE_LOG(DISK_FILE_ID);
+
+CREATE TABLE DRIVE_CONFIG (
+  DRIVE_NAME                  VARCHAR2(100)       CONSTRAINT DRIVE_CONFIG_DN_NN  NOT NULL,
+  CATEGORY                    VARCHAR2(100)       CONSTRAINT DRIVE_CONFIG_C_NN   NOT NULL,
+  KEY_NAME                    VARCHAR2(100)       CONSTRAINT DRIVE_CONFIG_KN_NN  NOT NULL,
+  VALUE                       VARCHAR2(1000)      CONSTRAINT DRIVE_CONFIG_V_NN   NOT NULL,
+  SOURCE                      VARCHAR2(100)       CONSTRAINT DRIVE_CONFIG_S_NN   NOT NULL,
+  CONSTRAINT DRIVE_CONFIG_DN_PK PRIMARY KEY(KEY_NAME, DRIVE_NAME)
+);
+
+CREATE TABLE TAPE_DRIVE (
+  DRIVE_NAME                  VARCHAR2(100)       CONSTRAINT DRIVE_STATE_DN_NN NOT NULL,
+  HOST                        VARCHAR2(100)       CONSTRAINT DRIVE_STATE_H_NN  NOT NULL,
+  LOGICAL_LIBRARY             VARCHAR2(100)       CONSTRAINT DRIVE_STATE_LL_NN NOT NULL,
+  SESSION_ID                  NUMERIC(20, 0),
+  BYTES_TRANSFERED_IN_SESSION NUMERIC(20, 0),
+  FILES_TRANSFERED_IN_SESSION NUMERIC(20, 0),
+  LATEST_BANDWIDTH            VARCHAR2(100),
+  SESSION_START_TIME          NUMERIC(20, 0),
+  MOUNT_START_TIME            NUMERIC(20, 0),
+  TRANSFER_START_TIME         NUMERIC(20, 0),
+  UNLOAD_START_TIME           NUMERIC(20, 0),
+  UNMOUNT_START_TIME          NUMERIC(20, 0),
+  DRAINING_START_TIME         NUMERIC(20, 0),
+  DOWN_OR_UP_START_TIME       NUMERIC(20, 0),
+  PROBE_START_TIME            NUMERIC(20, 0),
+  CLEANUP_START_TIME          NUMERIC(20, 0),
+  START_START_TIME            NUMERIC(20, 0),
+  SHUTDOWN_TIME               NUMERIC(20, 0),
+  MOUNT_TYPE                  NUMERIC(10, 0)      CONSTRAINT DRIVE_STATE_MT_NN NOT NULL,
+  DRIVE_STATUS                VARCHAR2(100)    DEFAULT 'UNKNOWN' CONSTRAINT DRIVE_STATE_DS_NN NOT NULL,
+  DESIRED_UP                  CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DU_NN  NOT NULL,
+  DESIRED_FORCE_DOWN          CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DFD_NN NOT NULL,
+  REASON_UP_DOWN              VARCHAR2(1000),
+  CURRENT_VID                 VARCHAR2(100),
+  CTA_VERSION                 VARCHAR2(100),
+  CURRENT_PRIORITY            NUMERIC(20, 0),
+  CURRENT_ACTIVITY            VARCHAR2(100),
+  CURRENT_ACTIVITY_WEIGHT     VARCHAR2(100),
+  CURRENT_TAPE_POOL           VARCHAR2(100),
+  NEXT_MOUNT_TYPE             NUMERIC(10, 0),
+  NEXT_VID                    VARCHAR2(100),
+  NEXT_TAPE_POOL              VARCHAR2(100),
+  NEXT_PRIORITY               NUMERIC(20, 0),
+  NEXT_ACTIVITY               VARCHAR2(100),
+  NEXT_ACTIVITY_WEIGHT        VARCHAR2(100),
+  DEV_FILE_NAME               VARCHAR2(100),
+  RAW_LIBRARY_SLOT            VARCHAR2(100),
+  CURRENT_VO                  VARCHAR2(100),
+  NEXT_VO                     VARCHAR2(100),
+  USER_COMMENT                VARCHAR2(1000),
+  CREATION_LOG_USER_NAME      VARCHAR2(100),
+  CREATION_LOG_HOST_NAME      VARCHAR2(100),
+  CREATION_LOG_TIME           NUMERIC(20, 0),
+  LAST_UPDATE_USER_NAME       VARCHAR2(100),
+  LAST_UPDATE_HOST_NAME       VARCHAR2(100),
+  LAST_UPDATE_TIME            NUMERIC(20, 0),
+  DISK_SYSTEM_NAME            VARCHAR2(100)       CONSTRAINT DRIVE_STATE_DSN_NN NOT NULL,
+  RESERVED_BYTES              NUMERIC(20, 0)         CONSTRAINT DRIVE_STATE_RB_NN  NOT NULL,
+  CONSTRAINT DRIVE_STATE_DN_PK PRIMARY KEY(DRIVE_NAME),
+  CONSTRAINT DRIVE_STATE_DU_BOOL_CK CHECK(DESIRED_UP IN ('0', '1')),
+  CONSTRAINT DRIVE_STATE_DFD_BOOL_CK CHECK(DESIRED_FORCE_DOWN IN ('0', '1')),
+  CONSTRAINT DRIVE_STATE_DS_STRING_CK CHECK(DRIVE_STATUS IN ('DOWN', 'UP', 'PROBING', 'STARTING',
+  'MOUNTING', 'TRANSFERING', 'UNLOADING', 'UNMOUNTING', 'DRAININGTODISK', 'CLEANINGUP', 'SHUTDOWN',
+  'UNKNOWN'))
+);
+INSERT INTO CTA_CATALOGUE(
+  SCHEMA_VERSION_MAJOR,
+  SCHEMA_VERSION_MINOR,
+  STATUS)
+VALUES(
+  4,
+  2,
+  'PRODUCTION');
+ALTER TABLE CTA_CATALOGUE ADD CONSTRAINT CATALOGUE_STATUS_CONTENT_CK CHECK((NEXT_SCHEMA_VERSION_MAJOR IS NULL AND NEXT_SCHEMA_VERSION_MINOR IS NULL AND STATUS='PRODUCTION') OR (NEXT_SCHEMA_VERSION_MAJOR IS NOT NULL AND NEXT_SCHEMA_VERSION_MINOR IS NOT NULL AND STATUS='UPGRADING')) INITIALLY DEFERRED;
+
+COMMIT;
diff --git a/catalogue/4.2/postgres_catalogue_schema.sql b/catalogue/4.2/postgres_catalogue_schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..fcd0ab2f91a54fcc388ba9a6c323114692ad7dc7
--- /dev/null
+++ b/catalogue/4.2/postgres_catalogue_schema.sql
@@ -0,0 +1,440 @@
+CREATE SEQUENCE ARCHIVE_FILE_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NO MAXVALUE
+  MINVALUE 1
+  NO CYCLE
+  CACHE 20;
+CREATE SEQUENCE LOGICAL_LIBRARY_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NO MAXVALUE
+  MINVALUE 1
+  NO CYCLE
+  CACHE 20;
+CREATE SEQUENCE MEDIA_TYPE_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NO MAXVALUE
+  MINVALUE 1
+  NO CYCLE
+  CACHE 20;
+CREATE SEQUENCE STORAGE_CLASS_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NO MAXVALUE
+  MINVALUE 1
+  NO CYCLE
+  CACHE 20;
+CREATE SEQUENCE TAPE_POOL_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NO MAXVALUE
+  MINVALUE 1
+  NO CYCLE
+  CACHE 20;
+CREATE SEQUENCE VIRTUAL_ORGANIZATION_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NO MAXVALUE
+  MINVALUE 1
+  NO CYCLE
+  CACHE 20;
+CREATE SEQUENCE FILE_RECYCLE_LOG_ID_SEQ
+  INCREMENT BY 1
+  START WITH 1
+  NO MAXVALUE
+  MINVALUE 1
+  NO CYCLE
+  CACHE 20;
+CREATE TABLE CTA_CATALOGUE(
+  SCHEMA_VERSION_MAJOR    NUMERIC(20, 0)      CONSTRAINT CTA_CATALOGUE_SVM1_NN NOT NULL,
+  SCHEMA_VERSION_MINOR    NUMERIC(20, 0)      CONSTRAINT CTA_CATALOGUE_SVM2_NN NOT NULL,
+  NEXT_SCHEMA_VERSION_MAJOR NUMERIC(20, 0),
+  NEXT_SCHEMA_VERSION_MINOR NUMERIC(20, 0),
+  STATUS                  VARCHAR(100),
+  IS_PRODUCTION           CHAR(1)         DEFAULT '0' CONSTRAINT CTA_CATALOGUE_IP_NN NOT NULL,
+  CONSTRAINT CTA_CATALOGUE_IP_BOOL_CK     CHECK(IS_PRODUCTION IN ('0','1'))
+);
+CREATE TABLE ADMIN_USER(
+  ADMIN_USER_NAME         VARCHAR(100)    CONSTRAINT ADMIN_USER_AUN_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ADMIN_USER_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT ADMIN_USER_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,
+  CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)
+);
+CREATE TABLE DISK_SYSTEM(
+  DISK_SYSTEM_NAME        VARCHAR(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,
+  FILE_REGEXP             VARCHAR(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,
+  FREE_SPACE_QUERY_URL    VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,
+  REFRESH_INTERVAL        NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,
+  TARGETED_FREE_SPACE     NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,
+  SLEEP_TIME              NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_ST_NN   NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,
+  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)
+);
+CREATE TABLE VIRTUAL_ORGANIZATION(
+  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_VOI_NN  NOT NULL,
+  VIRTUAL_ORGANIZATION_NAME VARCHAR(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,
+  READ_MAX_DRIVES NUMERIC(20, 0)              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,
+  WRITE_MAX_DRIVES NUMERIC(20, 0)             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,
+  MAX_FILE_SIZE NUMERIC(20, 0)                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_LUT_NN  NOT NULL,
+  CONSTRAINT VIRTUAL_ORGANIZATION_PK PRIMARY KEY(VIRTUAL_ORGANIZATION_ID),
+  CONSTRAINT VIRTUAL_ORGANIZATION_VON_UN UNIQUE(VIRTUAL_ORGANIZATION_NAME)
+);
+CREATE TABLE STORAGE_CLASS(
+  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,
+  STORAGE_CLASS_NAME      VARCHAR(100)    CONSTRAINT STORAGE_CLASS_SCN_NN  NOT NULL,
+  NB_COPIES               NUMERIC(3, 0)       CONSTRAINT STORAGE_CLASS_NC_NN   NOT NULL,
+  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_VOI_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT STORAGE_CLASS_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_LUT_NN  NOT NULL,
+  CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),
+  CONSTRAINT STORAGE_CLASS_SCN_UN UNIQUE(STORAGE_CLASS_NAME),
+  CONSTRAINT STORAGE_CLASS_VOI_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)
+);
+CREATE TABLE TAPE_POOL(
+  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_TPI_NN  NOT NULL,
+  TAPE_POOL_NAME          VARCHAR(100)    CONSTRAINT TAPE_POOL_TPN_NN  NOT NULL,
+  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_VOI_NN  NOT NULL,
+  NB_PARTIAL_TAPES        NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_NPT_NN  NOT NULL,
+  IS_ENCRYPTED            CHAR(1)         CONSTRAINT TAPE_POOL_IE_NN   NOT NULL,
+  SUPPLY                  VARCHAR(100),
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT TAPE_POOL_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_LUT_NN  NOT NULL,
+  CONSTRAINT TAPE_POOL_PK PRIMARY KEY(TAPE_POOL_ID),
+  CONSTRAINT TAPE_POOL_TPN_UN UNIQUE(TAPE_POOL_NAME),
+  CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN ('0', '1')),
+  CONSTRAINT TAPE_POOL_VO_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)
+);
+CREATE TABLE ARCHIVE_ROUTE(
+  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_SCI_NN  NOT NULL,
+  COPY_NB                 NUMERIC(3, 0)       CONSTRAINT ARCHIVE_ROUTE_CN_NN   NOT NULL,
+  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_TPI_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ARCHIVE_ROUTE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_LUT_NN  NOT NULL,
+  CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(STORAGE_CLASS_ID, COPY_NB),
+  CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
+  CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),
+  CONSTRAINT ARCHIVE_ROUTE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0),
+  CONSTRAINT ARCHIVE_ROUTE_SCI_TPI_UN UNIQUE(STORAGE_CLASS_ID, TAPE_POOL_ID)
+);
+CREATE TABLE MEDIA_TYPE(
+  MEDIA_TYPE_ID          NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_MTI_NN  NOT NULL,
+  MEDIA_TYPE_NAME        VARCHAR(100)  CONSTRAINT MEDIA_TYPE_MTN_NN  NOT NULL,
+  CARTRIDGE              VARCHAR(100)  CONSTRAINT MEDIA_TYPE_C_NN    NOT NULL,
+  CAPACITY_IN_BYTES      NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_CIB_NN  NOT NULL,
+  PRIMARY_DENSITY_CODE   NUMERIC(3, 0),
+  SECONDARY_DENSITY_CODE NUMERIC(3, 0),
+  NB_WRAPS               NUMERIC(10, 0),
+  MIN_LPOS               NUMERIC(20, 0),
+  MAX_LPOS               NUMERIC(20, 0),
+  USER_COMMENT           VARCHAR(1000) CONSTRAINT MEDIA_TYPE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_LUT_NN  NOT NULL,
+  CONSTRAINT MEDIA_TYPE_PK PRIMARY KEY(MEDIA_TYPE_ID),
+  CONSTRAINT MEDIA_TYPE_MTN_UN UNIQUE(MEDIA_TYPE_NAME)
+);
+CREATE TABLE LOGICAL_LIBRARY(
+  LOGICAL_LIBRARY_ID      NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_LLI_NN  NOT NULL,
+  LOGICAL_LIBRARY_NAME    VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LLN_NN  NOT NULL,
+  IS_DISABLED             CHAR(1)         DEFAULT '0' CONSTRAINT LOGICAL_LIBRARY_ID_NN NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT LOGICAL_LIBRARY_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_LUT_NN  NOT NULL,
+  CONSTRAINT LOGICAL_LIBRARY_PK PRIMARY KEY(LOGICAL_LIBRARY_ID),
+  CONSTRAINT LOGICAL_LIBRARY_LLN_UN UNIQUE(LOGICAL_LIBRARY_NAME),
+  CONSTRAINT LOGICAL_LIBRARY_ID_BOOL_CK CHECK(IS_DISABLED IN ('0', '1'))
+);
+CREATE TABLE TAPE(
+  VID                     VARCHAR(100)    CONSTRAINT TAPE_V_NN    NOT NULL,
+  MEDIA_TYPE_ID           NUMERIC(20, 0)      CONSTRAINT TAPE_MTID_NN   NOT NULL,
+  VENDOR                  VARCHAR(100)    CONSTRAINT TAPE_V2_NN   NOT NULL,
+  LOGICAL_LIBRARY_ID      NUMERIC(20, 0)      CONSTRAINT TAPE_LLI_NN  NOT NULL,
+  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT TAPE_TPI_NN  NOT NULL,
+  ENCRYPTION_KEY_NAME     VARCHAR(100),
+  DATA_IN_BYTES           NUMERIC(20, 0)      CONSTRAINT TAPE_DIB_NN  NOT NULL,
+  LAST_FSEQ               NUMERIC(20, 0)      CONSTRAINT TAPE_LF_NN   NOT NULL,
+  NB_MASTER_FILES         NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_NB_MASTER_FILES_NN NOT NULL,
+  MASTER_DATA_IN_BYTES    NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_MASTER_DATA_IN_BYTES_NN NOT NULL,
+  IS_FULL                 CHAR(1)         CONSTRAINT TAPE_IF_NN   NOT NULL,
+  IS_FROM_CASTOR          CHAR(1)         CONSTRAINT TAPE_IFC_NN  NOT NULL,
+  DIRTY                   CHAR(1)         DEFAULT '1' CONSTRAINT TAPE_DIRTY_NN NOT NULL,
+  NB_COPY_NB_1            NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_1_NN NOT NULL,
+  COPY_NB_1_IN_BYTES      NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_1_IN_BYTES_NN NOT NULL,
+  NB_COPY_NB_GT_1         NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_GT_1_NN NOT NULL,
+  COPY_NB_GT_1_IN_BYTES   NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_GT_1_IN_BYTES_NN NOT NULL,
+  LABEL_DRIVE             VARCHAR(100),
+  LABEL_TIME              NUMERIC(20, 0)    ,
+  LAST_READ_DRIVE         VARCHAR(100),
+  LAST_READ_TIME          NUMERIC(20, 0)    ,
+  LAST_WRITE_DRIVE        VARCHAR(100),
+  LAST_WRITE_TIME         NUMERIC(20, 0)    ,
+  READ_MOUNT_COUNT        NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_RMC_NN NOT NULL,
+  WRITE_MOUNT_COUNT       NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_WMC_NN NOT NULL,
+  USER_COMMENT            VARCHAR(1000),
+  TAPE_STATE              VARCHAR(100)    CONSTRAINT TAPE_TS_NN NOT NULL,
+  STATE_REASON            VARCHAR(1000),
+  STATE_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_SUT_NN NOT NULL,
+  STATE_MODIFIED_BY       VARCHAR(100)    CONSTRAINT TAPE_SMB_NN NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT TAPE_LUT_NN  NOT NULL,
+  CONSTRAINT TAPE_PK PRIMARY KEY(VID),
+  CONSTRAINT TAPE_LOGICAL_LIBRARY_FK FOREIGN KEY(LOGICAL_LIBRARY_ID) REFERENCES LOGICAL_LIBRARY(LOGICAL_LIBRARY_ID),
+  CONSTRAINT TAPE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),
+  CONSTRAINT TAPE_IS_FULL_BOOL_CK CHECK(IS_FULL IN ('0', '1')),
+  CONSTRAINT TAPE_IS_FROM_CASTOR_BOOL_CK CHECK(IS_FROM_CASTOR IN ('0', '1')),
+  CONSTRAINT TAPE_DIRTY_BOOL_CK CHECK(DIRTY IN ('0','1')),
+  CONSTRAINT TAPE_STATE_CK CHECK(TAPE_STATE IN ('ACTIVE', 'DISABLED', 'BROKEN')),
+  CONSTRAINT TAPE_MEDIA_TYPE_FK FOREIGN KEY(MEDIA_TYPE_ID) REFERENCES MEDIA_TYPE(MEDIA_TYPE_ID)
+);
+CREATE INDEX TAPE_TAPE_POOL_ID_IDX ON TAPE(TAPE_POOL_ID);
+CREATE INDEX TAPE_STATE_IDX ON TAPE(TAPE_STATE);
+CREATE TABLE MOUNT_POLICY(
+  MOUNT_POLICY_NAME          VARCHAR(100)    CONSTRAINT MOUNT_POLICY_MPN_NN  NOT NULL,
+  ARCHIVE_PRIORITY           NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_AP_NN   NOT NULL,
+  ARCHIVE_MIN_REQUEST_AGE    NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_AMRA_NN NOT NULL,
+  RETRIEVE_PRIORITY          NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_RP_NN   NOT NULL,
+  RETRIEVE_MIN_REQUEST_AGE   NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_RMRA_NN NOT NULL,
+  USER_COMMENT               VARCHAR(1000)   CONSTRAINT MOUNT_POLICY_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME          NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME           NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_LUT_NN  NOT NULL,
+  CONSTRAINT MOUNT_POLICY_PK PRIMARY KEY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE REQUESTER_MOUNT_RULE(
+  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_RULE_DIN_NN  NOT NULL,
+  REQUESTER_NAME         VARCHAR(100)    CONSTRAINT RQSTER_RULE_RN_NN   NOT NULL,
+  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_RULE_MPN_NN  NOT NULL,
+  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_RULE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      NUMERIC(20, 0)      CONSTRAINT RQSTER_RULE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT RQSTER_RULE_LUT_NN  NOT NULL,
+  CONSTRAINT RQSTER_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_NAME),
+  CONSTRAINT RQSTER_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)
+    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE REQUESTER_GROUP_MOUNT_RULE(
+  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_DIN_NN  NOT NULL,
+  REQUESTER_GROUP_NAME   VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_RGN_NN  NOT NULL,
+  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_MPN_NN  NOT NULL,
+  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_GRP_RULE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      NUMERIC(20, 0)      CONSTRAINT RQSTER_GRP_RULE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT RQSTER_GRP_RULE_LUT_NN  NOT NULL,
+  CONSTRAINT RQSTER_GRP_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME),
+  CONSTRAINT RQSTER_GRP_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)
+    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE ARCHIVE_FILE(
+  ARCHIVE_FILE_ID         NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_AFI_NN  NOT NULL,
+  DISK_INSTANCE_NAME      VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DIN_NN  NOT NULL,
+  DISK_FILE_ID            VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DFI_NN  NOT NULL,
+  DISK_FILE_UID           NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_DFUID_NN  NOT NULL,
+  DISK_FILE_GID           NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_DFGID_NN  NOT NULL,
+  SIZE_IN_BYTES           NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_SIB_NN  NOT NULL,
+  CHECKSUM_BLOB           BYTEA,
+  CHECKSUM_ADLER32        NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_CB2_NN  NOT NULL,
+  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_SCI_NN  NOT NULL,
+  CREATION_TIME           NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_CT2_NN  NOT NULL,
+  RECONCILIATION_TIME     NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_RT_NN   NOT NULL,
+  IS_DELETED              CHAR(1)         DEFAULT '0' CONSTRAINT ARCHIVE_FILE_ID_NN NOT NULL,
+  COLLOCATION_HINT        VARCHAR(100),
+  CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),
+  CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
+  CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID),
+  CONSTRAINT ARCHIVE_FILE_ID_BOOL_CK CHECK(IS_DELETED IN ('0', '1'))
+);
+CREATE INDEX ARCHIVE_FILE_DIN_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME);
+CREATE INDEX ARCHIVE_FILE_DFI_IDX ON ARCHIVE_FILE(DISK_FILE_ID);
+CREATE TABLE TAPE_FILE(
+  VID                      VARCHAR(100)   CONSTRAINT TAPE_FILE_V_NN    NOT NULL,
+  FSEQ                     NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_F_NN    NOT NULL,
+  BLOCK_ID                 NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_BI_NN   NOT NULL,
+  LOGICAL_SIZE_IN_BYTES    NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_CSIB_NN NOT NULL,
+  COPY_NB                  NUMERIC(3, 0)      CONSTRAINT TAPE_FILE_CN_NN   NOT NULL,
+  CREATION_TIME            NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_CT_NN   NOT NULL,
+  ARCHIVE_FILE_ID          NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_AFI_NN  NOT NULL,
+  CONSTRAINT TAPE_FILE_PK PRIMARY KEY(VID, FSEQ),
+  CONSTRAINT TAPE_FILE_TAPE_FK FOREIGN KEY(VID)
+    REFERENCES TAPE(VID),
+  CONSTRAINT TAPE_FILE_ARCHIVE_FILE_FK FOREIGN KEY(ARCHIVE_FILE_ID)
+    REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),
+  CONSTRAINT TAPE_FILE_VID_BLOCK_ID_UN UNIQUE(VID, BLOCK_ID),
+  CONSTRAINT TAPE_FILE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0)
+);
+CREATE INDEX TAPE_FILE_VID_IDX ON TAPE_FILE(VID);
+CREATE INDEX TAPE_FILE_ARCHIVE_FILE_ID_IDX ON TAPE_FILE(ARCHIVE_FILE_ID);
+CREATE TABLE ACTIVITIES_WEIGHTS (
+  DISK_INSTANCE_NAME       VARCHAR(100),
+  ACTIVITY                 VARCHAR(100),
+  WEIGHT                   VARCHAR(100),
+  USER_COMMENT             VARCHAR(1000)   CONSTRAINT ACTIV_WEIGHTS_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME        NUMERIC(20, 0)      CONSTRAINT ACTIV_WEIGHTS_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME         NUMERIC(20, 0)      CONSTRAINT ACTIV_WEIGHTS_LUT_NN  NOT NULL
+);
+CREATE TABLE FILE_RECYCLE_LOG(
+  FILE_RECYCLE_LOG_ID        NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_ID_NN NOT NULL,
+  VID                        VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_VID_NN NOT NULL,
+  FSEQ                       NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_FSEQ_NN NOT NULL,
+  BLOCK_ID                   NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_BID_NN NOT NULL,
+  COPY_NB                    NUMERIC(3, 0)           CONSTRAINT FILE_RECYCLE_LOG_COPY_NB_NN NOT NULL,
+  TAPE_FILE_CREATION_TIME    NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_TFCT_NN NOT NULL,
+  ARCHIVE_FILE_ID            NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_AFI_NN NOT NULL,
+  DISK_INSTANCE_NAME         VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DIN_NN NOT NULL,
+  DISK_FILE_ID               VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFI_NN NOT NULL,
+  DISK_FILE_ID_WHEN_DELETED  VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFIWD_NN NOT NULL,
+  DISK_FILE_UID              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_DFU_NN NOT NULL,
+  DISK_FILE_GID              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_DFG_NN NOT NULL,
+  SIZE_IN_BYTES              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_SIB_NN NOT NULL,
+  CHECKSUM_BLOB              BYTEA,
+  CHECKSUM_ADLER32           NUMERIC(10, 0)          CONSTRAINT FILE_RECYCLE_LOG_CA_NN NOT NULL,
+  STORAGE_CLASS_ID           NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_SCI_NN NOT NULL,
+  ARCHIVE_FILE_CREATION_TIME NUMERIC(20, 0)          CONSTRAINT FILE_RECYLE_LOG_CT_NN NOT NULL,
+  RECONCILIATION_TIME        NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_RT_NN NOT NULL,
+  COLLOCATION_HINT           VARCHAR(100),
+  DISK_FILE_PATH             VARCHAR(2000),
+  REASON_LOG                 VARCHAR(1000)       CONSTRAINT FILE_RECYCLE_LOG_RL_NN NOT NULL,
+  RECYCLE_LOG_TIME           NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_RLT_NN NOT NULL,
+  CONSTRAINT FILE_RECYCLE_LOG_PK PRIMARY KEY(FILE_RECYCLE_LOG_ID),
+  CONSTRAINT FILE_RECYCLE_LOG_VID_FK FOREIGN KEY(VID) REFERENCES TAPE(VID),
+  CONSTRAINT FILE_RECYCLE_LOG_SC_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID)
+);
+CREATE INDEX FILE_RECYCLE_LOG_DFI_IDX ON FILE_RECYCLE_LOG(DISK_FILE_ID);
+
+CREATE TABLE DRIVE_CONFIG (
+  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_DN_NN  NOT NULL,
+  CATEGORY                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_C_NN   NOT NULL,
+  KEY_NAME                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_KN_NN  NOT NULL,
+  VALUE                       VARCHAR(1000)      CONSTRAINT DRIVE_CONFIG_V_NN   NOT NULL,
+  SOURCE                      VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_S_NN   NOT NULL,
+  CONSTRAINT DRIVE_CONFIG_DN_PK PRIMARY KEY(KEY_NAME, DRIVE_NAME)
+);
+
+CREATE TABLE TAPE_DRIVE (
+  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_STATE_DN_NN NOT NULL,
+  HOST                        VARCHAR(100)       CONSTRAINT DRIVE_STATE_H_NN  NOT NULL,
+  LOGICAL_LIBRARY             VARCHAR(100)       CONSTRAINT DRIVE_STATE_LL_NN NOT NULL,
+  SESSION_ID                  NUMERIC(20, 0),
+  BYTES_TRANSFERED_IN_SESSION NUMERIC(20, 0),
+  FILES_TRANSFERED_IN_SESSION NUMERIC(20, 0),
+  LATEST_BANDWIDTH            VARCHAR(100),
+  SESSION_START_TIME          NUMERIC(20, 0),
+  MOUNT_START_TIME            NUMERIC(20, 0),
+  TRANSFER_START_TIME         NUMERIC(20, 0),
+  UNLOAD_START_TIME           NUMERIC(20, 0),
+  UNMOUNT_START_TIME          NUMERIC(20, 0),
+  DRAINING_START_TIME         NUMERIC(20, 0),
+  DOWN_OR_UP_START_TIME       NUMERIC(20, 0),
+  PROBE_START_TIME            NUMERIC(20, 0),
+  CLEANUP_START_TIME          NUMERIC(20, 0),
+  START_START_TIME            NUMERIC(20, 0),
+  SHUTDOWN_TIME               NUMERIC(20, 0),
+  MOUNT_TYPE                  NUMERIC(10, 0)      CONSTRAINT DRIVE_STATE_MT_NN NOT NULL,
+  DRIVE_STATUS                VARCHAR(100)    DEFAULT 'UNKNOWN' CONSTRAINT DRIVE_STATE_DS_NN NOT NULL,
+  DESIRED_UP                  CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DU_NN  NOT NULL,
+  DESIRED_FORCE_DOWN          CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DFD_NN NOT NULL,
+  REASON_UP_DOWN              VARCHAR(1000),
+  CURRENT_VID                 VARCHAR(100),
+  CTA_VERSION                 VARCHAR(100),
+  CURRENT_PRIORITY            NUMERIC(20, 0),
+  CURRENT_ACTIVITY            VARCHAR(100),
+  CURRENT_ACTIVITY_WEIGHT     VARCHAR(100),
+  CURRENT_TAPE_POOL           VARCHAR(100),
+  NEXT_MOUNT_TYPE             NUMERIC(10, 0),
+  NEXT_VID                    VARCHAR(100),
+  NEXT_TAPE_POOL              VARCHAR(100),
+  NEXT_PRIORITY               NUMERIC(20, 0),
+  NEXT_ACTIVITY               VARCHAR(100),
+  NEXT_ACTIVITY_WEIGHT        VARCHAR(100),
+  DEV_FILE_NAME               VARCHAR(100),
+  RAW_LIBRARY_SLOT            VARCHAR(100),
+  CURRENT_VO                  VARCHAR(100),
+  NEXT_VO                     VARCHAR(100),
+  USER_COMMENT                VARCHAR(1000),
+  CREATION_LOG_USER_NAME      VARCHAR(100),
+  CREATION_LOG_HOST_NAME      VARCHAR(100),
+  CREATION_LOG_TIME           NUMERIC(20, 0),
+  LAST_UPDATE_USER_NAME       VARCHAR(100),
+  LAST_UPDATE_HOST_NAME       VARCHAR(100),
+  LAST_UPDATE_TIME            NUMERIC(20, 0),
+  DISK_SYSTEM_NAME            VARCHAR(100)       CONSTRAINT DRIVE_STATE_DSN_NN NOT NULL,
+  RESERVED_BYTES              NUMERIC(20, 0)         CONSTRAINT DRIVE_STATE_RB_NN  NOT NULL,
+  CONSTRAINT DRIVE_STATE_DN_PK PRIMARY KEY(DRIVE_NAME),
+  CONSTRAINT DRIVE_STATE_DU_BOOL_CK CHECK(DESIRED_UP IN ('0', '1')),
+  CONSTRAINT DRIVE_STATE_DFD_BOOL_CK CHECK(DESIRED_FORCE_DOWN IN ('0', '1')),
+  CONSTRAINT DRIVE_STATE_DS_STRING_CK CHECK(DRIVE_STATUS IN ('DOWN', 'UP', 'PROBING', 'STARTING',
+  'MOUNTING', 'TRANSFERING', 'UNLOADING', 'UNMOUNTING', 'DRAININGTODISK', 'CLEANINGUP', 'SHUTDOWN',
+  'UNKNOWN'))
+);
+INSERT INTO CTA_CATALOGUE(
+  SCHEMA_VERSION_MAJOR,
+  SCHEMA_VERSION_MINOR,
+  STATUS)
+VALUES(
+  4,
+  2,
+  'PRODUCTION');
+ALTER TABLE ARCHIVE_FILE DROP CONSTRAINT
+  ARCHIVE_FILE_DIN_DFI_UN;
+ALTER TABLE ARCHIVE_FILE ADD CONSTRAINT
+  ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID) DEFERRABLE INITIALLY IMMEDIATE;
+ALTER TABLE CTA_CATALOGUE ADD CONSTRAINT
+  CATALOGUE_STATUS_CONTENT_CK CHECK((NEXT_SCHEMA_VERSION_MAJOR IS NULL AND NEXT_SCHEMA_VERSION_MINOR IS NULL AND STATUS='PRODUCTION') OR (STATUS='UPGRADING'));
diff --git a/catalogue/4.2/sqlite_catalogue_schema.sql b/catalogue/4.2/sqlite_catalogue_schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..43ab44ccccf9a52265114bd7e1ea7164d222225b
--- /dev/null
+++ b/catalogue/4.2/sqlite_catalogue_schema.sql
@@ -0,0 +1,406 @@
+CREATE TABLE ARCHIVE_FILE_ID(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT
+);
+CREATE TABLE LOGICAL_LIBRARY_ID(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT
+);
+CREATE TABLE MEDIA_TYPE_ID(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT
+);
+CREATE TABLE STORAGE_CLASS_ID(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT
+);
+CREATE TABLE TAPE_POOL_ID(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT
+);
+CREATE TABLE VIRTUAL_ORGANIZATION_ID(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT
+);
+CREATE TABLE FILE_RECYCLE_LOG_ID(
+  ID INTEGER PRIMARY KEY AUTOINCREMENT
+);
+CREATE TABLE CTA_CATALOGUE(
+  SCHEMA_VERSION_MAJOR    INTEGER      CONSTRAINT CTA_CATALOGUE_SVM1_NN NOT NULL,
+  SCHEMA_VERSION_MINOR    INTEGER      CONSTRAINT CTA_CATALOGUE_SVM2_NN NOT NULL,
+  NEXT_SCHEMA_VERSION_MAJOR INTEGER,
+  NEXT_SCHEMA_VERSION_MINOR INTEGER,
+  STATUS                  VARCHAR(100),
+  IS_PRODUCTION           CHAR(1)         DEFAULT '0' CONSTRAINT CTA_CATALOGUE_IP_NN NOT NULL,
+  CONSTRAINT CTA_CATALOGUE_IP_BOOL_CK     CHECK(IS_PRODUCTION IN ('0','1'))
+);
+CREATE TABLE ADMIN_USER(
+  ADMIN_USER_NAME         VARCHAR(100)    CONSTRAINT ADMIN_USER_AUN_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ADMIN_USER_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       INTEGER      CONSTRAINT ADMIN_USER_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        INTEGER      CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,
+  CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)
+);
+CREATE TABLE DISK_SYSTEM(
+  DISK_SYSTEM_NAME        VARCHAR(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,
+  FILE_REGEXP             VARCHAR(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,
+  FREE_SPACE_QUERY_URL    VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,
+  REFRESH_INTERVAL        INTEGER      CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,
+  TARGETED_FREE_SPACE     INTEGER      CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,
+  SLEEP_TIME              INTEGER      CONSTRAINT DISK_SYSTEM_ST_NN   NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       INTEGER      CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        INTEGER      CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,
+  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)
+);
+CREATE TABLE VIRTUAL_ORGANIZATION(
+  VIRTUAL_ORGANIZATION_ID INTEGER      CONSTRAINT VIRTUAL_ORGANIZATION_VOI_NN  NOT NULL,
+  VIRTUAL_ORGANIZATION_NAME VARCHAR(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,
+  READ_MAX_DRIVES INTEGER              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,
+  WRITE_MAX_DRIVES INTEGER             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,
+  MAX_FILE_SIZE INTEGER                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       INTEGER      CONSTRAINT VIRTUAL_ORGANIZATION_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        INTEGER      CONSTRAINT VIRTUAL_ORGANIZATION_LUT_NN  NOT NULL,
+  CONSTRAINT VIRTUAL_ORGANIZATION_PK PRIMARY KEY(VIRTUAL_ORGANIZATION_ID),
+  CONSTRAINT VIRTUAL_ORGANIZATION_VON_UN UNIQUE(VIRTUAL_ORGANIZATION_NAME)
+);
+CREATE TABLE STORAGE_CLASS(
+  STORAGE_CLASS_ID        INTEGER      CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,
+  STORAGE_CLASS_NAME      VARCHAR(100)    CONSTRAINT STORAGE_CLASS_SCN_NN  NOT NULL,
+  NB_COPIES               INTEGER       CONSTRAINT STORAGE_CLASS_NC_NN   NOT NULL,
+  VIRTUAL_ORGANIZATION_ID INTEGER      CONSTRAINT STORAGE_CLASS_VOI_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT STORAGE_CLASS_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       INTEGER      CONSTRAINT STORAGE_CLASS_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        INTEGER      CONSTRAINT STORAGE_CLASS_LUT_NN  NOT NULL,
+  CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),
+  CONSTRAINT STORAGE_CLASS_SCN_UN UNIQUE(STORAGE_CLASS_NAME),
+  CONSTRAINT STORAGE_CLASS_VOI_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)
+);
+CREATE TABLE TAPE_POOL(
+  TAPE_POOL_ID            INTEGER      CONSTRAINT TAPE_POOL_TPI_NN  NOT NULL,
+  TAPE_POOL_NAME          VARCHAR(100)    CONSTRAINT TAPE_POOL_TPN_NN  NOT NULL,
+  VIRTUAL_ORGANIZATION_ID INTEGER      CONSTRAINT TAPE_POOL_VOI_NN  NOT NULL,
+  NB_PARTIAL_TAPES        INTEGER      CONSTRAINT TAPE_POOL_NPT_NN  NOT NULL,
+  IS_ENCRYPTED            CHAR(1)         CONSTRAINT TAPE_POOL_IE_NN   NOT NULL,
+  SUPPLY                  VARCHAR(100),
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT TAPE_POOL_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       INTEGER      CONSTRAINT TAPE_POOL_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        INTEGER      CONSTRAINT TAPE_POOL_LUT_NN  NOT NULL,
+  CONSTRAINT TAPE_POOL_PK PRIMARY KEY(TAPE_POOL_ID),
+  CONSTRAINT TAPE_POOL_TPN_UN UNIQUE(TAPE_POOL_NAME),
+  CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN ('0', '1')),
+  CONSTRAINT TAPE_POOL_VO_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)
+);
+CREATE TABLE ARCHIVE_ROUTE(
+  STORAGE_CLASS_ID        INTEGER      CONSTRAINT ARCHIVE_ROUTE_SCI_NN  NOT NULL,
+  COPY_NB                 INTEGER       CONSTRAINT ARCHIVE_ROUTE_CN_NN   NOT NULL,
+  TAPE_POOL_ID            INTEGER      CONSTRAINT ARCHIVE_ROUTE_TPI_NN  NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ARCHIVE_ROUTE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       INTEGER      CONSTRAINT ARCHIVE_ROUTE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        INTEGER      CONSTRAINT ARCHIVE_ROUTE_LUT_NN  NOT NULL,
+  CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(STORAGE_CLASS_ID, COPY_NB),
+  CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
+  CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),
+  CONSTRAINT ARCHIVE_ROUTE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0),
+  CONSTRAINT ARCHIVE_ROUTE_SCI_TPI_UN UNIQUE(STORAGE_CLASS_ID, TAPE_POOL_ID)
+);
+CREATE TABLE MEDIA_TYPE(
+  MEDIA_TYPE_ID          INTEGER    CONSTRAINT MEDIA_TYPE_MTI_NN  NOT NULL,
+  MEDIA_TYPE_NAME        VARCHAR(100)  CONSTRAINT MEDIA_TYPE_MTN_NN  NOT NULL,
+  CARTRIDGE              VARCHAR(100)  CONSTRAINT MEDIA_TYPE_C_NN    NOT NULL,
+  CAPACITY_IN_BYTES      INTEGER    CONSTRAINT MEDIA_TYPE_CIB_NN  NOT NULL,
+  PRIMARY_DENSITY_CODE   INTEGER,
+  SECONDARY_DENSITY_CODE INTEGER,
+  NB_WRAPS               INTEGER,
+  MIN_LPOS               INTEGER,
+  MAX_LPOS               INTEGER,
+  USER_COMMENT           VARCHAR(1000) CONSTRAINT MEDIA_TYPE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      INTEGER    CONSTRAINT MEDIA_TYPE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       INTEGER    CONSTRAINT MEDIA_TYPE_LUT_NN  NOT NULL,
+  CONSTRAINT MEDIA_TYPE_PK PRIMARY KEY(MEDIA_TYPE_ID),
+  CONSTRAINT MEDIA_TYPE_MTN_UN UNIQUE(MEDIA_TYPE_NAME)
+);
+CREATE TABLE LOGICAL_LIBRARY(
+  LOGICAL_LIBRARY_ID      INTEGER      CONSTRAINT LOGICAL_LIBRARY_LLI_NN  NOT NULL,
+  LOGICAL_LIBRARY_NAME    VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LLN_NN  NOT NULL,
+  IS_DISABLED             CHAR(1)         DEFAULT '0' CONSTRAINT LOGICAL_LIBRARY_ID_NN NOT NULL,
+  USER_COMMENT            VARCHAR(1000)   CONSTRAINT LOGICAL_LIBRARY_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       INTEGER      CONSTRAINT LOGICAL_LIBRARY_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        INTEGER      CONSTRAINT LOGICAL_LIBRARY_LUT_NN  NOT NULL,
+  CONSTRAINT LOGICAL_LIBRARY_PK PRIMARY KEY(LOGICAL_LIBRARY_ID),
+  CONSTRAINT LOGICAL_LIBRARY_LLN_UN UNIQUE(LOGICAL_LIBRARY_NAME),
+  CONSTRAINT LOGICAL_LIBRARY_ID_BOOL_CK CHECK(IS_DISABLED IN ('0', '1'))
+);
+CREATE TABLE TAPE(
+  VID                     VARCHAR(100)    CONSTRAINT TAPE_V_NN    NOT NULL,
+  MEDIA_TYPE_ID           INTEGER      CONSTRAINT TAPE_MTID_NN   NOT NULL,
+  VENDOR                  VARCHAR(100)    CONSTRAINT TAPE_V2_NN   NOT NULL,
+  LOGICAL_LIBRARY_ID      INTEGER      CONSTRAINT TAPE_LLI_NN  NOT NULL,
+  TAPE_POOL_ID            INTEGER      CONSTRAINT TAPE_TPI_NN  NOT NULL,
+  ENCRYPTION_KEY_NAME     VARCHAR(100),
+  DATA_IN_BYTES           INTEGER      CONSTRAINT TAPE_DIB_NN  NOT NULL,
+  LAST_FSEQ               INTEGER      CONSTRAINT TAPE_LF_NN   NOT NULL,
+  NB_MASTER_FILES         INTEGER      DEFAULT 0 CONSTRAINT TAPE_NB_MASTER_FILES_NN NOT NULL,
+  MASTER_DATA_IN_BYTES    INTEGER      DEFAULT 0 CONSTRAINT TAPE_MASTER_DATA_IN_BYTES_NN NOT NULL,
+  IS_FULL                 CHAR(1)         CONSTRAINT TAPE_IF_NN   NOT NULL,
+  IS_FROM_CASTOR          CHAR(1)         CONSTRAINT TAPE_IFC_NN  NOT NULL,
+  DIRTY                   CHAR(1)         DEFAULT '1' CONSTRAINT TAPE_DIRTY_NN NOT NULL,
+  NB_COPY_NB_1            INTEGER     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_1_NN NOT NULL,
+  COPY_NB_1_IN_BYTES      INTEGER     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_1_IN_BYTES_NN NOT NULL,
+  NB_COPY_NB_GT_1         INTEGER     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_GT_1_NN NOT NULL,
+  COPY_NB_GT_1_IN_BYTES   INTEGER     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_GT_1_IN_BYTES_NN NOT NULL,
+  LABEL_DRIVE             VARCHAR(100),
+  LABEL_TIME              INTEGER    ,
+  LAST_READ_DRIVE         VARCHAR(100),
+  LAST_READ_TIME          INTEGER    ,
+  LAST_WRITE_DRIVE        VARCHAR(100),
+  LAST_WRITE_TIME         INTEGER    ,
+  READ_MOUNT_COUNT        INTEGER      DEFAULT 0 CONSTRAINT TAPE_RMC_NN NOT NULL,
+  WRITE_MOUNT_COUNT       INTEGER      DEFAULT 0 CONSTRAINT TAPE_WMC_NN NOT NULL,
+  USER_COMMENT            VARCHAR(1000),
+  TAPE_STATE              VARCHAR(100)    CONSTRAINT TAPE_TS_NN NOT NULL,
+  STATE_REASON            VARCHAR(1000),
+  STATE_UPDATE_TIME       INTEGER      CONSTRAINT TAPE_SUT_NN NOT NULL,
+  STATE_MODIFIED_BY       VARCHAR(100)    CONSTRAINT TAPE_SMB_NN NOT NULL,
+  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME       INTEGER      CONSTRAINT TAPE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME        INTEGER      CONSTRAINT TAPE_LUT_NN  NOT NULL,
+  CONSTRAINT TAPE_PK PRIMARY KEY(VID),
+  CONSTRAINT TAPE_LOGICAL_LIBRARY_FK FOREIGN KEY(LOGICAL_LIBRARY_ID) REFERENCES LOGICAL_LIBRARY(LOGICAL_LIBRARY_ID),
+  CONSTRAINT TAPE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),
+  CONSTRAINT TAPE_IS_FULL_BOOL_CK CHECK(IS_FULL IN ('0', '1')),
+  CONSTRAINT TAPE_IS_FROM_CASTOR_BOOL_CK CHECK(IS_FROM_CASTOR IN ('0', '1')),
+  CONSTRAINT TAPE_DIRTY_BOOL_CK CHECK(DIRTY IN ('0','1')),
+  CONSTRAINT TAPE_STATE_CK CHECK(TAPE_STATE IN ('ACTIVE', 'DISABLED', 'BROKEN')),
+  CONSTRAINT TAPE_MEDIA_TYPE_FK FOREIGN KEY(MEDIA_TYPE_ID) REFERENCES MEDIA_TYPE(MEDIA_TYPE_ID)
+);
+CREATE INDEX TAPE_TAPE_POOL_ID_IDX ON TAPE(TAPE_POOL_ID);
+CREATE INDEX TAPE_STATE_IDX ON TAPE(TAPE_STATE);
+CREATE TABLE MOUNT_POLICY(
+  MOUNT_POLICY_NAME          VARCHAR(100)    CONSTRAINT MOUNT_POLICY_MPN_NN  NOT NULL,
+  ARCHIVE_PRIORITY           INTEGER      CONSTRAINT MOUNT_POLICY_AP_NN   NOT NULL,
+  ARCHIVE_MIN_REQUEST_AGE    INTEGER      CONSTRAINT MOUNT_POLICY_AMRA_NN NOT NULL,
+  RETRIEVE_PRIORITY          INTEGER      CONSTRAINT MOUNT_POLICY_RP_NN   NOT NULL,
+  RETRIEVE_MIN_REQUEST_AGE   INTEGER      CONSTRAINT MOUNT_POLICY_RMRA_NN NOT NULL,
+  USER_COMMENT               VARCHAR(1000)   CONSTRAINT MOUNT_POLICY_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME          INTEGER      CONSTRAINT MOUNT_POLICY_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME           INTEGER      CONSTRAINT MOUNT_POLICY_LUT_NN  NOT NULL,
+  CONSTRAINT MOUNT_POLICY_PK PRIMARY KEY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE REQUESTER_MOUNT_RULE(
+  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_RULE_DIN_NN  NOT NULL,
+  REQUESTER_NAME         VARCHAR(100)    CONSTRAINT RQSTER_RULE_RN_NN   NOT NULL,
+  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_RULE_MPN_NN  NOT NULL,
+  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_RULE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      INTEGER      CONSTRAINT RQSTER_RULE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       INTEGER      CONSTRAINT RQSTER_RULE_LUT_NN  NOT NULL,
+  CONSTRAINT RQSTER_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_NAME),
+  CONSTRAINT RQSTER_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)
+    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE REQUESTER_GROUP_MOUNT_RULE(
+  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_DIN_NN  NOT NULL,
+  REQUESTER_GROUP_NAME   VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_RGN_NN  NOT NULL,
+  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_MPN_NN  NOT NULL,
+  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_GRP_RULE_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME      INTEGER      CONSTRAINT RQSTER_GRP_RULE_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME       INTEGER      CONSTRAINT RQSTER_GRP_RULE_LUT_NN  NOT NULL,
+  CONSTRAINT RQSTER_GRP_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME),
+  CONSTRAINT RQSTER_GRP_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)
+    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)
+);
+CREATE TABLE ARCHIVE_FILE(
+  ARCHIVE_FILE_ID         INTEGER      CONSTRAINT ARCHIVE_FILE_AFI_NN  NOT NULL,
+  DISK_INSTANCE_NAME      VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DIN_NN  NOT NULL,
+  DISK_FILE_ID            VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DFI_NN  NOT NULL,
+  DISK_FILE_UID           INTEGER      CONSTRAINT ARCHIVE_FILE_DFUID_NN  NOT NULL,
+  DISK_FILE_GID           INTEGER      CONSTRAINT ARCHIVE_FILE_DFGID_NN  NOT NULL,
+  SIZE_IN_BYTES           INTEGER      CONSTRAINT ARCHIVE_FILE_SIB_NN  NOT NULL,
+  CHECKSUM_BLOB           BLOB(200),
+  CHECKSUM_ADLER32        INTEGER      CONSTRAINT ARCHIVE_FILE_CB2_NN  NOT NULL,
+  STORAGE_CLASS_ID        INTEGER      CONSTRAINT ARCHIVE_FILE_SCI_NN  NOT NULL,
+  CREATION_TIME           INTEGER      CONSTRAINT ARCHIVE_FILE_CT2_NN  NOT NULL,
+  RECONCILIATION_TIME     INTEGER      CONSTRAINT ARCHIVE_FILE_RT_NN   NOT NULL,
+  IS_DELETED              CHAR(1)         DEFAULT '0' CONSTRAINT ARCHIVE_FILE_ID_NN NOT NULL,
+  COLLOCATION_HINT        VARCHAR(100),
+  CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),
+  CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),
+  CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID),
+  CONSTRAINT ARCHIVE_FILE_ID_BOOL_CK CHECK(IS_DELETED IN ('0', '1'))
+);
+CREATE INDEX ARCHIVE_FILE_DIN_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME);
+CREATE INDEX ARCHIVE_FILE_DFI_IDX ON ARCHIVE_FILE(DISK_FILE_ID);
+CREATE TABLE TAPE_FILE(
+  VID                      VARCHAR(100)   CONSTRAINT TAPE_FILE_V_NN    NOT NULL,
+  FSEQ                     INTEGER     CONSTRAINT TAPE_FILE_F_NN    NOT NULL,
+  BLOCK_ID                 INTEGER     CONSTRAINT TAPE_FILE_BI_NN   NOT NULL,
+  LOGICAL_SIZE_IN_BYTES    INTEGER     CONSTRAINT TAPE_FILE_CSIB_NN NOT NULL,
+  COPY_NB                  INTEGER      CONSTRAINT TAPE_FILE_CN_NN   NOT NULL,
+  CREATION_TIME            INTEGER     CONSTRAINT TAPE_FILE_CT_NN   NOT NULL,
+  ARCHIVE_FILE_ID          INTEGER     CONSTRAINT TAPE_FILE_AFI_NN  NOT NULL,
+  CONSTRAINT TAPE_FILE_PK PRIMARY KEY(VID, FSEQ),
+  CONSTRAINT TAPE_FILE_TAPE_FK FOREIGN KEY(VID)
+    REFERENCES TAPE(VID),
+  CONSTRAINT TAPE_FILE_ARCHIVE_FILE_FK FOREIGN KEY(ARCHIVE_FILE_ID)
+    REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),
+  CONSTRAINT TAPE_FILE_VID_BLOCK_ID_UN UNIQUE(VID, BLOCK_ID),
+  CONSTRAINT TAPE_FILE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0)
+);
+CREATE INDEX TAPE_FILE_VID_IDX ON TAPE_FILE(VID);
+CREATE INDEX TAPE_FILE_ARCHIVE_FILE_ID_IDX ON TAPE_FILE(ARCHIVE_FILE_ID);
+CREATE TABLE ACTIVITIES_WEIGHTS (
+  DISK_INSTANCE_NAME       VARCHAR(100),
+  ACTIVITY                 VARCHAR(100),
+  WEIGHT                   VARCHAR(100),
+  USER_COMMENT             VARCHAR(1000)   CONSTRAINT ACTIV_WEIGHTS_UC_NN   NOT NULL,
+  CREATION_LOG_USER_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLUN_NN NOT NULL,
+  CREATION_LOG_HOST_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLHN_NN NOT NULL,
+  CREATION_LOG_TIME        INTEGER      CONSTRAINT ACTIV_WEIGHTS_CLT_NN  NOT NULL,
+  LAST_UPDATE_USER_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUUN_NN NOT NULL,
+  LAST_UPDATE_HOST_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUHN_NN NOT NULL,
+  LAST_UPDATE_TIME         INTEGER      CONSTRAINT ACTIV_WEIGHTS_LUT_NN  NOT NULL
+);
+CREATE TABLE FILE_RECYCLE_LOG(
+  FILE_RECYCLE_LOG_ID        INTEGER          CONSTRAINT FILE_RECYCLE_LOG_ID_NN NOT NULL,
+  VID                        VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_VID_NN NOT NULL,
+  FSEQ                       INTEGER          CONSTRAINT FILE_RECYCLE_LOG_FSEQ_NN NOT NULL,
+  BLOCK_ID                   INTEGER          CONSTRAINT FILE_RECYCLE_LOG_BID_NN NOT NULL,
+  COPY_NB                    INTEGER           CONSTRAINT FILE_RECYCLE_LOG_COPY_NB_NN NOT NULL,
+  TAPE_FILE_CREATION_TIME    INTEGER          CONSTRAINT FILE_RECYCLE_LOG_TFCT_NN NOT NULL,
+  ARCHIVE_FILE_ID            INTEGER          CONSTRAINT FILE_RECYCLE_LOG_AFI_NN NOT NULL,
+  DISK_INSTANCE_NAME         VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DIN_NN NOT NULL,
+  DISK_FILE_ID               VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFI_NN NOT NULL,
+  DISK_FILE_ID_WHEN_DELETED  VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFIWD_NN NOT NULL,
+  DISK_FILE_UID              INTEGER          CONSTRAINT FILE_RECYCLE_LOG_DFU_NN NOT NULL,
+  DISK_FILE_GID              INTEGER          CONSTRAINT FILE_RECYCLE_LOG_DFG_NN NOT NULL,
+  SIZE_IN_BYTES              INTEGER          CONSTRAINT FILE_RECYCLE_LOG_SIB_NN NOT NULL,
+  CHECKSUM_BLOB              BLOB(200),
+  CHECKSUM_ADLER32           INTEGER          CONSTRAINT FILE_RECYCLE_LOG_CA_NN NOT NULL,
+  STORAGE_CLASS_ID           INTEGER          CONSTRAINT FILE_RECYCLE_LOG_SCI_NN NOT NULL,
+  ARCHIVE_FILE_CREATION_TIME INTEGER          CONSTRAINT FILE_RECYLE_LOG_CT_NN NOT NULL,
+  RECONCILIATION_TIME        INTEGER          CONSTRAINT FILE_RECYCLE_LOG_RT_NN NOT NULL,
+  COLLOCATION_HINT           VARCHAR(100),
+  DISK_FILE_PATH             VARCHAR(2000),
+  REASON_LOG                 VARCHAR(1000)       CONSTRAINT FILE_RECYCLE_LOG_RL_NN NOT NULL,
+  RECYCLE_LOG_TIME           INTEGER          CONSTRAINT FILE_RECYCLE_LOG_RLT_NN NOT NULL,
+  CONSTRAINT FILE_RECYCLE_LOG_PK PRIMARY KEY(FILE_RECYCLE_LOG_ID),
+  CONSTRAINT FILE_RECYCLE_LOG_VID_FK FOREIGN KEY(VID) REFERENCES TAPE(VID),
+  CONSTRAINT FILE_RECYCLE_LOG_SC_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID)
+);
+CREATE INDEX FILE_RECYCLE_LOG_DFI_IDX ON FILE_RECYCLE_LOG(DISK_FILE_ID);
+
+CREATE TABLE DRIVE_CONFIG (
+  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_DN_NN  NOT NULL,
+  CATEGORY                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_C_NN   NOT NULL,
+  KEY_NAME                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_KN_NN  NOT NULL,
+  VALUE                       VARCHAR(1000)      CONSTRAINT DRIVE_CONFIG_V_NN   NOT NULL,
+  SOURCE                      VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_S_NN   NOT NULL,
+  CONSTRAINT DRIVE_CONFIG_DN_PK PRIMARY KEY(KEY_NAME, DRIVE_NAME)
+);
+
+CREATE TABLE TAPE_DRIVE (
+  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_STATE_DN_NN NOT NULL,
+  HOST                        VARCHAR(100)       CONSTRAINT DRIVE_STATE_H_NN  NOT NULL,
+  LOGICAL_LIBRARY             VARCHAR(100)       CONSTRAINT DRIVE_STATE_LL_NN NOT NULL,
+  SESSION_ID                  INTEGER,
+  BYTES_TRANSFERED_IN_SESSION INTEGER,
+  FILES_TRANSFERED_IN_SESSION INTEGER,
+  LATEST_BANDWIDTH            VARCHAR(100),
+  SESSION_START_TIME          INTEGER,
+  MOUNT_START_TIME            INTEGER,
+  TRANSFER_START_TIME         INTEGER,
+  UNLOAD_START_TIME           INTEGER,
+  UNMOUNT_START_TIME          INTEGER,
+  DRAINING_START_TIME         INTEGER,
+  DOWN_OR_UP_START_TIME       INTEGER,
+  PROBE_START_TIME            INTEGER,
+  CLEANUP_START_TIME          INTEGER,
+  START_START_TIME            INTEGER,
+  SHUTDOWN_TIME               INTEGER,
+  MOUNT_TYPE                  INTEGER      CONSTRAINT DRIVE_STATE_MT_NN NOT NULL,
+  DRIVE_STATUS                VARCHAR(100)    DEFAULT 'UNKNOWN' CONSTRAINT DRIVE_STATE_DS_NN NOT NULL,
+  DESIRED_UP                  CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DU_NN  NOT NULL,
+  DESIRED_FORCE_DOWN          CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DFD_NN NOT NULL,
+  REASON_UP_DOWN              VARCHAR(1000),
+  CURRENT_VID                 VARCHAR(100),
+  CTA_VERSION                 VARCHAR(100),
+  CURRENT_PRIORITY            INTEGER,
+  CURRENT_ACTIVITY            VARCHAR(100),
+  CURRENT_ACTIVITY_WEIGHT     VARCHAR(100),
+  CURRENT_TAPE_POOL           VARCHAR(100),
+  NEXT_MOUNT_TYPE             INTEGER,
+  NEXT_VID                    VARCHAR(100),
+  NEXT_TAPE_POOL              VARCHAR(100),
+  NEXT_PRIORITY               INTEGER,
+  NEXT_ACTIVITY               VARCHAR(100),
+  NEXT_ACTIVITY_WEIGHT        VARCHAR(100),
+  DEV_FILE_NAME               VARCHAR(100),
+  RAW_LIBRARY_SLOT            VARCHAR(100),
+  CURRENT_VO                  VARCHAR(100),
+  NEXT_VO                     VARCHAR(100),
+  USER_COMMENT                VARCHAR(1000),
+  CREATION_LOG_USER_NAME      VARCHAR(100),
+  CREATION_LOG_HOST_NAME      VARCHAR(100),
+  CREATION_LOG_TIME           INTEGER,
+  LAST_UPDATE_USER_NAME       VARCHAR(100),
+  LAST_UPDATE_HOST_NAME       VARCHAR(100),
+  LAST_UPDATE_TIME            INTEGER,
+  DISK_SYSTEM_NAME            VARCHAR(100)       CONSTRAINT DRIVE_STATE_DSN_NN NOT NULL,
+  RESERVED_BYTES              INTEGER         CONSTRAINT DRIVE_STATE_RB_NN  NOT NULL,
+  CONSTRAINT DRIVE_STATE_DN_PK PRIMARY KEY(DRIVE_NAME),
+  CONSTRAINT DRIVE_STATE_DU_BOOL_CK CHECK(DESIRED_UP IN ('0', '1')),
+  CONSTRAINT DRIVE_STATE_DFD_BOOL_CK CHECK(DESIRED_FORCE_DOWN IN ('0', '1')),
+  CONSTRAINT DRIVE_STATE_DS_STRING_CK CHECK(DRIVE_STATUS IN ('DOWN', 'UP', 'PROBING', 'STARTING',
+  'MOUNTING', 'TRANSFERING', 'UNLOADING', 'UNMOUNTING', 'DRAININGTODISK', 'CLEANINGUP', 'SHUTDOWN',
+  'UNKNOWN'))
+);
+INSERT INTO CTA_CATALOGUE(
+  SCHEMA_VERSION_MAJOR,
+  SCHEMA_VERSION_MINOR,
+  STATUS)
+VALUES(
+  4,
+  2,
+  'PRODUCTION');
diff --git a/catalogue/AllCatalogueSchema.hpp b/catalogue/AllCatalogueSchema.hpp
index 4c56470c0808e81c276cee9cd6c92ed2c666e900..02b9a97212992db8c125f7315b7e264e80c6fe1c 100644
--- a/catalogue/AllCatalogueSchema.hpp
+++ b/catalogue/AllCatalogueSchema.hpp
@@ -11871,6 +11871,1736 @@ namespace catalogue{
   "  CATALOGUE_STATUS_CONTENT_CK CHECK((NEXT_SCHEMA_VERSION_MAJOR IS NULL AND NEXT_SCHEMA_VERSION_MINOR IS NULL AND STATUS='PRODUCTION') OR (STATUS='UPGRADING'));"
       },
     }  },
+  {"4.2",
+    {
+      {"oracle",  "CREATE SEQUENCE ARCHIVE_FILE_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 4294967296"
+  "  NOMAXVALUE"
+  "  MINVALUE 1"
+  "  NOCYCLE"
+  "  CACHE 20"
+  "  NOORDER;"
+  "CREATE SEQUENCE LOGICAL_LIBRARY_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NOMAXVALUE"
+  "  MINVALUE 1"
+  "  NOCYCLE"
+  "  CACHE 20"
+  "  NOORDER;"
+  "CREATE SEQUENCE MEDIA_TYPE_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NOMAXVALUE"
+  "  MINVALUE 1"
+  "  NOCYCLE"
+  "  CACHE 20"
+  "  NOORDER;"
+  "CREATE SEQUENCE STORAGE_CLASS_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 10000"
+  "  NOMAXVALUE"
+  "  MINVALUE 1"
+  "  NOCYCLE"
+  "  CACHE 20"
+  "  NOORDER;"
+  "CREATE SEQUENCE TAPE_POOL_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NOMAXVALUE"
+  "  MINVALUE 1"
+  "  NOCYCLE"
+  "  CACHE 20"
+  "  NOORDER;"
+  "CREATE SEQUENCE VIRTUAL_ORGANIZATION_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NOMAXVALUE"
+  "  MINVALUE 1"
+  "  NOCYCLE"
+  "  CACHE 20"
+  "  NOORDER;"
+  "CREATE SEQUENCE FILE_RECYCLE_LOG_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NOMAXVALUE"
+  "  MINVALUE 1"
+  "  NOCYCLE"
+  "  CACHE 20"
+  "  NOORDER;"
+  "CREATE GLOBAL TEMPORARY TABLE TEMP_TAPE_FILE_INSERTION_BATCH("
+  "  VID                   VARCHAR2(100),"
+  "  FSEQ                  NUMERIC(20, 0)  ,"
+  "  BLOCK_ID              NUMERIC(20, 0)  ,"
+  "  LOGICAL_SIZE_IN_BYTES NUMERIC(20, 0)  ,"
+  "  COPY_NB               NUMERIC(3, 0)   ,"
+  "  CREATION_TIME         NUMERIC(20, 0)  ,"
+  "  ARCHIVE_FILE_ID       NUMERIC(20, 0)"
+  ")"
+  "ON COMMIT DELETE ROWS;"
+  "CREATE INDEX TEMP_T_F_I_B_AFI_IDX ON TEMP_TAPE_FILE_INSERTION_BATCH(ARCHIVE_FILE_ID);"
+  "CREATE TABLE CTA_CATALOGUE("
+  "  SCHEMA_VERSION_MAJOR    NUMERIC(20, 0)      CONSTRAINT CTA_CATALOGUE_SVM1_NN NOT NULL,"
+  "  SCHEMA_VERSION_MINOR    NUMERIC(20, 0)      CONSTRAINT CTA_CATALOGUE_SVM2_NN NOT NULL,"
+  "  NEXT_SCHEMA_VERSION_MAJOR NUMERIC(20, 0),"
+  "  NEXT_SCHEMA_VERSION_MINOR NUMERIC(20, 0),"
+  "  STATUS                  VARCHAR2(100),"
+  "  IS_PRODUCTION           CHAR(1)         DEFAULT '0' CONSTRAINT CTA_CATALOGUE_IP_NN NOT NULL,"
+  "  CONSTRAINT CTA_CATALOGUE_IP_BOOL_CK     CHECK(IS_PRODUCTION IN ('0','1'))"
+  ");"
+  "CREATE TABLE ADMIN_USER("
+  "  ADMIN_USER_NAME         VARCHAR2(100)    CONSTRAINT ADMIN_USER_AUN_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT ADMIN_USER_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT ADMIN_USER_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT ADMIN_USER_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT ADMIN_USER_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT ADMIN_USER_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT ADMIN_USER_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,"
+  "  CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)"
+  ");"
+  "CREATE TABLE DISK_SYSTEM("
+  "  DISK_SYSTEM_NAME        VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,"
+  "  FILE_REGEXP             VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,"
+  "  FREE_SPACE_QUERY_URL    VARCHAR2(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,"
+  "  REFRESH_INTERVAL        NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,"
+  "  TARGETED_FREE_SPACE     NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,"
+  "  SLEEP_TIME              NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_ST_NN   NOT NULL,"
+  "  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,"
+  "  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)"
+  ");"
+  "CREATE TABLE VIRTUAL_ORGANIZATION("
+  "  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_VOI_NN  NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_NAME VARCHAR2(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,"
+  "  READ_MAX_DRIVES NUMERIC(20, 0)              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,"
+  "  WRITE_MAX_DRIVES NUMERIC(20, 0)             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,"
+  "  MAX_FILE_SIZE NUMERIC(20, 0)                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_LUT_NN  NOT NULL,"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_PK PRIMARY KEY(VIRTUAL_ORGANIZATION_ID),"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_VON_UN UNIQUE(VIRTUAL_ORGANIZATION_NAME)"
+  ");"
+  "CREATE TABLE STORAGE_CLASS("
+  "  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,"
+  "  STORAGE_CLASS_NAME      VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_SCN_NN  NOT NULL,"
+  "  NB_COPIES               NUMERIC(3, 0)       CONSTRAINT STORAGE_CLASS_NC_NN   NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_VOI_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT STORAGE_CLASS_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_LUT_NN  NOT NULL,"
+  "  CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),"
+  "  CONSTRAINT STORAGE_CLASS_SCN_UN UNIQUE(STORAGE_CLASS_NAME),"
+  "  CONSTRAINT STORAGE_CLASS_VOI_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)"
+  ");"
+  "CREATE TABLE TAPE_POOL("
+  "  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_TPI_NN  NOT NULL,"
+  "  TAPE_POOL_NAME          VARCHAR2(100)    CONSTRAINT TAPE_POOL_TPN_NN  NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_VOI_NN  NOT NULL,"
+  "  NB_PARTIAL_TAPES        NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_NPT_NN  NOT NULL,"
+  "  IS_ENCRYPTED            CHAR(1)         CONSTRAINT TAPE_POOL_IE_NN   NOT NULL,"
+  "  SUPPLY                  VARCHAR2(100),"
+  "  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT TAPE_POOL_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT TAPE_POOL_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT TAPE_POOL_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT TAPE_POOL_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT TAPE_POOL_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_LUT_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_POOL_PK PRIMARY KEY(TAPE_POOL_ID),"
+  "  CONSTRAINT TAPE_POOL_TPN_UN UNIQUE(TAPE_POOL_NAME),"
+  "  CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN ('0', '1')),"
+  "  CONSTRAINT TAPE_POOL_VO_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)"
+  ");"
+  "CREATE TABLE ARCHIVE_ROUTE("
+  "  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_SCI_NN  NOT NULL,"
+  "  COPY_NB                 NUMERIC(3, 0)       CONSTRAINT ARCHIVE_ROUTE_CN_NN   NOT NULL,"
+  "  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_TPI_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT ARCHIVE_ROUTE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT ARCHIVE_ROUTE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT ARCHIVE_ROUTE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT ARCHIVE_ROUTE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(STORAGE_CLASS_ID, COPY_NB),"
+  "  CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),"
+  "  CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),"
+  "  CONSTRAINT ARCHIVE_ROUTE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0),"
+  "  CONSTRAINT ARCHIVE_ROUTE_SCI_TPI_UN UNIQUE(STORAGE_CLASS_ID, TAPE_POOL_ID)"
+  ");"
+  "CREATE TABLE MEDIA_TYPE("
+  "  MEDIA_TYPE_ID          NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_MTI_NN  NOT NULL,"
+  "  MEDIA_TYPE_NAME        VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_MTN_NN  NOT NULL,"
+  "  CARTRIDGE              VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_C_NN    NOT NULL,"
+  "  CAPACITY_IN_BYTES      NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_CIB_NN  NOT NULL,"
+  "  PRIMARY_DENSITY_CODE   NUMERIC(3, 0),"
+  "  SECONDARY_DENSITY_CODE NUMERIC(3, 0),"
+  "  NB_WRAPS               NUMERIC(10, 0),"
+  "  MIN_LPOS               NUMERIC(20, 0),"
+  "  MAX_LPOS               NUMERIC(20, 0),"
+  "  USER_COMMENT           VARCHAR2(1000) CONSTRAINT MEDIA_TYPE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR2(100)  CONSTRAINT MEDIA_TYPE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT MEDIA_TYPE_PK PRIMARY KEY(MEDIA_TYPE_ID),"
+  "  CONSTRAINT MEDIA_TYPE_MTN_UN UNIQUE(MEDIA_TYPE_NAME)"
+  ");"
+  "CREATE TABLE LOGICAL_LIBRARY("
+  "  LOGICAL_LIBRARY_ID      NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_LLI_NN  NOT NULL,"
+  "  LOGICAL_LIBRARY_NAME    VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_LLN_NN  NOT NULL,"
+  "  IS_DISABLED             CHAR(1)         DEFAULT '0' CONSTRAINT LOGICAL_LIBRARY_ID_NN NOT NULL,"
+  "  USER_COMMENT            VARCHAR2(1000)   CONSTRAINT LOGICAL_LIBRARY_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT LOGICAL_LIBRARY_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_LUT_NN  NOT NULL,"
+  "  CONSTRAINT LOGICAL_LIBRARY_PK PRIMARY KEY(LOGICAL_LIBRARY_ID),"
+  "  CONSTRAINT LOGICAL_LIBRARY_LLN_UN UNIQUE(LOGICAL_LIBRARY_NAME),"
+  "  CONSTRAINT LOGICAL_LIBRARY_ID_BOOL_CK CHECK(IS_DISABLED IN ('0', '1'))"
+  ");"
+  "CREATE TABLE TAPE("
+  "  VID                     VARCHAR2(100)    CONSTRAINT TAPE_V_NN    NOT NULL,"
+  "  MEDIA_TYPE_ID           NUMERIC(20, 0)      CONSTRAINT TAPE_MTID_NN   NOT NULL,"
+  "  VENDOR                  VARCHAR2(100)    CONSTRAINT TAPE_V2_NN   NOT NULL,"
+  "  LOGICAL_LIBRARY_ID      NUMERIC(20, 0)      CONSTRAINT TAPE_LLI_NN  NOT NULL,"
+  "  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT TAPE_TPI_NN  NOT NULL,"
+  "  ENCRYPTION_KEY_NAME     VARCHAR2(100),"
+  "  DATA_IN_BYTES           NUMERIC(20, 0)      CONSTRAINT TAPE_DIB_NN  NOT NULL,"
+  "  LAST_FSEQ               NUMERIC(20, 0)      CONSTRAINT TAPE_LF_NN   NOT NULL,"
+  "  NB_MASTER_FILES         NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_NB_MASTER_FILES_NN NOT NULL,"
+  "  MASTER_DATA_IN_BYTES    NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_MASTER_DATA_IN_BYTES_NN NOT NULL,"
+  "  IS_FULL                 CHAR(1)         CONSTRAINT TAPE_IF_NN   NOT NULL,"
+  "  IS_FROM_CASTOR          CHAR(1)         CONSTRAINT TAPE_IFC_NN  NOT NULL,"
+  "  DIRTY                   CHAR(1)         DEFAULT '1' CONSTRAINT TAPE_DIRTY_NN NOT NULL,"
+  "  NB_COPY_NB_1            NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_1_NN NOT NULL,"
+  "  COPY_NB_1_IN_BYTES      NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_1_IN_BYTES_NN NOT NULL,"
+  "  NB_COPY_NB_GT_1         NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_GT_1_NN NOT NULL,"
+  "  COPY_NB_GT_1_IN_BYTES   NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_GT_1_IN_BYTES_NN NOT NULL,"
+  "  LABEL_DRIVE             VARCHAR2(100),"
+  "  LABEL_TIME              NUMERIC(20, 0)    ,"
+  "  LAST_READ_DRIVE         VARCHAR2(100),"
+  "  LAST_READ_TIME          NUMERIC(20, 0)    ,"
+  "  LAST_WRITE_DRIVE        VARCHAR2(100),"
+  "  LAST_WRITE_TIME         NUMERIC(20, 0)    ,"
+  "  READ_MOUNT_COUNT        NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_RMC_NN NOT NULL,"
+  "  WRITE_MOUNT_COUNT       NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_WMC_NN NOT NULL,"
+  "  USER_COMMENT            VARCHAR2(1000),"
+  "  TAPE_STATE              VARCHAR2(100)    CONSTRAINT TAPE_TS_NN NOT NULL,"
+  "  STATE_REASON            VARCHAR2(1000),"
+  "  STATE_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_SUT_NN NOT NULL,"
+  "  STATE_MODIFIED_BY       VARCHAR2(100)    CONSTRAINT TAPE_SMB_NN NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR2(100)    CONSTRAINT TAPE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR2(100)    CONSTRAINT TAPE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR2(100)    CONSTRAINT TAPE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR2(100)    CONSTRAINT TAPE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT TAPE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_PK PRIMARY KEY(VID),"
+  "  CONSTRAINT TAPE_LOGICAL_LIBRARY_FK FOREIGN KEY(LOGICAL_LIBRARY_ID) REFERENCES LOGICAL_LIBRARY(LOGICAL_LIBRARY_ID),"
+  "  CONSTRAINT TAPE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),"
+  "  CONSTRAINT TAPE_IS_FULL_BOOL_CK CHECK(IS_FULL IN ('0', '1')),"
+  "  CONSTRAINT TAPE_IS_FROM_CASTOR_BOOL_CK CHECK(IS_FROM_CASTOR IN ('0', '1')),"
+  "  CONSTRAINT TAPE_DIRTY_BOOL_CK CHECK(DIRTY IN ('0','1')),"
+  "  CONSTRAINT TAPE_STATE_CK CHECK(TAPE_STATE IN ('ACTIVE', 'DISABLED', 'BROKEN')),"
+  "  CONSTRAINT TAPE_MEDIA_TYPE_FK FOREIGN KEY(MEDIA_TYPE_ID) REFERENCES MEDIA_TYPE(MEDIA_TYPE_ID)"
+  ");"
+  "CREATE INDEX TAPE_TAPE_POOL_ID_IDX ON TAPE(TAPE_POOL_ID);"
+  "CREATE INDEX TAPE_STATE_IDX ON TAPE(TAPE_STATE);"
+  "CREATE TABLE MOUNT_POLICY("
+  "  MOUNT_POLICY_NAME          VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_MPN_NN  NOT NULL,"
+  "  ARCHIVE_PRIORITY           NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_AP_NN   NOT NULL,"
+  "  ARCHIVE_MIN_REQUEST_AGE    NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_AMRA_NN NOT NULL,"
+  "  RETRIEVE_PRIORITY          NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_RP_NN   NOT NULL,"
+  "  RETRIEVE_MIN_REQUEST_AGE   NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_RMRA_NN NOT NULL,"
+  "  USER_COMMENT               VARCHAR2(1000)   CONSTRAINT MOUNT_POLICY_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME     VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME     VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME          NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME      VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME      VARCHAR2(100)    CONSTRAINT MOUNT_POLICY_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME           NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_LUT_NN  NOT NULL,"
+  "  CONSTRAINT MOUNT_POLICY_PK PRIMARY KEY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE REQUESTER_MOUNT_RULE("
+  "  DISK_INSTANCE_NAME     VARCHAR2(100)    CONSTRAINT RQSTER_RULE_DIN_NN  NOT NULL,"
+  "  REQUESTER_NAME         VARCHAR2(100)    CONSTRAINT RQSTER_RULE_RN_NN   NOT NULL,"
+  "  MOUNT_POLICY_NAME      VARCHAR2(100)    CONSTRAINT RQSTER_RULE_MPN_NN  NOT NULL,"
+  "  USER_COMMENT           VARCHAR2(1000)   CONSTRAINT RQSTER_RULE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR2(100)    CONSTRAINT RQSTER_RULE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR2(100)    CONSTRAINT RQSTER_RULE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      NUMERIC(20, 0)      CONSTRAINT RQSTER_RULE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR2(100)    CONSTRAINT RQSTER_RULE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR2(100)    CONSTRAINT RQSTER_RULE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT RQSTER_RULE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT RQSTER_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_NAME),"
+  "  CONSTRAINT RQSTER_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)"
+  "    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE REQUESTER_GROUP_MOUNT_RULE("
+  "  DISK_INSTANCE_NAME     VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_DIN_NN  NOT NULL,"
+  "  REQUESTER_GROUP_NAME   VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_RGN_NN  NOT NULL,"
+  "  MOUNT_POLICY_NAME      VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_MPN_NN  NOT NULL,"
+  "  USER_COMMENT           VARCHAR2(1000)   CONSTRAINT RQSTER_GRP_RULE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      NUMERIC(20, 0)      CONSTRAINT RQSTER_GRP_RULE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR2(100)    CONSTRAINT RQSTER_GRP_RULE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT RQSTER_GRP_RULE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT RQSTER_GRP_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME),"
+  "  CONSTRAINT RQSTER_GRP_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)"
+  "    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE ARCHIVE_FILE("
+  "  ARCHIVE_FILE_ID         NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_AFI_NN  NOT NULL,"
+  "  DISK_INSTANCE_NAME      VARCHAR2(100)    CONSTRAINT ARCHIVE_FILE_DIN_NN  NOT NULL,"
+  "  DISK_FILE_ID            VARCHAR2(100)    CONSTRAINT ARCHIVE_FILE_DFI_NN  NOT NULL,"
+  "  DISK_FILE_UID           NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_DFUID_NN  NOT NULL,"
+  "  DISK_FILE_GID           NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_DFGID_NN  NOT NULL,"
+  "  SIZE_IN_BYTES           NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_SIB_NN  NOT NULL,"
+  "  CHECKSUM_BLOB           RAW(200),"
+  "  CHECKSUM_ADLER32        NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_CB2_NN  NOT NULL,"
+  "  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_SCI_NN  NOT NULL,"
+  "  CREATION_TIME           NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_CT2_NN  NOT NULL,"
+  "  RECONCILIATION_TIME     NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_RT_NN   NOT NULL,"
+  "  IS_DELETED              CHAR(1)         DEFAULT '0' CONSTRAINT ARCHIVE_FILE_ID_NN NOT NULL,"
+  "  COLLOCATION_HINT        VARCHAR2(100),"
+  "  CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_ID_BOOL_CK CHECK(IS_DELETED IN ('0', '1'))"
+  ");"
+  "CREATE INDEX ARCHIVE_FILE_DIN_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME);"
+  "CREATE INDEX ARCHIVE_FILE_DFI_IDX ON ARCHIVE_FILE(DISK_FILE_ID);"
+  "CREATE TABLE TAPE_FILE("
+  "  VID                      VARCHAR2(100)   CONSTRAINT TAPE_FILE_V_NN    NOT NULL,"
+  "  FSEQ                     NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_F_NN    NOT NULL,"
+  "  BLOCK_ID                 NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_BI_NN   NOT NULL,"
+  "  LOGICAL_SIZE_IN_BYTES    NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_CSIB_NN NOT NULL,"
+  "  COPY_NB                  NUMERIC(3, 0)      CONSTRAINT TAPE_FILE_CN_NN   NOT NULL,"
+  "  CREATION_TIME            NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_CT_NN   NOT NULL,"
+  "  ARCHIVE_FILE_ID          NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_AFI_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_FILE_PK PRIMARY KEY(VID, FSEQ),"
+  "  CONSTRAINT TAPE_FILE_TAPE_FK FOREIGN KEY(VID)"
+  "    REFERENCES TAPE(VID),"
+  "  CONSTRAINT TAPE_FILE_ARCHIVE_FILE_FK FOREIGN KEY(ARCHIVE_FILE_ID)"
+  "    REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),"
+  "  CONSTRAINT TAPE_FILE_VID_BLOCK_ID_UN UNIQUE(VID, BLOCK_ID),"
+  "  CONSTRAINT TAPE_FILE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0)"
+  ");"
+  "CREATE INDEX TAPE_FILE_VID_IDX ON TAPE_FILE(VID);"
+  "CREATE INDEX TAPE_FILE_ARCHIVE_FILE_ID_IDX ON TAPE_FILE(ARCHIVE_FILE_ID);"
+  "CREATE TABLE ACTIVITIES_WEIGHTS ("
+  "  DISK_INSTANCE_NAME       VARCHAR2(100),"
+  "  ACTIVITY                 VARCHAR2(100),"
+  "  WEIGHT                   VARCHAR2(100),"
+  "  USER_COMMENT             VARCHAR2(1000)   CONSTRAINT ACTIV_WEIGHTS_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME   VARCHAR2(100)    CONSTRAINT ACTIV_WEIGHTS_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME   VARCHAR2(100)    CONSTRAINT ACTIV_WEIGHTS_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME        NUMERIC(20, 0)      CONSTRAINT ACTIV_WEIGHTS_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME    VARCHAR2(100)    CONSTRAINT ACTIV_WEIGHTS_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME    VARCHAR2(100)    CONSTRAINT ACTIV_WEIGHTS_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME         NUMERIC(20, 0)      CONSTRAINT ACTIV_WEIGHTS_LUT_NN  NOT NULL"
+  ");"
+  "CREATE TABLE FILE_RECYCLE_LOG("
+  "  FILE_RECYCLE_LOG_ID        NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_ID_NN NOT NULL,"
+  "  VID                        VARCHAR2(100)        CONSTRAINT FILE_RECYCLE_LOG_VID_NN NOT NULL,"
+  "  FSEQ                       NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_FSEQ_NN NOT NULL,"
+  "  BLOCK_ID                   NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_BID_NN NOT NULL,"
+  "  COPY_NB                    NUMERIC(3, 0)           CONSTRAINT FILE_RECYCLE_LOG_COPY_NB_NN NOT NULL,"
+  "  TAPE_FILE_CREATION_TIME    NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_TFCT_NN NOT NULL,"
+  "  ARCHIVE_FILE_ID            NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_AFI_NN NOT NULL,"
+  "  DISK_INSTANCE_NAME         VARCHAR2(100)        CONSTRAINT FILE_RECYCLE_LOG_DIN_NN NOT NULL,"
+  "  DISK_FILE_ID               VARCHAR2(100)        CONSTRAINT FILE_RECYCLE_LOG_DFI_NN NOT NULL,"
+  "  DISK_FILE_ID_WHEN_DELETED  VARCHAR2(100)        CONSTRAINT FILE_RECYCLE_LOG_DFIWD_NN NOT NULL,"
+  "  DISK_FILE_UID              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_DFU_NN NOT NULL,"
+  "  DISK_FILE_GID              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_DFG_NN NOT NULL,"
+  "  SIZE_IN_BYTES              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_SIB_NN NOT NULL,"
+  "  CHECKSUM_BLOB              RAW(200),"
+  "  CHECKSUM_ADLER32           NUMERIC(10, 0)          CONSTRAINT FILE_RECYCLE_LOG_CA_NN NOT NULL,"
+  "  STORAGE_CLASS_ID           NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_SCI_NN NOT NULL,"
+  "  ARCHIVE_FILE_CREATION_TIME NUMERIC(20, 0)          CONSTRAINT FILE_RECYLE_LOG_CT_NN NOT NULL,"
+  "  RECONCILIATION_TIME        NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_RT_NN NOT NULL,"
+  "  COLLOCATION_HINT           VARCHAR2(100),"
+  "  DISK_FILE_PATH             VARCHAR2(2000),"
+  "  REASON_LOG                 VARCHAR2(1000)       CONSTRAINT FILE_RECYCLE_LOG_RL_NN NOT NULL,"
+  "  RECYCLE_LOG_TIME           NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_RLT_NN NOT NULL,"
+  "  CONSTRAINT FILE_RECYCLE_LOG_PK PRIMARY KEY(FILE_RECYCLE_LOG_ID),"
+  "  CONSTRAINT FILE_RECYCLE_LOG_VID_FK FOREIGN KEY(VID) REFERENCES TAPE(VID),"
+  "  CONSTRAINT FILE_RECYCLE_LOG_SC_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID)"
+  ");"
+  "CREATE INDEX FILE_RECYCLE_LOG_DFI_IDX ON FILE_RECYCLE_LOG(DISK_FILE_ID);"
+  ""
+  "CREATE TABLE DRIVE_CONFIG ("
+  "  DRIVE_NAME                  VARCHAR2(100)       CONSTRAINT DRIVE_CONFIG_DN_NN  NOT NULL,"
+  "  CATEGORY                    VARCHAR2(100)       CONSTRAINT DRIVE_CONFIG_C_NN   NOT NULL,"
+  "  KEY_NAME                    VARCHAR2(100)       CONSTRAINT DRIVE_CONFIG_KN_NN  NOT NULL,"
+  "  VALUE                       VARCHAR2(1000)      CONSTRAINT DRIVE_CONFIG_V_NN   NOT NULL,"
+  "  SOURCE                      VARCHAR2(100)       CONSTRAINT DRIVE_CONFIG_S_NN   NOT NULL,"
+  "  CONSTRAINT DRIVE_CONFIG_DN_PK PRIMARY KEY(KEY_NAME, DRIVE_NAME)"
+  ");"
+  ""
+  "CREATE TABLE TAPE_DRIVE ("
+  "  DRIVE_NAME                  VARCHAR2(100)       CONSTRAINT DRIVE_STATE_DN_NN NOT NULL,"
+  "  HOST                        VARCHAR2(100)       CONSTRAINT DRIVE_STATE_H_NN  NOT NULL,"
+  "  LOGICAL_LIBRARY             VARCHAR2(100)       CONSTRAINT DRIVE_STATE_LL_NN NOT NULL,"
+  "  SESSION_ID                  NUMERIC(20, 0),"
+  "  BYTES_TRANSFERED_IN_SESSION NUMERIC(20, 0),"
+  "  FILES_TRANSFERED_IN_SESSION NUMERIC(20, 0),"
+  "  LATEST_BANDWIDTH            VARCHAR2(100),"
+  "  SESSION_START_TIME          NUMERIC(20, 0),"
+  "  MOUNT_START_TIME            NUMERIC(20, 0),"
+  "  TRANSFER_START_TIME         NUMERIC(20, 0),"
+  "  UNLOAD_START_TIME           NUMERIC(20, 0),"
+  "  UNMOUNT_START_TIME          NUMERIC(20, 0),"
+  "  DRAINING_START_TIME         NUMERIC(20, 0),"
+  "  DOWN_OR_UP_START_TIME       NUMERIC(20, 0),"
+  "  PROBE_START_TIME            NUMERIC(20, 0),"
+  "  CLEANUP_START_TIME          NUMERIC(20, 0),"
+  "  START_START_TIME            NUMERIC(20, 0),"
+  "  SHUTDOWN_TIME               NUMERIC(20, 0),"
+  "  MOUNT_TYPE                  NUMERIC(10, 0)      CONSTRAINT DRIVE_STATE_MT_NN NOT NULL,"
+  "  DRIVE_STATUS                VARCHAR2(100)    DEFAULT 'UNKNOWN' CONSTRAINT DRIVE_STATE_DS_NN NOT NULL,"
+  "  DESIRED_UP                  CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DU_NN  NOT NULL,"
+  "  DESIRED_FORCE_DOWN          CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DFD_NN NOT NULL,"
+  "  REASON_UP_DOWN              VARCHAR2(1000),"
+  "  CURRENT_VID                 VARCHAR2(100),"
+  "  CTA_VERSION                 VARCHAR2(100),"
+  "  CURRENT_PRIORITY            NUMERIC(20, 0),"
+  "  CURRENT_ACTIVITY            VARCHAR2(100),"
+  "  CURRENT_ACTIVITY_WEIGHT     VARCHAR2(100),"
+  "  CURRENT_TAPE_POOL           VARCHAR2(100),"
+  "  NEXT_MOUNT_TYPE             NUMERIC(10, 0),"
+  "  NEXT_VID                    VARCHAR2(100),"
+  "  NEXT_TAPE_POOL              VARCHAR2(100),"
+  "  NEXT_PRIORITY               NUMERIC(20, 0),"
+  "  NEXT_ACTIVITY               VARCHAR2(100),"
+  "  NEXT_ACTIVITY_WEIGHT        VARCHAR2(100),"
+  "  DEV_FILE_NAME               VARCHAR2(100),"
+  "  RAW_LIBRARY_SLOT            VARCHAR2(100),"
+  "  CURRENT_VO                  VARCHAR2(100),"
+  "  NEXT_VO                     VARCHAR2(100),"
+  "  USER_COMMENT                VARCHAR2(1000),"
+  "  CREATION_LOG_USER_NAME      VARCHAR2(100),"
+  "  CREATION_LOG_HOST_NAME      VARCHAR2(100),"
+  "  CREATION_LOG_TIME           NUMERIC(20, 0),"
+  "  LAST_UPDATE_USER_NAME       VARCHAR2(100),"
+  "  LAST_UPDATE_HOST_NAME       VARCHAR2(100),"
+  "  LAST_UPDATE_TIME            NUMERIC(20, 0),"
+  "  DISK_SYSTEM_NAME            VARCHAR2(100)       CONSTRAINT DRIVE_STATE_DSN_NN NOT NULL,"
+  "  RESERVED_BYTES              NUMERIC(20, 0)         CONSTRAINT DRIVE_STATE_RB_NN  NOT NULL,"
+  "  CONSTRAINT DRIVE_STATE_DN_PK PRIMARY KEY(DRIVE_NAME),"
+  "  CONSTRAINT DRIVE_STATE_DU_BOOL_CK CHECK(DESIRED_UP IN ('0', '1')),"
+  "  CONSTRAINT DRIVE_STATE_DFD_BOOL_CK CHECK(DESIRED_FORCE_DOWN IN ('0', '1')),"
+  "  CONSTRAINT DRIVE_STATE_DS_STRING_CK CHECK(DRIVE_STATUS IN ('DOWN', 'UP', 'PROBING', 'STARTING',"
+  "  'MOUNTING', 'TRANSFERING', 'UNLOADING', 'UNMOUNTING', 'DRAININGTODISK', 'CLEANINGUP', 'SHUTDOWN',"
+  "  'UNKNOWN'))"
+  ");"
+  "INSERT INTO CTA_CATALOGUE("
+  "  SCHEMA_VERSION_MAJOR,"
+  "  SCHEMA_VERSION_MINOR,"
+  "  STATUS)"
+  "VALUES("
+  "  4,"
+  "  2,"
+  "  'PRODUCTION');"
+  "ALTER TABLE CTA_CATALOGUE ADD CONSTRAINT CATALOGUE_STATUS_CONTENT_CK CHECK((NEXT_SCHEMA_VERSION_MAJOR IS NULL AND NEXT_SCHEMA_VERSION_MINOR IS NULL AND STATUS='PRODUCTION') OR (NEXT_SCHEMA_VERSION_MAJOR IS NOT NULL AND NEXT_SCHEMA_VERSION_MINOR IS NOT NULL AND STATUS='UPGRADING')) INITIALLY DEFERRED;"
+  ""
+  "COMMIT;"
+      },
+  {"mysql",  "CREATE TABLE ARCHIVE_FILE_ID("
+  "  ID BIGINT UNSIGNED,"
+  "  CONSTRAINT ARCHIVE_FILE_ID_PK PRIMARY KEY(ID)"
+  ");"
+  "INSERT INTO ARCHIVE_FILE_ID(ID) VALUES(1);"
+  "CREATE TABLE LOGICAL_LIBRARY_ID("
+  "  ID BIGINT UNSIGNED,"
+  "  CONSTRAINT LOGICAL_LIBRARY_ID_PK PRIMARY KEY(ID)"
+  ");"
+  "INSERT INTO LOGICAL_LIBRARY_ID(ID) VALUES(1);"
+  "CREATE TABLE MEDIA_TYPE_ID("
+  "  ID BIGINT UNSIGNED,"
+  "  CONSTRAINT MEDIA_TYPE_ID_PK PRIMARY KEY(ID)"
+  ");"
+  "INSERT INTO MEDIA_TYPE_ID(ID) VALUES(1);"
+  "CREATE TABLE STORAGE_CLASS_ID("
+  "  ID BIGINT UNSIGNED,"
+  "  CONSTRAINT STORAGE_CLASS_ID_PK PRIMARY KEY(ID)"
+  ");"
+  "INSERT INTO STORAGE_CLASS_ID(ID) VALUES(1);"
+  "CREATE TABLE TAPE_POOL_ID("
+  "  ID BIGINT UNSIGNED,"
+  "  CONSTRAINT TAPE_POOL_ID_PK PRIMARY KEY(ID)"
+  ");"
+  "INSERT INTO TAPE_POOL_ID(ID) VALUES(1);"
+  "CREATE TABLE VIRTUAL_ORGANIZATION_ID("
+  "  ID BIGINT UNSIGNED,"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_ID_PK PRIMARY KEY(ID)"
+  ");"
+  "INSERT INTO VIRTUAL_ORGANIZATION_ID(ID) VALUES(1);"
+  "CREATE TABLE FILE_RECYCLE_LOG_ID("
+  "  ID BIGINT UNSIGNED,"
+  "  CONSTRAINT FILE_RECYCLE_LOG_ID PRIMARY KEY(ID)"
+  ");"
+  "INSERT INTO FILE_RECYCLE_LOG_ID(ID) VALUES (1);"
+  "CREATE TABLE CTA_CATALOGUE("
+  "  SCHEMA_VERSION_MAJOR    BIGINT UNSIGNED      CONSTRAINT CTA_CATALOGUE_SVM1_NN NOT NULL,"
+  "  SCHEMA_VERSION_MINOR    BIGINT UNSIGNED      CONSTRAINT CTA_CATALOGUE_SVM2_NN NOT NULL,"
+  "  NEXT_SCHEMA_VERSION_MAJOR BIGINT UNSIGNED,"
+  "  NEXT_SCHEMA_VERSION_MINOR BIGINT UNSIGNED,"
+  "  STATUS                  VARCHAR(100),"
+  "  IS_PRODUCTION           CHAR(1)         DEFAULT '0' CONSTRAINT CTA_CATALOGUE_IP_NN NOT NULL,"
+  "  CONSTRAINT CTA_CATALOGUE_IP_BOOL_CK     CHECK(IS_PRODUCTION IN ('0','1'))"
+  ");"
+  "CREATE TABLE ADMIN_USER("
+  "  ADMIN_USER_NAME         VARCHAR(100)    CONSTRAINT ADMIN_USER_AUN_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ADMIN_USER_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT ADMIN_USER_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,"
+  "  CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)"
+  ");"
+  "CREATE TABLE DISK_SYSTEM("
+  "  DISK_SYSTEM_NAME        VARCHAR(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,"
+  "  FILE_REGEXP             VARCHAR(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,"
+  "  FREE_SPACE_QUERY_URL    VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,"
+  "  REFRESH_INTERVAL        BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,"
+  "  TARGETED_FREE_SPACE     BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,"
+  "  SLEEP_TIME              BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_ST_NN   NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,"
+  "  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)"
+  ");"
+  "CREATE TABLE VIRTUAL_ORGANIZATION("
+  "  VIRTUAL_ORGANIZATION_ID BIGINT UNSIGNED      CONSTRAINT VIRTUAL_ORGANIZATION_VOI_NN  NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_NAME VARCHAR(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,"
+  "  READ_MAX_DRIVES BIGINT UNSIGNED              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,"
+  "  WRITE_MAX_DRIVES BIGINT UNSIGNED             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,"
+  "  MAX_FILE_SIZE BIGINT UNSIGNED                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT VIRTUAL_ORGANIZATION_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT VIRTUAL_ORGANIZATION_LUT_NN  NOT NULL,"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_PK PRIMARY KEY(VIRTUAL_ORGANIZATION_ID),"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_VON_UN UNIQUE(VIRTUAL_ORGANIZATION_NAME)"
+  ");"
+  "CREATE TABLE STORAGE_CLASS("
+  "  STORAGE_CLASS_ID        BIGINT UNSIGNED      CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,"
+  "  STORAGE_CLASS_NAME      VARCHAR(100)    CONSTRAINT STORAGE_CLASS_SCN_NN  NOT NULL,"
+  "  NB_COPIES               TINYINT UNSIGNED       CONSTRAINT STORAGE_CLASS_NC_NN   NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_ID BIGINT UNSIGNED      CONSTRAINT STORAGE_CLASS_VOI_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT STORAGE_CLASS_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT STORAGE_CLASS_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT STORAGE_CLASS_LUT_NN  NOT NULL,"
+  "  CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),"
+  "  CONSTRAINT STORAGE_CLASS_SCN_UN UNIQUE(STORAGE_CLASS_NAME),"
+  "  CONSTRAINT STORAGE_CLASS_VOI_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)"
+  ");"
+  "CREATE TABLE TAPE_POOL("
+  "  TAPE_POOL_ID            BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_TPI_NN  NOT NULL,"
+  "  TAPE_POOL_NAME          VARCHAR(100)    CONSTRAINT TAPE_POOL_TPN_NN  NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_ID BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_VOI_NN  NOT NULL,"
+  "  NB_PARTIAL_TAPES        BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_NPT_NN  NOT NULL,"
+  "  IS_ENCRYPTED            CHAR(1)         CONSTRAINT TAPE_POOL_IE_NN   NOT NULL,"
+  "  SUPPLY                  VARCHAR(100),"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT TAPE_POOL_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT TAPE_POOL_LUT_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_POOL_PK PRIMARY KEY(TAPE_POOL_ID),"
+  "  CONSTRAINT TAPE_POOL_TPN_UN UNIQUE(TAPE_POOL_NAME),"
+  "  CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN ('0', '1')),"
+  "  CONSTRAINT TAPE_POOL_VO_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)"
+  ");"
+  "CREATE TABLE ARCHIVE_ROUTE("
+  "  STORAGE_CLASS_ID        BIGINT UNSIGNED      CONSTRAINT ARCHIVE_ROUTE_SCI_NN  NOT NULL,"
+  "  COPY_NB                 TINYINT UNSIGNED       CONSTRAINT ARCHIVE_ROUTE_CN_NN   NOT NULL,"
+  "  TAPE_POOL_ID            BIGINT UNSIGNED      CONSTRAINT ARCHIVE_ROUTE_TPI_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ARCHIVE_ROUTE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT ARCHIVE_ROUTE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT ARCHIVE_ROUTE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(STORAGE_CLASS_ID, COPY_NB),"
+  "  CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),"
+  "  CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),"
+  "  CONSTRAINT ARCHIVE_ROUTE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0),"
+  "  CONSTRAINT ARCHIVE_ROUTE_SCI_TPI_UN UNIQUE(STORAGE_CLASS_ID, TAPE_POOL_ID)"
+  ");"
+  "CREATE TABLE MEDIA_TYPE("
+  "  MEDIA_TYPE_ID          BIGINT UNSIGNED    CONSTRAINT MEDIA_TYPE_MTI_NN  NOT NULL,"
+  "  MEDIA_TYPE_NAME        VARCHAR(100)  CONSTRAINT MEDIA_TYPE_MTN_NN  NOT NULL,"
+  "  CARTRIDGE              VARCHAR(100)  CONSTRAINT MEDIA_TYPE_C_NN    NOT NULL,"
+  "  CAPACITY_IN_BYTES      BIGINT UNSIGNED    CONSTRAINT MEDIA_TYPE_CIB_NN  NOT NULL,"
+  "  PRIMARY_DENSITY_CODE   TINYINT UNSIGNED,"
+  "  SECONDARY_DENSITY_CODE TINYINT UNSIGNED,"
+  "  NB_WRAPS               INT UNSIGNED,"
+  "  MIN_LPOS               BIGINT UNSIGNED,"
+  "  MAX_LPOS               BIGINT UNSIGNED,"
+  "  USER_COMMENT           VARCHAR(1000) CONSTRAINT MEDIA_TYPE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      BIGINT UNSIGNED    CONSTRAINT MEDIA_TYPE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       BIGINT UNSIGNED    CONSTRAINT MEDIA_TYPE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT MEDIA_TYPE_PK PRIMARY KEY(MEDIA_TYPE_ID),"
+  "  CONSTRAINT MEDIA_TYPE_MTN_UN UNIQUE(MEDIA_TYPE_NAME)"
+  ");"
+  "CREATE TABLE LOGICAL_LIBRARY("
+  "  LOGICAL_LIBRARY_ID      BIGINT UNSIGNED      CONSTRAINT LOGICAL_LIBRARY_LLI_NN  NOT NULL,"
+  "  LOGICAL_LIBRARY_NAME    VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LLN_NN  NOT NULL,"
+  "  IS_DISABLED             CHAR(1)         DEFAULT '0' CONSTRAINT LOGICAL_LIBRARY_ID_NN NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT LOGICAL_LIBRARY_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT LOGICAL_LIBRARY_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT LOGICAL_LIBRARY_LUT_NN  NOT NULL,"
+  "  CONSTRAINT LOGICAL_LIBRARY_PK PRIMARY KEY(LOGICAL_LIBRARY_ID),"
+  "  CONSTRAINT LOGICAL_LIBRARY_LLN_UN UNIQUE(LOGICAL_LIBRARY_NAME),"
+  "  CONSTRAINT LOGICAL_LIBRARY_ID_BOOL_CK CHECK(IS_DISABLED IN ('0', '1'))"
+  ");"
+  "CREATE TABLE TAPE("
+  "  VID                     VARCHAR(100)    CONSTRAINT TAPE_V_NN    NOT NULL,"
+  "  MEDIA_TYPE_ID           BIGINT UNSIGNED      CONSTRAINT TAPE_MTID_NN   NOT NULL,"
+  "  VENDOR                  VARCHAR(100)    CONSTRAINT TAPE_V2_NN   NOT NULL,"
+  "  LOGICAL_LIBRARY_ID      BIGINT UNSIGNED      CONSTRAINT TAPE_LLI_NN  NOT NULL,"
+  "  TAPE_POOL_ID            BIGINT UNSIGNED      CONSTRAINT TAPE_TPI_NN  NOT NULL,"
+  "  ENCRYPTION_KEY_NAME     VARCHAR(100),"
+  "  DATA_IN_BYTES           BIGINT UNSIGNED      CONSTRAINT TAPE_DIB_NN  NOT NULL,"
+  "  LAST_FSEQ               BIGINT UNSIGNED      CONSTRAINT TAPE_LF_NN   NOT NULL,"
+  "  NB_MASTER_FILES         BIGINT UNSIGNED      DEFAULT 0 CONSTRAINT TAPE_NB_MASTER_FILES_NN NOT NULL,"
+  "  MASTER_DATA_IN_BYTES    BIGINT UNSIGNED      DEFAULT 0 CONSTRAINT TAPE_MASTER_DATA_IN_BYTES_NN NOT NULL,"
+  "  IS_FULL                 CHAR(1)         CONSTRAINT TAPE_IF_NN   NOT NULL,"
+  "  IS_FROM_CASTOR          CHAR(1)         CONSTRAINT TAPE_IFC_NN  NOT NULL,"
+  "  DIRTY                   CHAR(1)         DEFAULT '1' CONSTRAINT TAPE_DIRTY_NN NOT NULL,"
+  "  NB_COPY_NB_1            BIGINT UNSIGNED     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_1_NN NOT NULL,"
+  "  COPY_NB_1_IN_BYTES      BIGINT UNSIGNED     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_1_IN_BYTES_NN NOT NULL,"
+  "  NB_COPY_NB_GT_1         BIGINT UNSIGNED     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_GT_1_NN NOT NULL,"
+  "  COPY_NB_GT_1_IN_BYTES   BIGINT UNSIGNED     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_GT_1_IN_BYTES_NN NOT NULL,"
+  "  LABEL_DRIVE             VARCHAR(100),"
+  "  LABEL_TIME              BIGINT UNSIGNED    ,"
+  "  LAST_READ_DRIVE         VARCHAR(100),"
+  "  LAST_READ_TIME          BIGINT UNSIGNED    ,"
+  "  LAST_WRITE_DRIVE        VARCHAR(100),"
+  "  LAST_WRITE_TIME         BIGINT UNSIGNED    ,"
+  "  READ_MOUNT_COUNT        BIGINT UNSIGNED      DEFAULT 0 CONSTRAINT TAPE_RMC_NN NOT NULL,"
+  "  WRITE_MOUNT_COUNT       BIGINT UNSIGNED      DEFAULT 0 CONSTRAINT TAPE_WMC_NN NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000),"
+  "  TAPE_STATE              VARCHAR(100)    CONSTRAINT TAPE_TS_NN NOT NULL,"
+  "  STATE_REASON            VARCHAR(1000),"
+  "  STATE_UPDATE_TIME       BIGINT UNSIGNED      CONSTRAINT TAPE_SUT_NN NOT NULL,"
+  "  STATE_MODIFIED_BY       VARCHAR(100)    CONSTRAINT TAPE_SMB_NN NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       BIGINT UNSIGNED      CONSTRAINT TAPE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        BIGINT UNSIGNED      CONSTRAINT TAPE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_PK PRIMARY KEY(VID),"
+  "  CONSTRAINT TAPE_LOGICAL_LIBRARY_FK FOREIGN KEY(LOGICAL_LIBRARY_ID) REFERENCES LOGICAL_LIBRARY(LOGICAL_LIBRARY_ID),"
+  "  CONSTRAINT TAPE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),"
+  "  CONSTRAINT TAPE_IS_FULL_BOOL_CK CHECK(IS_FULL IN ('0', '1')),"
+  "  CONSTRAINT TAPE_IS_FROM_CASTOR_BOOL_CK CHECK(IS_FROM_CASTOR IN ('0', '1')),"
+  "  CONSTRAINT TAPE_DIRTY_BOOL_CK CHECK(DIRTY IN ('0','1')),"
+  "  CONSTRAINT TAPE_STATE_CK CHECK(TAPE_STATE IN ('ACTIVE', 'DISABLED', 'BROKEN')),"
+  "  CONSTRAINT TAPE_MEDIA_TYPE_FK FOREIGN KEY(MEDIA_TYPE_ID) REFERENCES MEDIA_TYPE(MEDIA_TYPE_ID)"
+  ");"
+  "CREATE INDEX TAPE_TAPE_POOL_ID_IDX ON TAPE(TAPE_POOL_ID);"
+  "CREATE INDEX TAPE_STATE_IDX ON TAPE(TAPE_STATE);"
+  "CREATE TABLE MOUNT_POLICY("
+  "  MOUNT_POLICY_NAME          VARCHAR(100)    CONSTRAINT MOUNT_POLICY_MPN_NN  NOT NULL,"
+  "  ARCHIVE_PRIORITY           BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_AP_NN   NOT NULL,"
+  "  ARCHIVE_MIN_REQUEST_AGE    BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_AMRA_NN NOT NULL,"
+  "  RETRIEVE_PRIORITY          BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_RP_NN   NOT NULL,"
+  "  RETRIEVE_MIN_REQUEST_AGE   BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_RMRA_NN NOT NULL,"
+  "  USER_COMMENT               VARCHAR(1000)   CONSTRAINT MOUNT_POLICY_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME          BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME           BIGINT UNSIGNED      CONSTRAINT MOUNT_POLICY_LUT_NN  NOT NULL,"
+  "  CONSTRAINT MOUNT_POLICY_PK PRIMARY KEY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE REQUESTER_MOUNT_RULE("
+  "  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_RULE_DIN_NN  NOT NULL,"
+  "  REQUESTER_NAME         VARCHAR(100)    CONSTRAINT RQSTER_RULE_RN_NN   NOT NULL,"
+  "  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_RULE_MPN_NN  NOT NULL,"
+  "  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_RULE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      BIGINT UNSIGNED      CONSTRAINT RQSTER_RULE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       BIGINT UNSIGNED      CONSTRAINT RQSTER_RULE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT RQSTER_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_NAME),"
+  "  CONSTRAINT RQSTER_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)"
+  "    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE REQUESTER_GROUP_MOUNT_RULE("
+  "  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_DIN_NN  NOT NULL,"
+  "  REQUESTER_GROUP_NAME   VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_RGN_NN  NOT NULL,"
+  "  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_MPN_NN  NOT NULL,"
+  "  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_GRP_RULE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      BIGINT UNSIGNED      CONSTRAINT RQSTER_GRP_RULE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       BIGINT UNSIGNED      CONSTRAINT RQSTER_GRP_RULE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT RQSTER_GRP_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME),"
+  "  CONSTRAINT RQSTER_GRP_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)"
+  "    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE ARCHIVE_FILE("
+  "  ARCHIVE_FILE_ID         BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_AFI_NN  NOT NULL,"
+  "  DISK_INSTANCE_NAME      VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DIN_NN  NOT NULL,"
+  "  DISK_FILE_ID            VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DFI_NN  NOT NULL,"
+  "  DISK_FILE_UID           INT UNSIGNED      CONSTRAINT ARCHIVE_FILE_DFUID_NN  NOT NULL,"
+  "  DISK_FILE_GID           INT UNSIGNED      CONSTRAINT ARCHIVE_FILE_DFGID_NN  NOT NULL,"
+  "  SIZE_IN_BYTES           BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_SIB_NN  NOT NULL,"
+  "  CHECKSUM_BLOB           VARBINARY(200),"
+  "  CHECKSUM_ADLER32        INT UNSIGNED      CONSTRAINT ARCHIVE_FILE_CB2_NN  NOT NULL,"
+  "  STORAGE_CLASS_ID        BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_SCI_NN  NOT NULL,"
+  "  CREATION_TIME           BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_CT2_NN  NOT NULL,"
+  "  RECONCILIATION_TIME     BIGINT UNSIGNED      CONSTRAINT ARCHIVE_FILE_RT_NN   NOT NULL,"
+  "  IS_DELETED              CHAR(1)         DEFAULT '0' CONSTRAINT ARCHIVE_FILE_ID_NN NOT NULL,"
+  "  COLLOCATION_HINT        VARCHAR(100),"
+  "  CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_ID_BOOL_CK CHECK(IS_DELETED IN ('0', '1'))"
+  ");"
+  "CREATE INDEX ARCHIVE_FILE_DIN_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME);"
+  "CREATE INDEX ARCHIVE_FILE_DFI_IDX ON ARCHIVE_FILE(DISK_FILE_ID);"
+  "CREATE TABLE TAPE_FILE("
+  "  VID                      VARCHAR(100)   CONSTRAINT TAPE_FILE_V_NN    NOT NULL,"
+  "  FSEQ                     BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_F_NN    NOT NULL,"
+  "  BLOCK_ID                 BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_BI_NN   NOT NULL,"
+  "  LOGICAL_SIZE_IN_BYTES    BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_CSIB_NN NOT NULL,"
+  "  COPY_NB                  TINYINT UNSIGNED      CONSTRAINT TAPE_FILE_CN_NN   NOT NULL,"
+  "  CREATION_TIME            BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_CT_NN   NOT NULL,"
+  "  ARCHIVE_FILE_ID          BIGINT UNSIGNED     CONSTRAINT TAPE_FILE_AFI_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_FILE_PK PRIMARY KEY(VID, FSEQ),"
+  "  CONSTRAINT TAPE_FILE_TAPE_FK FOREIGN KEY(VID)"
+  "    REFERENCES TAPE(VID),"
+  "  CONSTRAINT TAPE_FILE_ARCHIVE_FILE_FK FOREIGN KEY(ARCHIVE_FILE_ID)"
+  "    REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),"
+  "  CONSTRAINT TAPE_FILE_VID_BLOCK_ID_UN UNIQUE(VID, BLOCK_ID),"
+  "  CONSTRAINT TAPE_FILE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0)"
+  ");"
+  "CREATE INDEX TAPE_FILE_VID_IDX ON TAPE_FILE(VID);"
+  "CREATE INDEX TAPE_FILE_ARCHIVE_FILE_ID_IDX ON TAPE_FILE(ARCHIVE_FILE_ID);"
+  "CREATE TABLE ACTIVITIES_WEIGHTS ("
+  "  DISK_INSTANCE_NAME       VARCHAR(100),"
+  "  ACTIVITY                 VARCHAR(100),"
+  "  WEIGHT                   VARCHAR(100),"
+  "  USER_COMMENT             VARCHAR(1000)   CONSTRAINT ACTIV_WEIGHTS_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME        BIGINT UNSIGNED      CONSTRAINT ACTIV_WEIGHTS_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME         BIGINT UNSIGNED      CONSTRAINT ACTIV_WEIGHTS_LUT_NN  NOT NULL"
+  ");"
+  "CREATE TABLE FILE_RECYCLE_LOG("
+  "  FILE_RECYCLE_LOG_ID        BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_ID_NN NOT NULL,"
+  "  VID                        VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_VID_NN NOT NULL,"
+  "  FSEQ                       BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_FSEQ_NN NOT NULL,"
+  "  BLOCK_ID                   BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_BID_NN NOT NULL,"
+  "  COPY_NB                    TINYINT UNSIGNED           CONSTRAINT FILE_RECYCLE_LOG_COPY_NB_NN NOT NULL,"
+  "  TAPE_FILE_CREATION_TIME    BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_TFCT_NN NOT NULL,"
+  "  ARCHIVE_FILE_ID            BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_AFI_NN NOT NULL,"
+  "  DISK_INSTANCE_NAME         VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DIN_NN NOT NULL,"
+  "  DISK_FILE_ID               VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFI_NN NOT NULL,"
+  "  DISK_FILE_ID_WHEN_DELETED  VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFIWD_NN NOT NULL,"
+  "  DISK_FILE_UID              BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_DFU_NN NOT NULL,"
+  "  DISK_FILE_GID              BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_DFG_NN NOT NULL,"
+  "  SIZE_IN_BYTES              BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_SIB_NN NOT NULL,"
+  "  CHECKSUM_BLOB              VARBINARY(200),"
+  "  CHECKSUM_ADLER32           INT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_CA_NN NOT NULL,"
+  "  STORAGE_CLASS_ID           BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_SCI_NN NOT NULL,"
+  "  ARCHIVE_FILE_CREATION_TIME BIGINT UNSIGNED          CONSTRAINT FILE_RECYLE_LOG_CT_NN NOT NULL,"
+  "  RECONCILIATION_TIME        BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_RT_NN NOT NULL,"
+  "  COLLOCATION_HINT           VARCHAR(100),"
+  "  DISK_FILE_PATH             VARCHAR(2000),"
+  "  REASON_LOG                 VARCHAR(1000)       CONSTRAINT FILE_RECYCLE_LOG_RL_NN NOT NULL,"
+  "  RECYCLE_LOG_TIME           BIGINT UNSIGNED          CONSTRAINT FILE_RECYCLE_LOG_RLT_NN NOT NULL,"
+  "  CONSTRAINT FILE_RECYCLE_LOG_PK PRIMARY KEY(FILE_RECYCLE_LOG_ID),"
+  "  CONSTRAINT FILE_RECYCLE_LOG_VID_FK FOREIGN KEY(VID) REFERENCES TAPE(VID),"
+  "  CONSTRAINT FILE_RECYCLE_LOG_SC_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID)"
+  ");"
+  "CREATE INDEX FILE_RECYCLE_LOG_DFI_IDX ON FILE_RECYCLE_LOG(DISK_FILE_ID);"
+  ""
+  "CREATE TABLE DRIVE_CONFIG ("
+  "  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_DN_NN  NOT NULL,"
+  "  CATEGORY                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_C_NN   NOT NULL,"
+  "  KEY_NAME                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_KN_NN  NOT NULL,"
+  "  VALUE                       VARCHAR(1000)      CONSTRAINT DRIVE_CONFIG_V_NN   NOT NULL,"
+  "  SOURCE                      VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_S_NN   NOT NULL,"
+  "  CONSTRAINT DRIVE_CONFIG_DN_PK PRIMARY KEY(KEY_NAME, DRIVE_NAME)"
+  ");"
+  ""
+  "CREATE TABLE TAPE_DRIVE ("
+  "  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_STATE_DN_NN NOT NULL,"
+  "  HOST                        VARCHAR(100)       CONSTRAINT DRIVE_STATE_H_NN  NOT NULL,"
+  "  LOGICAL_LIBRARY             VARCHAR(100)       CONSTRAINT DRIVE_STATE_LL_NN NOT NULL,"
+  "  SESSION_ID                  BIGINT UNSIGNED,"
+  "  BYTES_TRANSFERED_IN_SESSION BIGINT UNSIGNED,"
+  "  FILES_TRANSFERED_IN_SESSION BIGINT UNSIGNED,"
+  "  LATEST_BANDWIDTH            VARCHAR(100),"
+  "  SESSION_START_TIME          BIGINT UNSIGNED,"
+  "  MOUNT_START_TIME            BIGINT UNSIGNED,"
+  "  TRANSFER_START_TIME         BIGINT UNSIGNED,"
+  "  UNLOAD_START_TIME           BIGINT UNSIGNED,"
+  "  UNMOUNT_START_TIME          BIGINT UNSIGNED,"
+  "  DRAINING_START_TIME         BIGINT UNSIGNED,"
+  "  DOWN_OR_UP_START_TIME       BIGINT UNSIGNED,"
+  "  PROBE_START_TIME            BIGINT UNSIGNED,"
+  "  CLEANUP_START_TIME          BIGINT UNSIGNED,"
+  "  START_START_TIME            BIGINT UNSIGNED,"
+  "  SHUTDOWN_TIME               BIGINT UNSIGNED,"
+  "  MOUNT_TYPE                  INT UNSIGNED      CONSTRAINT DRIVE_STATE_MT_NN NOT NULL,"
+  "  DRIVE_STATUS                VARCHAR(100)    DEFAULT 'UNKNOWN' CONSTRAINT DRIVE_STATE_DS_NN NOT NULL,"
+  "  DESIRED_UP                  CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DU_NN  NOT NULL,"
+  "  DESIRED_FORCE_DOWN          CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DFD_NN NOT NULL,"
+  "  REASON_UP_DOWN              VARCHAR(1000),"
+  "  CURRENT_VID                 VARCHAR(100),"
+  "  CTA_VERSION                 VARCHAR(100),"
+  "  CURRENT_PRIORITY            BIGINT UNSIGNED,"
+  "  CURRENT_ACTIVITY            VARCHAR(100),"
+  "  CURRENT_ACTIVITY_WEIGHT     VARCHAR(100),"
+  "  CURRENT_TAPE_POOL           VARCHAR(100),"
+  "  NEXT_MOUNT_TYPE             INT UNSIGNED,"
+  "  NEXT_VID                    VARCHAR(100),"
+  "  NEXT_TAPE_POOL              VARCHAR(100),"
+  "  NEXT_PRIORITY               BIGINT UNSIGNED,"
+  "  NEXT_ACTIVITY               VARCHAR(100),"
+  "  NEXT_ACTIVITY_WEIGHT        VARCHAR(100),"
+  "  DEV_FILE_NAME               VARCHAR(100),"
+  "  RAW_LIBRARY_SLOT            VARCHAR(100),"
+  "  CURRENT_VO                  VARCHAR(100),"
+  "  NEXT_VO                     VARCHAR(100),"
+  "  USER_COMMENT                VARCHAR(1000),"
+  "  CREATION_LOG_USER_NAME      VARCHAR(100),"
+  "  CREATION_LOG_HOST_NAME      VARCHAR(100),"
+  "  CREATION_LOG_TIME           BIGINT UNSIGNED,"
+  "  LAST_UPDATE_USER_NAME       VARCHAR(100),"
+  "  LAST_UPDATE_HOST_NAME       VARCHAR(100),"
+  "  LAST_UPDATE_TIME            BIGINT UNSIGNED,"
+  "  DISK_SYSTEM_NAME            VARCHAR(100)       CONSTRAINT DRIVE_STATE_DSN_NN NOT NULL,"
+  "  RESERVED_BYTES              BIGINT UNSIGNED         CONSTRAINT DRIVE_STATE_RB_NN  NOT NULL,"
+  "  CONSTRAINT DRIVE_STATE_DN_PK PRIMARY KEY(DRIVE_NAME),"
+  "  CONSTRAINT DRIVE_STATE_DU_BOOL_CK CHECK(DESIRED_UP IN ('0', '1')),"
+  "  CONSTRAINT DRIVE_STATE_DFD_BOOL_CK CHECK(DESIRED_FORCE_DOWN IN ('0', '1')),"
+  "  CONSTRAINT DRIVE_STATE_DS_STRING_CK CHECK(DRIVE_STATUS IN ('DOWN', 'UP', 'PROBING', 'STARTING',"
+  "  'MOUNTING', 'TRANSFERING', 'UNLOADING', 'UNMOUNTING', 'DRAININGTODISK', 'CLEANINGUP', 'SHUTDOWN',"
+  "  'UNKNOWN'))"
+  ");"
+  "INSERT INTO CTA_CATALOGUE("
+  "  SCHEMA_VERSION_MAJOR,"
+  "  SCHEMA_VERSION_MINOR,"
+  "  STATUS)"
+  "VALUES("
+  "  4,"
+  "  2,"
+  "  'PRODUCTION');"
+  "ALTER TABLE CTA_CATALOGUE ADD CONSTRAINT"
+  "  CATALOGUE_STATUS_CONTENT_CK CHECK((NEXT_SCHEMA_VERSION_MAJOR IS NULL AND NEXT_SCHEMA_VERSION_MINOR IS NULL AND STATUS='PRODUCTION') OR (STATUS='UPGRADING'));"
+      },
+  {"sqlite",  "CREATE TABLE ARCHIVE_FILE_ID("
+  "  ID INTEGER PRIMARY KEY AUTOINCREMENT"
+  ");"
+  "CREATE TABLE LOGICAL_LIBRARY_ID("
+  "  ID INTEGER PRIMARY KEY AUTOINCREMENT"
+  ");"
+  "CREATE TABLE MEDIA_TYPE_ID("
+  "  ID INTEGER PRIMARY KEY AUTOINCREMENT"
+  ");"
+  "CREATE TABLE STORAGE_CLASS_ID("
+  "  ID INTEGER PRIMARY KEY AUTOINCREMENT"
+  ");"
+  "CREATE TABLE TAPE_POOL_ID("
+  "  ID INTEGER PRIMARY KEY AUTOINCREMENT"
+  ");"
+  "CREATE TABLE VIRTUAL_ORGANIZATION_ID("
+  "  ID INTEGER PRIMARY KEY AUTOINCREMENT"
+  ");"
+  "CREATE TABLE FILE_RECYCLE_LOG_ID("
+  "  ID INTEGER PRIMARY KEY AUTOINCREMENT"
+  ");"
+  "CREATE TABLE CTA_CATALOGUE("
+  "  SCHEMA_VERSION_MAJOR    INTEGER      CONSTRAINT CTA_CATALOGUE_SVM1_NN NOT NULL,"
+  "  SCHEMA_VERSION_MINOR    INTEGER      CONSTRAINT CTA_CATALOGUE_SVM2_NN NOT NULL,"
+  "  NEXT_SCHEMA_VERSION_MAJOR INTEGER,"
+  "  NEXT_SCHEMA_VERSION_MINOR INTEGER,"
+  "  STATUS                  VARCHAR(100),"
+  "  IS_PRODUCTION           CHAR(1)         DEFAULT '0' CONSTRAINT CTA_CATALOGUE_IP_NN NOT NULL,"
+  "  CONSTRAINT CTA_CATALOGUE_IP_BOOL_CK     CHECK(IS_PRODUCTION IN ('0','1'))"
+  ");"
+  "CREATE TABLE ADMIN_USER("
+  "  ADMIN_USER_NAME         VARCHAR(100)    CONSTRAINT ADMIN_USER_AUN_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ADMIN_USER_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       INTEGER      CONSTRAINT ADMIN_USER_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        INTEGER      CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,"
+  "  CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)"
+  ");"
+  "CREATE TABLE DISK_SYSTEM("
+  "  DISK_SYSTEM_NAME        VARCHAR(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,"
+  "  FILE_REGEXP             VARCHAR(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,"
+  "  FREE_SPACE_QUERY_URL    VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,"
+  "  REFRESH_INTERVAL        INTEGER      CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,"
+  "  TARGETED_FREE_SPACE     INTEGER      CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,"
+  "  SLEEP_TIME              INTEGER      CONSTRAINT DISK_SYSTEM_ST_NN   NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       INTEGER      CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        INTEGER      CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,"
+  "  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)"
+  ");"
+  "CREATE TABLE VIRTUAL_ORGANIZATION("
+  "  VIRTUAL_ORGANIZATION_ID INTEGER      CONSTRAINT VIRTUAL_ORGANIZATION_VOI_NN  NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_NAME VARCHAR(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,"
+  "  READ_MAX_DRIVES INTEGER              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,"
+  "  WRITE_MAX_DRIVES INTEGER             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,"
+  "  MAX_FILE_SIZE INTEGER                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       INTEGER      CONSTRAINT VIRTUAL_ORGANIZATION_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        INTEGER      CONSTRAINT VIRTUAL_ORGANIZATION_LUT_NN  NOT NULL,"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_PK PRIMARY KEY(VIRTUAL_ORGANIZATION_ID),"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_VON_UN UNIQUE(VIRTUAL_ORGANIZATION_NAME)"
+  ");"
+  "CREATE TABLE STORAGE_CLASS("
+  "  STORAGE_CLASS_ID        INTEGER      CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,"
+  "  STORAGE_CLASS_NAME      VARCHAR(100)    CONSTRAINT STORAGE_CLASS_SCN_NN  NOT NULL,"
+  "  NB_COPIES               INTEGER       CONSTRAINT STORAGE_CLASS_NC_NN   NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_ID INTEGER      CONSTRAINT STORAGE_CLASS_VOI_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT STORAGE_CLASS_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       INTEGER      CONSTRAINT STORAGE_CLASS_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        INTEGER      CONSTRAINT STORAGE_CLASS_LUT_NN  NOT NULL,"
+  "  CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),"
+  "  CONSTRAINT STORAGE_CLASS_SCN_UN UNIQUE(STORAGE_CLASS_NAME),"
+  "  CONSTRAINT STORAGE_CLASS_VOI_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)"
+  ");"
+  "CREATE TABLE TAPE_POOL("
+  "  TAPE_POOL_ID            INTEGER      CONSTRAINT TAPE_POOL_TPI_NN  NOT NULL,"
+  "  TAPE_POOL_NAME          VARCHAR(100)    CONSTRAINT TAPE_POOL_TPN_NN  NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_ID INTEGER      CONSTRAINT TAPE_POOL_VOI_NN  NOT NULL,"
+  "  NB_PARTIAL_TAPES        INTEGER      CONSTRAINT TAPE_POOL_NPT_NN  NOT NULL,"
+  "  IS_ENCRYPTED            CHAR(1)         CONSTRAINT TAPE_POOL_IE_NN   NOT NULL,"
+  "  SUPPLY                  VARCHAR(100),"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT TAPE_POOL_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       INTEGER      CONSTRAINT TAPE_POOL_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        INTEGER      CONSTRAINT TAPE_POOL_LUT_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_POOL_PK PRIMARY KEY(TAPE_POOL_ID),"
+  "  CONSTRAINT TAPE_POOL_TPN_UN UNIQUE(TAPE_POOL_NAME),"
+  "  CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN ('0', '1')),"
+  "  CONSTRAINT TAPE_POOL_VO_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)"
+  ");"
+  "CREATE TABLE ARCHIVE_ROUTE("
+  "  STORAGE_CLASS_ID        INTEGER      CONSTRAINT ARCHIVE_ROUTE_SCI_NN  NOT NULL,"
+  "  COPY_NB                 INTEGER       CONSTRAINT ARCHIVE_ROUTE_CN_NN   NOT NULL,"
+  "  TAPE_POOL_ID            INTEGER      CONSTRAINT ARCHIVE_ROUTE_TPI_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ARCHIVE_ROUTE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       INTEGER      CONSTRAINT ARCHIVE_ROUTE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        INTEGER      CONSTRAINT ARCHIVE_ROUTE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(STORAGE_CLASS_ID, COPY_NB),"
+  "  CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),"
+  "  CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),"
+  "  CONSTRAINT ARCHIVE_ROUTE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0),"
+  "  CONSTRAINT ARCHIVE_ROUTE_SCI_TPI_UN UNIQUE(STORAGE_CLASS_ID, TAPE_POOL_ID)"
+  ");"
+  "CREATE TABLE MEDIA_TYPE("
+  "  MEDIA_TYPE_ID          INTEGER    CONSTRAINT MEDIA_TYPE_MTI_NN  NOT NULL,"
+  "  MEDIA_TYPE_NAME        VARCHAR(100)  CONSTRAINT MEDIA_TYPE_MTN_NN  NOT NULL,"
+  "  CARTRIDGE              VARCHAR(100)  CONSTRAINT MEDIA_TYPE_C_NN    NOT NULL,"
+  "  CAPACITY_IN_BYTES      INTEGER    CONSTRAINT MEDIA_TYPE_CIB_NN  NOT NULL,"
+  "  PRIMARY_DENSITY_CODE   INTEGER,"
+  "  SECONDARY_DENSITY_CODE INTEGER,"
+  "  NB_WRAPS               INTEGER,"
+  "  MIN_LPOS               INTEGER,"
+  "  MAX_LPOS               INTEGER,"
+  "  USER_COMMENT           VARCHAR(1000) CONSTRAINT MEDIA_TYPE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      INTEGER    CONSTRAINT MEDIA_TYPE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       INTEGER    CONSTRAINT MEDIA_TYPE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT MEDIA_TYPE_PK PRIMARY KEY(MEDIA_TYPE_ID),"
+  "  CONSTRAINT MEDIA_TYPE_MTN_UN UNIQUE(MEDIA_TYPE_NAME)"
+  ");"
+  "CREATE TABLE LOGICAL_LIBRARY("
+  "  LOGICAL_LIBRARY_ID      INTEGER      CONSTRAINT LOGICAL_LIBRARY_LLI_NN  NOT NULL,"
+  "  LOGICAL_LIBRARY_NAME    VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LLN_NN  NOT NULL,"
+  "  IS_DISABLED             CHAR(1)         DEFAULT '0' CONSTRAINT LOGICAL_LIBRARY_ID_NN NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT LOGICAL_LIBRARY_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       INTEGER      CONSTRAINT LOGICAL_LIBRARY_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        INTEGER      CONSTRAINT LOGICAL_LIBRARY_LUT_NN  NOT NULL,"
+  "  CONSTRAINT LOGICAL_LIBRARY_PK PRIMARY KEY(LOGICAL_LIBRARY_ID),"
+  "  CONSTRAINT LOGICAL_LIBRARY_LLN_UN UNIQUE(LOGICAL_LIBRARY_NAME),"
+  "  CONSTRAINT LOGICAL_LIBRARY_ID_BOOL_CK CHECK(IS_DISABLED IN ('0', '1'))"
+  ");"
+  "CREATE TABLE TAPE("
+  "  VID                     VARCHAR(100)    CONSTRAINT TAPE_V_NN    NOT NULL,"
+  "  MEDIA_TYPE_ID           INTEGER      CONSTRAINT TAPE_MTID_NN   NOT NULL,"
+  "  VENDOR                  VARCHAR(100)    CONSTRAINT TAPE_V2_NN   NOT NULL,"
+  "  LOGICAL_LIBRARY_ID      INTEGER      CONSTRAINT TAPE_LLI_NN  NOT NULL,"
+  "  TAPE_POOL_ID            INTEGER      CONSTRAINT TAPE_TPI_NN  NOT NULL,"
+  "  ENCRYPTION_KEY_NAME     VARCHAR(100),"
+  "  DATA_IN_BYTES           INTEGER      CONSTRAINT TAPE_DIB_NN  NOT NULL,"
+  "  LAST_FSEQ               INTEGER      CONSTRAINT TAPE_LF_NN   NOT NULL,"
+  "  NB_MASTER_FILES         INTEGER      DEFAULT 0 CONSTRAINT TAPE_NB_MASTER_FILES_NN NOT NULL,"
+  "  MASTER_DATA_IN_BYTES    INTEGER      DEFAULT 0 CONSTRAINT TAPE_MASTER_DATA_IN_BYTES_NN NOT NULL,"
+  "  IS_FULL                 CHAR(1)         CONSTRAINT TAPE_IF_NN   NOT NULL,"
+  "  IS_FROM_CASTOR          CHAR(1)         CONSTRAINT TAPE_IFC_NN  NOT NULL,"
+  "  DIRTY                   CHAR(1)         DEFAULT '1' CONSTRAINT TAPE_DIRTY_NN NOT NULL,"
+  "  NB_COPY_NB_1            INTEGER     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_1_NN NOT NULL,"
+  "  COPY_NB_1_IN_BYTES      INTEGER     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_1_IN_BYTES_NN NOT NULL,"
+  "  NB_COPY_NB_GT_1         INTEGER     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_GT_1_NN NOT NULL,"
+  "  COPY_NB_GT_1_IN_BYTES   INTEGER     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_GT_1_IN_BYTES_NN NOT NULL,"
+  "  LABEL_DRIVE             VARCHAR(100),"
+  "  LABEL_TIME              INTEGER    ,"
+  "  LAST_READ_DRIVE         VARCHAR(100),"
+  "  LAST_READ_TIME          INTEGER    ,"
+  "  LAST_WRITE_DRIVE        VARCHAR(100),"
+  "  LAST_WRITE_TIME         INTEGER    ,"
+  "  READ_MOUNT_COUNT        INTEGER      DEFAULT 0 CONSTRAINT TAPE_RMC_NN NOT NULL,"
+  "  WRITE_MOUNT_COUNT       INTEGER      DEFAULT 0 CONSTRAINT TAPE_WMC_NN NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000),"
+  "  TAPE_STATE              VARCHAR(100)    CONSTRAINT TAPE_TS_NN NOT NULL,"
+  "  STATE_REASON            VARCHAR(1000),"
+  "  STATE_UPDATE_TIME       INTEGER      CONSTRAINT TAPE_SUT_NN NOT NULL,"
+  "  STATE_MODIFIED_BY       VARCHAR(100)    CONSTRAINT TAPE_SMB_NN NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       INTEGER      CONSTRAINT TAPE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        INTEGER      CONSTRAINT TAPE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_PK PRIMARY KEY(VID),"
+  "  CONSTRAINT TAPE_LOGICAL_LIBRARY_FK FOREIGN KEY(LOGICAL_LIBRARY_ID) REFERENCES LOGICAL_LIBRARY(LOGICAL_LIBRARY_ID),"
+  "  CONSTRAINT TAPE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),"
+  "  CONSTRAINT TAPE_IS_FULL_BOOL_CK CHECK(IS_FULL IN ('0', '1')),"
+  "  CONSTRAINT TAPE_IS_FROM_CASTOR_BOOL_CK CHECK(IS_FROM_CASTOR IN ('0', '1')),"
+  "  CONSTRAINT TAPE_DIRTY_BOOL_CK CHECK(DIRTY IN ('0','1')),"
+  "  CONSTRAINT TAPE_STATE_CK CHECK(TAPE_STATE IN ('ACTIVE', 'DISABLED', 'BROKEN')),"
+  "  CONSTRAINT TAPE_MEDIA_TYPE_FK FOREIGN KEY(MEDIA_TYPE_ID) REFERENCES MEDIA_TYPE(MEDIA_TYPE_ID)"
+  ");"
+  "CREATE INDEX TAPE_TAPE_POOL_ID_IDX ON TAPE(TAPE_POOL_ID);"
+  "CREATE INDEX TAPE_STATE_IDX ON TAPE(TAPE_STATE);"
+  "CREATE TABLE MOUNT_POLICY("
+  "  MOUNT_POLICY_NAME          VARCHAR(100)    CONSTRAINT MOUNT_POLICY_MPN_NN  NOT NULL,"
+  "  ARCHIVE_PRIORITY           INTEGER      CONSTRAINT MOUNT_POLICY_AP_NN   NOT NULL,"
+  "  ARCHIVE_MIN_REQUEST_AGE    INTEGER      CONSTRAINT MOUNT_POLICY_AMRA_NN NOT NULL,"
+  "  RETRIEVE_PRIORITY          INTEGER      CONSTRAINT MOUNT_POLICY_RP_NN   NOT NULL,"
+  "  RETRIEVE_MIN_REQUEST_AGE   INTEGER      CONSTRAINT MOUNT_POLICY_RMRA_NN NOT NULL,"
+  "  USER_COMMENT               VARCHAR(1000)   CONSTRAINT MOUNT_POLICY_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME          INTEGER      CONSTRAINT MOUNT_POLICY_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME           INTEGER      CONSTRAINT MOUNT_POLICY_LUT_NN  NOT NULL,"
+  "  CONSTRAINT MOUNT_POLICY_PK PRIMARY KEY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE REQUESTER_MOUNT_RULE("
+  "  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_RULE_DIN_NN  NOT NULL,"
+  "  REQUESTER_NAME         VARCHAR(100)    CONSTRAINT RQSTER_RULE_RN_NN   NOT NULL,"
+  "  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_RULE_MPN_NN  NOT NULL,"
+  "  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_RULE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      INTEGER      CONSTRAINT RQSTER_RULE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       INTEGER      CONSTRAINT RQSTER_RULE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT RQSTER_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_NAME),"
+  "  CONSTRAINT RQSTER_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)"
+  "    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE REQUESTER_GROUP_MOUNT_RULE("
+  "  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_DIN_NN  NOT NULL,"
+  "  REQUESTER_GROUP_NAME   VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_RGN_NN  NOT NULL,"
+  "  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_MPN_NN  NOT NULL,"
+  "  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_GRP_RULE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      INTEGER      CONSTRAINT RQSTER_GRP_RULE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       INTEGER      CONSTRAINT RQSTER_GRP_RULE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT RQSTER_GRP_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME),"
+  "  CONSTRAINT RQSTER_GRP_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)"
+  "    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE ARCHIVE_FILE("
+  "  ARCHIVE_FILE_ID         INTEGER      CONSTRAINT ARCHIVE_FILE_AFI_NN  NOT NULL,"
+  "  DISK_INSTANCE_NAME      VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DIN_NN  NOT NULL,"
+  "  DISK_FILE_ID            VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DFI_NN  NOT NULL,"
+  "  DISK_FILE_UID           INTEGER      CONSTRAINT ARCHIVE_FILE_DFUID_NN  NOT NULL,"
+  "  DISK_FILE_GID           INTEGER      CONSTRAINT ARCHIVE_FILE_DFGID_NN  NOT NULL,"
+  "  SIZE_IN_BYTES           INTEGER      CONSTRAINT ARCHIVE_FILE_SIB_NN  NOT NULL,"
+  "  CHECKSUM_BLOB           BLOB(200),"
+  "  CHECKSUM_ADLER32        INTEGER      CONSTRAINT ARCHIVE_FILE_CB2_NN  NOT NULL,"
+  "  STORAGE_CLASS_ID        INTEGER      CONSTRAINT ARCHIVE_FILE_SCI_NN  NOT NULL,"
+  "  CREATION_TIME           INTEGER      CONSTRAINT ARCHIVE_FILE_CT2_NN  NOT NULL,"
+  "  RECONCILIATION_TIME     INTEGER      CONSTRAINT ARCHIVE_FILE_RT_NN   NOT NULL,"
+  "  IS_DELETED              CHAR(1)         DEFAULT '0' CONSTRAINT ARCHIVE_FILE_ID_NN NOT NULL,"
+  "  COLLOCATION_HINT        VARCHAR(100),"
+  "  CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_ID_BOOL_CK CHECK(IS_DELETED IN ('0', '1'))"
+  ");"
+  "CREATE INDEX ARCHIVE_FILE_DIN_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME);"
+  "CREATE INDEX ARCHIVE_FILE_DFI_IDX ON ARCHIVE_FILE(DISK_FILE_ID);"
+  "CREATE TABLE TAPE_FILE("
+  "  VID                      VARCHAR(100)   CONSTRAINT TAPE_FILE_V_NN    NOT NULL,"
+  "  FSEQ                     INTEGER     CONSTRAINT TAPE_FILE_F_NN    NOT NULL,"
+  "  BLOCK_ID                 INTEGER     CONSTRAINT TAPE_FILE_BI_NN   NOT NULL,"
+  "  LOGICAL_SIZE_IN_BYTES    INTEGER     CONSTRAINT TAPE_FILE_CSIB_NN NOT NULL,"
+  "  COPY_NB                  INTEGER      CONSTRAINT TAPE_FILE_CN_NN   NOT NULL,"
+  "  CREATION_TIME            INTEGER     CONSTRAINT TAPE_FILE_CT_NN   NOT NULL,"
+  "  ARCHIVE_FILE_ID          INTEGER     CONSTRAINT TAPE_FILE_AFI_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_FILE_PK PRIMARY KEY(VID, FSEQ),"
+  "  CONSTRAINT TAPE_FILE_TAPE_FK FOREIGN KEY(VID)"
+  "    REFERENCES TAPE(VID),"
+  "  CONSTRAINT TAPE_FILE_ARCHIVE_FILE_FK FOREIGN KEY(ARCHIVE_FILE_ID)"
+  "    REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),"
+  "  CONSTRAINT TAPE_FILE_VID_BLOCK_ID_UN UNIQUE(VID, BLOCK_ID),"
+  "  CONSTRAINT TAPE_FILE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0)"
+  ");"
+  "CREATE INDEX TAPE_FILE_VID_IDX ON TAPE_FILE(VID);"
+  "CREATE INDEX TAPE_FILE_ARCHIVE_FILE_ID_IDX ON TAPE_FILE(ARCHIVE_FILE_ID);"
+  "CREATE TABLE ACTIVITIES_WEIGHTS ("
+  "  DISK_INSTANCE_NAME       VARCHAR(100),"
+  "  ACTIVITY                 VARCHAR(100),"
+  "  WEIGHT                   VARCHAR(100),"
+  "  USER_COMMENT             VARCHAR(1000)   CONSTRAINT ACTIV_WEIGHTS_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME        INTEGER      CONSTRAINT ACTIV_WEIGHTS_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME         INTEGER      CONSTRAINT ACTIV_WEIGHTS_LUT_NN  NOT NULL"
+  ");"
+  "CREATE TABLE FILE_RECYCLE_LOG("
+  "  FILE_RECYCLE_LOG_ID        INTEGER          CONSTRAINT FILE_RECYCLE_LOG_ID_NN NOT NULL,"
+  "  VID                        VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_VID_NN NOT NULL,"
+  "  FSEQ                       INTEGER          CONSTRAINT FILE_RECYCLE_LOG_FSEQ_NN NOT NULL,"
+  "  BLOCK_ID                   INTEGER          CONSTRAINT FILE_RECYCLE_LOG_BID_NN NOT NULL,"
+  "  COPY_NB                    INTEGER           CONSTRAINT FILE_RECYCLE_LOG_COPY_NB_NN NOT NULL,"
+  "  TAPE_FILE_CREATION_TIME    INTEGER          CONSTRAINT FILE_RECYCLE_LOG_TFCT_NN NOT NULL,"
+  "  ARCHIVE_FILE_ID            INTEGER          CONSTRAINT FILE_RECYCLE_LOG_AFI_NN NOT NULL,"
+  "  DISK_INSTANCE_NAME         VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DIN_NN NOT NULL,"
+  "  DISK_FILE_ID               VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFI_NN NOT NULL,"
+  "  DISK_FILE_ID_WHEN_DELETED  VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFIWD_NN NOT NULL,"
+  "  DISK_FILE_UID              INTEGER          CONSTRAINT FILE_RECYCLE_LOG_DFU_NN NOT NULL,"
+  "  DISK_FILE_GID              INTEGER          CONSTRAINT FILE_RECYCLE_LOG_DFG_NN NOT NULL,"
+  "  SIZE_IN_BYTES              INTEGER          CONSTRAINT FILE_RECYCLE_LOG_SIB_NN NOT NULL,"
+  "  CHECKSUM_BLOB              BLOB(200),"
+  "  CHECKSUM_ADLER32           INTEGER          CONSTRAINT FILE_RECYCLE_LOG_CA_NN NOT NULL,"
+  "  STORAGE_CLASS_ID           INTEGER          CONSTRAINT FILE_RECYCLE_LOG_SCI_NN NOT NULL,"
+  "  ARCHIVE_FILE_CREATION_TIME INTEGER          CONSTRAINT FILE_RECYLE_LOG_CT_NN NOT NULL,"
+  "  RECONCILIATION_TIME        INTEGER          CONSTRAINT FILE_RECYCLE_LOG_RT_NN NOT NULL,"
+  "  COLLOCATION_HINT           VARCHAR(100),"
+  "  DISK_FILE_PATH             VARCHAR(2000),"
+  "  REASON_LOG                 VARCHAR(1000)       CONSTRAINT FILE_RECYCLE_LOG_RL_NN NOT NULL,"
+  "  RECYCLE_LOG_TIME           INTEGER          CONSTRAINT FILE_RECYCLE_LOG_RLT_NN NOT NULL,"
+  "  CONSTRAINT FILE_RECYCLE_LOG_PK PRIMARY KEY(FILE_RECYCLE_LOG_ID),"
+  "  CONSTRAINT FILE_RECYCLE_LOG_VID_FK FOREIGN KEY(VID) REFERENCES TAPE(VID),"
+  "  CONSTRAINT FILE_RECYCLE_LOG_SC_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID)"
+  ");"
+  "CREATE INDEX FILE_RECYCLE_LOG_DFI_IDX ON FILE_RECYCLE_LOG(DISK_FILE_ID);"
+  ""
+  "CREATE TABLE DRIVE_CONFIG ("
+  "  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_DN_NN  NOT NULL,"
+  "  CATEGORY                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_C_NN   NOT NULL,"
+  "  KEY_NAME                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_KN_NN  NOT NULL,"
+  "  VALUE                       VARCHAR(1000)      CONSTRAINT DRIVE_CONFIG_V_NN   NOT NULL,"
+  "  SOURCE                      VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_S_NN   NOT NULL,"
+  "  CONSTRAINT DRIVE_CONFIG_DN_PK PRIMARY KEY(KEY_NAME, DRIVE_NAME)"
+  ");"
+  ""
+  "CREATE TABLE TAPE_DRIVE ("
+  "  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_STATE_DN_NN NOT NULL,"
+  "  HOST                        VARCHAR(100)       CONSTRAINT DRIVE_STATE_H_NN  NOT NULL,"
+  "  LOGICAL_LIBRARY             VARCHAR(100)       CONSTRAINT DRIVE_STATE_LL_NN NOT NULL,"
+  "  SESSION_ID                  INTEGER,"
+  "  BYTES_TRANSFERED_IN_SESSION INTEGER,"
+  "  FILES_TRANSFERED_IN_SESSION INTEGER,"
+  "  LATEST_BANDWIDTH            VARCHAR(100),"
+  "  SESSION_START_TIME          INTEGER,"
+  "  MOUNT_START_TIME            INTEGER,"
+  "  TRANSFER_START_TIME         INTEGER,"
+  "  UNLOAD_START_TIME           INTEGER,"
+  "  UNMOUNT_START_TIME          INTEGER,"
+  "  DRAINING_START_TIME         INTEGER,"
+  "  DOWN_OR_UP_START_TIME       INTEGER,"
+  "  PROBE_START_TIME            INTEGER,"
+  "  CLEANUP_START_TIME          INTEGER,"
+  "  START_START_TIME            INTEGER,"
+  "  SHUTDOWN_TIME               INTEGER,"
+  "  MOUNT_TYPE                  INTEGER      CONSTRAINT DRIVE_STATE_MT_NN NOT NULL,"
+  "  DRIVE_STATUS                VARCHAR(100)    DEFAULT 'UNKNOWN' CONSTRAINT DRIVE_STATE_DS_NN NOT NULL,"
+  "  DESIRED_UP                  CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DU_NN  NOT NULL,"
+  "  DESIRED_FORCE_DOWN          CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DFD_NN NOT NULL,"
+  "  REASON_UP_DOWN              VARCHAR(1000),"
+  "  CURRENT_VID                 VARCHAR(100),"
+  "  CTA_VERSION                 VARCHAR(100),"
+  "  CURRENT_PRIORITY            INTEGER,"
+  "  CURRENT_ACTIVITY            VARCHAR(100),"
+  "  CURRENT_ACTIVITY_WEIGHT     VARCHAR(100),"
+  "  CURRENT_TAPE_POOL           VARCHAR(100),"
+  "  NEXT_MOUNT_TYPE             INTEGER,"
+  "  NEXT_VID                    VARCHAR(100),"
+  "  NEXT_TAPE_POOL              VARCHAR(100),"
+  "  NEXT_PRIORITY               INTEGER,"
+  "  NEXT_ACTIVITY               VARCHAR(100),"
+  "  NEXT_ACTIVITY_WEIGHT        VARCHAR(100),"
+  "  DEV_FILE_NAME               VARCHAR(100),"
+  "  RAW_LIBRARY_SLOT            VARCHAR(100),"
+  "  CURRENT_VO                  VARCHAR(100),"
+  "  NEXT_VO                     VARCHAR(100),"
+  "  USER_COMMENT                VARCHAR(1000),"
+  "  CREATION_LOG_USER_NAME      VARCHAR(100),"
+  "  CREATION_LOG_HOST_NAME      VARCHAR(100),"
+  "  CREATION_LOG_TIME           INTEGER,"
+  "  LAST_UPDATE_USER_NAME       VARCHAR(100),"
+  "  LAST_UPDATE_HOST_NAME       VARCHAR(100),"
+  "  LAST_UPDATE_TIME            INTEGER,"
+  "  DISK_SYSTEM_NAME            VARCHAR(100)       CONSTRAINT DRIVE_STATE_DSN_NN NOT NULL,"
+  "  RESERVED_BYTES              INTEGER         CONSTRAINT DRIVE_STATE_RB_NN  NOT NULL,"
+  "  CONSTRAINT DRIVE_STATE_DN_PK PRIMARY KEY(DRIVE_NAME),"
+  "  CONSTRAINT DRIVE_STATE_DU_BOOL_CK CHECK(DESIRED_UP IN ('0', '1')),"
+  "  CONSTRAINT DRIVE_STATE_DFD_BOOL_CK CHECK(DESIRED_FORCE_DOWN IN ('0', '1')),"
+  "  CONSTRAINT DRIVE_STATE_DS_STRING_CK CHECK(DRIVE_STATUS IN ('DOWN', 'UP', 'PROBING', 'STARTING',"
+  "  'MOUNTING', 'TRANSFERING', 'UNLOADING', 'UNMOUNTING', 'DRAININGTODISK', 'CLEANINGUP', 'SHUTDOWN',"
+  "  'UNKNOWN'))"
+  ");"
+  "INSERT INTO CTA_CATALOGUE("
+  "  SCHEMA_VERSION_MAJOR,"
+  "  SCHEMA_VERSION_MINOR,"
+  "  STATUS)"
+  "VALUES("
+  "  4,"
+  "  2,"
+  "  'PRODUCTION');"
+      },
+  {"postgres",  "CREATE SEQUENCE ARCHIVE_FILE_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NO MAXVALUE"
+  "  MINVALUE 1"
+  "  NO CYCLE"
+  "  CACHE 20;"
+  "CREATE SEQUENCE LOGICAL_LIBRARY_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NO MAXVALUE"
+  "  MINVALUE 1"
+  "  NO CYCLE"
+  "  CACHE 20;"
+  "CREATE SEQUENCE MEDIA_TYPE_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NO MAXVALUE"
+  "  MINVALUE 1"
+  "  NO CYCLE"
+  "  CACHE 20;"
+  "CREATE SEQUENCE STORAGE_CLASS_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NO MAXVALUE"
+  "  MINVALUE 1"
+  "  NO CYCLE"
+  "  CACHE 20;"
+  "CREATE SEQUENCE TAPE_POOL_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NO MAXVALUE"
+  "  MINVALUE 1"
+  "  NO CYCLE"
+  "  CACHE 20;"
+  "CREATE SEQUENCE VIRTUAL_ORGANIZATION_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NO MAXVALUE"
+  "  MINVALUE 1"
+  "  NO CYCLE"
+  "  CACHE 20;"
+  "CREATE SEQUENCE FILE_RECYCLE_LOG_ID_SEQ"
+  "  INCREMENT BY 1"
+  "  START WITH 1"
+  "  NO MAXVALUE"
+  "  MINVALUE 1"
+  "  NO CYCLE"
+  "  CACHE 20;"
+  "CREATE TABLE CTA_CATALOGUE("
+  "  SCHEMA_VERSION_MAJOR    NUMERIC(20, 0)      CONSTRAINT CTA_CATALOGUE_SVM1_NN NOT NULL,"
+  "  SCHEMA_VERSION_MINOR    NUMERIC(20, 0)      CONSTRAINT CTA_CATALOGUE_SVM2_NN NOT NULL,"
+  "  NEXT_SCHEMA_VERSION_MAJOR NUMERIC(20, 0),"
+  "  NEXT_SCHEMA_VERSION_MINOR NUMERIC(20, 0),"
+  "  STATUS                  VARCHAR(100),"
+  "  IS_PRODUCTION           CHAR(1)         DEFAULT '0' CONSTRAINT CTA_CATALOGUE_IP_NN NOT NULL,"
+  "  CONSTRAINT CTA_CATALOGUE_IP_BOOL_CK     CHECK(IS_PRODUCTION IN ('0','1'))"
+  ");"
+  "CREATE TABLE ADMIN_USER("
+  "  ADMIN_USER_NAME         VARCHAR(100)    CONSTRAINT ADMIN_USER_AUN_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ADMIN_USER_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ADMIN_USER_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT ADMIN_USER_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ADMIN_USER_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT ADMIN_USER_LUT_NN  NOT NULL,"
+  "  CONSTRAINT ADMIN_USER_PK PRIMARY KEY(ADMIN_USER_NAME)"
+  ");"
+  "CREATE TABLE DISK_SYSTEM("
+  "  DISK_SYSTEM_NAME        VARCHAR(100)    CONSTRAINT DISK_SYSTEM_DSNM_NN NOT NULL,"
+  "  FILE_REGEXP             VARCHAR(100)    CONSTRAINT DISK_SYSTEM_FR_NN   NOT NULL,"
+  "  FREE_SPACE_QUERY_URL    VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_FSQU_NN NOT NULL,"
+  "  REFRESH_INTERVAL        NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_RI_NN   NOT NULL,"
+  "  TARGETED_FREE_SPACE     NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_TFS_NN  NOT NULL,"
+  "  SLEEP_TIME              NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_ST_NN   NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT DISK_SYSTEM_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT DISK_SYSTEM_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT DISK_SYSTEM_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT DISK_SYSTEM_LUT_NN  NOT NULL,"
+  "  CONSTRAINT NAME_PK PRIMARY KEY(DISK_SYSTEM_NAME)"
+  ");"
+  "CREATE TABLE VIRTUAL_ORGANIZATION("
+  "  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_VOI_NN  NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_NAME VARCHAR(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,"
+  "  READ_MAX_DRIVES NUMERIC(20, 0)              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,"
+  "  WRITE_MAX_DRIVES NUMERIC(20, 0)             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,"
+  "  MAX_FILE_SIZE NUMERIC(20, 0)                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT VIRTUAL_ORGANIZATION_LUT_NN  NOT NULL,"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_PK PRIMARY KEY(VIRTUAL_ORGANIZATION_ID),"
+  "  CONSTRAINT VIRTUAL_ORGANIZATION_VON_UN UNIQUE(VIRTUAL_ORGANIZATION_NAME)"
+  ");"
+  "CREATE TABLE STORAGE_CLASS("
+  "  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_SCI_NN  NOT NULL,"
+  "  STORAGE_CLASS_NAME      VARCHAR(100)    CONSTRAINT STORAGE_CLASS_SCN_NN  NOT NULL,"
+  "  NB_COPIES               NUMERIC(3, 0)       CONSTRAINT STORAGE_CLASS_NC_NN   NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_VOI_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT STORAGE_CLASS_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT STORAGE_CLASS_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT STORAGE_CLASS_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT STORAGE_CLASS_LUT_NN  NOT NULL,"
+  "  CONSTRAINT STORAGE_CLASS_PK PRIMARY KEY(STORAGE_CLASS_ID),"
+  "  CONSTRAINT STORAGE_CLASS_SCN_UN UNIQUE(STORAGE_CLASS_NAME),"
+  "  CONSTRAINT STORAGE_CLASS_VOI_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)"
+  ");"
+  "CREATE TABLE TAPE_POOL("
+  "  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_TPI_NN  NOT NULL,"
+  "  TAPE_POOL_NAME          VARCHAR(100)    CONSTRAINT TAPE_POOL_TPN_NN  NOT NULL,"
+  "  VIRTUAL_ORGANIZATION_ID NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_VOI_NN  NOT NULL,"
+  "  NB_PARTIAL_TAPES        NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_NPT_NN  NOT NULL,"
+  "  IS_ENCRYPTED            CHAR(1)         CONSTRAINT TAPE_POOL_IE_NN   NOT NULL,"
+  "  SUPPLY                  VARCHAR(100),"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT TAPE_POOL_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_POOL_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_POOL_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT TAPE_POOL_LUT_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_POOL_PK PRIMARY KEY(TAPE_POOL_ID),"
+  "  CONSTRAINT TAPE_POOL_TPN_UN UNIQUE(TAPE_POOL_NAME),"
+  "  CONSTRAINT TAPE_POOL_IS_ENCRYPTED_BOOL_CK CHECK(IS_ENCRYPTED IN ('0', '1')),"
+  "  CONSTRAINT TAPE_POOL_VO_FK FOREIGN KEY(VIRTUAL_ORGANIZATION_ID) REFERENCES VIRTUAL_ORGANIZATION(VIRTUAL_ORGANIZATION_ID)"
+  ");"
+  "CREATE TABLE ARCHIVE_ROUTE("
+  "  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_SCI_NN  NOT NULL,"
+  "  COPY_NB                 NUMERIC(3, 0)       CONSTRAINT ARCHIVE_ROUTE_CN_NN   NOT NULL,"
+  "  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_TPI_NN  NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT ARCHIVE_ROUTE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT ARCHIVE_ROUTE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_ROUTE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT ARCHIVE_ROUTE_PK PRIMARY KEY(STORAGE_CLASS_ID, COPY_NB),"
+  "  CONSTRAINT ARCHIVE_ROUTE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),"
+  "  CONSTRAINT ARCHIVE_ROUTE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),"
+  "  CONSTRAINT ARCHIVE_ROUTE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0),"
+  "  CONSTRAINT ARCHIVE_ROUTE_SCI_TPI_UN UNIQUE(STORAGE_CLASS_ID, TAPE_POOL_ID)"
+  ");"
+  "CREATE TABLE MEDIA_TYPE("
+  "  MEDIA_TYPE_ID          NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_MTI_NN  NOT NULL,"
+  "  MEDIA_TYPE_NAME        VARCHAR(100)  CONSTRAINT MEDIA_TYPE_MTN_NN  NOT NULL,"
+  "  CARTRIDGE              VARCHAR(100)  CONSTRAINT MEDIA_TYPE_C_NN    NOT NULL,"
+  "  CAPACITY_IN_BYTES      NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_CIB_NN  NOT NULL,"
+  "  PRIMARY_DENSITY_CODE   NUMERIC(3, 0),"
+  "  SECONDARY_DENSITY_CODE NUMERIC(3, 0),"
+  "  NB_WRAPS               NUMERIC(10, 0),"
+  "  MIN_LPOS               NUMERIC(20, 0),"
+  "  MAX_LPOS               NUMERIC(20, 0),"
+  "  USER_COMMENT           VARCHAR(1000) CONSTRAINT MEDIA_TYPE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)  CONSTRAINT MEDIA_TYPE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)  CONSTRAINT MEDIA_TYPE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       NUMERIC(20, 0)    CONSTRAINT MEDIA_TYPE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT MEDIA_TYPE_PK PRIMARY KEY(MEDIA_TYPE_ID),"
+  "  CONSTRAINT MEDIA_TYPE_MTN_UN UNIQUE(MEDIA_TYPE_NAME)"
+  ");"
+  "CREATE TABLE LOGICAL_LIBRARY("
+  "  LOGICAL_LIBRARY_ID      NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_LLI_NN  NOT NULL,"
+  "  LOGICAL_LIBRARY_NAME    VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LLN_NN  NOT NULL,"
+  "  IS_DISABLED             CHAR(1)         DEFAULT '0' CONSTRAINT LOGICAL_LIBRARY_ID_NN NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000)   CONSTRAINT LOGICAL_LIBRARY_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT LOGICAL_LIBRARY_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT LOGICAL_LIBRARY_LUT_NN  NOT NULL,"
+  "  CONSTRAINT LOGICAL_LIBRARY_PK PRIMARY KEY(LOGICAL_LIBRARY_ID),"
+  "  CONSTRAINT LOGICAL_LIBRARY_LLN_UN UNIQUE(LOGICAL_LIBRARY_NAME),"
+  "  CONSTRAINT LOGICAL_LIBRARY_ID_BOOL_CK CHECK(IS_DISABLED IN ('0', '1'))"
+  ");"
+  "CREATE TABLE TAPE("
+  "  VID                     VARCHAR(100)    CONSTRAINT TAPE_V_NN    NOT NULL,"
+  "  MEDIA_TYPE_ID           NUMERIC(20, 0)      CONSTRAINT TAPE_MTID_NN   NOT NULL,"
+  "  VENDOR                  VARCHAR(100)    CONSTRAINT TAPE_V2_NN   NOT NULL,"
+  "  LOGICAL_LIBRARY_ID      NUMERIC(20, 0)      CONSTRAINT TAPE_LLI_NN  NOT NULL,"
+  "  TAPE_POOL_ID            NUMERIC(20, 0)      CONSTRAINT TAPE_TPI_NN  NOT NULL,"
+  "  ENCRYPTION_KEY_NAME     VARCHAR(100),"
+  "  DATA_IN_BYTES           NUMERIC(20, 0)      CONSTRAINT TAPE_DIB_NN  NOT NULL,"
+  "  LAST_FSEQ               NUMERIC(20, 0)      CONSTRAINT TAPE_LF_NN   NOT NULL,"
+  "  NB_MASTER_FILES         NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_NB_MASTER_FILES_NN NOT NULL,"
+  "  MASTER_DATA_IN_BYTES    NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_MASTER_DATA_IN_BYTES_NN NOT NULL,"
+  "  IS_FULL                 CHAR(1)         CONSTRAINT TAPE_IF_NN   NOT NULL,"
+  "  IS_FROM_CASTOR          CHAR(1)         CONSTRAINT TAPE_IFC_NN  NOT NULL,"
+  "  DIRTY                   CHAR(1)         DEFAULT '1' CONSTRAINT TAPE_DIRTY_NN NOT NULL,"
+  "  NB_COPY_NB_1            NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_1_NN NOT NULL,"
+  "  COPY_NB_1_IN_BYTES      NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_1_IN_BYTES_NN NOT NULL,"
+  "  NB_COPY_NB_GT_1         NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_NB_COPY_NB_GT_1_NN NOT NULL,"
+  "  COPY_NB_GT_1_IN_BYTES   NUMERIC(20, 0)     DEFAULT 0 CONSTRAINT TAPE_COPY_NB_GT_1_IN_BYTES_NN NOT NULL,"
+  "  LABEL_DRIVE             VARCHAR(100),"
+  "  LABEL_TIME              NUMERIC(20, 0)    ,"
+  "  LAST_READ_DRIVE         VARCHAR(100),"
+  "  LAST_READ_TIME          NUMERIC(20, 0)    ,"
+  "  LAST_WRITE_DRIVE        VARCHAR(100),"
+  "  LAST_WRITE_TIME         NUMERIC(20, 0)    ,"
+  "  READ_MOUNT_COUNT        NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_RMC_NN NOT NULL,"
+  "  WRITE_MOUNT_COUNT       NUMERIC(20, 0)      DEFAULT 0 CONSTRAINT TAPE_WMC_NN NOT NULL,"
+  "  USER_COMMENT            VARCHAR(1000),"
+  "  TAPE_STATE              VARCHAR(100)    CONSTRAINT TAPE_TS_NN NOT NULL,"
+  "  STATE_REASON            VARCHAR(1000),"
+  "  STATE_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_SUT_NN NOT NULL,"
+  "  STATE_MODIFIED_BY       VARCHAR(100)    CONSTRAINT TAPE_SMB_NN NOT NULL,"
+  "  CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT TAPE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME       NUMERIC(20, 0)      CONSTRAINT TAPE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME   VARCHAR(100)    CONSTRAINT TAPE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME        NUMERIC(20, 0)      CONSTRAINT TAPE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_PK PRIMARY KEY(VID),"
+  "  CONSTRAINT TAPE_LOGICAL_LIBRARY_FK FOREIGN KEY(LOGICAL_LIBRARY_ID) REFERENCES LOGICAL_LIBRARY(LOGICAL_LIBRARY_ID),"
+  "  CONSTRAINT TAPE_TAPE_POOL_FK FOREIGN KEY(TAPE_POOL_ID) REFERENCES TAPE_POOL(TAPE_POOL_ID),"
+  "  CONSTRAINT TAPE_IS_FULL_BOOL_CK CHECK(IS_FULL IN ('0', '1')),"
+  "  CONSTRAINT TAPE_IS_FROM_CASTOR_BOOL_CK CHECK(IS_FROM_CASTOR IN ('0', '1')),"
+  "  CONSTRAINT TAPE_DIRTY_BOOL_CK CHECK(DIRTY IN ('0','1')),"
+  "  CONSTRAINT TAPE_STATE_CK CHECK(TAPE_STATE IN ('ACTIVE', 'DISABLED', 'BROKEN')),"
+  "  CONSTRAINT TAPE_MEDIA_TYPE_FK FOREIGN KEY(MEDIA_TYPE_ID) REFERENCES MEDIA_TYPE(MEDIA_TYPE_ID)"
+  ");"
+  "CREATE INDEX TAPE_TAPE_POOL_ID_IDX ON TAPE(TAPE_POOL_ID);"
+  "CREATE INDEX TAPE_STATE_IDX ON TAPE(TAPE_STATE);"
+  "CREATE TABLE MOUNT_POLICY("
+  "  MOUNT_POLICY_NAME          VARCHAR(100)    CONSTRAINT MOUNT_POLICY_MPN_NN  NOT NULL,"
+  "  ARCHIVE_PRIORITY           NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_AP_NN   NOT NULL,"
+  "  ARCHIVE_MIN_REQUEST_AGE    NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_AMRA_NN NOT NULL,"
+  "  RETRIEVE_PRIORITY          NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_RP_NN   NOT NULL,"
+  "  RETRIEVE_MIN_REQUEST_AGE   NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_RMRA_NN NOT NULL,"
+  "  USER_COMMENT               VARCHAR(1000)   CONSTRAINT MOUNT_POLICY_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME     VARCHAR(100)    CONSTRAINT MOUNT_POLICY_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME          NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME      VARCHAR(100)    CONSTRAINT MOUNT_POLICY_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME           NUMERIC(20, 0)      CONSTRAINT MOUNT_POLICY_LUT_NN  NOT NULL,"
+  "  CONSTRAINT MOUNT_POLICY_PK PRIMARY KEY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE REQUESTER_MOUNT_RULE("
+  "  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_RULE_DIN_NN  NOT NULL,"
+  "  REQUESTER_NAME         VARCHAR(100)    CONSTRAINT RQSTER_RULE_RN_NN   NOT NULL,"
+  "  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_RULE_MPN_NN  NOT NULL,"
+  "  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_RULE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_RULE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      NUMERIC(20, 0)      CONSTRAINT RQSTER_RULE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_RULE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT RQSTER_RULE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT RQSTER_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_NAME),"
+  "  CONSTRAINT RQSTER_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)"
+  "    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE REQUESTER_GROUP_MOUNT_RULE("
+  "  DISK_INSTANCE_NAME     VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_DIN_NN  NOT NULL,"
+  "  REQUESTER_GROUP_NAME   VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_RGN_NN  NOT NULL,"
+  "  MOUNT_POLICY_NAME      VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_MPN_NN  NOT NULL,"
+  "  USER_COMMENT           VARCHAR(1000)   CONSTRAINT RQSTER_GRP_RULE_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME      NUMERIC(20, 0)      CONSTRAINT RQSTER_GRP_RULE_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME  VARCHAR(100)    CONSTRAINT RQSTER_GRP_RULE_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME       NUMERIC(20, 0)      CONSTRAINT RQSTER_GRP_RULE_LUT_NN  NOT NULL,"
+  "  CONSTRAINT RQSTER_GRP_RULE_PK PRIMARY KEY(DISK_INSTANCE_NAME, REQUESTER_GROUP_NAME),"
+  "  CONSTRAINT RQSTER_GRP_RULE_MNT_PLC_FK FOREIGN KEY(MOUNT_POLICY_NAME)"
+  "    REFERENCES MOUNT_POLICY(MOUNT_POLICY_NAME)"
+  ");"
+  "CREATE TABLE ARCHIVE_FILE("
+  "  ARCHIVE_FILE_ID         NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_AFI_NN  NOT NULL,"
+  "  DISK_INSTANCE_NAME      VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DIN_NN  NOT NULL,"
+  "  DISK_FILE_ID            VARCHAR(100)    CONSTRAINT ARCHIVE_FILE_DFI_NN  NOT NULL,"
+  "  DISK_FILE_UID           NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_DFUID_NN  NOT NULL,"
+  "  DISK_FILE_GID           NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_DFGID_NN  NOT NULL,"
+  "  SIZE_IN_BYTES           NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_SIB_NN  NOT NULL,"
+  "  CHECKSUM_BLOB           BYTEA,"
+  "  CHECKSUM_ADLER32        NUMERIC(10, 0)      CONSTRAINT ARCHIVE_FILE_CB2_NN  NOT NULL,"
+  "  STORAGE_CLASS_ID        NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_SCI_NN  NOT NULL,"
+  "  CREATION_TIME           NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_CT2_NN  NOT NULL,"
+  "  RECONCILIATION_TIME     NUMERIC(20, 0)      CONSTRAINT ARCHIVE_FILE_RT_NN   NOT NULL,"
+  "  IS_DELETED              CHAR(1)         DEFAULT '0' CONSTRAINT ARCHIVE_FILE_ID_NN NOT NULL,"
+  "  COLLOCATION_HINT        VARCHAR(100),"
+  "  CONSTRAINT ARCHIVE_FILE_PK PRIMARY KEY(ARCHIVE_FILE_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_STORAGE_CLASS_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID),"
+  "  CONSTRAINT ARCHIVE_FILE_ID_BOOL_CK CHECK(IS_DELETED IN ('0', '1'))"
+  ");"
+  "CREATE INDEX ARCHIVE_FILE_DIN_IDX ON ARCHIVE_FILE(DISK_INSTANCE_NAME);"
+  "CREATE INDEX ARCHIVE_FILE_DFI_IDX ON ARCHIVE_FILE(DISK_FILE_ID);"
+  "CREATE TABLE TAPE_FILE("
+  "  VID                      VARCHAR(100)   CONSTRAINT TAPE_FILE_V_NN    NOT NULL,"
+  "  FSEQ                     NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_F_NN    NOT NULL,"
+  "  BLOCK_ID                 NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_BI_NN   NOT NULL,"
+  "  LOGICAL_SIZE_IN_BYTES    NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_CSIB_NN NOT NULL,"
+  "  COPY_NB                  NUMERIC(3, 0)      CONSTRAINT TAPE_FILE_CN_NN   NOT NULL,"
+  "  CREATION_TIME            NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_CT_NN   NOT NULL,"
+  "  ARCHIVE_FILE_ID          NUMERIC(20, 0)     CONSTRAINT TAPE_FILE_AFI_NN  NOT NULL,"
+  "  CONSTRAINT TAPE_FILE_PK PRIMARY KEY(VID, FSEQ),"
+  "  CONSTRAINT TAPE_FILE_TAPE_FK FOREIGN KEY(VID)"
+  "    REFERENCES TAPE(VID),"
+  "  CONSTRAINT TAPE_FILE_ARCHIVE_FILE_FK FOREIGN KEY(ARCHIVE_FILE_ID)"
+  "    REFERENCES ARCHIVE_FILE(ARCHIVE_FILE_ID),"
+  "  CONSTRAINT TAPE_FILE_VID_BLOCK_ID_UN UNIQUE(VID, BLOCK_ID),"
+  "  CONSTRAINT TAPE_FILE_COPY_NB_GT_0_CK CHECK(COPY_NB > 0)"
+  ");"
+  "CREATE INDEX TAPE_FILE_VID_IDX ON TAPE_FILE(VID);"
+  "CREATE INDEX TAPE_FILE_ARCHIVE_FILE_ID_IDX ON TAPE_FILE(ARCHIVE_FILE_ID);"
+  "CREATE TABLE ACTIVITIES_WEIGHTS ("
+  "  DISK_INSTANCE_NAME       VARCHAR(100),"
+  "  ACTIVITY                 VARCHAR(100),"
+  "  WEIGHT                   VARCHAR(100),"
+  "  USER_COMMENT             VARCHAR(1000)   CONSTRAINT ACTIV_WEIGHTS_UC_NN   NOT NULL,"
+  "  CREATION_LOG_USER_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLUN_NN NOT NULL,"
+  "  CREATION_LOG_HOST_NAME   VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_CLHN_NN NOT NULL,"
+  "  CREATION_LOG_TIME        NUMERIC(20, 0)      CONSTRAINT ACTIV_WEIGHTS_CLT_NN  NOT NULL,"
+  "  LAST_UPDATE_USER_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUUN_NN NOT NULL,"
+  "  LAST_UPDATE_HOST_NAME    VARCHAR(100)    CONSTRAINT ACTIV_WEIGHTS_LUHN_NN NOT NULL,"
+  "  LAST_UPDATE_TIME         NUMERIC(20, 0)      CONSTRAINT ACTIV_WEIGHTS_LUT_NN  NOT NULL"
+  ");"
+  "CREATE TABLE FILE_RECYCLE_LOG("
+  "  FILE_RECYCLE_LOG_ID        NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_ID_NN NOT NULL,"
+  "  VID                        VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_VID_NN NOT NULL,"
+  "  FSEQ                       NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_FSEQ_NN NOT NULL,"
+  "  BLOCK_ID                   NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_BID_NN NOT NULL,"
+  "  COPY_NB                    NUMERIC(3, 0)           CONSTRAINT FILE_RECYCLE_LOG_COPY_NB_NN NOT NULL,"
+  "  TAPE_FILE_CREATION_TIME    NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_TFCT_NN NOT NULL,"
+  "  ARCHIVE_FILE_ID            NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_AFI_NN NOT NULL,"
+  "  DISK_INSTANCE_NAME         VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DIN_NN NOT NULL,"
+  "  DISK_FILE_ID               VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFI_NN NOT NULL,"
+  "  DISK_FILE_ID_WHEN_DELETED  VARCHAR(100)        CONSTRAINT FILE_RECYCLE_LOG_DFIWD_NN NOT NULL,"
+  "  DISK_FILE_UID              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_DFU_NN NOT NULL,"
+  "  DISK_FILE_GID              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_DFG_NN NOT NULL,"
+  "  SIZE_IN_BYTES              NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_SIB_NN NOT NULL,"
+  "  CHECKSUM_BLOB              BYTEA,"
+  "  CHECKSUM_ADLER32           NUMERIC(10, 0)          CONSTRAINT FILE_RECYCLE_LOG_CA_NN NOT NULL,"
+  "  STORAGE_CLASS_ID           NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_SCI_NN NOT NULL,"
+  "  ARCHIVE_FILE_CREATION_TIME NUMERIC(20, 0)          CONSTRAINT FILE_RECYLE_LOG_CT_NN NOT NULL,"
+  "  RECONCILIATION_TIME        NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_RT_NN NOT NULL,"
+  "  COLLOCATION_HINT           VARCHAR(100),"
+  "  DISK_FILE_PATH             VARCHAR(2000),"
+  "  REASON_LOG                 VARCHAR(1000)       CONSTRAINT FILE_RECYCLE_LOG_RL_NN NOT NULL,"
+  "  RECYCLE_LOG_TIME           NUMERIC(20, 0)          CONSTRAINT FILE_RECYCLE_LOG_RLT_NN NOT NULL,"
+  "  CONSTRAINT FILE_RECYCLE_LOG_PK PRIMARY KEY(FILE_RECYCLE_LOG_ID),"
+  "  CONSTRAINT FILE_RECYCLE_LOG_VID_FK FOREIGN KEY(VID) REFERENCES TAPE(VID),"
+  "  CONSTRAINT FILE_RECYCLE_LOG_SC_FK FOREIGN KEY(STORAGE_CLASS_ID) REFERENCES STORAGE_CLASS(STORAGE_CLASS_ID)"
+  ");"
+  "CREATE INDEX FILE_RECYCLE_LOG_DFI_IDX ON FILE_RECYCLE_LOG(DISK_FILE_ID);"
+  ""
+  "CREATE TABLE DRIVE_CONFIG ("
+  "  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_DN_NN  NOT NULL,"
+  "  CATEGORY                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_C_NN   NOT NULL,"
+  "  KEY_NAME                    VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_KN_NN  NOT NULL,"
+  "  VALUE                       VARCHAR(1000)      CONSTRAINT DRIVE_CONFIG_V_NN   NOT NULL,"
+  "  SOURCE                      VARCHAR(100)       CONSTRAINT DRIVE_CONFIG_S_NN   NOT NULL,"
+  "  CONSTRAINT DRIVE_CONFIG_DN_PK PRIMARY KEY(KEY_NAME, DRIVE_NAME)"
+  ");"
+  ""
+  "CREATE TABLE TAPE_DRIVE ("
+  "  DRIVE_NAME                  VARCHAR(100)       CONSTRAINT DRIVE_STATE_DN_NN NOT NULL,"
+  "  HOST                        VARCHAR(100)       CONSTRAINT DRIVE_STATE_H_NN  NOT NULL,"
+  "  LOGICAL_LIBRARY             VARCHAR(100)       CONSTRAINT DRIVE_STATE_LL_NN NOT NULL,"
+  "  SESSION_ID                  NUMERIC(20, 0),"
+  "  BYTES_TRANSFERED_IN_SESSION NUMERIC(20, 0),"
+  "  FILES_TRANSFERED_IN_SESSION NUMERIC(20, 0),"
+  "  LATEST_BANDWIDTH            VARCHAR(100),"
+  "  SESSION_START_TIME          NUMERIC(20, 0),"
+  "  MOUNT_START_TIME            NUMERIC(20, 0),"
+  "  TRANSFER_START_TIME         NUMERIC(20, 0),"
+  "  UNLOAD_START_TIME           NUMERIC(20, 0),"
+  "  UNMOUNT_START_TIME          NUMERIC(20, 0),"
+  "  DRAINING_START_TIME         NUMERIC(20, 0),"
+  "  DOWN_OR_UP_START_TIME       NUMERIC(20, 0),"
+  "  PROBE_START_TIME            NUMERIC(20, 0),"
+  "  CLEANUP_START_TIME          NUMERIC(20, 0),"
+  "  START_START_TIME            NUMERIC(20, 0),"
+  "  SHUTDOWN_TIME               NUMERIC(20, 0),"
+  "  MOUNT_TYPE                  NUMERIC(10, 0)      CONSTRAINT DRIVE_STATE_MT_NN NOT NULL,"
+  "  DRIVE_STATUS                VARCHAR(100)    DEFAULT 'UNKNOWN' CONSTRAINT DRIVE_STATE_DS_NN NOT NULL,"
+  "  DESIRED_UP                  CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DU_NN  NOT NULL,"
+  "  DESIRED_FORCE_DOWN          CHAR(1)         DEFAULT '0' CONSTRAINT DRIVE_STATE_DFD_NN NOT NULL,"
+  "  REASON_UP_DOWN              VARCHAR(1000),"
+  "  CURRENT_VID                 VARCHAR(100),"
+  "  CTA_VERSION                 VARCHAR(100),"
+  "  CURRENT_PRIORITY            NUMERIC(20, 0),"
+  "  CURRENT_ACTIVITY            VARCHAR(100),"
+  "  CURRENT_ACTIVITY_WEIGHT     VARCHAR(100),"
+  "  CURRENT_TAPE_POOL           VARCHAR(100),"
+  "  NEXT_MOUNT_TYPE             NUMERIC(10, 0),"
+  "  NEXT_VID                    VARCHAR(100),"
+  "  NEXT_TAPE_POOL              VARCHAR(100),"
+  "  NEXT_PRIORITY               NUMERIC(20, 0),"
+  "  NEXT_ACTIVITY               VARCHAR(100),"
+  "  NEXT_ACTIVITY_WEIGHT        VARCHAR(100),"
+  "  DEV_FILE_NAME               VARCHAR(100),"
+  "  RAW_LIBRARY_SLOT            VARCHAR(100),"
+  "  CURRENT_VO                  VARCHAR(100),"
+  "  NEXT_VO                     VARCHAR(100),"
+  "  USER_COMMENT                VARCHAR(1000),"
+  "  CREATION_LOG_USER_NAME      VARCHAR(100),"
+  "  CREATION_LOG_HOST_NAME      VARCHAR(100),"
+  "  CREATION_LOG_TIME           NUMERIC(20, 0),"
+  "  LAST_UPDATE_USER_NAME       VARCHAR(100),"
+  "  LAST_UPDATE_HOST_NAME       VARCHAR(100),"
+  "  LAST_UPDATE_TIME            NUMERIC(20, 0),"
+  "  DISK_SYSTEM_NAME            VARCHAR(100)       CONSTRAINT DRIVE_STATE_DSN_NN NOT NULL,"
+  "  RESERVED_BYTES              NUMERIC(20, 0)         CONSTRAINT DRIVE_STATE_RB_NN  NOT NULL,"
+  "  CONSTRAINT DRIVE_STATE_DN_PK PRIMARY KEY(DRIVE_NAME),"
+  "  CONSTRAINT DRIVE_STATE_DU_BOOL_CK CHECK(DESIRED_UP IN ('0', '1')),"
+  "  CONSTRAINT DRIVE_STATE_DFD_BOOL_CK CHECK(DESIRED_FORCE_DOWN IN ('0', '1')),"
+  "  CONSTRAINT DRIVE_STATE_DS_STRING_CK CHECK(DRIVE_STATUS IN ('DOWN', 'UP', 'PROBING', 'STARTING',"
+  "  'MOUNTING', 'TRANSFERING', 'UNLOADING', 'UNMOUNTING', 'DRAININGTODISK', 'CLEANINGUP', 'SHUTDOWN',"
+  "  'UNKNOWN'))"
+  ");"
+  "INSERT INTO CTA_CATALOGUE("
+  "  SCHEMA_VERSION_MAJOR,"
+  "  SCHEMA_VERSION_MINOR,"
+  "  STATUS)"
+  "VALUES("
+  "  4,"
+  "  2,"
+  "  'PRODUCTION');"
+  "ALTER TABLE ARCHIVE_FILE DROP CONSTRAINT"
+  "  ARCHIVE_FILE_DIN_DFI_UN;"
+  "ALTER TABLE ARCHIVE_FILE ADD CONSTRAINT"
+  "  ARCHIVE_FILE_DIN_DFI_UN UNIQUE(DISK_INSTANCE_NAME, DISK_FILE_ID) DEFERRABLE INITIALLY IMMEDIATE;"
+  "ALTER TABLE CTA_CATALOGUE ADD CONSTRAINT"
+  "  CATALOGUE_STATUS_CONTENT_CK CHECK((NEXT_SCHEMA_VERSION_MAJOR IS NULL AND NEXT_SCHEMA_VERSION_MINOR IS NULL AND STATUS='PRODUCTION') OR (STATUS='UPGRADING'));"
+      },
+    }  },
 };
 
 }}
diff --git a/catalogue/Catalogue.hpp b/catalogue/Catalogue.hpp
index 2e8aa1358ff1f97413e57764165fcdf5546c6fdf..2d7426a353f201b3dce8ace99803b9e29c333455 100644
--- a/catalogue/Catalogue.hpp
+++ b/catalogue/Catalogue.hpp
@@ -124,6 +124,7 @@ CTA_GENERATE_USER_EXCEPTION_CLASS(UserSpecifiedStorageClassUsedByArchiveFiles);
 CTA_GENERATE_USER_EXCEPTION_CLASS(UserSpecifiedStorageClassUsedByArchiveRoutes);
 CTA_GENERATE_USER_EXCEPTION_CLASS(UserSpecifiedStorageClassUsedByFileRecycleLogs);
 CTA_GENERATE_USER_EXCEPTION_CLASS(UserSpecifiedTapePoolUsedInAnArchiveRoute);
+CTA_GENERATE_USER_EXCEPTION_CLASS(UserSpecifiedExistingDeletedFileCopy);
 CTA_GENERATE_USER_EXCEPTION_CLASS(UserSpecifiedANonExistentTapeState);
 CTA_GENERATE_USER_EXCEPTION_CLASS(UserSpecifiedAnEmptyStringReasonWhenTapeStateNotActive);
 
@@ -333,6 +334,14 @@ public:
    */
   virtual void modifyVirtualOrganizationWriteMaxDrives(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t writeMaxDrives) = 0;
 
+  /**
+   * Modifies the max size of files  for the specified Virtual Organization
+   *
+   * @param voName the VO name
+   * @param maxFileSize the new max file size for the specified Virtual Organization
+   */
+  virtual void modifyVirtualOrganizationMaxFileSize(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t maxFileSize) = 0;
+
   /**
    * Modifies the comment of the specified Virtual Organization
    *
@@ -359,6 +368,8 @@ public:
   virtual void deleteStorageClass(const std::string &storageClassName) = 0;
 
   virtual std::list<common::dataStructures::StorageClass> getStorageClasses() const = 0;
+  virtual common::dataStructures::StorageClass getStorageClass(const std::string &name) const = 0;
+
   virtual void modifyStorageClassNbCopies(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const uint64_t nbCopies) = 0;
   virtual void modifyStorageClassComment(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &comment) = 0;
   virtual void modifyStorageClassVo(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &vo) = 0;
@@ -902,6 +913,15 @@ public:
    */
   virtual FileRecycleLogItor getFileRecycleLogItor(const RecycleTapeFileSearchCriteria & searchCriteria = RecycleTapeFileSearchCriteria()) const = 0;
 
+
+  /**
+   * Restores the deleted files in the Recycle log that match the criteria passed
+   *
+   * @param searchCriteria The search criteria
+   */
+  virtual void restoreFilesInRecycleLog(const RecycleTapeFileSearchCriteria & searchCriteria = RecycleTapeFileSearchCriteria()) = 0;
+
+
   /**
    * Returns the specified files in tape file sequence order.
    *
@@ -970,6 +990,7 @@ public:
       const std::string &reason) = 0;
 
 
+
   /**
    * Returns the archive file with the specified unique identifier.
    *
diff --git a/catalogue/CatalogueRetryWrapper.hpp b/catalogue/CatalogueRetryWrapper.hpp
index e64e0426359a75951485951810de76e8518f1e33..aa0aed2d9de95ddec15d7c2726c93c63a9de40cb 100644
--- a/catalogue/CatalogueRetryWrapper.hpp
+++ b/catalogue/CatalogueRetryWrapper.hpp
@@ -147,6 +147,9 @@ public:
     return retryOnLostConnection(m_log, [&]{return m_catalogue->modifyVirtualOrganizationWriteMaxDrives(admin,voName,writeMaxDrives);}, m_maxTriesToConnect);
   }
 
+  void modifyVirtualOrganizationMaxFileSize(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t maxFileSize) override {
+    return retryOnLostConnection(m_log, [&]{return m_catalogue->modifyVirtualOrganizationMaxFileSize(admin,voName,maxFileSize);}, m_maxTriesToConnect);
+  }
 
 
   void modifyVirtualOrganizationComment(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const std::string &comment) override {
@@ -165,6 +168,10 @@ public:
     return retryOnLostConnection(m_log, [&]{return m_catalogue->getStorageClasses();}, m_maxTriesToConnect);
   }
 
+  common::dataStructures::StorageClass getStorageClass(const std::string &name) const override {
+   return retryOnLostConnection(m_log, [&]{return m_catalogue->getStorageClass(name);}, m_maxTriesToConnect);
+  }
+
   void modifyStorageClassNbCopies(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const uint64_t nbCopies) override {
     return retryOnLostConnection(m_log, [&]{return m_catalogue->modifyStorageClassNbCopies(admin, name, nbCopies);}, m_maxTriesToConnect);
   }
@@ -533,6 +540,10 @@ public:
     return retryOnLostConnection(m_log, [&]{return m_catalogue->getFileRecycleLogItor(searchCriteria);}, m_maxTriesToConnect);
   }
 
+  void restoreFilesInRecycleLog(const RecycleTapeFileSearchCriteria & searchCriteria) override {
+    return retryOnLostConnection(m_log, [&]{return m_catalogue->restoreFilesInRecycleLog(searchCriteria);}, m_maxTriesToConnect);
+  }
+
   void deleteFileFromRecycleBin(const uint64_t archiveFileId, log::LogContext &lc){
     return retryOnLostConnection(m_log,[&]{return m_catalogue->deleteFileFromRecycleBin(archiveFileId,lc);},m_maxTriesToConnect);
   }
diff --git a/catalogue/CatalogueTest.cpp b/catalogue/CatalogueTest.cpp
index bdd6bf47e1b2e0278fcc4250139353812d3b8340..1660e54594d5fe023653b09ce5b3cb9418dbeb7f 100644
--- a/catalogue/CatalogueTest.cpp
+++ b/catalogue/CatalogueTest.cpp
@@ -81,6 +81,7 @@ namespace {
     vo.comment = "Creation of virtual organization vo";
     vo.readMaxDrives = 1;
     vo.writeMaxDrives = 1;
+    vo.maxFileSize = 0;
     return vo;
   }
 
@@ -92,6 +93,7 @@ namespace {
     vo.comment = "Creation of another virtual organization vo";
     vo.readMaxDrives = 1;
     vo.writeMaxDrives = 1;
+    vo.maxFileSize = 0;
     return vo;
   }
 
@@ -128,6 +130,17 @@ namespace {
     return storageClass;
   }
 
+  cta::common::dataStructures::StorageClass getStorageClassTripleCopy() {
+    using namespace cta;
+
+    common::dataStructures::StorageClass storageClass;
+    storageClass.name = "storage_class_triple_copy";
+    storageClass.nbCopies = 3;
+    storageClass.vo.name = getVo().name;
+    storageClass.comment = "Creation of storage class with 3 copies on tape";
+    return storageClass;
+  }
+
   cta::catalogue::MediaType getMediaType() {
     using namespace cta;
 
@@ -169,6 +182,14 @@ namespace {
     return tape;
   }
 
+  cta::catalogue::CreateTapeAttributes getTape3() {
+    // Tape 3 is an exact copy of tape 1 except for its VID and comment
+    auto tape = getTape1();
+    tape.vid = "VIDTHREE";
+    tape.comment = "Creation of tape three";
+    return tape;
+  }
+
   cta::catalogue::CreateMountPolicyAttributes getMountPolicy1() {
     using namespace cta;
 
@@ -261,9 +282,11 @@ cta_catalogue_CatalogueTest::cta_catalogue_CatalogueTest():
         m_storageClassSingleCopy(getStorageClass()),
         m_anotherStorageClass(getAnotherStorageClass()),
         m_storageClassDualCopy(getStorageClassDualCopy()),
+        m_storageClassTripleCopy(getStorageClassTripleCopy()),
         m_mediaType(getMediaType()),
         m_tape1(getTape1()),
-        m_tape2(getTape2()) {
+        m_tape2(getTape2()),
+        m_tape3(getTape3()) {
 }
 
 //------------------------------------------------------------------------------
@@ -8891,6 +8914,17 @@ TEST_P(cta_catalogue_CatalogueTest, getArchiveFiles_non_existance_archiveFileId)
   ASSERT_THROW(m_catalogue->getArchiveFilesItor(searchCriteria), exception::UserError);
 }
 
+TEST_P(cta_catalogue_CatalogueTest, getArchiveFiles_fSeq_without_vid) {
+  using namespace cta;
+
+  ASSERT_FALSE(m_catalogue->getArchiveFilesItor().hasMore());
+
+  catalogue::TapeFileSearchCriteria searchCriteria;
+  searchCriteria.fSeq = 1234;
+
+  ASSERT_THROW(m_catalogue->getArchiveFilesItor(searchCriteria), exception::UserError);
+}
+
 TEST_P(cta_catalogue_CatalogueTest, getArchiveFiles_disk_file_id_without_instance) {
   using namespace cta;
 
@@ -15195,6 +15229,24 @@ TEST_P(cta_catalogue_CatalogueTest, modifyVirtualOrganizationWriteMaxDrives) {
   ASSERT_THROW(m_catalogue->modifyVirtualOrganizationWriteMaxDrives(m_admin,"DOES not exists",writeMaxDrives),cta::exception::UserError);
 }
 
+TEST_P(cta_catalogue_CatalogueTest, modifyVirtualOrganizationMaxFileSize) {
+  using namespace cta;
+
+  common::dataStructures::VirtualOrganization vo = getVo();
+
+  ASSERT_NO_THROW(m_catalogue->createVirtualOrganization(m_admin,vo));
+
+  uint64_t maxFileSize = 1;
+  ASSERT_NO_THROW(m_catalogue->modifyVirtualOrganizationMaxFileSize(m_admin,vo.name,maxFileSize));
+
+  auto vos = m_catalogue->getVirtualOrganizations();
+  auto &frontVo = vos.front();
+
+  ASSERT_EQ(maxFileSize,frontVo.maxFileSize);
+
+  ASSERT_THROW(m_catalogue->modifyVirtualOrganizationMaxFileSize(m_admin,"DOES not exists", maxFileSize),cta::exception::UserError);
+}
+
 TEST_P(cta_catalogue_CatalogueTest, getVirtualOrganizationOfTapepool) {
   using namespace cta;
 
@@ -15808,9 +15860,9 @@ TEST_P(cta_catalogue_CatalogueTest, filesArePutInTheFileRecycleLogInsteadOfBeing
     criteria.diskFileIds = std::vector<std::string>();
     criteria.diskFileIds->push_back(diskFileId);
     criteria.vid = tape1.vid;
-    
+
     auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor(criteria);
-    
+
     ASSERT_TRUE(fileRecycleLogItor.hasMore());
     auto fileRecycleLog = fileRecycleLogItor.next();
     ASSERT_EQ(archiveFileId, fileRecycleLog.archiveFileId);
@@ -15818,7 +15870,7 @@ TEST_P(cta_catalogue_CatalogueTest, filesArePutInTheFileRecycleLogInsteadOfBeing
     ASSERT_EQ(copynb, fileRecycleLog.copyNb);
     ASSERT_EQ(tape1.vid, fileRecycleLog.vid);
     ASSERT_EQ(diskInstance, fileRecycleLog.diskInstanceName);
-    
+
     ASSERT_FALSE(fileRecycleLogItor.hasMore());
   }
 }
@@ -16247,7 +16299,7 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyUsingArchiveID) {
   // Write a file on tape
   {
     std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
-    
+
     std::ostringstream diskFileId;
     diskFileId << 12345677;
 
@@ -16271,14 +16323,14 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyUsingArchiveID) {
     fileWritten.copyNb = 1;
     fileWritten.tapeDrive = tapeDrive;
     tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
-    
+
     m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
   }
-  
+
   // Write a second copy of file on tape
   {
     std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
-    
+
     std::ostringstream diskFileId;
     diskFileId << 12345677;
 
@@ -16302,19 +16354,19 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyUsingArchiveID) {
     fileWritten.copyNb = 2;
     fileWritten.tapeDrive = tapeDrive;
     tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
-    
+
     m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
   }
   {
     //Assert both copies written
-    auto archiveFile = m_catalogue->getArchiveFileById(1);  
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
     ASSERT_EQ(2, archiveFile.tapeFiles.size());
   }
 
   {
     //delete copy of file on tape1
     m_catalogue->deleteTapeFileCopy(tape1.vid, 1, reason);
-    auto archiveFile = m_catalogue->getArchiveFileById(1);  
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
     ASSERT_EQ(1, archiveFile.tapeFiles.size());
     auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor();
     ASSERT_TRUE(fileRecycleLogItor.hasMore());
@@ -16332,7 +16384,7 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyUsingArchiveID) {
   {
     //delete last copy of file should fail
     ASSERT_THROW(m_catalogue->deleteTapeFileCopy(tape2.vid, 1, "reason"), exception::UserError);
-    
+
   }
 }
 
@@ -16367,7 +16419,7 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyDoesNotExist) {
   {
     //delete copy of file that does not exist should fail
     ASSERT_THROW(m_catalogue->deleteTapeFileCopy(tape2.vid, 1, reason), exception::UserError);
-    
+
   }
 }
 
@@ -16406,7 +16458,7 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyUsingFXID) {
   // Write a file on tape
   {
     std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
-    
+
     std::ostringstream diskFileId;
     diskFileId << 12345677;
 
@@ -16430,14 +16482,14 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyUsingFXID) {
     fileWritten.copyNb = 1;
     fileWritten.tapeDrive = tapeDrive;
     tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
-    
+
     m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
   }
-  
+
   // Write a second copy of file on tape
   {
     std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
-    
+
     std::ostringstream diskFileId;
     diskFileId << 12345677;
 
@@ -16461,19 +16513,19 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyUsingFXID) {
     fileWritten.copyNb = 2;
     fileWritten.tapeDrive = tapeDrive;
     tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
-    
+
     m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
   }
   {
     //Assert both copies written
-    auto archiveFile = m_catalogue->getArchiveFileById(1);  
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
     ASSERT_EQ(2, archiveFile.tapeFiles.size());
   }
 
   {
     //delete copy of file on tape1
     m_catalogue->deleteTapeFileCopy(tape1.vid, "BC614D", diskInstance, reason);
-    auto archiveFile = m_catalogue->getArchiveFileById(1);  
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
     ASSERT_EQ(1, archiveFile.tapeFiles.size());
     auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor();
     ASSERT_TRUE(fileRecycleLogItor.hasMore());
@@ -16490,8 +16542,456 @@ TEST_P(cta_catalogue_CatalogueTest, DeleteTapeFileCopyUsingFXID) {
 
   {
     //delete last copy of file should fail
-    ASSERT_THROW(m_catalogue->deleteTapeFileCopy(tape2.vid, "BC614D", diskInstance, reason), exception::UserError); 
+    ASSERT_THROW(m_catalogue->deleteTapeFileCopy(tape2.vid, "BC614D", diskInstance, reason), exception::UserError);
   }
 }
 
+TEST_P(cta_catalogue_CatalogueTest, RestoreTapeFileCopy) {
+  using namespace cta;
+
+  const bool logicalLibraryIsDisabled= false;
+  const std::string tapePoolName1 = "tape_pool_name_1";
+  const std::string tapePoolName2 = "tape_pool_name_2";
+  const uint64_t nbPartialTapes = 1;
+  const bool isEncrypted = true;
+  const cta::optional<std::string> supply("value for the supply pool mechanism");
+  const std::string diskInstance = "disk_instance";
+  const std::string tapeDrive = "tape_drive";
+  const std::string reason = "reason";
+
+  m_catalogue->createMediaType(m_admin, m_mediaType);
+  m_catalogue->createLogicalLibrary(m_admin, m_tape1.logicalLibraryName, logicalLibraryIsDisabled, "Create logical library");
+  m_catalogue->createVirtualOrganization(m_admin, m_vo);
+  m_catalogue->createTapePool(m_admin, tapePoolName1, m_vo.name, nbPartialTapes, isEncrypted, supply, "Create tape pool");
+  m_catalogue->createTapePool(m_admin, tapePoolName2, m_vo.name, nbPartialTapes, isEncrypted, supply, "Create tape pool");
+  m_catalogue->createStorageClass(m_admin, m_storageClassDualCopy);
+
+  auto tape1 = m_tape1;
+  auto tape2 = m_tape2;
+  tape1.tapePoolName = tapePoolName1;
+  tape2.tapePoolName = tapePoolName2;
+
+  m_catalogue->createTape(m_admin, tape1);
+  m_catalogue->createTape(m_admin, tape2);
+
+  ASSERT_FALSE(m_catalogue->getArchiveFilesItor().hasMore());
+  const uint64_t archiveFileSize = 2 * 1000 * 1000 * 1000;
+
+
+  // Write a file on tape
+  {
+    std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
+
+    std::ostringstream diskFileId;
+    diskFileId << 12345677;
+
+    std::ostringstream diskFilePath;
+    diskFilePath << "/test/file1";
+
+    auto fileWrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>();
+    auto & fileWritten = *fileWrittenUP;
+    fileWritten.archiveFileId = 1;
+    fileWritten.diskInstance = diskInstance;
+    fileWritten.diskFileId = diskFileId.str();
+    fileWritten.diskFilePath = diskFilePath.str();
+    fileWritten.diskFileOwnerUid = PUBLIC_DISK_USER;
+    fileWritten.diskFileGid = PUBLIC_DISK_GROUP;
+    fileWritten.size = archiveFileSize;
+    fileWritten.checksumBlob.insert(checksum::ADLER32, "1357");
+    fileWritten.storageClassName = m_storageClassDualCopy.name;
+    fileWritten.vid = tape1.vid;
+    fileWritten.fSeq = 1;
+    fileWritten.blockId = 1 * 100;
+    fileWritten.copyNb = 1;
+    fileWritten.tapeDrive = tapeDrive;
+    tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
+
+    m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
+  }
+
+  // Write a second copy of file on tape
+  {
+    std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
+
+    std::ostringstream diskFileId;
+    diskFileId << 12345677;
+
+    std::ostringstream diskFilePath;
+    diskFilePath << "/test/file1";
+
+    auto fileWrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>();
+    auto & fileWritten = *fileWrittenUP;
+    fileWritten.archiveFileId = 1;
+    fileWritten.diskInstance = diskInstance;
+    fileWritten.diskFileId = diskFileId.str();
+    fileWritten.diskFilePath = diskFilePath.str();
+    fileWritten.diskFileOwnerUid = PUBLIC_DISK_USER;
+    fileWritten.diskFileGid = PUBLIC_DISK_GROUP;
+    fileWritten.size = archiveFileSize;
+    fileWritten.checksumBlob.insert(checksum::ADLER32, "1357");
+    fileWritten.storageClassName = m_storageClassDualCopy.name;
+    fileWritten.vid = tape2.vid;
+    fileWritten.fSeq = 1;
+    fileWritten.blockId = 1 * 100;
+    fileWritten.copyNb = 2;
+    fileWritten.tapeDrive = tapeDrive;
+    tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
+
+    m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
+  }
+  {
+    //Assert both copies written
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    ASSERT_EQ(2, archiveFile.tapeFiles.size());
+  }
+
+  {
+    //delete copy of file on tape1
+    m_catalogue->deleteTapeFileCopy(tape1.vid, "BC614D", diskInstance, reason);
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    ASSERT_EQ(1, archiveFile.tapeFiles.size());
+  }
+
+
+  {
+    //restore copy of file on tape1
+    catalogue::RecycleTapeFileSearchCriteria searchCriteria;
+    searchCriteria.archiveFileId = 1;
+    searchCriteria.vid = tape1.vid;
+
+    m_catalogue->restoreFilesInRecycleLog(searchCriteria);
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    //assert both copies present
+    ASSERT_EQ(2, archiveFile.tapeFiles.size());
+
+    //assert recycle log is empty
+    auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor();
+    ASSERT_FALSE(fileRecycleLogItor.hasMore());
+
+  }
+}
+
+TEST_P(cta_catalogue_CatalogueTest, RestoreRewrittenTapeFileCopyFails) {
+  using namespace cta;
+
+  const bool logicalLibraryIsDisabled= false;
+  const std::string tapePoolName1 = "tape_pool_name_1";
+  const std::string tapePoolName2 = "tape_pool_name_2";
+  const uint64_t nbPartialTapes = 1;
+  const bool isEncrypted = true;
+  const cta::optional<std::string> supply("value for the supply pool mechanism");
+  const std::string diskInstance = "disk_instance";
+  const std::string tapeDrive = "tape_drive";
+  const std::string reason = "reason";
+
+  m_catalogue->createMediaType(m_admin, m_mediaType);
+  m_catalogue->createLogicalLibrary(m_admin, m_tape1.logicalLibraryName, logicalLibraryIsDisabled, "Create logical library");
+  m_catalogue->createVirtualOrganization(m_admin, m_vo);
+  m_catalogue->createTapePool(m_admin, tapePoolName1, m_vo.name, nbPartialTapes, isEncrypted, supply, "Create tape pool");
+  m_catalogue->createTapePool(m_admin, tapePoolName2, m_vo.name, nbPartialTapes, isEncrypted, supply, "Create tape pool");
+  m_catalogue->createStorageClass(m_admin, m_storageClassDualCopy);
+
+  auto tape1 = m_tape1;
+  auto tape2 = m_tape2;
+  tape1.tapePoolName = tapePoolName1;
+  tape2.tapePoolName = tapePoolName2;
+
+  m_catalogue->createTape(m_admin, tape1);
+  m_catalogue->createTape(m_admin, tape2);
+
+  ASSERT_FALSE(m_catalogue->getArchiveFilesItor().hasMore());
+  const uint64_t archiveFileSize = 2 * 1000 * 1000 * 1000;
+
+
+  // Write a file on tape
+  {
+    std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
+
+    std::ostringstream diskFileId;
+    diskFileId << 12345677;
+
+    std::ostringstream diskFilePath;
+    diskFilePath << "/test/file1";
+
+    auto fileWrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>();
+    auto & fileWritten = *fileWrittenUP;
+    fileWritten.archiveFileId = 1;
+    fileWritten.diskInstance = diskInstance;
+    fileWritten.diskFileId = diskFileId.str();
+    fileWritten.diskFilePath = diskFilePath.str();
+    fileWritten.diskFileOwnerUid = PUBLIC_DISK_USER;
+    fileWritten.diskFileGid = PUBLIC_DISK_GROUP;
+    fileWritten.size = archiveFileSize;
+    fileWritten.checksumBlob.insert(checksum::ADLER32, "1357");
+    fileWritten.storageClassName = m_storageClassDualCopy.name;
+    fileWritten.vid = tape1.vid;
+    fileWritten.fSeq = 1;
+    fileWritten.blockId = 1 * 100;
+    fileWritten.copyNb = 1;
+    fileWritten.tapeDrive = tapeDrive;
+    tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
+
+    m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
+  }
+
+  // Write a second copy of file on tape
+  {
+    std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
+
+    std::ostringstream diskFileId;
+    diskFileId << 12345677;
+
+    std::ostringstream diskFilePath;
+    diskFilePath << "/test/file1";
+
+    auto fileWrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>();
+    auto & fileWritten = *fileWrittenUP;
+    fileWritten.archiveFileId = 1;
+    fileWritten.diskInstance = diskInstance;
+    fileWritten.diskFileId = diskFileId.str();
+    fileWritten.diskFilePath = diskFilePath.str();
+    fileWritten.diskFileOwnerUid = PUBLIC_DISK_USER;
+    fileWritten.diskFileGid = PUBLIC_DISK_GROUP;
+    fileWritten.size = archiveFileSize;
+    fileWritten.checksumBlob.insert(checksum::ADLER32, "1357");
+    fileWritten.storageClassName = m_storageClassDualCopy.name;
+    fileWritten.vid = tape2.vid;
+    fileWritten.fSeq = 1;
+    fileWritten.blockId = 1 * 100;
+    fileWritten.copyNb = 2;
+    fileWritten.tapeDrive = tapeDrive;
+    tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
+
+    m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
+  }
+  {
+    //Assert both copies written
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    ASSERT_EQ(2, archiveFile.tapeFiles.size());
+  }
+
+  {
+    //delete copy of file on tape1
+    m_catalogue->deleteTapeFileCopy(tape1.vid, "BC614D", diskInstance, reason);
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    ASSERT_EQ(1, archiveFile.tapeFiles.size());
+  }
+
+    // Rewrite deleted copy of file on tape
+  {
+    std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
+
+    std::ostringstream diskFileId;
+    diskFileId << 12345677;
+
+    std::ostringstream diskFilePath;
+    diskFilePath << "/test/file1";
+
+    auto fileWrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>();
+    auto & fileWritten = *fileWrittenUP;
+    fileWritten.archiveFileId = 1;
+    fileWritten.diskInstance = diskInstance;
+    fileWritten.diskFileId = diskFileId.str();
+    fileWritten.diskFilePath = diskFilePath.str();
+    fileWritten.diskFileOwnerUid = PUBLIC_DISK_USER;
+    fileWritten.diskFileGid = PUBLIC_DISK_GROUP;
+    fileWritten.size = archiveFileSize;
+    fileWritten.checksumBlob.insert(checksum::ADLER32, "1357");
+    fileWritten.storageClassName = m_storageClassDualCopy.name;
+    fileWritten.vid = tape1.vid;
+    fileWritten.fSeq = 2;
+    fileWritten.blockId = 1 * 100;
+    fileWritten.copyNb = 1;
+    fileWritten.tapeDrive = tapeDrive;
+    tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
+
+    m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
+  }
+
+  {
+    //restore copy of file on tape1
+    catalogue::RecycleTapeFileSearchCriteria searchCriteria;
+    searchCriteria.archiveFileId = 1;
+    searchCriteria.vid = tape1.vid;
+
+    ASSERT_THROW(m_catalogue->restoreFilesInRecycleLog(searchCriteria), catalogue::UserSpecifiedExistingDeletedFileCopy);
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    //assert only two copies present
+    ASSERT_EQ(2, archiveFile.tapeFiles.size());
+
+    //assert recycle log still contains deleted copy
+    auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor();
+    ASSERT_TRUE(fileRecycleLogItor.hasMore());
+
+  }
+}
+
+TEST_P(cta_catalogue_CatalogueTest, RestoreVariousDeletedTapeFileCopies) {
+  using namespace cta;
+
+  const bool logicalLibraryIsDisabled= false;
+  const std::string tapePoolName1 = "tape_pool_name_1";
+  const std::string tapePoolName2 = "tape_pool_name_2";
+  const std::string tapePoolName3 = "tape_pool_name_3";
+  const uint64_t nbPartialTapes = 1;
+  const bool isEncrypted = true;
+  const cta::optional<std::string> supply("value for the supply pool mechanism");
+  const std::string diskInstance = "disk_instance";
+  const std::string tapeDrive = "tape_drive";
+  const std::string reason = "reason";
+
+  m_catalogue->createMediaType(m_admin, m_mediaType);
+  m_catalogue->createLogicalLibrary(m_admin, m_tape1.logicalLibraryName, logicalLibraryIsDisabled, "Create logical library");
+  m_catalogue->createVirtualOrganization(m_admin, m_vo);
+  m_catalogue->createTapePool(m_admin, tapePoolName1, m_vo.name, nbPartialTapes, isEncrypted, supply, "Create tape pool");
+  m_catalogue->createTapePool(m_admin, tapePoolName2, m_vo.name, nbPartialTapes, isEncrypted, supply, "Create tape pool");
+  m_catalogue->createTapePool(m_admin, tapePoolName3, m_vo.name, nbPartialTapes, isEncrypted, supply, "Create tape pool");
+  m_catalogue->createStorageClass(m_admin, m_storageClassTripleCopy);
+
+  auto tape1 = m_tape1;
+  auto tape2 = m_tape2;
+  auto tape3 = m_tape3;
+  tape1.tapePoolName = tapePoolName1;
+  tape2.tapePoolName = tapePoolName2;
+  tape3.tapePoolName = tapePoolName3;
+
+  m_catalogue->createTape(m_admin, tape1);
+  m_catalogue->createTape(m_admin, tape2);
+  m_catalogue->createTape(m_admin, tape3);
+
+  ASSERT_FALSE(m_catalogue->getArchiveFilesItor().hasMore());
+  const uint64_t archiveFileSize = 2 * 1000 * 1000 * 1000;
+
+
+  // Write a file on tape
+  {
+    std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
+
+    std::ostringstream diskFileId;
+    diskFileId << 12345677;
+
+    std::ostringstream diskFilePath;
+    diskFilePath << "/test/file1";
+
+    auto fileWrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>();
+    auto & fileWritten = *fileWrittenUP;
+    fileWritten.archiveFileId = 1;
+    fileWritten.diskInstance = diskInstance;
+    fileWritten.diskFileId = diskFileId.str();
+    fileWritten.diskFilePath = diskFilePath.str();
+    fileWritten.diskFileOwnerUid = PUBLIC_DISK_USER;
+    fileWritten.diskFileGid = PUBLIC_DISK_GROUP;
+    fileWritten.size = archiveFileSize;
+    fileWritten.checksumBlob.insert(checksum::ADLER32, "1357");
+    fileWritten.storageClassName = m_storageClassTripleCopy.name;
+    fileWritten.vid = tape1.vid;
+    fileWritten.fSeq = 1;
+    fileWritten.blockId = 1 * 100;
+    fileWritten.copyNb = 1;
+    fileWritten.tapeDrive = tapeDrive;
+    tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
+
+    m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
+  }
+
+  // Write a second copy of file on tape
+  {
+    std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
+
+    std::ostringstream diskFileId;
+    diskFileId << 12345677;
+
+    std::ostringstream diskFilePath;
+    diskFilePath << "/test/file1";
+
+    auto fileWrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>();
+    auto & fileWritten = *fileWrittenUP;
+    fileWritten.archiveFileId = 1;
+    fileWritten.diskInstance = diskInstance;
+    fileWritten.diskFileId = diskFileId.str();
+    fileWritten.diskFilePath = diskFilePath.str();
+    fileWritten.diskFileOwnerUid = PUBLIC_DISK_USER;
+    fileWritten.diskFileGid = PUBLIC_DISK_GROUP;
+    fileWritten.size = archiveFileSize;
+    fileWritten.checksumBlob.insert(checksum::ADLER32, "1357");
+    fileWritten.storageClassName = m_storageClassTripleCopy.name;
+    fileWritten.vid = tape2.vid;
+    fileWritten.fSeq = 1;
+    fileWritten.blockId = 1 * 100;
+    fileWritten.copyNb = 2;
+    fileWritten.tapeDrive = tapeDrive;
+    tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
+
+    m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
+  }
+
+  // Write a third copy of file on tape
+  {
+    std::set<catalogue::TapeItemWrittenPointer> tapeFilesWrittenCopy1;
+
+    std::ostringstream diskFileId;
+    diskFileId << 12345677;
+
+    std::ostringstream diskFilePath;
+    diskFilePath << "/test/file1";
+
+    auto fileWrittenUP=cta::make_unique<cta::catalogue::TapeFileWritten>();
+    auto & fileWritten = *fileWrittenUP;
+    fileWritten.archiveFileId = 1;
+    fileWritten.diskInstance = diskInstance;
+    fileWritten.diskFileId = diskFileId.str();
+    fileWritten.diskFilePath = diskFilePath.str();
+    fileWritten.diskFileOwnerUid = PUBLIC_DISK_USER;
+    fileWritten.diskFileGid = PUBLIC_DISK_GROUP;
+    fileWritten.size = archiveFileSize;
+    fileWritten.checksumBlob.insert(checksum::ADLER32, "1357");
+    fileWritten.storageClassName = m_storageClassTripleCopy.name;
+    fileWritten.vid = tape3.vid;
+    fileWritten.fSeq = 1;
+    fileWritten.blockId = 1 * 100;
+    fileWritten.copyNb = 3;
+    fileWritten.tapeDrive = tapeDrive;
+    tapeFilesWrittenCopy1.emplace(fileWrittenUP.release());
+
+    m_catalogue->filesWrittenToTape(tapeFilesWrittenCopy1);
+  }
+  {
+    //Assert all copies written
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    ASSERT_EQ(3, archiveFile.tapeFiles.size());
+  }
+
+  {
+    //delete copy of file on tape1
+    m_catalogue->deleteTapeFileCopy(tape1.vid, "BC614D", diskInstance, reason);
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    ASSERT_EQ(2, archiveFile.tapeFiles.size());
+  }
+
+  {
+    //delete copy of file on tape2
+    m_catalogue->deleteTapeFileCopy(tape2.vid, "BC614D", diskInstance, reason);
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    ASSERT_EQ(1, archiveFile.tapeFiles.size());
+  }
+
+
+  {
+    //restore all deleted copies
+    catalogue::RecycleTapeFileSearchCriteria searchCriteria;
+    searchCriteria.archiveFileId = 1;
+
+    m_catalogue->restoreFilesInRecycleLog(searchCriteria);
+    auto archiveFile = m_catalogue->getArchiveFileById(1);
+    //assert only two copies present
+    ASSERT_EQ(3, archiveFile.tapeFiles.size());
+
+    //assert recycle log still contains deleted copy
+    auto fileRecycleLogItor = m_catalogue->getFileRecycleLogItor();
+    ASSERT_FALSE(fileRecycleLogItor.hasMore());
+
+  }
+}
+
+
 } // namespace unitTests
diff --git a/catalogue/CatalogueTest.hpp b/catalogue/CatalogueTest.hpp
index b15bb24f6b9e6a3f3c22bec44c2997921388acfa..d556ad63aa0688e09d1bec7bff67fb21d4fc6ab2 100644
--- a/catalogue/CatalogueTest.hpp
+++ b/catalogue/CatalogueTest.hpp
@@ -46,9 +46,11 @@ protected:
   const cta::common::dataStructures::StorageClass m_storageClassSingleCopy;
   const cta::common::dataStructures::StorageClass m_anotherStorageClass;
   const cta::common::dataStructures::StorageClass m_storageClassDualCopy;
+  const cta::common::dataStructures::StorageClass m_storageClassTripleCopy;
   const cta::catalogue::MediaType m_mediaType;
   const cta::catalogue::CreateTapeAttributes m_tape1;
   const cta::catalogue::CreateTapeAttributes m_tape2;
+  const cta::catalogue::CreateTapeAttributes m_tape3;
 
   virtual void SetUp();
 
diff --git a/catalogue/DummyCatalogue.hpp b/catalogue/DummyCatalogue.hpp
index 05a0a1a357e44bfcb854be426f077b8ecb0c9e27..dae4b7201c4946cf1f15c301820a2919047b436c 100644
--- a/catalogue/DummyCatalogue.hpp
+++ b/catalogue/DummyCatalogue.hpp
@@ -85,6 +85,7 @@ public:
   common::dataStructures::ArchiveFile getArchiveFileById(const uint64_t id) const override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   ArchiveFileItor getArchiveFilesItor(const TapeFileSearchCriteria& searchCriteria) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   FileRecycleLogItor getFileRecycleLogItor(const RecycleTapeFileSearchCriteria & searchCriteria) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  void restoreFilesInRecycleLog(const RecycleTapeFileSearchCriteria & searchCriteria) { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void deleteFileFromRecycleBin(const uint64_t archiveFileId, log::LogContext &lc) {throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented");}
   void deleteFilesFromRecycleLog(const std::string & vid, log::LogContext & lc) {throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented");}
   void createTapeDrive(const common::dataStructures::TapeDrive &tapeDrive) {throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented");}
@@ -102,6 +103,7 @@ public:
   std::list<common::dataStructures::RequesterGroupMountRule> getRequesterGroupMountRules() const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   std::list<common::dataStructures::RequesterMountRule> getRequesterMountRules() const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   std::list<common::dataStructures::StorageClass> getStorageClasses() const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  common::dataStructures::StorageClass getStorageClass(const std::string &name) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   common::dataStructures::ArchiveFileSummary getTapeFileSummary(const TapeFileSearchCriteria& searchCriteria) const { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void deleteTapeFileCopy(const std::string &vid, const uint64_t archiveFileId, const std::string &reason) override {throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented");}
   void deleteTapeFileCopy(const std::string &vid, const std::string &diskFileId, const std::string &diskInstanceName, const std::string &reason) override {throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented");}
@@ -122,6 +124,7 @@ public:
   void modifyVirtualOrganizationName(const common::dataStructures::SecurityIdentity &admin, const std::string &currentVoName, const std::string &newVoName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyVirtualOrganizationReadMaxDrives(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t readMaxDrives) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyVirtualOrganizationWriteMaxDrives(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t writeMaxDrives) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
+  void modifyVirtualOrganizationMaxFileSize(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t maxFileSize) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyVirtualOrganizationComment(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const std::string &comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyArchiveRouteComment(const common::dataStructures::SecurityIdentity& admin, const std::string& storageClassName, const uint32_t copyNb, const std::string& comment) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
   void modifyArchiveRouteTapePoolName(const common::dataStructures::SecurityIdentity& admin, const std::string& storageClassName, const uint32_t copyNb, const std::string& tapePoolName) override { throw exception::Exception(std::string("In ")+__PRETTY_FUNCTION__+": not implemented"); }
diff --git a/catalogue/MysqlCatalogue.cpp b/catalogue/MysqlCatalogue.cpp
index f9c184f415ac7979b9c60bae07289dbd074117c3..f8f450b0064fdf6a635e4bc723e48e32fd8c6b1d 100644
--- a/catalogue/MysqlCatalogue.cpp
+++ b/catalogue/MysqlCatalogue.cpp
@@ -820,5 +820,95 @@ void MysqlCatalogue::copyTapeFileToFileRecyleLogAndDelete(rdbms::Conn & conn, co
   } 
 }
 
+//------------------------------------------------------------------------------
+// restoreFileCopiesInRecycleLog
+//------------------------------------------------------------------------------
+void MysqlCatalogue::restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) {
+try {
+    utils::Timer t;
+    log::TimingList tl;
+
+    //put fileRecycleLogs in std::list so we can release the underlying fileRecycleLogItor database connection
+    //otherwise we are using two conns when calling getArchiveFilesItor
+    std::list<common::dataStructures::FileRecycleLog> fileRecycleLogList;
+    while (fileRecycleLogItor.hasMore()) {
+      auto fileRecycleLog = fileRecycleLogItor.next();
+      fileRecycleLogList.push_back(fileRecycleLog);
+    }
+
+    //We currently do all file copies restoring in a single transaction
+    conn.executeNonQuery("START TRANSACTION");
+    for (auto &fileRecycleLog: fileRecycleLogList) {     
+      TapeFileSearchCriteria searchCriteria;
+      searchCriteria.archiveFileId = fileRecycleLog.archiveFileId;
+      searchCriteria.diskInstance = fileRecycleLog.diskInstanceName;
+      searchCriteria.diskFileIds = std::vector<std::string>();
+      searchCriteria.diskFileIds.value().push_back(fileRecycleLog.diskFileId);
+
+      auto itor = getArchiveFilesItor(conn, searchCriteria); 
+      if (itor.hasMore()) {
+        //only restore file copies, do nothing if file has been completely deleted in CTA
+        cta::common::dataStructures::ArchiveFile archiveFile = itor.next();
+        if (archiveFile.tapeFiles.find(fileRecycleLog.copyNb) != archiveFile.tapeFiles.end()) {
+          //copy with same copy_nb exists, cannot restore
+          UserSpecifiedExistingDeletedFileCopy ex;
+          ex.getMessage() << "Cannot restore file copy with archiveFileId " << std::to_string(fileRecycleLog.archiveFileId) 
+          << " and copy_nb " << std::to_string(fileRecycleLog.copyNb) << " because a tapefile with same archiveFileId and copy_nb already exists";
+          throw ex;
+        }
+        restoreFileCopyInRecycleLog(conn, fileRecycleLog, lc);
+      }
+    }
+    conn.commit();
+
+    log::ScopedParamContainer spc(lc);
+    tl.insertAndReset("commitTime",t);
+    tl.addToLog(spc);
+    lc.log(log::INFO,"In MysqlCatalogue::restoreFileCopiesInRecycleLog: all file copies successfully restored.");
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+//------------------------------------------------------------------------------
+// restoreFileCopyInRecycleLog
+//------------------------------------------------------------------------------
+void MysqlCatalogue::restoreFileCopyInRecycleLog(rdbms::Conn & conn, const common::dataStructures::FileRecycleLog &fileRecycleLog, log::LogContext & lc) {
+  try {
+    utils::Timer t;
+    log::TimingList tl;
+    cta::common::dataStructures::TapeFile tapeFile;
+    tapeFile.vid = fileRecycleLog.vid;
+    tapeFile.fSeq = fileRecycleLog.fSeq;
+    tapeFile.copyNb = fileRecycleLog.copyNb;
+    tapeFile.blockId = fileRecycleLog.blockId;
+    tapeFile.fileSize = fileRecycleLog.sizeInBytes;
+    tapeFile.creationTime = fileRecycleLog.tapeFileCreationTime;
+
+    insertTapeFile(conn, tapeFile, fileRecycleLog.archiveFileId);
+    tl.insertAndReset("insertTapeFileTime",t);
+    
+    deleteTapeFileCopyFromRecycleBin(conn, fileRecycleLog);
+    tl.insertAndReset("deleteTapeFileCopyFromRecycleBinTime",t);
+    
+    log::ScopedParamContainer spc(lc);
+    spc.add("vid", tapeFile.vid);
+    spc.add("archiveFileId", fileRecycleLog.archiveFileId);
+    spc.add("fSeq", tapeFile.fSeq);
+    spc.add("copyNb", tapeFile.copyNb);
+    spc.add("fileSize", tapeFile.fileSize);
+    tl.addToLog(spc);
+    lc.log(log::INFO,"In MysqlCatalogue::restoreFileCopyInRecycleLog: File restored from the recycle log.");
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
 } // namespace catalogue
 } // namespace cta
diff --git a/catalogue/MysqlCatalogue.hpp b/catalogue/MysqlCatalogue.hpp
index 74ed0b0f5efd921bb7e425d520b7ea0f8af0ab55..75df118fd39fbd9d4da9adf8d5f62617771f7a5b 100644
--- a/catalogue/MysqlCatalogue.hpp
+++ b/catalogue/MysqlCatalogue.hpp
@@ -219,6 +219,22 @@ protected:
   void copyTapeFileToFileRecyleLogAndDelete(rdbms::Conn & conn, const cta::common::dataStructures::ArchiveFile &file, 
                                             const std::string &reason, log::LogContext & lc) override;
 
+  /**
+   * Copy the files in fileRecycleLogItor to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entries
+   * @param conn the database connection
+   * @param fileRecycleLogItor the collection of fileRecycleLogs we want to restore
+   * @param lc the log context
+   */
+  void restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) override;
+
+  /**
+   * Copy the fileRecycleLog to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entry
+   * @param conn the database connection
+   * @param fileRecycleLog the fileRecycleLog we want to restore
+   * @param lc the log context
+   */
+  void restoreFileCopyInRecycleLog(rdbms::Conn & conn, const common::dataStructures::FileRecycleLog &fileRecycleLogItor, log::LogContext & lc);
+
 
 private:
 
diff --git a/catalogue/OracleCatalogue.cpp b/catalogue/OracleCatalogue.cpp
index e15b23d3d0f994cb26bc57a0c5f3364ddd859e56..98717eee30bc6ff9500e5670629ec3c5d6cd9c52 100644
--- a/catalogue/OracleCatalogue.cpp
+++ b/catalogue/OracleCatalogue.cpp
@@ -1149,6 +1149,99 @@ void OracleCatalogue::copyTapeFileToFileRecyleLogAndDelete(rdbms::Conn & conn, c
   } 
 }
 
+//------------------------------------------------------------------------------
+// restoreFileCopiesInRecycleLog
+//------------------------------------------------------------------------------
+void OracleCatalogue::restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) {
+try {
+    utils::Timer t;
+    log::TimingList tl;
+
+    //put fileRecycleLogs in std::list so we can release the underlying fileRecycleLogItor database connection
+    //otherwise we are using two conns when calling getArchiveFilesItor
+    std::list<common::dataStructures::FileRecycleLog> fileRecycleLogList;
+    while (fileRecycleLogItor.hasMore()) {
+      auto fileRecycleLog = fileRecycleLogItor.next();
+      fileRecycleLogList.push_back(fileRecycleLog);
+    }
+
+    //We currently do all file copies restoring in a single transaction
+    conn.setAutocommitMode(rdbms::AutocommitMode::AUTOCOMMIT_OFF);
+    for (auto &fileRecycleLog: fileRecycleLogList) {     
+      TapeFileSearchCriteria searchCriteria;
+      searchCriteria.archiveFileId = fileRecycleLog.archiveFileId;
+      searchCriteria.diskInstance = fileRecycleLog.diskInstanceName;
+      searchCriteria.diskFileIds = std::vector<std::string>();
+      searchCriteria.diskFileIds.value().push_back(fileRecycleLog.diskFileId);
+
+      auto itor = getArchiveFilesItor(conn, searchCriteria); 
+      if (itor.hasMore()) {
+        //only restore file copies, do nothing if file has been completely deleted in CTA
+        cta::common::dataStructures::ArchiveFile archiveFile = itor.next();
+        if (archiveFile.tapeFiles.find(fileRecycleLog.copyNb) != archiveFile.tapeFiles.end()) {
+          //copy with same copy_nb exists, cannot restore
+          UserSpecifiedExistingDeletedFileCopy ex;
+          ex.getMessage() << "Cannot restore file copy with archiveFileId " << std::to_string(fileRecycleLog.archiveFileId) 
+          << " and copy_nb " << std::to_string(fileRecycleLog.copyNb) << " because a tapefile with same archiveFileId and copy_nb already exists";
+          throw ex;
+        }
+        restoreFileCopyInRecycleLog(conn, fileRecycleLog, lc);
+      }
+    }
+    conn.setAutocommitMode(rdbms::AutocommitMode::AUTOCOMMIT_ON);
+    conn.commit();
+
+    log::ScopedParamContainer spc(lc);
+    tl.insertAndReset("commitTime",t);
+    tl.addToLog(spc);
+    lc.log(log::INFO,"In OracleCatalogue::restoreFileCopiesInRecycleLog: all file copies successfully restored.");
+
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+//------------------------------------------------------------------------------
+// restoreFileCopyInRecycleLog
+//------------------------------------------------------------------------------
+void OracleCatalogue::restoreFileCopyInRecycleLog(rdbms::Conn & conn, const common::dataStructures::FileRecycleLog &fileRecycleLog, log::LogContext & lc) {
+  try {
+    utils::Timer t;
+    log::TimingList tl;
+    cta::common::dataStructures::TapeFile tapeFile;
+    tapeFile.vid = fileRecycleLog.vid;
+    tapeFile.fSeq = fileRecycleLog.fSeq;
+    tapeFile.copyNb = fileRecycleLog.copyNb;
+    tapeFile.blockId = fileRecycleLog.blockId;
+    tapeFile.fileSize = fileRecycleLog.sizeInBytes;
+    tapeFile.creationTime = fileRecycleLog.tapeFileCreationTime;
+
+    insertTapeFile(conn, tapeFile, fileRecycleLog.archiveFileId);
+    tl.insertAndReset("insertTapeFileTime",t);
+    
+    deleteTapeFileCopyFromRecycleBin(conn, fileRecycleLog);
+    tl.insertAndReset("deleteTapeFileCopyFromRecycleBinTime",t);
+    
+    log::ScopedParamContainer spc(lc);
+    spc.add("vid", tapeFile.vid);
+    spc.add("archiveFileId", fileRecycleLog.archiveFileId);
+    spc.add("fSeq", tapeFile.fSeq);
+    spc.add("copyNb", tapeFile.copyNb);
+    spc.add("fileSize", tapeFile.fileSize);
+    tl.addToLog(spc);
+    lc.log(log::INFO,"In OracleCatalogue::restoreFileCopyInRecycleLog: File restored from the recycle log.");
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+
 
 } // namespace catalogue
 } // namespace cta
diff --git a/catalogue/OracleCatalogue.hpp b/catalogue/OracleCatalogue.hpp
index f0c05cf0176a027691eb1eb17f90958f59a36719..172cb55e0fe1f8502355ec607ce271689a236162 100644
--- a/catalogue/OracleCatalogue.hpp
+++ b/catalogue/OracleCatalogue.hpp
@@ -262,6 +262,22 @@ private:
   void copyTapeFileToFileRecyleLogAndDelete(rdbms::Conn & conn, const cta::common::dataStructures::ArchiveFile &file, 
                                             const std::string &reason, log::LogContext & lc) override;
 
+  /**
+   * Copy the files in fileRecycleLogItor to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entries
+   * @param conn the database connection
+   * @param fileRecycleLogItor the collection of fileRecycleLogs we want to restore
+   * @param lc the log context
+   */
+  void restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) override;
+
+  /**
+   * Copy the fileRecycleLog to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entry
+   * @param conn the database connection
+   * @param fileRecycleLog the fileRecycleLog we want to restore
+   * @param lc the log context
+   */
+  void restoreFileCopyInRecycleLog(rdbms::Conn & conn, const common::dataStructures::FileRecycleLog &fileRecycleLogItor, log::LogContext & lc);
+
   /**
    * The size and checksum of a file.
    */
diff --git a/catalogue/PostgresCatalogue.cpp b/catalogue/PostgresCatalogue.cpp
index 8967dd6901303673dbb3df209f735744e46e8534..7b06ba81b33c23e5aa601ed3575d3dc467888885 100644
--- a/catalogue/PostgresCatalogue.cpp
+++ b/catalogue/PostgresCatalogue.cpp
@@ -1109,5 +1109,96 @@ void PostgresCatalogue::copyTapeFileToFileRecyleLogAndDelete(rdbms::Conn & conn,
   } 
 }
 
+//------------------------------------------------------------------------------
+// restoreFileCopiesInRecycleLog
+//------------------------------------------------------------------------------
+void PostgresCatalogue::restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) {
+try {
+    utils::Timer t;
+    log::TimingList tl;
+    
+    //put fileRecycleLogs in std::list so we can release the underlying fileRecycleLogItor database connection
+    //otherwise we are using two conns when calling getArchiveFilesItor
+    std::list<common::dataStructures::FileRecycleLog> fileRecycleLogList;
+    while (fileRecycleLogItor.hasMore()) {
+      auto fileRecycleLog = fileRecycleLogItor.next();
+      fileRecycleLogList.push_back(fileRecycleLog);
+    }
+
+    //We currently do all file copies restoring in a single transaction
+    conn.executeNonQuery("BEGIN");
+    for (auto &fileRecycleLog: fileRecycleLogList) {     
+      TapeFileSearchCriteria searchCriteria;
+      searchCriteria.archiveFileId = fileRecycleLog.archiveFileId;
+      searchCriteria.diskInstance = fileRecycleLog.diskInstanceName;
+      searchCriteria.diskFileIds = std::vector<std::string>();
+      searchCriteria.diskFileIds.value().push_back(fileRecycleLog.diskFileId);
+
+      auto itor = getArchiveFilesItor(conn, searchCriteria); 
+      if (itor.hasMore()) {
+        //only restore file copies, do nothing if file has been completely deleted in CTA
+        cta::common::dataStructures::ArchiveFile archiveFile = itor.next();
+        if (archiveFile.tapeFiles.find(fileRecycleLog.copyNb) != archiveFile.tapeFiles.end()) {
+          //copy with same copy_nb exists, cannot restore
+          UserSpecifiedExistingDeletedFileCopy ex;
+          ex.getMessage() << "Cannot restore file copy with archiveFileId " << std::to_string(fileRecycleLog.archiveFileId) 
+          << " and copy_nb " << std::to_string(fileRecycleLog.copyNb) << " because a tapefile with same archiveFileId and copy_nb already exists";
+          throw ex;
+        }
+        restoreFileCopyInRecycleLog(conn, fileRecycleLog, lc);
+      }
+    }
+    conn.commit();
+
+    log::ScopedParamContainer spc(lc);
+    tl.insertAndReset("commitTime",t);
+    tl.addToLog(spc);
+    lc.log(log::INFO,"In PostgresCatalogue::restoreFileCopiesInRecycleLog: all file copies successfully restored.");
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+//------------------------------------------------------------------------------
+// restoreFileCopyInRecycleLog
+//------------------------------------------------------------------------------
+void PostgresCatalogue::restoreFileCopyInRecycleLog(rdbms::Conn & conn, const common::dataStructures::FileRecycleLog &fileRecycleLog, log::LogContext & lc) {
+  try {
+    utils::Timer t;
+    log::TimingList tl;
+    cta::common::dataStructures::TapeFile tapeFile;
+    tapeFile.vid = fileRecycleLog.vid;
+    tapeFile.fSeq = fileRecycleLog.fSeq;
+    tapeFile.copyNb = fileRecycleLog.copyNb;
+    tapeFile.blockId = fileRecycleLog.blockId;
+    tapeFile.fileSize = fileRecycleLog.sizeInBytes;
+    tapeFile.creationTime = fileRecycleLog.tapeFileCreationTime;
+
+    insertTapeFile(conn, tapeFile, fileRecycleLog.archiveFileId);
+    tl.insertAndReset("insertTapeFileTime",t);
+    
+    deleteTapeFileCopyFromRecycleBin(conn, fileRecycleLog);
+    tl.insertAndReset("deleteTapeFileCopyFromRecycleBinTime",t);
+    
+    log::ScopedParamContainer spc(lc);
+    spc.add("vid", tapeFile.vid);
+    spc.add("archiveFileId", fileRecycleLog.archiveFileId);
+    spc.add("fSeq", tapeFile.fSeq);
+    spc.add("copyNb", tapeFile.copyNb);
+    spc.add("fileSize", tapeFile.fileSize);
+    tl.addToLog(spc);
+    lc.log(log::INFO,"In PostgresCatalogue::restoreFileCopyInRecycleLog: File restored from the recycle log.");
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+
 } // namespace catalogue
 } // namespace cta
diff --git a/catalogue/PostgresCatalogue.hpp b/catalogue/PostgresCatalogue.hpp
index 90bacb1e28ad5833af7c823b934e3423ed2a1cfe..4d50cef0d35d6fcc8062de55f08719d7b0c11ed2 100644
--- a/catalogue/PostgresCatalogue.hpp
+++ b/catalogue/PostgresCatalogue.hpp
@@ -296,6 +296,22 @@ private:
   void copyTapeFileToFileRecyleLogAndDelete(rdbms::Conn & conn, const cta::common::dataStructures::ArchiveFile &file, 
                                             const std::string &reason, log::LogContext & lc) override;
 
+  /**
+   * Copy the files in fileRecycleLogItor to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entries
+   * @param conn the database connection
+   * @param fileRecycleLogItor the collection of fileRecycleLogs we want to restore
+   * @param lc the log context
+   */
+  void restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) override;
+
+  /**
+   * Copy the fileRecycleLog to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entry
+   * @param conn the database connection
+   * @param fileRecycleLog the fileRecycleLog we want to restore
+   * @param lc the log context
+   */
+  void restoreFileCopyInRecycleLog(rdbms::Conn & conn, const common::dataStructures::FileRecycleLog &fileRecycleLogItor, log::LogContext & lc);
+
 }; // class PostgresCatalogue
 
 } // namespace catalogue
diff --git a/catalogue/RdbmsCatalogue.cpp b/catalogue/RdbmsCatalogue.cpp
index 1f3a640fe6b985a86120af6f55b48df91e1675bc..afec1c7a2bfc6116fc74ddd48593c282afa38d89 100644
--- a/catalogue/RdbmsCatalogue.cpp
+++ b/catalogue/RdbmsCatalogue.cpp
@@ -332,6 +332,7 @@ void RdbmsCatalogue::createVirtualOrganization(const common::dataStructures::Sec
 
         "READ_MAX_DRIVES,"
         "WRITE_MAX_DRIVES,"
+        "MAX_FILE_SIZE,"
 
         "USER_COMMENT,"
 
@@ -347,6 +348,7 @@ void RdbmsCatalogue::createVirtualOrganization(const common::dataStructures::Sec
         ":VIRTUAL_ORGANIZATION_NAME,"
         ":READ_MAX_DRIVES,"
         ":WRITE_MAX_DRIVES,"
+        ":MAX_FILE_SIZE,"
 
         ":USER_COMMENT,"
 
@@ -364,6 +366,7 @@ void RdbmsCatalogue::createVirtualOrganization(const common::dataStructures::Sec
 
     stmt.bindUint64(":READ_MAX_DRIVES",vo.readMaxDrives);
     stmt.bindUint64(":WRITE_MAX_DRIVES",vo.writeMaxDrives);
+    stmt.bindUint64(":MAX_FILE_SIZE", vo.maxFileSize);
 
     stmt.bindString(":USER_COMMENT", vo.comment);
 
@@ -439,6 +442,7 @@ std::list<common::dataStructures::VirtualOrganization> RdbmsCatalogue::getVirtua
 
         "READ_MAX_DRIVES AS READ_MAX_DRIVES,"
         "WRITE_MAX_DRIVES AS WRITE_MAX_DRIVES,"
+        "MAX_FILE_SIZE AS MAX_FILE_SIZE,"
 
         "USER_COMMENT AS USER_COMMENT,"
 
@@ -463,6 +467,7 @@ std::list<common::dataStructures::VirtualOrganization> RdbmsCatalogue::getVirtua
 
       virtualOrganization.readMaxDrives = rset.columnUint64("READ_MAX_DRIVES");
       virtualOrganization.writeMaxDrives = rset.columnUint64("WRITE_MAX_DRIVES");
+      virtualOrganization.maxFileSize = rset.columnUint64("MAX_FILE_SIZE");
       virtualOrganization.comment = rset.columnString("USER_COMMENT");
       virtualOrganization.creationLog.username = rset.columnString("CREATION_LOG_USER_NAME");
       virtualOrganization.creationLog.host = rset.columnString("CREATION_LOG_HOST_NAME");
@@ -509,7 +514,8 @@ common::dataStructures::VirtualOrganization RdbmsCatalogue::getVirtualOrganizati
 
         "VIRTUAL_ORGANIZATION.READ_MAX_DRIVES AS READ_MAX_DRIVES,"
         "VIRTUAL_ORGANIZATION.WRITE_MAX_DRIVES AS WRITE_MAX_DRIVES,"
-
+        "VIRTUAL_ORGANIZATION.MAX_FILE_SIZE AS MAX_FILE_SIZE,"
+        
         "VIRTUAL_ORGANIZATION.USER_COMMENT AS USER_COMMENT,"
 
         "VIRTUAL_ORGANIZATION.CREATION_LOG_USER_NAME AS CREATION_LOG_USER_NAME,"
@@ -538,6 +544,7 @@ common::dataStructures::VirtualOrganization RdbmsCatalogue::getVirtualOrganizati
     virtualOrganization.name = rset.columnString("VIRTUAL_ORGANIZATION_NAME");
     virtualOrganization.readMaxDrives = rset.columnUint64("READ_MAX_DRIVES");
     virtualOrganization.writeMaxDrives = rset.columnUint64("WRITE_MAX_DRIVES");
+    virtualOrganization.maxFileSize = rset.columnUint64("MAX_FILE_SIZE");
     virtualOrganization.comment = rset.columnString("USER_COMMENT");
     virtualOrganization.creationLog.username = rset.columnString("CREATION_LOG_USER_NAME");
     virtualOrganization.creationLog.host = rset.columnString("CREATION_LOG_HOST_NAME");
@@ -689,6 +696,42 @@ void RdbmsCatalogue::modifyVirtualOrganizationWriteMaxDrives(const common::dataS
   }
 }
 
+void RdbmsCatalogue::modifyVirtualOrganizationMaxFileSize(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t maxFileSize){
+  try {
+    const time_t now = time(nullptr);
+    const char *const sql =
+      "UPDATE VIRTUAL_ORGANIZATION SET "
+        "MAX_FILE_SIZE = :MAX_FILE_SIZE,"
+        "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME,"
+        "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME,"
+        "LAST_UPDATE_TIME = :LAST_UPDATE_TIME "
+      "WHERE "
+        "VIRTUAL_ORGANIZATION_NAME = :VIRTUAL_ORGANIZATION_NAME";
+    auto conn = m_connPool.getConn();
+   
+    auto stmt = conn.createStmt(sql);
+    stmt.bindUint64(":MAX_FILE_SIZE", maxFileSize);
+    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
+    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
+    stmt.bindUint64(":LAST_UPDATE_TIME", now);
+    stmt.bindString(":VIRTUAL_ORGANIZATION_NAME", voName);
+    stmt.executeNonQuery();
+
+    if(0 == stmt.getNbAffectedRows()) {
+      throw exception::UserError(std::string("Cannot modify virtual organization : ") + voName +
+        " because it does not exist");
+    }
+    
+    m_tapepoolVirtualOrganizationCache.invalidate();
+    
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
 void RdbmsCatalogue::modifyVirtualOrganizationComment(const common::dataStructures::SecurityIdentity& admin, const std::string& voName, const std::string& comment) {
 try {
     const time_t now = time(nullptr);
@@ -1107,6 +1150,65 @@ std::list<common::dataStructures::StorageClass> RdbmsCatalogue::getStorageClasse
   }
 }
 
+//------------------------------------------------------------------------------
+// getStorageClasses
+//------------------------------------------------------------------------------
+common::dataStructures::StorageClass RdbmsCatalogue::getStorageClass(const std::string &name) const {
+  try {
+    const char *const sql =
+      "SELECT "
+        "STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
+        "NB_COPIES AS NB_COPIES,"
+        "VIRTUAL_ORGANIZATION.VIRTUAL_ORGANIZATION_NAME AS VIRTUAL_ORGANIZATION_NAME,"
+        "VIRTUAL_ORGANIZATION.MAX_FILE_SIZE AS MAX_FILE_SIZE,"
+        "STORAGE_CLASS.USER_COMMENT AS USER_COMMENT,"
+
+        "STORAGE_CLASS.CREATION_LOG_USER_NAME AS CREATION_LOG_USER_NAME,"
+        "STORAGE_CLASS.CREATION_LOG_HOST_NAME AS CREATION_LOG_HOST_NAME,"
+        "STORAGE_CLASS.CREATION_LOG_TIME AS CREATION_LOG_TIME,"
+
+        "STORAGE_CLASS.LAST_UPDATE_USER_NAME AS LAST_UPDATE_USER_NAME,"
+        "STORAGE_CLASS.LAST_UPDATE_HOST_NAME AS LAST_UPDATE_HOST_NAME,"
+        "STORAGE_CLASS.LAST_UPDATE_TIME AS LAST_UPDATE_TIME "
+      "FROM "
+        "STORAGE_CLASS "
+      "INNER JOIN "
+        "VIRTUAL_ORGANIZATION ON STORAGE_CLASS.VIRTUAL_ORGANIZATION_ID = VIRTUAL_ORGANIZATION.VIRTUAL_ORGANIZATION_ID "
+      "WHERE "
+        "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
+    auto conn = m_connPool.getConn();
+    auto stmt = conn.createStmt(sql);
+    stmt.bindString(":STORAGE_CLASS_NAME", name);
+    auto rset = stmt.executeQuery();
+    if (rset.isEmpty()) {
+      throw exception::UserError(std::string("Cannot get storage class : ") + name +
+        " because it does not exist");
+    }
+    rset.next();
+    common::dataStructures::StorageClass storageClass;
+
+    storageClass.name = rset.columnString("STORAGE_CLASS_NAME");
+    storageClass.nbCopies = rset.columnUint64("NB_COPIES");
+    storageClass.vo.name = rset.columnString("VIRTUAL_ORGANIZATION_NAME");
+    storageClass.vo.maxFileSize = rset.columnUint64("MAX_FILE_SIZE");
+    storageClass.comment = rset.columnString("USER_COMMENT");
+    storageClass.creationLog.username = rset.columnString("CREATION_LOG_USER_NAME");
+    storageClass.creationLog.host = rset.columnString("CREATION_LOG_HOST_NAME");
+    storageClass.creationLog.time = rset.columnUint64("CREATION_LOG_TIME");
+    storageClass.lastModificationLog.username = rset.columnString("LAST_UPDATE_USER_NAME");
+    storageClass.lastModificationLog.host = rset.columnString("LAST_UPDATE_HOST_NAME");
+    storageClass.lastModificationLog.time = rset.columnUint64("LAST_UPDATE_TIME");
+  
+    return storageClass;
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+
 //------------------------------------------------------------------------------
 // modifyStorageClassNbCopies
 //------------------------------------------------------------------------------
@@ -6939,7 +7041,14 @@ void RdbmsCatalogue::insertArchiveFile(rdbms::Conn &conn, const ArchiveFileRowWi
 //------------------------------------------------------------------------------
 void RdbmsCatalogue::checkTapeFileSearchCriteria(const TapeFileSearchCriteria &searchCriteria) const {
   auto conn = m_connPool.getConn();
+  checkTapeFileSearchCriteria(conn, searchCriteria);
+
+}
 
+//------------------------------------------------------------------------------
+// checkTapeFileSearchCriteria
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::checkTapeFileSearchCriteria(rdbms::Conn &conn, const TapeFileSearchCriteria &searchCriteria) const {
   if(searchCriteria.archiveFileId) {
     if(!archiveFileIdExists(conn, searchCriteria.archiveFileId.value())) {
       throw exception::UserError(std::string("Archive file with ID ") +
@@ -6951,6 +7060,10 @@ void RdbmsCatalogue::checkTapeFileSearchCriteria(const TapeFileSearchCriteria &s
     throw exception::UserError(std::string("Disk file IDs are ambiguous without disk instance name"));
   }
 
+  if (searchCriteria.fSeq && !searchCriteria.vid) {
+    throw exception::UserError(std::string("fSeq makes no sense without vid"));  
+  }
+
   if(searchCriteria.vid) {
     if(!tapeExists(conn, searchCriteria.vid.value())) {
       throw exception::UserError(std::string("Tape ") + searchCriteria.vid.value() + " does not exist");
@@ -6966,8 +7079,8 @@ Catalogue::ArchiveFileItor RdbmsCatalogue::getArchiveFilesItor(const TapeFileSea
   checkTapeFileSearchCriteria(searchCriteria);
 
   // If this is the listing of the contents of a tape
-  if (!searchCriteria.archiveFileId && !searchCriteria.diskInstance && !searchCriteria.diskFileIds &&
-    searchCriteria.vid) {
+  if (!searchCriteria.archiveFileId && !searchCriteria.diskInstance && !searchCriteria.diskFileIds && 
+    !searchCriteria.fSeq && searchCriteria.vid) {
     return getTapeContentsItor(searchCriteria.vid.value());
   }
 
@@ -6986,6 +7099,33 @@ Catalogue::ArchiveFileItor RdbmsCatalogue::getArchiveFilesItor(const TapeFileSea
   }
 }
 
+//------------------------------------------------------------------------------
+// getArchiveFilesItor
+//------------------------------------------------------------------------------
+Catalogue::ArchiveFileItor RdbmsCatalogue::getArchiveFilesItor(rdbms::Conn &conn, const TapeFileSearchCriteria &searchCriteria) const {
+
+  checkTapeFileSearchCriteria(conn, searchCriteria);
+
+  // If this is the listing of the contents of a tape
+  if (!searchCriteria.archiveFileId && !searchCriteria.diskInstance && !searchCriteria.diskFileIds &&
+    searchCriteria.vid) {
+    return getTapeContentsItor(searchCriteria.vid.value());
+  }
+
+  try {
+    auto archiveListingConn = m_archiveFileListingConnPool.getConn();
+    const auto tempDiskFxidsTableName = createAndPopulateTempTableFxid(archiveListingConn, searchCriteria.diskFileIds);
+    // Pass ownership of the connection to the Iterator object
+    auto impl = new RdbmsCatalogueGetArchiveFilesItor(m_log, std::move(archiveListingConn), searchCriteria, tempDiskFxidsTableName);
+    return ArchiveFileItor(impl);
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
 //------------------------------------------------------------------------------
 // getTapeContentsItor
 //------------------------------------------------------------------------------
@@ -7029,6 +7169,24 @@ Catalogue::FileRecycleLogItor RdbmsCatalogue::getFileRecycleLogItor(const Recycl
   }
 }
 
+
+//------------------------------------------------------------------------------
+// restoreFilesInRecycleLog
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::restoreFilesInRecycleLog(const RecycleTapeFileSearchCriteria & searchCriteria) {
+  try {
+    auto fileRecycleLogitor = getFileRecycleLogItor(searchCriteria);
+    auto conn = m_connPool.getConn();
+    log::LogContext lc(m_log);  
+    restoreFileCopiesInRecycleLog(conn, fileRecycleLogitor, lc);
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
 //------------------------------------------------------------------------------
 // getFilesForRepack
 //------------------------------------------------------------------------------
@@ -9120,6 +9278,34 @@ void RdbmsCatalogue::deleteArchiveFileFromRecycleBin(rdbms::Conn& conn, const ui
   }
 }
 
+//------------------------------------------------------------------------------
+// deleteTapeFileCopyFromRecycleBin
+//------------------------------------------------------------------------------
+void RdbmsCatalogue::deleteTapeFileCopyFromRecycleBin(cta::rdbms::Conn & conn, const common::dataStructures::FileRecycleLog fileRecycleLog) {
+  try {
+    const char *const deleteTapeFilesSql = 
+    "DELETE FROM "
+      "FILE_RECYCLE_LOG "
+    "WHERE FILE_RECYCLE_LOG.ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID AND FILE_RECYCLE_LOG.VID = :VID AND "
+    "FILE_RECYCLE_LOG.FSEQ = :FSEQ AND FILE_RECYCLE_LOG.COPY_NB = :COPY_NB AND "
+    "FILE_RECYCLE_LOG.DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME";
+    
+    auto deleteTapeFilesStmt = conn.createStmt(deleteTapeFilesSql);
+    deleteTapeFilesStmt.bindUint64(":ARCHIVE_FILE_ID", fileRecycleLog.archiveFileId);
+    deleteTapeFilesStmt.bindString(":VID", fileRecycleLog.vid);
+    deleteTapeFilesStmt.bindUint64(":FSEQ", fileRecycleLog.fSeq);
+    deleteTapeFilesStmt.bindUint64(":COPY_NB", fileRecycleLog.copyNb);
+    deleteTapeFilesStmt.bindString(":DISK_INSTANCE_NAME", fileRecycleLog.diskInstanceName);
+    deleteTapeFilesStmt.executeNonQuery();
+    
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
 //------------------------------------------------------------------------------
 // insertOldCopiesOfFilesIfAnyOnFileRecycleLog
 //------------------------------------------------------------------------------
diff --git a/catalogue/RdbmsCatalogue.hpp b/catalogue/RdbmsCatalogue.hpp
index ecb4934b741285eba88d38f4d8ff9d59f8fa5660..5451b916cd6952ec3490f4ab38508f6d2c2a065b 100644
--- a/catalogue/RdbmsCatalogue.hpp
+++ b/catalogue/RdbmsCatalogue.hpp
@@ -282,6 +282,15 @@ public:
    * @param writeMaxDrives the new max number of allocated drives for write for the specified Virtual Organization
    */
   void modifyVirtualOrganizationWriteMaxDrives(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t writeMaxDrives) override;
+
+  /**
+   * Modifies the max file size for the specified Virtual Organization
+   *
+   * @param voName the VO name
+   * @param maxFileSize the new max file size for the specified Virtual Organization
+   */
+
+  void modifyVirtualOrganizationMaxFileSize(const common::dataStructures::SecurityIdentity &admin, const std::string &voName, const uint64_t maxFileSize) override;
   /**
    * Modifies the comment of the specified Virtual Organization
    *
@@ -309,6 +318,9 @@ public:
   void deleteStorageClass(const std::string &storageClassName) override;
 
   std::list<common::dataStructures::StorageClass> getStorageClasses() const override;
+  common::dataStructures::StorageClass getStorageClass(const std::string &name) const override;
+
+
   void modifyStorageClassNbCopies(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const uint64_t nbCopies) override;
   void modifyStorageClassComment(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &comment) override;
   void modifyStorageClassVo(const common::dataStructures::SecurityIdentity &admin, const std::string &name, const std::string &vo) override;
@@ -839,6 +851,15 @@ public:
    */
   void checkTapeFileSearchCriteria(const TapeFileSearchCriteria &searchCriteria) const;
 
+    /**
+   * Throws a UserError exception if the specified searchCriteria is not valid
+   * due to a user error.
+   *
+   * @param conn The database connection.
+   * @param searchCriteria The search criteria.
+   */
+  void checkTapeFileSearchCriteria(rdbms::Conn &conn, const TapeFileSearchCriteria &searchCriteria) const;
+
   /**
    * Returns the specified archive files.  Please note that the list of files
    * is ordered by archive file ID.
@@ -848,6 +869,17 @@ public:
    */
   ArchiveFileItor getArchiveFilesItor(const TapeFileSearchCriteria &searchCriteria) const override;
 
+
+  /**
+   * Returns the specified archive files.  Please note that the list of files
+   * is ordered by archive file ID.
+   *
+   * @param conn The database connection.
+   * @param searchCriteria The search criteria.
+   * @return The archive files.
+   */
+  ArchiveFileItor getArchiveFilesItor(rdbms::Conn &conn, const TapeFileSearchCriteria &searchCriteria) const;
+
   /**
    * Throws a UserError exception if the specified searchCriteria is not valid
    * due to a user error.
@@ -864,6 +896,13 @@ public:
    */
   FileRecycleLogItor getFileRecycleLogItor(const RecycleTapeFileSearchCriteria & searchCriteria) const override;
 
+  /**
+   * Restores the deleted files in the Recycle log that match the criteria passed
+   *
+   * @param searchCriteria The search criteria
+   */
+  void restoreFilesInRecycleLog(const RecycleTapeFileSearchCriteria & searchCriteria) override;
+
   /**
    * Returns the specified files in tape file sequence order.
    *
@@ -1923,6 +1962,14 @@ protected:
    */
   virtual void copyArchiveFileToFileRecyleLogAndDelete(rdbms::Conn & conn,const common::dataStructures::DeleteArchiveRequest &request, log::LogContext & lc) = 0;
 
+  /**
+   * Copy the fileRecycleLog to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entry
+   * @param conn the database connection
+   * @param fileRecycleLog the fileRecycleLog we want to restore
+   * @param lc the log context
+   */
+  virtual void restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) = 0;
+
   /**
    * Copies the ARCHIVE_FILE and TAPE_FILE entries to the recycle-bin tables
    * @param conn the database connection
@@ -2037,6 +2084,8 @@ protected:
    */
   void deleteTapeFilesFromRecycleBin(rdbms::Conn & conn, const uint64_t archiveFileId);
 
+  void deleteTapeFileCopyFromRecycleBin(cta::rdbms::Conn & conn, const common::dataStructures::FileRecycleLog fileRecycleLog);
+
   /**
    * Delete the archive file from the ARCHIVE_FILE recycle-bin
    * @param conn the database connection
diff --git a/catalogue/RdbmsCatalogueGetArchiveFilesItor.cpp b/catalogue/RdbmsCatalogueGetArchiveFilesItor.cpp
index bef739104e2ebef88b109dd4426c7a32ad8a1acd..c7092b6e35cb6e58ab21e27f854710c58076431a 100644
--- a/catalogue/RdbmsCatalogueGetArchiveFilesItor.cpp
+++ b/catalogue/RdbmsCatalogueGetArchiveFilesItor.cpp
@@ -114,7 +114,8 @@ RdbmsCatalogueGetArchiveFilesItor::RdbmsCatalogueGetArchiveFilesItor(
       searchCriteria.archiveFileId  ||
       searchCriteria.diskInstance   ||
       searchCriteria.vid            ||
-      searchCriteria.diskFileIds;
+      searchCriteria.diskFileIds    ||
+      searchCriteria.fSeq;
 
     if(thereIsAtLeastOneSearchCriteria) {
     sql += " WHERE ";
@@ -136,15 +137,24 @@ RdbmsCatalogueGetArchiveFilesItor::RdbmsCatalogueGetArchiveFilesItor(
       sql += "TAPE_FILE.VID = :VID";
       addedAWhereConstraint = true;
     }
+    if (searchCriteria.fSeq) {
+      if(addedAWhereConstraint) sql += " AND ";
+      sql += "TAPE_FILE.FSEQ = :FSEQ";
+      addedAWhereConstraint = true;
+    }
     if(searchCriteria.diskFileIds) {
       if(addedAWhereConstraint) sql += " AND ";
       sql += "ARCHIVE_FILE.DISK_FILE_ID IN (SELECT DISK_FILE_ID FROM " + tempDiskFxidsTableName + ")";
       addedAWhereConstraint = true;
     }
 
-    // Order by FSEQ if we are listing the contents of a tape, else order by archive file ID
+    // Order by FSEQ if we are listing the contents of a tape, 
+    // by DISK_FILE_ID if listing the contents of a DISK_INSTANCE 
+    // else order by archive file ID
     if(searchCriteria.vid) {
       sql += " ORDER BY FSEQ";
+    } else if (searchCriteria.diskInstance) {
+      sql += " ORDER BY DISK_FILE_ID";
     } else {
       sql += " ORDER BY ARCHIVE_FILE_ID, COPY_NB";
     }
@@ -159,6 +169,11 @@ RdbmsCatalogueGetArchiveFilesItor::RdbmsCatalogueGetArchiveFilesItor(
     if(searchCriteria.vid) {
       m_stmt.bindString(":VID", searchCriteria.vid.value());
     }
+
+    if(searchCriteria.fSeq) {
+      m_stmt.bindUint64(":FSEQ", searchCriteria.fSeq.value());
+    }
+    
     m_rset = m_stmt.executeQuery();
     {
       log::LogContext lc(m_log);
diff --git a/catalogue/SqliteCatalogue.cpp b/catalogue/SqliteCatalogue.cpp
index f235c0279b3e224e75d9b0ea14512e7373091b3b..a3f3b98c7a30adc3823ca61e359d5b6b3729213d 100644
--- a/catalogue/SqliteCatalogue.cpp
+++ b/catalogue/SqliteCatalogue.cpp
@@ -685,5 +685,95 @@ void SqliteCatalogue::copyTapeFileToFileRecyleLogAndDelete(rdbms::Conn & conn, c
   } 
 }
 
+//------------------------------------------------------------------------------
+// restoreFileCopiesInRecycleLog
+//------------------------------------------------------------------------------
+void SqliteCatalogue::restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) {
+try {
+    utils::Timer t;
+    log::TimingList tl;
+
+    //put fileRecycleLogs in std::list so we can release the underlying fileRecycleLogItor database connection
+    //otherwise we are using two conns when calling getArchiveFilesItor
+    std::list<common::dataStructures::FileRecycleLog> fileRecycleLogList;
+    while (fileRecycleLogItor.hasMore()) {
+      auto fileRecycleLog = fileRecycleLogItor.next();
+      fileRecycleLogList.push_back(fileRecycleLog);
+    }
+
+    //We currently do all file copy restoring in a single transaction
+    conn.executeNonQuery("BEGIN TRANSACTION");
+    for (auto &fileRecycleLog: fileRecycleLogList) {     
+      TapeFileSearchCriteria searchCriteria;
+      searchCriteria.archiveFileId = fileRecycleLog.archiveFileId;
+      searchCriteria.diskInstance = fileRecycleLog.diskInstanceName;
+      searchCriteria.diskFileIds = std::vector<std::string>();
+      searchCriteria.diskFileIds.value().push_back(fileRecycleLog.diskFileId);
+
+      auto itor = getArchiveFilesItor(conn, searchCriteria); 
+      if (itor.hasMore()) {
+        //only restore file copies, do nothing if file has been completely deleted in CTA
+        cta::common::dataStructures::ArchiveFile archiveFile = itor.next();
+        if (archiveFile.tapeFiles.find(fileRecycleLog.copyNb) != archiveFile.tapeFiles.end()) {
+          //copy with same copy_nb exists, cannot restore
+          UserSpecifiedExistingDeletedFileCopy ex;
+          ex.getMessage() << "Cannot restore file copy with archiveFileId " << std::to_string(fileRecycleLog.archiveFileId) 
+          << " and copy_nb " << std::to_string(fileRecycleLog.copyNb) << " because a tapefile with same archiveFileId and copy_nb already exists";
+          throw ex;
+        }
+        restoreFileCopyInRecycleLog(conn, fileRecycleLog, lc);
+      }
+    }
+    conn.commit();
+
+    log::ScopedParamContainer spc(lc);
+    tl.insertAndReset("commitTime",t);
+    tl.addToLog(spc);
+    lc.log(log::INFO,"In SqliteCatalogue::restoreFileCopiesInRecycleLog: all file copies successfully restored.");
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
+//------------------------------------------------------------------------------
+// restoreFileCopyInRecycleLog
+//------------------------------------------------------------------------------
+void SqliteCatalogue::restoreFileCopyInRecycleLog(rdbms::Conn &conn, const common::dataStructures::FileRecycleLog &fileRecycleLog, log::LogContext & lc) {
+  try {
+    utils::Timer t;
+    log::TimingList tl;
+    cta::common::dataStructures::TapeFile tapeFile;
+    tapeFile.vid = fileRecycleLog.vid;
+    tapeFile.fSeq = fileRecycleLog.fSeq;
+    tapeFile.copyNb = fileRecycleLog.copyNb;
+    tapeFile.blockId = fileRecycleLog.blockId;
+    tapeFile.fileSize = fileRecycleLog.sizeInBytes;
+    tapeFile.creationTime = fileRecycleLog.tapeFileCreationTime;
+
+    insertTapeFile(conn, tapeFile, fileRecycleLog.archiveFileId);
+    tl.insertAndReset("insertTapeFileTime",t);
+    
+    deleteTapeFileCopyFromRecycleBin(conn, fileRecycleLog);
+    tl.insertAndReset("deleteTapeFileCopyFromRecycleBinTime",t);
+    
+    log::ScopedParamContainer spc(lc);
+    spc.add("vid", tapeFile.vid);
+    spc.add("archiveFileId", fileRecycleLog.archiveFileId);
+    spc.add("fSeq", tapeFile.fSeq);
+    spc.add("copyNb", tapeFile.copyNb);
+    spc.add("fileSize", tapeFile.fileSize);
+    tl.addToLog(spc);
+    lc.log(log::INFO,"In SqliteCatalogue::restoreFileCopyInRecycleLog: File restored from the recycle log.");
+  } catch(exception::UserError &) {
+    throw;
+  } catch(exception::Exception &ex) {
+    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
+    throw;
+  }
+}
+
 } // namespace catalogue
 } // namespace cta
diff --git a/catalogue/SqliteCatalogue.hpp b/catalogue/SqliteCatalogue.hpp
index 4102a8532ba2b638de1643b88859246f99aed3aa..70394195df73617de384388c2f98d67583983fb0 100644
--- a/catalogue/SqliteCatalogue.hpp
+++ b/catalogue/SqliteCatalogue.hpp
@@ -227,6 +227,24 @@ protected:
   void copyTapeFileToFileRecyleLogAndDelete(rdbms::Conn & conn, const cta::common::dataStructures::ArchiveFile &file, 
                                             const std::string &reason, log::LogContext & lc) override;
 
+  /**
+   * Copy the files in fileRecycleLogItor to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entries
+   * @param conn the database connection
+   * @param fileRecycleLogItor the collection of fileRecycleLogs we want to restore
+   * @param lc the log context
+   */
+  void restoreFileCopiesInRecycleLog(rdbms::Conn & conn, FileRecycleLogItor &fileRecycleLogItor, log::LogContext & lc) override;
+
+  /**
+   * Copy the fileRecycleLog to the TAPE_FILE table and deletes the corresponding FILE_RECYCLE_LOG table entry
+   * @param conn the database connection
+   * @param fileRecycleLog the fileRecycleLog we want to restore
+   * @param lc the log context
+   */
+  void restoreFileCopyInRecycleLog(rdbms::Conn & conn, const common::dataStructures::FileRecycleLog &fileRecycleLogItor, log::LogContext & lc);
+
+
+
 private:
 
   /**
diff --git a/catalogue/TapeFileSearchCriteria.hpp b/catalogue/TapeFileSearchCriteria.hpp
index df604f20d1fff7f9f1c94e94da2ab5679cd3d339..efd52ab41e7d1f5ea195a7dffb2f79757d3d9d29 100644
--- a/catalogue/TapeFileSearchCriteria.hpp
+++ b/catalogue/TapeFileSearchCriteria.hpp
@@ -47,6 +47,11 @@ struct TapeFileSearchCriteria {
    */
   optional<std::string> vid;
 
+  /**
+   * The fSeq of the file on tape.
+   */
+  optional<uint64_t> fSeq;
+
   /**
    * List of disk file IDs.
    *
diff --git a/catalogue/common_catalogue_schema.sql b/catalogue/common_catalogue_schema.sql
index b0fbdc2adf7871cafde16894227fea24d5ef5509..6443c3d985300e96108769cd732e416c9aa2b35c 100644
--- a/catalogue/common_catalogue_schema.sql
+++ b/catalogue/common_catalogue_schema.sql
@@ -39,6 +39,7 @@ CREATE TABLE VIRTUAL_ORGANIZATION(
   VIRTUAL_ORGANIZATION_NAME VARCHAR(100)  CONSTRAINT VIRTUAL_ORGANIZATION_VON_NN  NOT NULL,
   READ_MAX_DRIVES UINT64TYPE              CONSTRAINT VIRTUAL_ORGANIZATION_RMD_NN  NOT NULL,
   WRITE_MAX_DRIVES UINT64TYPE             CONSTRAINT VIRTUAL_ORGANIZATION_WMD_NN  NOT NULL,
+  MAX_FILE_SIZE UINT64TYPE                CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN  NOT NULL,
   USER_COMMENT            VARCHAR(1000)   CONSTRAINT VIRTUAL_ORGANIZATION_UC_NN   NOT NULL,
   CREATION_LOG_USER_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLUN_NN NOT NULL,
   CREATION_LOG_HOST_NAME  VARCHAR(100)    CONSTRAINT VIRTUAL_ORGANIZATION_CLHN_NN NOT NULL,
diff --git a/catalogue/migrations/liquibase/oracle/4.1to4.2.sql b/catalogue/migrations/liquibase/oracle/4.1to4.2.sql
new file mode 100644
index 0000000000000000000000000000000000000000..e76b7c4c018561a166f707884a2f5dd8d279d613
--- /dev/null
+++ b/catalogue/migrations/liquibase/oracle/4.1to4.2.sql
@@ -0,0 +1,33 @@
+--liquibase formatted sql
+
+--changeset mvelosob:1 failOnError:true dbms:oracle
+--preconditions onFail:HALT onError:HALT
+--precondition-sql-check expectedResult:"4.1" SELECT CONCAT(CONCAT(CAST(SCHEMA_VERSION_MAJOR as VARCHAR(10)),'.'), CAST(SCHEMA_VERSION_MINOR AS VARCHAR(10))) AS CATALOGUE_VERSION FROM CTA_CATALOGUE;
+UPDATE CTA_CATALOGUE SET STATUS='UPGRADING';
+UPDATE CTA_CATALOGUE SET NEXT_SCHEMA_VERSION_MAJOR=4;
+UPDATE CTA_CATALOGUE SET NEXT_SCHEMA_VERSION_MINOR=2;
+--rollback UPDATE CTA_CATALOGUE SET NEXT_SCHEMA_VERSION_MAJOR=NULL;
+--rollback UPDATE CTA_CATALOGUE SET NEXT_SCHEMA_VERSION_MINOR=NULL;
+--rollback UPDATE CTA_CATALOGUE SET STATUS='PRODUCTION';
+
+--changeset mvelosob:2 failOnError:true dbms:oracle
+--preconditions onFail:HALT onError:HALT
+--precondition-sql-check expectedResult:"4.1" SELECT CONCAT(CONCAT(CAST(SCHEMA_VERSION_MAJOR as VARCHAR(10)),'.'), CAST(SCHEMA_VERSION_MINOR AS VARCHAR(10))) AS CATALOGUE_VERSION FROM CTA_CATALOGUE;
+ALTER TABLE VIRTUAL_ORGANIZATION ADD (MAX_FILE_SIZE NUMERIC(20, 0));
+UPDATE VIRTUAL_ORGANIZATION SET MAX_FILE_SIZE=128849018880;
+ALTER TABLE VIRTUAL_ORGANIZATION MODIFY MAX_FILE_SIZE CONSTRAINT VIRTUAL_ORGANIZATION_MFS_NN NOT NULL;
+--rollback ALTER TABLE VIRTUAL_ORGANIZATION DROP COLUMN MAX_FILE_SIZE
+
+--changeset mvelosob:3 failOnError:true dbms:oracle
+--preconditions onFail:HALT onError:HALT
+--precondition-sql-check expectedResult:"4.1" SELECT CONCAT(CONCAT(CAST(SCHEMA_VERSION_MAJOR as VARCHAR(10)),'.'), CAST(SCHEMA_VERSION_MINOR AS VARCHAR(10))) AS CATALOGUE_VERSION FROM CTA_CATALOGUE;
+UPDATE CTA_CATALOGUE SET STATUS='PRODUCTION';
+UPDATE CTA_CATALOGUE SET SCHEMA_VERSION_MAJOR=4;
+UPDATE CTA_CATALOGUE SET SCHEMA_VERSION_MINOR=2;
+UPDATE CTA_CATALOGUE SET NEXT_SCHEMA_VERSION_MAJOR=NULL;
+UPDATE CTA_CATALOGUE SET NEXT_SCHEMA_VERSION_MINOR=NULL;
+--rollback UPDATE CTA_CATALOGUE SET STATUS='UPGRADING';
+--rollback UPDATE CTA_CATALOGUE SET SCHEMA_VERSION_MAJOR=4;
+--rollback UPDATE CTA_CATALOGUE SET SCHEMA_VERSION_MINOR=1;
+--rollback UPDATE CTA_CATALOGUE SET NEXT_SCHEMA_VERSION_MAJOR=4;
+--rollback UPDATE CTA_CATALOGUE SET NEXT_SCHEMA_VERSION_MINOR=2;
diff --git a/cmake/CTAVersions.cmake b/cmake/CTAVersions.cmake
index 13f75929eb1e51494859e76a085d3fa9c6563df4..6ee868bdcf94fff06002e94577549b6b0e632e31 100644
--- a/cmake/CTAVersions.cmake
+++ b/cmake/CTAVersions.cmake
@@ -19,7 +19,7 @@ set(XROOTD_SSI_PROTOBUF_INTERFACE_VERSION "v0.0")
 
 # Catalogue Schema Version
 set(CTA_CATALOGUE_SCHEMA_VERSION_MAJOR 4)
-set(CTA_CATALOGUE_SCHEMA_VERSION_MINOR 1)
+set(CTA_CATALOGUE_SCHEMA_VERSION_MINOR 2)
 
 # Shared object internal version (used in SONAME)
 set(CTA_SOVERSION 0)
diff --git a/cmdline/CtaAdminCmd.cpp b/cmdline/CtaAdminCmd.cpp
index 334e55dc4ddb09edd295d03c4ed47977f66d947e..eb600d7df98b7d5d967ea15a43f604d2f37e0d1b 100644
--- a/cmdline/CtaAdminCmd.cpp
+++ b/cmdline/CtaAdminCmd.cpp
@@ -34,6 +34,8 @@ std::atomic<bool> isHeaderSent(false);
 cta::admin::TextFormatter formattedText(1000);
 
 
+std::string tp_config_file = "/etc/cta/TPCONFIG";
+
 namespace XrdSsiPb {
 
 /*!
@@ -229,7 +231,7 @@ void CtaAdminCmd::send() const
    } catch(std::runtime_error &ex) {
       throwUsage(ex.what());
    }
-   
+
    // Set configuration options
    const std::string config_file = "/etc/cta/cta-cli.conf";
    XrdSsiPb::Config config(config_file, "cta");
@@ -346,7 +348,36 @@ void CtaAdminCmd::parseOptions(int start, int argc, const char *const *const arg
    }
 }
 
+std::string CtaAdminCmd::getDriveFromTpConfig() {
+   std::ifstream file(tp_config_file);
+   if (file.fail()) {
+      throw std::runtime_error("Unable to open file " + tp_config_file);
+   }
+
+   std::string line;
 
+   while(std::getline(file, line)) {
+      // Strip out comments
+      auto pos = line.find('#');
+      if(pos != std::string::npos) {
+         line.resize(pos);
+      }
+
+      // Extract the list items
+      std::stringstream ss(line);
+      while(!ss.eof()) {
+         std::string item;
+         ss >> item;
+         // skip blank lines or lines consisting only of whitespace
+         if(item.empty()) continue;
+
+         std::string drivename = item.substr(0, item.find(" ")); // first word of line
+         return drivename;
+         
+      }
+   }
+   throw std::runtime_error("File " + tp_config_file + " is empty");
+}
 
 void CtaAdminCmd::addOption(const Option &option, const std::string &value)
 {
@@ -359,7 +390,11 @@ void CtaAdminCmd::addOption(const Option &option, const std::string &value)
          auto key = strOptions.at(option.get_key());
          auto new_opt = admincmd_ptr->add_option_str();
          new_opt->set_key(key);
-         new_opt->set_value(value);
+         if (option == opt_drivename_cmd && value == "first") {
+            new_opt->set_value(getDriveFromTpConfig());
+         } else {
+            new_opt->set_value(value);
+         }
          break;
       }
       case Option::OPT_STR_LIST: {
diff --git a/cmdline/CtaAdminCmd.hpp b/cmdline/CtaAdminCmd.hpp
index fa5bfee36f7be15aa64a1c59f455859a93381966..3c53f016f0551d242c1314599780895fb4ce9fe5 100644
--- a/cmdline/CtaAdminCmd.hpp
+++ b/cmdline/CtaAdminCmd.hpp
@@ -49,6 +49,9 @@ private:
    //! Add a valid option to the protocol buffer
    void addOption(const Option &option, const std::string &value);
 
+   //! Parses the TPCONFIG file to obtain the first drive in the tapeserver
+   std::string getDriveFromTpConfig();
+
    //! Read a list of string options from a file
    void readListFromFile(cta::admin::OptionStrList &str_list, const std::string &filename);
 
diff --git a/cmdline/CtaAdminCmdParse.hpp b/cmdline/CtaAdminCmdParse.hpp
index 3d4d1a377989c2e06e943eb6e4330d4cf8517dcf..3fd5377c36a37627509c4185376ad58b6a7c4340 100644
--- a/cmdline/CtaAdminCmdParse.hpp
+++ b/cmdline/CtaAdminCmdParse.hpp
@@ -66,6 +66,13 @@ public:
       return option == m_short_opt || option == m_long_opt;
    }
 
+   /*!
+    * Check if the supplied option matches the option
+    */
+   bool operator==(const Option &option) const {
+      return option == m_short_opt || option == m_long_opt;
+   }
+
    /*!
     * Return the type of this option
     */
@@ -238,6 +245,7 @@ const subcmdLookup_t subcmdLookup = {
    { "rm",                      AdminCmd::SUBCMD_RM },
    { "up",                      AdminCmd::SUBCMD_UP },
    { "down",                    AdminCmd::SUBCMD_DOWN },
+   { "restore",                 AdminCmd::SUBCMD_RESTORE }
 };
 
 
@@ -276,6 +284,7 @@ const std::map<std::string, OptionUInt64::Key> uint64Options = {
    { "--capacity",              OptionUInt64::CAPACITY },
    { "--copynb",                OptionUInt64::COPY_NUMBER },
    { "--id",                    OptionUInt64::ARCHIVE_FILE_ID },
+   {"--maxfilesize",            OptionUInt64::MAX_FILE_SIZE},
    { "--maxlpos",               OptionUInt64::MAX_LPOS },
    { "--minarchiverequestage",  OptionUInt64::MIN_ARCHIVE_REQUEST_AGE },
    { "--minlpos",               OptionUInt64::MIN_LPOS },
@@ -345,7 +354,9 @@ const std::map<AdminCmd::Cmd, CmdHelp> cmdHelp = {
                         "\n  This is a synchronous command that sets and reads back the state of one or\n"
                           "  more drives. The <drive_name> option accepts a regular expression. If the\n"
                           "  --force option is not set, the drives will complete any running mount and\n"
-                          "  drives must be in the down state before deleting.\n\n"
+                          "  drives must be in the down state before deleting. If the <drive_name> option\n"
+                          "  is set to first, the up, down, ls and ch commands will use the first drive\n"
+                          "  listed in TPCONFIG\n\n"
                                          }},
    { AdminCmd::CMD_FAILEDREQUEST,        { "failedrequest",        "fr",  { "ls", "rm" } }},
    { AdminCmd::CMD_GROUPMOUNTRULE,       { "groupmountrule",       "gmr", { "add", "ch", "rm", "ls" } }},
@@ -404,14 +415,17 @@ const std::map<AdminCmd::Cmd, CmdHelp> cmdHelp = {
                                            "   * Specify the name (--vo) of the virtual organization. It must be unique.\n"
                                            "   * Specify the maximum number of drives the virtual organization is allowed to use for writing with the --writemaxdrives parameter\n"
                                            "   * Specify the maximum number of drives the virtual organization is allowed to use for reading with the --readmaxdrives parameter\n"
-                                           "   * Specify the comment (--comment) associated to the virtual organization"
+                                           "   * Specify the comment (--comment) associated to the virtual organization\n"
+                                           "   * Specify the maximum file size (--maxfilesize) associated to the virtual organization (optional, a value of 0 means no limit)"
                                            "\n\n"
                                          }},
    { AdminCmd::CMD_VERSION,              { "version",               "v",  { } }},
    { AdminCmd::CMD_SCHEDULINGINFOS,      { "schedulinginfo",        "si",  { "ls" } }},
-   { AdminCmd::CMD_RECYCLETAPEFILE,      { "recycletf",        "rtf",  { "ls" },
+   { AdminCmd::CMD_RECYCLETAPEFILE,      { "recycletf",        "rtf",  { "ls", "restore" },
+                            "  This command allows to manage files in the recycle log.\n"
                             "  Tape files in the recycle log can be listed by VID, EOS disk file ID, EOS disk instance, ArchiveFileId or copy number.\n"
-                            "  Disk file IDs should be provided in hexadecimal (fxid).\n\n" }},
+                            "  Disk file IDs should be provided in hexadecimal (fxid).\n"
+                            "  Deleted files can be restored with the restore command\n\n" }},
 };
 
 
@@ -429,7 +443,6 @@ const Option opt_comment              { Option::OPT_STR,  "--comment",
 const Option opt_copynb               { Option::OPT_UINT, "--copynb",                "-c",   " <copy_number>" };
 const Option opt_copynb_alias         { Option::OPT_UINT, "--numberofcopies",        "-c",   " <number_of_copies>", "--copynb" };
 const Option opt_disabled             { Option::OPT_BOOL, "--disabled",              "-d",   " <\"true\" or \"false\">" };
-const Option opt_drivename            { Option::OPT_STR,  "--drive",                 "-d",   " <drive_name>" };
 const Option opt_drivename_cmd        { Option::OPT_CMD,  "--drive",                 "",     "<drive_name>" };
 const Option opt_encrypted            { Option::OPT_BOOL, "--encrypted",             "-e",   " <\"true\" or \"false\">" };
 const Option opt_encryptionkeyname    { Option::OPT_STR,  "--encryptionkeyname",     "-k",   " <encryption_key_name>" };
@@ -448,6 +461,7 @@ const Option opt_log                  { Option::OPT_FLAG, "--log",
 const Option opt_logicallibrary       { Option::OPT_STR,  "--logicallibrary",        "-l",   " <logical_library_name>" };
 const Option opt_logicallibrary_alias { Option::OPT_STR,  "--name",                  "-n",   " <logical_library_name>", "--logicallibrary" };
 const Option opt_lookupns             { Option::OPT_FLAG, "--lookupnamespace",       "-l",   "" };
+const Option opt_maxfilesize          { Option::OPT_UINT, "--maxfilesize",           "-mfs", " <maximum_file_size>" };
 const Option opt_maxlpos              { Option::OPT_UINT, "--maxlpos",               "-maxl", " <maximum_longitudinal_position>" };
 const Option opt_mediatype            { Option::OPT_STR,  "--mediatype",             "--mt", " <media_type_name>" };
 const Option opt_mediatype_alias      { Option::OPT_STR,  "--name",                  "-n",   " <media_type_name>", "--mediatype" };
@@ -470,6 +484,7 @@ const Option opt_tapepool             { Option::OPT_STR,  "--tapepool",
 const Option opt_tapepool_alias       { Option::OPT_STR,  "--name",                  "-n",   " <tapepool_name>", "--tapepool" };
 const Option opt_username             { Option::OPT_STR,  "--username",              "-u",   " <user_name>" };
 const Option opt_username_alias       { Option::OPT_STR,  "--name",                  "-n",   " <user_name>", "--username" };
+const Option opt_groupname_alias      { Option::OPT_STR,  "--name",                  "-n",   " <group_name>", "--username" };
 const Option opt_vendor               { Option::OPT_STR,  "--vendor",                "--ve", " <vendor>" };
 const Option opt_vid                  { Option::OPT_STR,  "--vid",                   "-v",   " <vid>" };
 const Option opt_vo                   { Option::OPT_STR,  "--virtualorganisation",   "--vo", " <virtual_organisation>" };
@@ -508,8 +523,8 @@ const std::map<cmd_key_t, cmd_val_t> cmdOptions = {
    /*----------------------------------------------------------------------------------------------------*/
    {{ AdminCmd::CMD_DRIVE,                AdminCmd::SUBCMD_UP    }, { opt_drivename_cmd, opt_reason.optional() }},
    {{ AdminCmd::CMD_DRIVE,                AdminCmd::SUBCMD_DOWN  }, { opt_drivename_cmd, opt_reason, opt_force_flag.optional() }},
-   {{ AdminCmd::CMD_DRIVE,                AdminCmd::SUBCMD_LS    }, { opt_drivename.optional() }},
-   {{ AdminCmd::CMD_DRIVE,                AdminCmd::SUBCMD_RM    }, { opt_drivename_cmd, opt_force_flag.optional() }},
+   {{ AdminCmd::CMD_DRIVE,                AdminCmd::SUBCMD_LS    }, { opt_drivename_cmd.optional() }},
+   {{ AdminCmd::CMD_DRIVE,                AdminCmd::SUBCMD_RM    }, { opt_drivename_cmd, opt_force_flag.optional()}},
    {{ AdminCmd::CMD_DRIVE,                AdminCmd::SUBCMD_CH    }, { opt_drivename_cmd, opt_comment }},
    /*----------------------------------------------------------------------------------------------------*/
    {{ AdminCmd::CMD_FAILEDREQUEST,        AdminCmd::SUBCMD_LS    },
@@ -518,10 +533,10 @@ const std::map<cmd_key_t, cmd_val_t> cmdOptions = {
    {{ AdminCmd::CMD_FAILEDREQUEST,        AdminCmd::SUBCMD_RM    }, { opt_object_id }},
    /*----------------------------------------------------------------------------------------------------*/
    {{ AdminCmd::CMD_GROUPMOUNTRULE,       AdminCmd::SUBCMD_ADD   },
-      { opt_instance, opt_username_alias, opt_mountpolicy, opt_comment }},
+      { opt_instance, opt_groupname_alias, opt_mountpolicy, opt_comment }},
    {{ AdminCmd::CMD_GROUPMOUNTRULE,       AdminCmd::SUBCMD_CH    },
-      { opt_instance, opt_username_alias, opt_mountpolicy.optional(), opt_comment.optional() }},
-   {{ AdminCmd::CMD_GROUPMOUNTRULE,       AdminCmd::SUBCMD_RM    }, { opt_instance, opt_username_alias }},
+      { opt_instance, opt_groupname_alias, opt_mountpolicy.optional(), opt_comment.optional() }},
+   {{ AdminCmd::CMD_GROUPMOUNTRULE,       AdminCmd::SUBCMD_RM    }, { opt_instance, opt_groupname_alias }},
    {{ AdminCmd::CMD_GROUPMOUNTRULE,       AdminCmd::SUBCMD_LS    }, { }},
    /*----------------------------------------------------------------------------------------------------*/
    {{ AdminCmd::CMD_LOGICALLIBRARY,       AdminCmd::SUBCMD_ADD   },
@@ -609,9 +624,9 @@ const std::map<cmd_key_t, cmd_val_t> cmdOptions = {
    {{ AdminCmd::CMD_DISKSYSTEM,           AdminCmd::SUBCMD_RM    }, { opt_disksystem }},
    {{ AdminCmd::CMD_DISKSYSTEM,           AdminCmd::SUBCMD_LS    }, { }},
    {{ AdminCmd::CMD_VIRTUALORGANIZATION,           AdminCmd::SUBCMD_ADD   },
-      { opt_vo, opt_read_max_drives, opt_write_max_drives, opt_comment }},
+      { opt_vo, opt_read_max_drives, opt_write_max_drives, opt_comment, opt_maxfilesize.optional() }},
    {{ AdminCmd::CMD_VIRTUALORGANIZATION,           AdminCmd::SUBCMD_CH   },
-      { opt_vo, opt_comment.optional(), opt_read_max_drives.optional(), opt_write_max_drives.optional() }},
+      { opt_vo, opt_comment.optional(), opt_read_max_drives.optional(), opt_write_max_drives.optional(), opt_maxfilesize.optional() }},
    {{ AdminCmd::CMD_VIRTUALORGANIZATION,           AdminCmd::SUBCMD_RM   },
       { opt_vo }},
    {{ AdminCmd::CMD_VIRTUALORGANIZATION,           AdminCmd::SUBCMD_LS   },
@@ -620,6 +635,8 @@ const std::map<cmd_key_t, cmd_val_t> cmdOptions = {
    {{ AdminCmd::CMD_SCHEDULINGINFOS,      AdminCmd::SUBCMD_LS   }, { }},
    {{ AdminCmd::CMD_RECYCLETAPEFILE, AdminCmd::SUBCMD_LS }, 
    { opt_vid.optional(), opt_fid.optional(), opt_fidfile.optional(), opt_copynb.optional(), opt_archivefileid.optional(), opt_instance.optional() }},
+   {{ AdminCmd::CMD_RECYCLETAPEFILE, AdminCmd::SUBCMD_RESTORE }, 
+   { opt_vid.optional(), opt_fid.optional(), opt_fidfile.optional(), opt_copynb.optional(), opt_archivefileid.optional(), opt_instance.optional() }},
 };
 
 
@@ -630,5 +647,4 @@ const std::map<cmd_key_t, cmd_val_t> cmdOptions = {
  * Throws a std::runtime_error if the command is invalid
  */
 void validateCmd(const cta::admin::AdminCmd &admincmd);
-
 }} // namespace cta::admin
diff --git a/cmdline/CtaAdminTextFormatter.cpp b/cmdline/CtaAdminTextFormatter.cpp
index 80ca2425d7e6f369ac37f8f17944229b8a7c1124..986fac9961d1a766f56ad0700c2260ed03091f85 100644
--- a/cmdline/CtaAdminTextFormatter.cpp
+++ b/cmdline/CtaAdminTextFormatter.cpp
@@ -994,6 +994,7 @@ void TextFormatter::printVirtualOrganizationLsHeader(){
     "name",
     "read max drives",
     "write max drives",
+    "max file size",
     "c.user",
     "c.host",
     "c.time",
@@ -1009,6 +1010,7 @@ void TextFormatter::print(const VirtualOrganizationLsItem& vols_item){
     vols_item.name(),
     vols_item.read_max_drives(),
     vols_item.write_max_drives(),
+    dataSizeToStr(vols_item.max_file_size()),
     vols_item.creation_log().username(),
     vols_item.creation_log().host(),
     timeToStr(vols_item.creation_log().time()),
diff --git a/common/dataStructures/VirtualOrganization.hpp b/common/dataStructures/VirtualOrganization.hpp
index df28140a35e7e4804d287a398351046e4576214d..a8d31b04426111b83104b64327fc2311f6b7c4cd 100644
--- a/common/dataStructures/VirtualOrganization.hpp
+++ b/common/dataStructures/VirtualOrganization.hpp
@@ -41,6 +41,12 @@ struct VirtualOrganization {
    * Max number of drives allocated for writing per VO
    */
   uint64_t writeMaxDrives;
+
+  /**
+   * Max size of files belonging to VO
+   */
+  uint64_t maxFileSize;
+  
   /**
    * The creation log.
    */
@@ -52,7 +58,8 @@ struct VirtualOrganization {
   EntryLog lastModificationLog;
   
   bool operator==(const VirtualOrganization & other) const{
-    return (name == other.name && comment == other.comment && readMaxDrives == other.readMaxDrives && writeMaxDrives == other.writeMaxDrives);
+    return (name == other.name && comment == other.comment && readMaxDrives == other.readMaxDrives && 
+      writeMaxDrives == other.writeMaxDrives && maxFileSize == other.maxFileSize);
   }
 };
 
diff --git a/continuousintegration/buildtree_runner/vmBootstrap/bootstrapCTA.sh b/continuousintegration/buildtree_runner/vmBootstrap/bootstrapCTA.sh
index ee35b5f822f09a203375d634279c6bd5dc9ec106..2168fd66a709c759fe7f4e5647a3e30ce59c71dd 100755
--- a/continuousintegration/buildtree_runner/vmBootstrap/bootstrapCTA.sh
+++ b/continuousintegration/buildtree_runner/vmBootstrap/bootstrapCTA.sh
@@ -63,6 +63,7 @@ echo Installing build dependencies
 sudo yum-builddep -y ~/CTA-build-srpm/RPM/SRPMS/cta-0-1.src.rpm
 
 echo Building CTA
+rm -rf ~/CTA-build
 mkdir -p ~/CTA-build
 (cd ~/CTA-build && cmake ../CTA; make -j 4)
 
diff --git a/cta.spec.in b/cta.spec.in
index fd91fa999a9155e78d4e9b9b056037780a2dfd4b..fa403efb3cab4ee499ab5b74399b8eea4e526cb7 100644
--- a/cta.spec.in
+++ b/cta.spec.in
@@ -441,6 +441,22 @@ The command-line tool for pre-labelling a CTA tape.
 %post -n cta-tape-label
 /usr/sbin/setcap cap_sys_rawio+ep  %{_bindir}/cta-tape-label
 
+%package -n cta-readtp
+Summary: The command-line tool for reading files from a CTA tape.
+Group: Application/CTA
+Requires: cta-lib = %{version}-%{release}
+Requires: xrootd-client-libs >= %{xrootdVersion}
+Requires(post): /usr/sbin/setcap
+%description -n cta-readtp
+CERN Tape Archive:
+The command-line tool for reading files from a CTA tape.
+%files -n cta-readtp
+%defattr(-,root,root)
+%attr(0750,cta,tape) %{_bindir}/cta-readtp
+%attr(0644,root,root) %doc /usr/share/man/man1/cta-readtp.1cta.gz
+%post -n cta-readtp
+/usr/sbin/setcap cap_sys_rawio+ep  %{_bindir}/cta-readtp
+
 %package -n cta-common
 Summary: CERN Tape Archive common items
 Group: Application/CTA
@@ -513,6 +529,12 @@ Remember to add its content to "%{_sysconfdir}/yum/pluginconf.d/versionlock.list
 EOF
 
 %changelog
+* Wed Aug 18 2021 volodymyr.yurchenko (at) cern.ch - 4.1-1
+- cta/CTA#1016 New options for filtering deleted files using `cta-admin rtf ls` command.
+- cta/CTA#983 Add cta-release package for public binary rpm distribution.
+- cta/CTA#980 Add external encryption script option
+- [frontend] New command "tapefile rm" allows deleting a copy of a file from tape
+- cta/CTA#1014 Fix last column alignment when more than 1000 items are listed.
 * Tue Jul 27 2021 julien.leduc (at) cern.ch - 4.0-5
 - [frontend] Add options to "tapepool ls" to filter tapepools on their name, vo and encryption
 - cta/CTA#898 cta-send-event now gets the requester id and eos instance as command line arguments
diff --git a/scheduler/SchedulerTest.cpp b/scheduler/SchedulerTest.cpp
index 6b91d36bfb09085e048b31cd085c98ac6d42ac95..cb3f1d6e7324b2e2432c17b2c7a09f8f55eb37b9 100644
--- a/scheduler/SchedulerTest.cpp
+++ b/scheduler/SchedulerTest.cpp
@@ -212,6 +212,7 @@ public:
     vo.comment = "comment";
     vo.writeMaxDrives = 1;
     vo.readMaxDrives = 1;
+    vo.maxFileSize = 0;
     m_catalogue->createVirtualOrganization(s_adminOnAdminHost,vo);
 
     common::dataStructures::StorageClass storageClass;
@@ -706,6 +707,7 @@ TEST_P(SchedulerTest, archive_report_and_retrieve_new_dual_copy_file) {
     vo.comment = "comment";
     vo.writeMaxDrives = 1;
     vo.readMaxDrives = 1;
+    vo.maxFileSize = 0;
     catalogue.createVirtualOrganization(s_adminOnAdminHost,vo);
 
     common::dataStructures::StorageClass storageClass;
diff --git a/tapeserver/CMakeLists.txt b/tapeserver/CMakeLists.txt
index 8e94972cb38ccfde9feec7e0c0775006bba6664d..6f492b91cb296421ecb32cf20bbe48f8c123b8bf 100644
--- a/tapeserver/CMakeLists.txt
+++ b/tapeserver/CMakeLists.txt
@@ -23,6 +23,7 @@ add_subdirectory (session)
 # The tape session's threads are in a separate directory (session, but compiled
 # from the previous one to create a single library).
 add_subdirectory (tapelabel)
+add_subdirectory (readtp)
 
 include_directories (${PROTOBUF3_INCLUDE_DIRS})
 add_executable (cta-taped cta-taped.cpp)
diff --git a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
index eb0f2b1ed606d9db864dd02b6a8728222d3f09ce..fd04f5e65483abe0327d67c38faf9cbb05471d2f 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/DataTransferSessionTest.cpp
@@ -279,6 +279,7 @@ public:
     vo.name = "vo";
     vo.readMaxDrives = 1;
     vo.writeMaxDrives = 1;
+    vo.maxFileSize = 0;
     vo.comment = "comment";
     return vo;
   }
@@ -2322,21 +2323,24 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullMigration) {
   std::string temp = logger.getLog();
   temp += "";
   ASSERT_EQ(s_vid, sess.getVid());
-  auto afiiter = archiveFileIds.begin();
-  size_t archiveFileCount = 0;
-  for(auto & sf: sourceFiles) {
-    auto afi = *(afiiter++);
-    archiveFileCount++;
+  cta::catalogue::TapeFileSearchCriteria criteria;
+  auto afsItor = catalogue.getArchiveFilesItor(criteria);
+  for (size_t i = 1; i <= sourceFiles.size(); ++i) {
     // Only the first files made it through.
-    if (archiveFileCount <= 3) {
-      auto afs = catalogue.getArchiveFileById(afi);
+    if (i <= 3) {
+      ASSERT_TRUE(afsItor.hasMore());
+      auto afs = afsItor.next();
       ASSERT_EQ(1, afs.tapeFiles.size());
       cta::checksum::ChecksumBlob checksumBlob;
-      checksumBlob.insert(cta::checksum::ADLER32, sf->adler32());
+      // Get the element of the list sourceFiles correspondent with afs.archiveFileID (https://stackoverflow.com/a/16747600)
+      // archiveFileID starts on "1" that's why it removes one position in the list
+      auto sourceFiles_front = sourceFiles.begin();
+      std::advance(sourceFiles_front, afs.archiveFileID - 1);
+      checksumBlob.insert(cta::checksum::ADLER32, (*sourceFiles_front)->adler32());
       ASSERT_EQ(afs.checksumBlob, checksumBlob);
       ASSERT_EQ(1000, afs.fileSize);
     } else {
-      ASSERT_THROW(catalogue.getArchiveFileById(afi), cta::exception::Exception);
+      ASSERT_FALSE(afsItor.hasMore());
     }
     // The tape should now be marked as full
     cta::catalogue::TapeSearchCriteria crit;
@@ -2485,21 +2489,24 @@ TEST_P(DataTransferSessionTest, DataTransferSessionTapeFullOnFlushMigration) {
   std::string temp = logger.getLog();
   temp += "";
   ASSERT_EQ(s_vid, sess.getVid());
-  auto afiiter = archiveFileIds.begin();
-  size_t archiveFileCount = 0;
-  for(auto & sf: sourceFiles) {
-    auto afi = *(afiiter++);
-    archiveFileCount++;
+  cta::catalogue::TapeFileSearchCriteria criteria;
+  auto afsItor = catalogue.getArchiveFilesItor(criteria);
+  for (size_t i = 1; i <= sourceFiles.size(); ++i) {
     // Only the first files made it through.
-    if (archiveFileCount <= 3) {
-      auto afs = catalogue.getArchiveFileById(afi);
+    if (i <= 3) {
+      ASSERT_TRUE(afsItor.hasMore());
+      auto afs = afsItor.next();
       ASSERT_EQ(1, afs.tapeFiles.size());
       cta::checksum::ChecksumBlob checksumBlob;
-      checksumBlob.insert(cta::checksum::ADLER32, sf->adler32());
+      // Get the element of the list sourceFiles correspondent with afs.archiveFileID (https://stackoverflow.com/a/16747600)
+      // archiveFileID starts on "1" that's why it removes one position in the list
+      auto sourceFiles_front = sourceFiles.begin();
+      std::advance(sourceFiles_front, afs.archiveFileID - 1);
+      checksumBlob.insert(cta::checksum::ADLER32, (*sourceFiles_front)->adler32());
       ASSERT_EQ(afs.checksumBlob, checksumBlob);
       ASSERT_EQ(1000, afs.fileSize);
     } else {
-      ASSERT_THROW(catalogue.getArchiveFileById(afi), cta::exception::Exception);
+      ASSERT_FALSE(afsItor.hasMore());
     }
     // The tape should now be marked as full
     cta::catalogue::TapeSearchCriteria crit;
diff --git a/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPackerTest.cpp b/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPackerTest.cpp
index df3e47b3d6a939d6ec1b512843d33740941296e7..99829be23eb68090c12a7c2a214d7272855b558e 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPackerTest.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/MigrationReportPackerTest.cpp
@@ -70,6 +70,7 @@ const uint32_t TEST_GROUP_2 = 9754;
       vo.name = "vo";
       vo.readMaxDrives = 1;
       vo.writeMaxDrives = 1;
+      vo.maxFileSize = 0;
       vo.comment = "comment";
       return vo;
     }
diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp
index a0b122c996e99804ac2642f14dad558ddafa1b83..675a8e22cc4d02b5701bcb5781b557148e487ef5 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/TapeReadSingleThread.cpp
@@ -376,7 +376,7 @@ void castor::tape::tapeserver::daemon::TapeReadSingleThread::run() {
     // This can happen late in the session, so we can still print the stats.
     cta::log::ScopedParamContainer params(m_logContext);
     params.add("status", "error")
-          .add("ErrorMesage", e.getMessageValue());
+          .add("ErrorMessage", e.getMessageValue());
     m_stats.totalTime = totalTimer.secs();
     logWithStat(cta::log::INFO, "Tape thread complete",
             params);
diff --git a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp
index c3e8cd5c9489dfae699a04bcd7f16d783eceb2bc..b4ee79fe3e6ee050f05c56061aa58a4e72a724ea 100644
--- a/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp
+++ b/tapeserver/castor/tape/tapeserver/daemon/TapeWriteSingleThread.cpp
@@ -515,7 +515,7 @@ void castor::tape::tapeserver::daemon::TapeWriteSingleThread::run() {
     // then log the end of write thread
     cta::log::ScopedParamContainer params(m_logContext);
     params.add("status", "error")
-          .add("ErrorMesage", errorMessage);
+          .add("ErrorMessage", errorMessage);
     m_stats.totalTime = totalTimer.secs();
     logWithStats(cta::log::INFO, "Tape thread complete",
             params);
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
index 73a8b3c543c11fd8531c346cfb287ddd93f72bcd..b48328311d8f09424820d52e584fc7b0ad80bd05 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.cpp
@@ -753,11 +753,43 @@ bool drive::DriveIBM3592::isEncryptionCapEnabled() {
   cta::exception::Errnum::throwOnMinusOne(
     m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
     "Failed SG_IO ioctl in DriveIBM3592::isEncryptionCapEnabled");
-  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::clearEncryptionKey");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveIBM3592::isEncryptionCapEnabled");
 
   return SCSI::Structures::toU16(pl.supportedProtocolListLength) > 1;
 }
 
+bool drive::DriveLTO::isEncryptionCapEnabled() {
+  /*
+   * Encryption enable support. Initially copied from IBM enterprise implementation.
+   */
+  /*
+   * We are acquiring the encryption capability from the length of the SPIN index page.
+   * If it has one page (only 0x00), then encryption is disabled from the libary.
+   * If it has more pages, the encryption(0x00, 0x20 at the moment of writing), then it is enabled.
+   */
+  SCSI::Structures::LinuxSGIO_t sgh;
+  SCSI::Structures::encryption::spinCDB_t cdb;
+  SCSI::Structures::senseData_t<255> senseBuff;
+  SCSI::Structures::encryption::spinPageList_t<20> pl;
+
+  cdb.securityProtocol = SCSI::encryption::spinSecurityProtocolPages::securityProtocolInformation;
+  SCSI::Structures::setU16(cdb.securityProtocolSpecific, 0x0000);
+  SCSI::Structures::setU32(cdb.allocationLength, sizeof(pl));
+
+  sgh.setCDB(&cdb);
+  sgh.setDataBuffer(&pl);
+  sgh.setSenseBuffer(&senseBuff);
+  sgh.dxfer_direction = SG_DXFER_FROM_DEV;
+
+  cta::exception::Errnum::throwOnMinusOne(
+    m_sysWrapper.ioctl(this->m_tapeFD, SG_IO, &sgh),
+    "Failed SG_IO ioctl in DriveLTO::isEncryptionCapEnabled");
+  SCSI::ExceptionLauncher(sgh, "SCSI error in DriveLTO::isEncryptionCapEnabled");
+
+  return SCSI::Structures::toU16(pl.supportedProtocolListLength) > 1;
+}
+
+
 bool drive::DriveT10000::isEncryptionCapEnabled() {
   /*
    * We are acquiring the encryption capability from the inquiry page on Oracle T10k drives
diff --git a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
index 575ea21c3b9edbd91de9490cd5313929f302243f..d22d1f8b15a0733db50f95bee948ee6cf23002f0 100644
--- a/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
+++ b/tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp
@@ -589,6 +589,7 @@ namespace drive {
     virtual compressionStats getCompression();
     virtual void clearCompressionStats();
     virtual std::vector<castor::tape::tapeserver::drive::endOfWrapPosition> getEndOfWrapPositions();
+    virtual bool isEncryptionCapEnabled();
   };
 
   class DriveIBM3592 : public DriveGeneric {
diff --git a/tapeserver/cta-taped.1cta b/tapeserver/cta-taped.1cta
index c755ed3817d5374d2d2912347f8cce5d23549a8d..6fc04eb924e4f53147c57e6a47811aa6f88faef4 100644
--- a/tapeserver/cta-taped.1cta
+++ b/tapeserver/cta-taped.1cta
@@ -141,6 +141,10 @@ The number of disk I/O threads.
 The protocol to be used when transferring files to and from disk servers.
 Possible values are RFIO or XROOT.  The value is not case sensitive.
 
+.TP
+\fBtaped externalEncryptionKeyScript
+The Python script to interface with the encryption data store.
+
 .TP
 \fBXROOT PrivateKey
 The file hosting the Xroot private key, needed to sign Xroot URLs.
diff --git a/tapeserver/daemon/DriveHandler.cpp b/tapeserver/daemon/DriveHandler.cpp
index 856a38b17112a86c4fb98822ad1a70c709e5cc8d..f179ceabc12700efb4b63c82b97db4867559af9b 100644
--- a/tapeserver/daemon/DriveHandler.cpp
+++ b/tapeserver/daemon/DriveHandler.cpp
@@ -1069,6 +1069,7 @@ int DriveHandler::runChild() {
     dataTransferConfig.fetchEosFreeSpaceScript = m_tapedConfig.fetchEosFreeSpaceScript.value();
     dataTransferConfig.tapeLoadTimeout = m_tapedConfig.tapeLoadTimeout.value();
     dataTransferConfig.xrootPrivateKey = "";
+    dataTransferConfig.externalEncryptionKeyScript = m_tapedConfig.externalEncryptionKeyScript.value();
 
     // Before launching, and if this is the first session since daemon start, we will
     // put the drive down.
diff --git a/tapeserver/daemon/MaintenanceHandler.cpp b/tapeserver/daemon/MaintenanceHandler.cpp
index 9476a755d6d4ccbb9d3303390a19d73bbc03b8fc..3fda54d22346ccab1c3f25374ed01f8944bbf1d3 100644
--- a/tapeserver/daemon/MaintenanceHandler.cpp
+++ b/tapeserver/daemon/MaintenanceHandler.cpp
@@ -42,7 +42,7 @@ SubprocessHandler("maintenanceHandler"), m_processManager(pm), m_tapedConfig(tap
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::getInitialStatus
+// MaintenanceHandler::getInitialStatus
 //------------------------------------------------------------------------------
 SubprocessHandler::ProcessingStatus MaintenanceHandler::getInitialStatus() {
   m_processingStatus.forkRequested=true;
@@ -50,7 +50,7 @@ SubprocessHandler::ProcessingStatus MaintenanceHandler::getInitialStatus() {
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::getInitialStatus
+// MaintenanceHandler::getInitialStatus
 //------------------------------------------------------------------------------
 void MaintenanceHandler::postForkCleanup() {
   // We are in the child process of another handler. We can close our socket pair
@@ -62,7 +62,7 @@ void MaintenanceHandler::postForkCleanup() {
 
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::fork
+// MaintenanceHandler::fork
 //------------------------------------------------------------------------------
 SubprocessHandler::ProcessingStatus MaintenanceHandler::fork() {
   // If anything fails while attempting to fork, we will have to declare ourselves
@@ -103,7 +103,7 @@ SubprocessHandler::ProcessingStatus MaintenanceHandler::fork() {
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::kill
+// MaintenanceHandler::kill
 //------------------------------------------------------------------------------
 void MaintenanceHandler::kill() {
   // If we have a subprocess, kill it and wait for completion (if needed). We do not need to keep
@@ -136,7 +136,7 @@ void MaintenanceHandler::kill() {
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::processEvent
+// MaintenanceHandler::processEvent
 //------------------------------------------------------------------------------
 SubprocessHandler::ProcessingStatus MaintenanceHandler::processEvent() {
   // We do not expect any feedback for the child process...
@@ -145,7 +145,7 @@ SubprocessHandler::ProcessingStatus MaintenanceHandler::processEvent() {
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::processSigChild
+// MaintenanceHandler::processSigChild
 //------------------------------------------------------------------------------
 SubprocessHandler::ProcessingStatus MaintenanceHandler::processSigChild() {
   // Check out child process's status. If the child process is still around,
@@ -212,7 +212,7 @@ SubprocessHandler::ProcessingStatus MaintenanceHandler::processSigChild() {
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::processTimeout
+// MaintenanceHandler::processTimeout
 //------------------------------------------------------------------------------
 SubprocessHandler::ProcessingStatus MaintenanceHandler::processTimeout() {
   // The only time we expect a timeout is when shutting down
@@ -236,7 +236,7 @@ SubprocessHandler::ProcessingStatus MaintenanceHandler::processTimeout() {
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::runChild
+// MaintenanceHandler::runChild
 //------------------------------------------------------------------------------
 int MaintenanceHandler::runChild() {
   try{
@@ -350,7 +350,7 @@ void MaintenanceHandler::exceptionThrowingRunChild(){
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::shutdown
+// MaintenanceHandler::shutdown
 //------------------------------------------------------------------------------
 SubprocessHandler::ProcessingStatus MaintenanceHandler::shutdown() {
   // We will signal the shutdown to the child process by sending a byte over the 
@@ -366,7 +366,7 @@ SubprocessHandler::ProcessingStatus MaintenanceHandler::shutdown() {
 }
 
 //------------------------------------------------------------------------------
-// GarbageCollectorHandler::~GarbageCollectorHandler
+// MaintenanceHandler::~MaintenanceHandler
 //------------------------------------------------------------------------------
 MaintenanceHandler::~MaintenanceHandler() {
   // If we still have a child process (should not), just stop it the hard way.
diff --git a/tapeserver/daemon/SubprocessHandler.hpp b/tapeserver/daemon/SubprocessHandler.hpp
index c03fdd358f8701381ed564327730801efb702e3f..b8ad22d60fffe9284f36ad367036c904c25a3ffc 100644
--- a/tapeserver/daemon/SubprocessHandler.hpp
+++ b/tapeserver/daemon/SubprocessHandler.hpp
@@ -27,8 +27,8 @@ namespace daemon {
 /** 
  * The interface to classes managing subprocesses. It allows an external loop
  * to handle global polling and timeouts for a set of them. Several children
- * classes are expected to be developed: a DriveHandler, a GarbageCollector
- * handler and a SignalHandler (using signalfd()).
+ * classes are expected to be developed: a DriveHandler, a MaintenanceHandler 
+ * and a SignalHandler (using signalfd()).
  * The main loop will typically be:
  * statuses[] = [all]->getInitialStatus(); // This implicitly registers the right fds in epoll (if needed)
  * loop forever
@@ -99,4 +99,4 @@ public:
   virtual int runChild() = 0;
 };
 
-}}} // namespace cta::tape::daemon
\ No newline at end of file
+}}} // namespace cta::tape::daemon
diff --git a/tapeserver/daemon/TapedConfiguration.cpp b/tapeserver/daemon/TapedConfiguration.cpp
index 530f63b4da07e46651700dba228cbfd33789e1d1..83b41062a478df4fa85833b35897ed9574193d8d 100644
--- a/tapeserver/daemon/TapedConfiguration.cpp
+++ b/tapeserver/daemon/TapedConfiguration.cpp
@@ -95,6 +95,7 @@ TapedConfiguration TapedConfiguration::createFromCtaConf(
   ret.daemonGroupName.setFromConfigurationFile(cf, generalConfigPath);
   ret.logMask.setFromConfigurationFile(cf, generalConfigPath);
   ret.tpConfigPath.setFromConfigurationFile(cf, generalConfigPath);
+  ret.externalEncryptionKeyScript.setFromConfigurationFile(cf, generalConfigPath);
   // Memory management
   ret.bufferSizeBytes.setFromConfigurationFile(cf, generalConfigPath);
   ret.bufferCount.setFromConfigurationFile(cf, generalConfigPath);
@@ -137,6 +138,7 @@ TapedConfiguration TapedConfiguration::createFromCtaConf(
   ret.daemonGroupName.log(log);
   ret.logMask.log(log);
   ret.tpConfigPath.log(log);
+  ret.externalEncryptionKeyScript.log(log);
   
   ret.bufferSizeBytes.log(log);
   ret.bufferCount.log(log);
@@ -149,7 +151,7 @@ TapedConfiguration TapedConfiguration::createFromCtaConf(
   
   ret.nbDiskThreads.log(log);
   ret.useRAO.log(log);
-  
+
   ret.wdIdleSessionTimer.log(log);
   ret.wdMountMaxSecs.log(log);
   ret.wdNoBlockMoveMaxSecs.log(log);
diff --git a/tapeserver/daemon/TapedConfiguration.hpp b/tapeserver/daemon/TapedConfiguration.hpp
index d975ce72c1fb702c9a0debde3af8038965a86e1c..3c95ba98af3f5a6c3e9c39514c37e54fe17566ca 100644
--- a/tapeserver/daemon/TapedConfiguration.hpp
+++ b/tapeserver/daemon/TapedConfiguration.hpp
@@ -161,6 +161,13 @@ struct TapedConfiguration {
   cta::SourcedParameter<uint32_t> tapeLoadTimeout {
     "taped", "TapeLoadTimeout",60,"Compile time default"
   };
+
+  //----------------------------------------------------------------------------
+  // Tape encryption script
+  //----------------------------------------------------------------------------
+  cta::SourcedParameter<std::string> externalEncryptionKeyScript {
+    "taped", "externalEncryptionKeyScript","","Compile time default"
+  };
   
 private:
   /** A private dummy logger which will simplify the implementation of the 
diff --git a/tapeserver/readtp/CMakeLists.txt b/tapeserver/readtp/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..6607d13cd832fd4f0c136ae5d0ed84bbddae74d4
--- /dev/null
+++ b/tapeserver/readtp/CMakeLists.txt
@@ -0,0 +1,48 @@
+# @project        The CERN Tape Archive (CTA)
+# @copyright      Copyright(C) 2015-2021 CERN
+# @license        This program is free software: you can redistribute it and/or modify
+#                 it under the terms of the GNU General Public License as published by
+#                 the Free Software Foundation, either version 3 of the License, or
+#                 (at your option) any later version.
+#
+#                 This program is distributed in the hope that it will be useful,
+#                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+#                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#                 GNU General Public License for more details.
+#
+#                 You should have received a copy of the GNU General Public License
+#                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+cmake_minimum_required (VERSION 2.6)
+
+include_directories(${CMAKE_SOURCE_DIR}/tapeserver)
+
+find_package( ZLIB REQUIRED )
+
+
+add_executable(cta-readtp
+  ReadtpCmd.cpp
+  ReadtpCmdMain.cpp
+  ReadtpCmdLineArgs.cpp
+  CmdLineTool.cpp
+  TapeFseqRange.cpp
+  TapeFseqRangeSequence.cpp
+  TapeFseqRangeListSequence.cpp
+  TapeFseqSequenceParser.cpp)
+
+target_link_libraries (cta-readtp
+  ctacommon
+  TapeDrive
+  ctamediachanger
+  ctacatalogue
+  SCSI
+)
+
+# need to be removed when drop dependencies to taped
+find_package(Protobuf3 REQUIRED)
+set_property (TARGET cta-readtp APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
+if (OCCI_SUPPORT)
+  set_property (TARGET cta-readtp APPEND PROPERTY INSTALL_RPATH ${ORACLE-INSTANTCLIENT_RPATH})
+endif (OCCI_SUPPORT)
+
+install (TARGETS cta-readtp DESTINATION /usr/bin)
+install (FILES ${CMAKE_CURRENT_SOURCE_DIR}/cta-readtp.1cta DESTINATION /usr/share/man/man1)
\ No newline at end of file
diff --git a/tapeserver/readtp/CmdLineTool.cpp b/tapeserver/readtp/CmdLineTool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bc1e38b077583de83c5c17b18f3f7b2c658e77a9
--- /dev/null
+++ b/tapeserver/readtp/CmdLineTool.cpp
@@ -0,0 +1,105 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tapeserver/readtp/CmdLineTool.hpp"
+#include "common/exception/CommandLineNotParsed.hpp"
+
+#include <unistd.h>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+CmdLineTool::CmdLineTool(
+  std::istream &inStream,
+  std::ostream &outStream,
+  std::ostream &errStream) noexcept:
+  m_in(inStream),
+  m_out(outStream),
+  m_err(errStream) {
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+CmdLineTool::~CmdLineTool() noexcept {
+}
+
+//------------------------------------------------------------------------------
+// getUsername
+//------------------------------------------------------------------------------
+std::string CmdLineTool::getUsername() {
+  char buf[256];
+
+  if(getlogin_r(buf, sizeof(buf))) {
+    return "UNKNOWN";
+  } else {
+    return buf;
+  }
+}
+
+//------------------------------------------------------------------------------
+// getHostname
+//------------------------------------------------------------------------------
+std::string CmdLineTool::getHostname() {
+  char buf[256];
+
+  if(gethostname(buf, sizeof(buf))) {
+    return "UNKNOWN";
+  } else {
+    buf[sizeof(buf) - 1] = '\0';
+    return buf;
+  }
+}
+
+//------------------------------------------------------------------------------
+// main
+//------------------------------------------------------------------------------
+int CmdLineTool::main(const int argc, char *const *const argv) {
+  bool cmdLineNotParsed = false;
+  std::string errorMessage;
+
+  try {
+    return exceptionThrowingMain(argc, argv);
+  } catch(exception::CommandLineNotParsed &ue) {
+    errorMessage = ue.getMessage().str();
+    cmdLineNotParsed = true;
+  } catch(exception::Exception &ex) {
+    errorMessage = ex.getMessage().str();
+  } catch(std::exception &se) {
+    errorMessage = se.what();
+  } catch(...) {
+    errorMessage = "An unknown exception was thrown";
+  }
+
+  // Reaching this point means the command has failed, an exception was throw
+  // and errorMessage has been set accordingly
+
+  m_err << "Aborting: " << errorMessage << std::endl;
+  if(cmdLineNotParsed) {
+    m_err << std::endl;
+    printUsage(m_err);
+  }
+  return 1;
+}
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
diff --git a/tapeserver/readtp/CmdLineTool.hpp b/tapeserver/readtp/CmdLineTool.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..90a236af75bbd7bd6c22a0b785cfea95ae307eb2
--- /dev/null
+++ b/tapeserver/readtp/CmdLineTool.hpp
@@ -0,0 +1,108 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <istream>
+#include <ostream>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+/**
+ * Abstract class implementing common code and data structures for a
+ * command-line tool.
+ */
+class CmdLineTool {
+public:
+  /**
+   * Constructor.
+   *
+   * @param inStream Standard input stream.
+   * @param outStream Standard output stream.
+   * @param errStream Standard error stream.
+   */
+  CmdLineTool(std::istream &inStream, std::ostream &outStream, std::ostream &errStream) noexcept;
+
+  /**
+   * Pure-virtual destructor to guarantee this class is abstract.
+   */
+  virtual ~CmdLineTool() noexcept = 0;
+
+  /**
+   * The object's implementation of main() that should be called from the main()
+   * of the program.
+   *
+   * @param argc The number of command-line arguments including the program name.
+   * @param argv The command-line arguments.
+   * @return The exit value of the program.
+   */
+  int main(const int argc, char *const *const argv);
+
+protected:
+
+  /**
+   * An exception throwing version of main().
+   *
+   * @param argc The number of command-line arguments including the program name.
+   * @param argv The command-line arguments.
+   * @return The exit value of the program.
+   */
+  virtual int exceptionThrowingMain(const int argc, char *const *const argv) = 0;
+
+  /**
+   * Prints the usage message of the command-line tool.
+   *
+   * @param os The output stream to which the usage message is to be printed.
+   */
+  virtual void printUsage(std::ostream &os) = 0;
+
+  /**
+   * Standard input stream.
+   */
+  std::istream &m_in;
+
+  /**
+   * Standard output stream.
+   */
+  std::ostream &m_out;
+
+  /**
+   * Standard error stream.
+   */
+  std::ostream &m_err;
+
+  /**
+   * Returns the name of the user running the command-line tool.
+   *
+   * @return The name of the user running the command-line tool.
+   */
+  static std::string getUsername();
+
+  /**
+   * Returns the name of the host on which the command-line tool is running.
+   *
+   * @return The name of the host on which the command-line tool is running.
+   */
+  static std::string getHostname();
+
+}; // class CmdLineTool
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
diff --git a/tapeserver/readtp/ReadtpCmd.cpp b/tapeserver/readtp/ReadtpCmd.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2419d83949c522701fb7ad8b1fe021a474fc7726
--- /dev/null
+++ b/tapeserver/readtp/ReadtpCmd.cpp
@@ -0,0 +1,588 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common/Constants.hpp"
+#include "common/log/DummyLogger.hpp"
+#include "tapeserver/castor/tape/Constants.hpp"
+#include "tapeserver/castor/tape/tapeserver/file/File.hpp"
+#include "tapeserver/castor/tape/tapeserver/file/Structures.hpp"
+#include "tapeserver/readtp/ReadtpCmd.hpp"
+#include "tapeserver/readtp/ReadtpCmdLineArgs.hpp"
+#include "tapeserver/readtp/TapeFseqRange.hpp"
+#include "tapeserver/readtp/TapeFseqRangeListSequence.hpp"
+#include "tapeserver/daemon/Tpconfig.hpp"
+#include "tapeserver/castor/tape/tapeserver/daemon/Payload.hpp"
+#include "mediachanger/LibrarySlotParser.hpp"
+#include "disk/DiskFile.hpp"
+#include "disk/RadosStriperPool.hpp"
+#include "catalogue/TapeSearchCriteria.hpp"
+
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+ReadtpCmd::ReadtpCmd(std::istream &inStream, std::ostream &outStream,
+  std::ostream &errStream, cta::log::StdoutLogger &log, cta::log::DummyLogger &dummyLog,
+  cta::mediachanger::MediaChangerFacade &mc):
+  CmdLineTool(inStream, outStream, errStream),
+  m_log(log),
+  m_dummyLog(dummyLog),
+  m_mc(mc),
+  m_useLbp(true),
+  m_nbSuccessReads(0),
+  m_nbFailedReads(0) {
+}
+
+//------------------------------------------------------------------------------
+// destructor
+//------------------------------------------------------------------------------
+ReadtpCmd::~ReadtpCmd() noexcept {
+}
+
+//------------------------------------------------------------------------------
+// exceptionThrowingMain
+//------------------------------------------------------------------------------
+int ReadtpCmd::exceptionThrowingMain(const int argc, char *const *const argv) {
+  const ReadtpCmdLineArgs cmdLineArgs(argc, argv);
+  if (cmdLineArgs.help) {
+    printUsage(m_out);
+    return 0;
+  }
+  
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", getUsername()));
+  params.push_back(cta::log::Param("tapeVid", cmdLineArgs.m_vid));
+  m_log(cta::log::INFO, "Started", params);
+  
+  readAndSetConfiguration(getUsername(), cmdLineArgs);
+
+  setProcessCapabilities("cap_sys_rawio+ep");
+
+  std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> drivePtr = createDrive();
+  castor::tape::tapeserver::drive::DriveInterface &drive = *drivePtr.get();
+  
+  if (!isDriveSupportLbp(drive)) {
+    m_log(cta::log::WARNING, "Drive does not support LBP", params);
+    m_driveSupportLbp = false;
+  } else {
+    m_driveSupportLbp = true;
+  };
+  
+  mountTape(m_vid);
+  waitUntilTapeLoaded(drive, TAPE_LABEL_UNITREADY_TIMEOUT);
+
+  int returnCode = 0;
+  try {
+    readTapeFiles(drive);
+      
+  } catch(cta::exception::Exception &ne) {
+    params.push_back(cta::log::Param("tapeReadError", ne.getMessage().str()));
+    m_log(cta::log::ERR, "Failed to read the tape", params);
+    returnCode = 1; 
+  }
+  unloadTape(m_vid, drive);
+  dismountTape(m_vid);
+
+  return returnCode;
+}
+
+//------------------------------------------------------------------------------
+// readAndSetConfiguration
+//------------------------------------------------------------------------------
+void ReadtpCmd::readAndSetConfiguration(const std::string &userName, const ReadtpCmdLineArgs &cmdLineArgs) {
+  m_vid = cmdLineArgs.m_vid;
+  m_fSeqRangeList = cmdLineArgs.m_fSeqRangeList;
+  m_xrootPrivateKeyPath = cmdLineArgs.m_xrootPrivateKeyPath;
+  m_userName = userName;
+  m_destinationFiles = readListFromFile(cmdLineArgs.m_destinationFileListURL);
+  cta::tape::daemon::Tpconfig tpConfig;
+  tpConfig  = cta::tape::daemon::Tpconfig::parseFile(castor::tape::TPCONFIGPATH);
+  
+  if (tpConfig.empty()) {
+    cta::exception::Exception ex;
+    ex.getMessage() << "Unable to obtain drive info as TPCONFIG is empty";
+    throw ex;
+  }
+  const auto &tpConfigLine = tpConfig.begin()->second.value();
+  m_devFilename    = tpConfigLine.devFilename;
+  m_rawLibrarySlot = tpConfigLine.rawLibrarySlot;
+  m_logicalLibrary = tpConfigLine.logicalLibrary;
+  m_unitName       = tpConfigLine.unitName;
+
+  const cta::rdbms::Login catalogueLogin = cta::rdbms::Login::parseFile(CATALOGUE_CONFIG_PATH);
+  const uint64_t nbConns = 1;
+  const uint64_t nbArchiveFileListingConns = 1;
+  
+  auto catalogueFactory = cta::catalogue::CatalogueFactoryFactory::create(m_dummyLog, // to supress catalogue output messages
+    catalogueLogin, nbConns, nbArchiveFileListingConns);
+  m_catalogue = catalogueFactory->create();
+    
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("catalogueDbType", catalogueLogin.dbTypeToString(catalogueLogin.dbType)));
+  params.push_back(cta::log::Param("catalogueDatabase", catalogueLogin.database));
+  params.push_back(cta::log::Param("catalogueUsername", catalogueLogin.username));
+  params.push_back(cta::log::Param("devFilename", m_devFilename));
+  params.push_back(cta::log::Param("rawLibrarySlot", m_rawLibrarySlot));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("unitName", m_unitName));
+  m_log(cta::log::INFO, "Read configuration", params);
+}
+
+//------------------------------------------------------------------------------
+// readListFromFile
+//------------------------------------------------------------------------------
+std::list<std::string> ReadtpCmd::readListFromFile(const std::string &filename) const {
+  std::ifstream file(filename);
+  std::list<std::string> str_list;
+  if (file.fail()) {
+    throw std::runtime_error("Unable to open file " + filename);
+  }
+
+  std::string line;
+
+  while(std::getline(file, line)) {
+    // Strip out comments
+    auto pos = line.find('#');
+    if(pos != std::string::npos) {
+      line.resize(pos);
+    }
+
+    // Extract the list items
+    std::stringstream ss(line);
+    while(!ss.eof()) {
+      std::string item;
+      ss >> item;
+      // skip blank lines or lines consisting only of whitespace
+      if(item.empty()) continue;
+
+      str_list.push_back(item);
+    }
+  }
+  return str_list;
+}
+
+
+//------------------------------------------------------------------------------
+// setProcessCapabilities
+//------------------------------------------------------------------------------
+void ReadtpCmd::setProcessCapabilities(const std::string &capabilities) {
+  m_capUtils.setProcText(capabilities);
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("capabilities", capabilities));
+  m_log(cta::log::DEBUG, "Set process capabilities", params);
+}
+
+//------------------------------------------------------------------------------
+// createDrive
+//------------------------------------------------------------------------------
+std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface>
+  ReadtpCmd::createDrive() {
+  castor::tape::SCSI::DeviceVector dv(m_sysWrapper);    
+  castor::tape::SCSI::DeviceInfo driveInfo = dv.findBySymlink(m_devFilename);
+  
+  // Instantiate the drive object
+  std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface>
+    drive(castor::tape::tapeserver::drive::createDrive(driveInfo, m_sysWrapper));
+
+  if(NULL == drive.get()) {
+    cta::exception::Exception ex;
+    ex.getMessage() << "Failed to instantiate drive object";
+    throw ex;
+  }
+  
+  return drive;
+}
+
+//------------------------------------------------------------------------------
+// isDriveSupportLbp
+//------------------------------------------------------------------------------
+bool ReadtpCmd::isDriveSupportLbp(
+  castor::tape::tapeserver::drive::DriveInterface &drive) const {
+  castor::tape::tapeserver::drive::deviceInfo devInfo = drive.getDeviceInfo();
+  if (devInfo.isPIsupported) { //drive supports LBP
+    return true;
+  } else {
+    return false;
+  }
+}
+
+//------------------------------------------------------------------------------
+// setLbpMode
+//------------------------------------------------------------------------------
+void ReadtpCmd::setLbpMode(
+  castor::tape::tapeserver::drive::DriveInterface &drive) {
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", m_userName));
+  params.push_back(cta::log::Param("tapeVid", m_vid));
+  params.push_back(cta::log::Param("tapeDrive", m_unitName));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+  params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+  
+  if(m_useLbp) {
+    if (m_driveSupportLbp) {
+      // only crc32c lbp mode is supported
+      drive.enableCRC32CLogicalBlockProtectionReadWrite();
+      m_log(cta::log::INFO, "Enabling LBP on drive", params);
+    } else {
+      m_useLbp = false;
+      drive.disableLogicalBlockProtection();
+      m_log(cta::log::WARNING, "Disabling LBP on not supported drive", params);
+    }
+  } else {
+    drive.disableLogicalBlockProtection();
+    m_log(cta::log::INFO, "Disabling LBP on drive", params);
+  }
+}
+
+//------------------------------------------------------------------------------
+// mountTape
+//------------------------------------------------------------------------------
+void ReadtpCmd::mountTape(const std::string &vid) {
+  std::unique_ptr<cta::mediachanger::LibrarySlot> librarySlotPtr;
+  librarySlotPtr.reset(
+    cta::mediachanger::LibrarySlotParser::parse(m_rawLibrarySlot));
+  const cta::mediachanger::LibrarySlot &librarySlot = *librarySlotPtr.get();
+    
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", m_userName));
+  params.push_back(cta::log::Param("tapeVid", vid));
+  params.push_back(cta::log::Param("tapeDrive", m_unitName));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("librarySlot", librarySlot.str()));
+  params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+  params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+  
+  m_log(cta::log::INFO, "Mounting tape", params);
+  m_mc.mountTapeReadOnly(vid, librarySlot);
+  if(cta::mediachanger::TAPE_LIBRARY_TYPE_MANUAL == librarySlot.getLibraryType()) {
+    m_log(cta::log::INFO, "Did not mount the tape because the media"
+      " changer is manual", params);
+  } else {
+   m_log(cta::log::INFO, "Mounted tape", params);
+  }
+}
+
+//------------------------------------------------------------------------------
+// waitUntilTapeLoaded
+//------------------------------------------------------------------------------
+void ReadtpCmd::waitUntilTapeLoaded(
+  castor::tape::tapeserver::drive::DriveInterface &drive, const int timeoutSecond) { 
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", m_userName));
+  params.push_back(cta::log::Param("tapeVid", m_vid));
+  params.push_back(cta::log::Param("tapeDrive", m_unitName));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+  params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+  
+  try {
+    m_log(cta::log::INFO, "Loading tape", params);
+    drive.waitUntilReady(timeoutSecond);
+    m_log(cta::log::INFO, "Loaded tape", params);
+  } catch(cta::exception::Exception &ne) {
+    cta::exception::Exception ex;
+    ex.getMessage() << "Failed to wait for tape to be loaded: " <<
+      ne.getMessage().str();
+    throw ex;
+  }
+}
+
+//Basic class representing a read job
+class BasicRetrieveJob: public cta::RetrieveJob {
+public:
+  BasicRetrieveJob() : cta::RetrieveJob(nullptr,
+    cta::common::dataStructures::RetrieveRequest(), 
+    cta::common::dataStructures::ArchiveFile(), 1,
+    cta::PositioningMethod::ByFSeq) {}
+};
+
+
+//------------------------------------------------------------------------------
+// getNextDestinationUrl
+//------------------------------------------------------------------------------
+std::string ReadtpCmd::getNextDestinationUrl() {
+  if (m_destinationFiles.empty()) {
+    return "file:///dev/null";
+  } else {
+    std::string ret = m_destinationFiles.front();
+    m_destinationFiles.pop_front();
+    return ret;
+  }
+}
+
+//------------------------------------------------------------------------------
+// readTapeFiles
+//------------------------------------------------------------------------------
+void ReadtpCmd::readTapeFiles(
+  castor::tape::tapeserver::drive::DriveInterface &drive) {
+    cta::disk::RadosStriperPool striperPool;
+    cta::disk::DiskFileFactory fileFactory(m_xrootPrivateKeyPath, 0, striperPool);
+    
+    catalogue::TapeSearchCriteria searchCriteria;
+    searchCriteria.vid = m_vid;
+    
+    auto tapeList = m_catalogue->getTapes(searchCriteria);
+    if (tapeList.empty()) {
+      std::list<cta::log::Param> params;
+        params.push_back(cta::log::Param("userName", getUsername()));
+        params.push_back(cta::log::Param("tapeVid", m_vid));
+        params.push_back(cta::log::Param("tapeDrive", m_unitName));
+        params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+        params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+        params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+        m_log(cta::log::ERR, "Failed to get tape from catalogue", params);  
+        return;
+    }
+    auto tape = tapeList.front();
+
+    TapeFseqRangeListSequence fSeqRangeListSequence(&m_fSeqRangeList);
+    std::string destinationFile = getNextDestinationUrl();
+    uint64_t fSeq;
+    while (fSeqRangeListSequence.hasMore()) {
+      try {
+        fSeq = fSeqRangeListSequence.next();
+        if (fSeq > tape.lastFSeq) {
+          break; //reached end of tape
+        }
+        std::unique_ptr<cta::disk::WriteFile> wfptr;
+        wfptr.reset(fileFactory.createWriteFile(destinationFile));
+        cta::disk::WriteFile &wf = *wfptr.get();
+        readTapeFile(drive, fSeq, wf);
+        m_nbSuccessReads++; // if readTapeFile returns, file was read successfully
+        destinationFile = getNextDestinationUrl();
+      } catch (tapeserver::readtp::NoSuchFSeqException) {
+        //Do nothing
+      } catch(exception::Exception &ne) {
+        std::list<cta::log::Param> params;
+        params.push_back(cta::log::Param("userName", getUsername()));
+        params.push_back(cta::log::Param("tapeVid", m_vid));
+        params.push_back(cta::log::Param("destinationFile", destinationFile));   
+        params.push_back(cta::log::Param("tapeDrive", m_unitName));
+        params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+        params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+        params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+        params.push_back(cta::log::Param("fSeq", fSeq));
+        params.push_back(cta::log::Param("tapeReadError", ne.getMessage().str()));
+        m_log(cta::log::ERR, "Failed to read file from tape", params);  
+        m_nbFailedReads++; 
+      }
+    }
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", getUsername()));
+  params.push_back(cta::log::Param("tapeVid", m_vid));
+  params.push_back(cta::log::Param("tapeDrive", m_unitName));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+  params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+  params.push_back(cta::log::Param("nbReads", m_nbSuccessReads + m_nbFailedReads));
+  params.push_back(cta::log::Param("nbSuccessfullReads", m_nbSuccessReads));
+  params.push_back(cta::log::Param("nbFailedReads", m_nbFailedReads));
+  
+  m_log(cta::log::INFO, "Finished reading tape", params);  
+        
+}
+
+//------------------------------------------------------------------------------
+// readTapeFile
+//------------------------------------------------------------------------------
+void ReadtpCmd::readTapeFile(
+  castor::tape::tapeserver::drive::DriveInterface &drive, const uint64_t &fSeq, cta::disk::WriteFile &wf) {
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", m_userName));
+  params.push_back(cta::log::Param("tapeVid", m_vid));
+  params.push_back(cta::log::Param("fSeq", fSeq));
+  params.push_back(cta::log::Param("tapeDrive", m_unitName));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+  params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+  params.push_back(cta::log::Param("destinationURL", wf.URL()));
+  
+  castor::tape::tapeserver::daemon::VolumeInfo volInfo;
+  volInfo.vid=m_vid;
+  volInfo.nbFiles = 0;
+  volInfo.mountType = cta::common::dataStructures::MountType::Retrieve;
+  castor::tape::tapeFile::ReadSession rs(drive, volInfo, m_useLbp);
+
+  catalogue::TapeFileSearchCriteria searchCriteria;
+  searchCriteria.vid = m_vid;
+  searchCriteria.fSeq = fSeq;
+  auto itor = m_catalogue->getArchiveFilesItor(searchCriteria);
+
+  if (!itor.hasMore()) {
+    throw tapeserver::readtp::NoSuchFSeqException();
+  }
+
+  m_log(cta::log::INFO, "Reading file from tape", params);
+  
+  const auto archiveFile = itor.next();
+
+  BasicRetrieveJob fileToRecall;
+  fileToRecall.retrieveRequest.archiveFileID = archiveFile.archiveFileID;
+  fileToRecall.selectedCopyNb = 0;
+  fileToRecall.archiveFile.tapeFiles.push_back(cta::common::dataStructures::TapeFile());
+  fileToRecall.selectedTapeFile().fSeq = fSeq;
+  fileToRecall.positioningMethod = cta::PositioningMethod::ByFSeq;
+
+  castor::tape::tapeFile::ReadFile rf(&rs, fileToRecall); 
+  auto checksum_adler32 = castor::tape::tapeserver::daemon::Payload::zeroAdler32();
+  const size_t buffer_size = 1 * 1024 * 1024 * 1024; //1Gb
+  size_t read_data_size = 0;
+  auto payload = new castor::tape::tapeserver::daemon::Payload(buffer_size); //allocate one gigabyte buffer 
+  try  {
+    while(1) {
+      if (payload->remainingFreeSpace() <= rf.getBlockSize()) {
+        //buffer is full, flush to file and update checksum
+        read_data_size += payload->size();
+        checksum_adler32 = payload->adler32(checksum_adler32);
+        payload->write(wf);
+        payload->reset();
+      }
+      payload->append(rf);
+    }
+  } catch (cta::exception::EndOfFile ex) {
+    //File completely read
+  }   
+  read_data_size += payload->size();
+  checksum_adler32 = payload->adler32(checksum_adler32);
+  payload->write(wf);
+  auto cb = cta::checksum::ChecksumBlob(cta::checksum::ChecksumType::ADLER32, checksum_adler32);
+
+  archiveFile.checksumBlob.validate(cb);  //exception thrown if checksums differ
+  
+  params.push_back(cta::log::Param("checksumType", "ADLER32"));
+  std::stringstream sstream;
+  sstream << std::hex << checksum_adler32;
+  params.push_back(cta::log::Param("checksumValue", "0x" + sstream.str()));
+  params.push_back(cta::log::Param("readFileSize", read_data_size));
+  m_log(cta::log::INFO, "Read file from tape successfully", params);
+}
+
+//------------------------------------------------------------------------------
+// unloadTape
+//------------------------------------------------------------------------------
+void ReadtpCmd::unloadTape(
+  const std::string &vid, castor::tape::tapeserver::drive::DriveInterface &drive) {
+  std::unique_ptr<cta::mediachanger::LibrarySlot> librarySlotPtr;
+  librarySlotPtr.reset(
+    cta::mediachanger::LibrarySlotParser::parse(m_rawLibrarySlot));
+  const cta::mediachanger::LibrarySlot &librarySlot = *librarySlotPtr.get();
+  
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", m_userName));
+  params.push_back(cta::log::Param("tapeVid", m_vid));
+  params.push_back(cta::log::Param("tapeDrive", m_unitName));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+  params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+  
+  // We implement the same policy as with the tape sessions: 
+  // if the librarySlot parameter is "manual", do nothing.
+  if(cta::mediachanger::TAPE_LIBRARY_TYPE_MANUAL == librarySlot.getLibraryType()) {
+    m_log(cta::log::INFO, "Not unloading tape because media changer is"
+      " manual", params);
+    return;
+  }
+  try {
+    m_log(cta::log::INFO, "Unloading tape", params);
+    drive.unloadTape();
+    m_log(cta::log::INFO, "Unloaded tape", params);
+  } catch (cta::exception::Exception &ne) {
+    cta::exception::Exception ex;
+    ex.getMessage() << "Failed to unload tape: " <<
+      ne.getMessage().str();
+    throw ex;
+  }
+}
+
+//------------------------------------------------------------------------------
+// dismountTape
+//------------------------------------------------------------------------------
+void ReadtpCmd::dismountTape(const std::string &vid) {
+  std::unique_ptr<cta::mediachanger::LibrarySlot> librarySlotPtr;
+  librarySlotPtr.reset(
+    cta::mediachanger::LibrarySlotParser::parse(m_rawLibrarySlot));
+  const cta::mediachanger::LibrarySlot &librarySlot = *librarySlotPtr.get();
+  
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", m_userName));
+  params.push_back(cta::log::Param("tapeVid", m_vid));
+  params.push_back(cta::log::Param("tapeDrive", m_unitName));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("librarySlot", librarySlot.str()));
+  params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+  params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+  
+  try {
+    m_log(cta::log::INFO, "Dismounting tape", params);
+    m_mc.dismountTape(vid, librarySlot);
+    const bool dismountWasManual = cta::mediachanger::TAPE_LIBRARY_TYPE_MANUAL ==
+      librarySlot.getLibraryType();
+    if(dismountWasManual) {
+      m_log(cta::log::INFO, "Did not dismount tape because media"
+        " changer is manual", params);
+    } else {
+      m_log(cta::log::INFO, "Dismounted tape", params);
+    }
+  } catch(cta::exception::Exception &ne) {
+    cta::exception::Exception ex;
+    ex.getMessage() << "Failed to dismount tape: " <<
+      ne.getMessage().str();
+    throw ex;
+  }
+}
+
+//------------------------------------------------------------------------------
+// rewindDrive
+//------------------------------------------------------------------------------
+void ReadtpCmd::rewindDrive(
+  castor::tape::tapeserver::drive::DriveInterface &drive) {
+  std::list<cta::log::Param> params;
+  params.push_back(cta::log::Param("userName", m_userName));
+  params.push_back(cta::log::Param("tapeVid", m_vid));
+  params.push_back(cta::log::Param("tapeDrive", m_unitName));
+  params.push_back(cta::log::Param("logicalLibrary", m_logicalLibrary));
+  params.push_back(cta::log::Param("useLbp",boolToStr(m_useLbp)));
+  params.push_back(cta::log::Param("driveSupportLbp",boolToStr(m_driveSupportLbp)));
+  
+  m_log(cta::log::INFO, "Rewinding tape", params);
+  drive.rewind();
+  m_log(cta::log::INFO, "Successfully rewound tape", params);
+}
+
+//------------------------------------------------------------------------------
+// printUsage
+//------------------------------------------------------------------------------
+void ReadtpCmd::printUsage(std::ostream &os) {
+  ReadtpCmdLineArgs::printUsage(os);
+}
+
+//------------------------------------------------------------------------------
+// boolToStr
+//------------------------------------------------------------------------------
+const char *ReadtpCmd::boolToStr(
+  const bool value) {
+  return value ? "true" : "false";
+}
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
\ No newline at end of file
diff --git a/tapeserver/readtp/ReadtpCmd.hpp b/tapeserver/readtp/ReadtpCmd.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..75f8d79fa07ff3a6ab93841556d682c33fc95f9c
--- /dev/null
+++ b/tapeserver/readtp/ReadtpCmd.hpp
@@ -0,0 +1,311 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "common/log/StdoutLogger.hpp"
+#include "common/log/DummyLogger.hpp"
+#include "common/log/LogContext.hpp"
+#include "common/processCap/ProcessCap.hpp"
+#include "tapeserver/readtp/ReadtpCmdLineArgs.hpp"
+#include "tapeserver/castor/tape/tapeserver/drive/DriveInterface.hpp"
+#include "tapeserver/castor/tape/tapeserver/drive/DriveGeneric.hpp"
+#include "tapeserver/castor/tape/tapeserver/daemon/EncryptionControl.hpp"
+#include "tapeserver/daemon/Tpconfig.hpp"
+#include "tapeserver/readtp/CmdLineTool.hpp"
+#include "tapeserver/readtp/TapeFseqRange.hpp"
+#include "tapeserver/readtp/TapeFseqRangeListSequence.hpp"
+#include "catalogue/CatalogueFactoryFactory.hpp"
+#include "mediachanger/MediaChangerFacade.hpp"
+#include "disk/DiskFile.hpp"
+
+#include <memory>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+/**
+ * Command-line tool for reading files from a CTA tape.
+ */
+class ReadtpCmd: public CmdLineTool {
+public:
+
+  /**
+   * Constructor.
+   *
+   * @param inStream Standard input stream.
+   * @param outStream Standard output stream.
+   * @param errStream Standard error stream.
+   * @param log The object representing the API of the CTA logging system.
+   * @param mc Interface to the media changer.
+   */
+  ReadtpCmd(std::istream &inStream, std::ostream &outStream,
+    std::ostream &errStream, cta::log::StdoutLogger &log,
+    cta::log::DummyLogger &dummyLog,
+    cta::mediachanger::MediaChangerFacade &mc);
+
+  /**
+   * Destructor.
+   */
+  ~ReadtpCmd() noexcept;
+
+private:
+
+  /**
+   * An exception throwing version of main().
+   *
+   * @param argc The number of command-line arguments including the program name.
+   * @param argv The command-line arguments.
+   * @return The exit value of the program.
+   */
+  int exceptionThrowingMain(const int argc, char *const *const argv) override;
+
+  /**
+   * Prints the usage message of the command-line tool.
+   *
+   * @param os The output stream to which the usage message is to be printed.
+   */
+  void printUsage(std::ostream &os) override;
+
+  /**
+   * Sets internal configuration parameters to be used for reading.
+   * It reads drive and library parameters from /etc/cta/TPCONFIG and catalogue
+   * login parameters from /etc/cta/cta-catalogue.conf.
+   *
+   * @param username The name of the user running the command-line tool.
+   * @param cmdLineArgs The arguments parsed from the command line.
+   */
+  void readAndSetConfiguration(const std::string &userName, const ReadtpCmdLineArgs &cmdLineArgs);
+
+  /**
+   * Reads a file line by line, strips comments and returns a list of the file lines.
+   *
+   * @param filename The name of the file to be read.
+   * @return A list of line strings after stripping comments.
+   */
+  std::list<std::string> readListFromFile(const std::string &filename) const;
+
+  /**
+   * Returns the next destination file URL, or file:///dev/null if all destination files have been used.
+   *
+   * @return The URL of the next destination file.
+   */
+  std::string getNextDestinationUrl();
+
+  /**
+   * Sets the capabilities of the process and logs the result.
+   *
+   * @param capabilities The string representation of the capabilities.
+   */
+  void setProcessCapabilities(const std::string &capabilities);
+
+  /**
+   * Returns a Drive object representing the tape drive to be used to read
+   * the tape.
+   *
+   * @return The drive object.
+   */
+  std::unique_ptr<castor::tape::tapeserver::drive::DriveInterface> createDrive();
+
+  /**
+   * Detects if the drive supports the logical block protection.
+   *
+   * @param drive The tape drive.
+   * @return The boolean value true if the drive supports LBP or false otherwise.
+   */
+  bool isDriveSupportLbp(castor::tape::tapeserver::drive::DriveInterface &drive) const;
+
+  /**
+   * Sets the logical block protection mode on the drive
+   * depending on useLbp and driveSupportLbp parameters. This method needs to
+   * be used to avoid exceptions in setLbp if drive does not support LBP (mhvtl).
+   *
+   * @param drive The tape drive.
+   */
+  void setLbpMode(castor::tape::tapeserver::drive::DriveInterface &drive);
+
+   /**
+   * Mounts the tape to be read.
+   * @param vid The volume identifier of the tape to be mounted.
+   */
+  void mountTape(const std::string &vid);
+
+  /**
+   * Waits for the tape to be loaded into the tape drive.
+   *
+   * @param drive Object representing the drive hardware.
+   * @param timeoutSecond The number of seconds to wait for the tape to be
+   * loaded into the tape drive. 
+   */
+  void waitUntilTapeLoaded(castor::tape::tapeserver::drive::DriveInterface &drive,
+    const int timeoutSecond);
+
+  /**
+   * Read the files requested from tape
+   *
+   * @param drive Object representing the drive hardware.
+   */
+  void readTapeFiles(castor::tape::tapeserver::drive::DriveInterface &drive);
+
+  /**
+   * Read a specific file from tape
+   * @param drive Object representing the drive hardware.
+   * @param fSeq The tape file fSeq.
+   */
+  void readTapeFile(castor::tape::tapeserver::drive::DriveInterface &drive, const uint64_t &fSeq,
+    cta::disk::WriteFile &wf);
+
+
+  /**
+   * Unloads the specified tape from the specified tape drive.
+   *
+   * @param vid The volume identifier of the tape to be unloaded.  Please note
+   * that the value of this field is only used for logging purposes.
+   * @param drive The tape drive.
+   */
+  void unloadTape(const std::string &vid, castor::tape::tapeserver::drive::DriveInterface &drive);
+  
+  /**
+   * Dismounts the specified tape.
+   *
+   * @param vid The volume identifier of the tape to be dismounted.
+   */
+  void dismountTape(const std::string &vid);
+  
+  /**
+   * Rewinds the specified tape drive.
+   *
+   * @param drive The tape drive.
+   */
+  void rewindDrive(castor::tape::tapeserver::drive::DriveInterface &drive);
+
+  /**
+   * Returns the string representation of the specified boolean value.
+   *
+   * @param value The boolean value.
+   * @return The string representation.
+   */
+  const char *boolToStr(const bool value);
+
+  /**
+   * The object representing the API of the CTA logging system.
+   */
+  cta::log::StdoutLogger  &m_log;
+
+/**
+   *Dummy logger for the catalogue
+   */
+  cta::log::DummyLogger &m_dummyLog;
+  
+  /**
+   * Hard coded path for the catalogue login configuration.
+   */
+  const std::string CATALOGUE_CONFIG_PATH = "/etc/cta/cta-catalogue.conf";
+
+  /**
+   * Unique pointer to the catalogue interface;
+   */
+  std::unique_ptr<cta::catalogue::Catalogue> m_catalogue;
+  
+  /**
+   * Object providing utilities for working UNIX capabilities.
+   */
+  cta::server::ProcessCap m_capUtils;
+  
+  /**
+   * The system wrapper used to find the device and instantiate the drive object.
+   */
+  castor::tape::System::realWrapper m_sysWrapper;
+  
+  /**
+   * The filename of the device file of the tape drive.
+   */
+  std::string m_devFilename;
+  
+  /**
+   * The slot in the tape library that contains the tape drive (string encoded).
+   */
+  std::string m_rawLibrarySlot;
+  
+  /**
+   * The logical library of the tape drive.
+   */
+  std::string m_logicalLibrary;
+  
+  /**
+   * The unit name of the tape drive.
+   */
+  std::string m_unitName;
+  
+  /**
+   * The name of the user running the command-line tool.
+   */
+  std::string m_userName;
+
+  /**
+   * The tape VID to read.
+   */
+  std::string m_vid;
+  
+  /**
+   * Path to the xroot private key file.
+   */
+  std::string m_xrootPrivateKeyPath;
+
+  /**
+   * The iterator of destination urls the data read is sent to
+   */
+  std::list<std::string> m_destinationFiles;
+
+  /**
+   * The file fSeq to read.
+   */
+  TapeFseqRangeList m_fSeqRangeList;
+
+  /**
+   * The object representing the media changer.
+   */
+  cta::mediachanger::MediaChangerFacade &m_mc;
+  
+  /**
+   * The boolean variable which determinate logical block protection usage by
+   * readtp commands. Hard coded when we create the class.
+   */
+  bool m_useLbp;
+
+  /**
+   * The boolean variable to store if drive support LBP.
+   */
+  bool m_driveSupportLbp;
+
+  /**
+   * Number of files read successsfully.
+   */
+  uint64_t m_nbSuccessReads;
+
+  /**
+   * Number of failed reads.
+   */
+  uint64_t m_nbFailedReads;
+}; // class ReadtpCmd
+
+CTA_GENERATE_EXCEPTION_CLASS(NoSuchFSeqException);
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
\ No newline at end of file
diff --git a/tapeserver/readtp/ReadtpCmdLineArgs.cpp b/tapeserver/readtp/ReadtpCmdLineArgs.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f409ffc2bd637f41d0fffab3d9ad145849112e9
--- /dev/null
+++ b/tapeserver/readtp/ReadtpCmdLineArgs.cpp
@@ -0,0 +1,133 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tapeserver/readtp/ReadtpCmdLineArgs.hpp"
+#include "tapeserver/readtp/TapeFseqSequenceParser.hpp"
+#include "common/exception/CommandLineNotParsed.hpp"
+#include "common/utils/utils.hpp"
+#include "common/Constants.hpp"
+
+#include <getopt.h>
+#include <ostream>
+
+#include <string.h>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+ReadtpCmdLineArgs::ReadtpCmdLineArgs(const int argc, char *const *const argv):
+  help(false), m_vid(""), m_destinationFileListURL(""), m_xrootPrivateKeyPath("") {
+  if (argc < 3) {
+    help = true;
+    return;
+  }
+  if ((strlen(argv[1])) > CA_MAXVIDLEN) {
+    exception::CommandLineNotParsed ex;
+    ex.getMessage() << "The vid is too long";
+    throw ex;
+  }
+  m_vid = std::string(argv[1]);
+  utils::toUpper(m_vid);
+
+  m_fSeqRangeList = TapeFileSequenceParser::parse(argv[2]);
+  
+  static struct option longopts[] = {
+    {"destination_files",      required_argument, NULL, 'f'},
+    {"xroot_private_key", required_argument, NULL, 'p'},
+    {"help",                   no_argument,       NULL, 'h'},
+    {NULL  ,                   0,                 NULL,   0}
+  };
+
+  opterr = 0;
+  int opt = 0;
+  int opt_index = 3;
+
+  while ((opt = getopt_long(argc, argv, ":d:f:p:h", longopts, &opt_index)) != -1) {
+    switch(opt) {
+    case 'f':
+      m_destinationFileListURL = std::string(optarg);
+      break;
+    case 'p':
+      m_xrootPrivateKeyPath = std::string(optarg);
+      break;
+    case 'h':
+      help = true;
+      break;
+    case ':': // Missing parameter
+      {
+        exception::CommandLineNotParsed ex;
+        ex.getMessage() << "The -" << (char)optopt << " option requires a parameter";
+        throw ex;
+      }
+    case '?': // Unknown option
+      {
+        exception::CommandLineNotParsed ex;
+        if(0 == optopt) {
+          ex.getMessage() << "Unknown command-line option";
+        } else {
+          ex.getMessage() << "Unknown command-line option: -" << (char)optopt;
+        }
+        throw ex;
+      }
+    default:
+      {
+        exception::CommandLineNotParsed ex;
+        ex.getMessage() <<
+        "getopt_long returned the following unknown value: 0x" <<
+        std::hex << (int)opt;
+        throw ex;
+      }
+    } // switch(opt)
+  } // while getopt_long()
+
+  if (m_destinationFileListURL.empty()) {
+    m_destinationFileListURL = "/dev/null"; // Equivalent to an empty file
+  }         
+}
+
+
+//------------------------------------------------------------------------------
+// printUsage
+//------------------------------------------------------------------------------
+void ReadtpCmdLineArgs::printUsage(std::ostream &os) {
+  os <<
+    "Usage:" << std::endl <<
+    "  cta-readtp <VID> <SEQUENCE> [options]" << std::endl <<
+    "Where:" << std::endl <<
+    "  <VID>            The VID of the tape to be read" << std::endl <<
+    "  <SEQUENCE>       A sequence of tape file sequence numbers. The syntax to be used is:" << std::endl <<
+    "      f1-f2            Files f1 to f2 inclusive" << std::endl <<
+    "      f1-              Files f1 to the last file on the tape" << std::endl <<
+    "      f1-f2,f4,f6-     A series of non-consecutive ranges of files" << std::endl <<
+    "Options:" <<std::endl <<
+    "  -h, --help                              Print this help message and exit." << std::endl <<
+    "  -p, --xroot_private_key <KEY PATH>      Path to the xroot private key file. Necessary if" << std::endl << 
+    "                                          read files are to be written using xroot." << std::endl <<
+    "  -f, --destination_files <FILE URL>      URL to file containing a list of destination files."  << std::endl <<
+    "                                          If not set, all data read is written to file:///dev/null" << std::endl <<
+    "                                          If there are less destination files than read files, the remaining" << std::endl <<
+    "                                          files read will be written to file:///dev/null." << std::endl;  
+}
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
\ No newline at end of file
diff --git a/tapeserver/readtp/ReadtpCmdLineArgs.hpp b/tapeserver/readtp/ReadtpCmdLineArgs.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..e62cea3bb819ef2ca1e3f816b61efe4ceeb42ce0
--- /dev/null
+++ b/tapeserver/readtp/ReadtpCmdLineArgs.hpp
@@ -0,0 +1,77 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "tapeserver/readtp/TapeFseqRangeListSequence.hpp"
+
+#include <string>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+/**
+ * Structure to store the command-line arguments of the command-line tool
+ * named cta-readtp.
+ */
+struct ReadtpCmdLineArgs {
+  /**
+   * True if the usage message should be printed.
+   */
+  bool help;
+  
+  /**
+   * The tape VID to read.
+   */
+  std::string m_vid;
+
+  /**
+   * Sequence of file fSeqs to read.
+   */
+  TapeFseqRangeList m_fSeqRangeList;
+    
+  /**
+   * The destination file list url.
+   */  
+  std::string m_destinationFileListURL;
+
+  /**
+   * Path to the xroot private key file.
+   */
+  std::string m_xrootPrivateKeyPath;
+
+  /**
+   * Constructor that parses the specified command-line arguments.
+   *
+   * @param argc The number of command-line arguments including the name of the
+   * executable.
+   * @param argv The vector of command-line arguments.
+   */
+  ReadtpCmdLineArgs(const int argc, char *const *const argv);
+
+  /**
+   * Prints the usage message of the command-line tool.
+   *
+   * @param os The output stream to which the usage message is to be printed.
+   */
+  static void printUsage(std::ostream &os);
+}; // class ReadtpCmdLineArgs
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
diff --git a/tapeserver/readtp/ReadtpCmdMain.cpp b/tapeserver/readtp/ReadtpCmdMain.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4ec024ccfcdcbeea016e291681647f9b8199dd8c
--- /dev/null
+++ b/tapeserver/readtp/ReadtpCmdMain.cpp
@@ -0,0 +1,40 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tapeserver/readtp/ReadtpCmd.hpp"
+#include <iostream>
+
+//------------------------------------------------------------------------------
+// main
+//------------------------------------------------------------------------------
+int main(const int argc, char *const *const argv) {
+  char buf[256];
+  std::string hostName;
+  if(gethostname(buf, sizeof(buf))) {
+    hostName = "UNKNOWN";
+  } else {
+    buf[sizeof(buf) - 1] = '\0';
+    hostName = buf;
+  }
+  cta::log::StdoutLogger log(hostName, "cta-readtp");
+  cta::log::DummyLogger dummyLog("dummy", "dummy");
+  cta::mediachanger::MediaChangerFacade mc(log);
+
+  cta::tapeserver::readtp::ReadtpCmd cmd(std::cin, std::cout, std::cerr, log, dummyLog, mc);
+  return cmd.main(argc, argv);
+}
\ No newline at end of file
diff --git a/tapeserver/readtp/TapeFseqRange.cpp b/tapeserver/readtp/TapeFseqRange.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..81cd07918bdfffe6536ab688f2201c4bc822d733
--- /dev/null
+++ b/tapeserver/readtp/TapeFseqRange.cpp
@@ -0,0 +1,152 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tapeserver/readtp/TapeFseqRange.hpp"
+#include "common/exception/InvalidArgument.hpp"
+
+#include <getopt.h>
+#include <ostream>
+
+#include <string.h>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+TapeFseqRange::TapeFseqRange() throw() {
+
+  reset();
+}
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+TapeFseqRange::TapeFseqRange(const uint32_t lower, const uint32_t upper)  {
+
+  reset(lower, upper);
+}
+
+//------------------------------------------------------------------------------
+// reset
+//------------------------------------------------------------------------------
+void TapeFseqRange::reset() throw() {
+  m_isEmpty = true;
+  m_lower   = 0; // Ignored
+  m_upper   = 0; // Ignored
+}
+
+
+//------------------------------------------------------------------------------
+// reset
+//------------------------------------------------------------------------------
+void TapeFseqRange::reset(const uint32_t lower,
+  const uint32_t upper)  {
+
+  if(lower == 0) {
+    exception::InvalidArgument ex;
+
+    ex.getMessage() << "Lower boundary must not be zero";
+    throw ex;
+  }
+
+  // If the upper boundary is not 0 meaning infinity and the lower boundary is
+  // greater than the upper boundary
+  if(upper != 0 && lower > upper) {
+    exception::InvalidArgument ex;
+
+    ex.getMessage() <<
+      "Lower boundary must be less than or equal to the upper boundary"
+      ": lower=" << lower << " upper=" << upper;
+
+    throw ex;
+  }
+
+  m_isEmpty = false;
+  m_lower   = lower;
+  m_upper   = upper;
+}
+
+
+//------------------------------------------------------------------------------
+// isEmpty
+//------------------------------------------------------------------------------
+bool TapeFseqRange::isEmpty() const throw() {
+  return m_isEmpty;
+}
+
+//------------------------------------------------------------------------------
+// lower
+//------------------------------------------------------------------------------
+uint32_t TapeFseqRange::lower() const throw() {
+
+  return m_isEmpty ? 0 : m_lower;
+}
+
+//------------------------------------------------------------------------------
+// upper
+//------------------------------------------------------------------------------
+uint32_t TapeFseqRange::upper() const throw() {
+
+  return m_isEmpty ? 0 : m_upper;
+}
+
+//------------------------------------------------------------------------------
+// size
+//------------------------------------------------------------------------------
+uint32_t TapeFseqRange::size() const throw() {
+
+  return m_isEmpty || m_upper == 0 ? 0 : m_upper - m_lower + 1;
+}
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
+
+//------------------------------------------------------------------------------
+// ostream << operator for cta::tapeserver::readtp::TapeFseqRange
+//------------------------------------------------------------------------------
+std::ostream &operator<<(std::ostream &os,
+  const cta::tapeserver::readtp::TapeFseqRange &value) {
+
+  if(value.isEmpty()) {
+    os << "EMPTY";
+  } else {
+    uint32_t lower = 0;
+    uint32_t upper = 0;
+
+    try {
+      lower = value.lower();
+      upper = value.upper();
+
+      os << lower << "-";
+
+      // An upper value of 0 means END of tape
+      if(upper !=0) {
+        os << upper;
+      } else {
+        os << "END";
+      }
+    } catch(cta::exception::Exception &ex) {
+      os << "ERROR";
+    }
+  }
+
+  return os;
+}
diff --git a/tapeserver/readtp/TapeFseqRange.hpp b/tapeserver/readtp/TapeFseqRange.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..35d903cc7faeea222986baf5abef2f63709c9633
--- /dev/null
+++ b/tapeserver/readtp/TapeFseqRange.hpp
@@ -0,0 +1,129 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <string>
+#include <ostream>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+/**
+ * A range of tape file sequence numbers specified by an inclusive lower
+ * boundary and an inclusive upper boundary.
+ */
+class TapeFseqRange {
+
+public:
+
+  /**
+   * Constructor.
+   *
+   * Constructs an empty range.
+   */
+  TapeFseqRange() throw();
+
+  /**
+   * Constructor.
+   *
+   * Constructs a range with the specified inclusive lower and upper
+   * boundaries.  An upper boundary of 0 means infinity.
+   *
+   * Throws an InvalidArgument exception if either the lower boundary is 0
+   * or if the lower boundary is greater than the upper boundary.
+   *
+   * @param lower The inclusive lower bound of the range.
+   * @param upper The inclusive upper bound of the range.
+   */
+  TapeFseqRange(const uint32_t lower, const uint32_t upper)
+    ;
+
+  /**
+   * Resets the range to be an empty range.
+   */
+  void reset() throw();
+
+  /**
+   * Resets the range to be a finite range with the specified inclusive lower
+   * and upper boundaries.
+   *
+   * Throws an InvalidArgument exception if either the lower boundary is 0
+   * or if the lower boundary is greater than the upper boundary.
+   *
+   * @param lower The inclusive lower bound of the range.
+   * @param upper The inclusive upper bound of the range.
+   */
+  void reset(const uint32_t lower, const uint32_t upper)
+    ;
+
+  /**
+   * Returns true if the range is empty.
+   */
+  bool isEmpty() const throw();
+
+  /**
+   * Returns the inclusive lower bound of the range or 0 if the range is empty.
+   */
+  uint32_t lower() const throw();
+
+  /**
+   * Returns the inclusive upper bound of the range.  If the range is finite,
+   * then a value greater than 0 is returned.  If the range is either empty or
+   * infinite then 0 is returned.  The method isEmpty() or a lower() return
+   * value of 0 can be used to distinguish between the two cases when upper()
+   * returns 0.
+   */
+  uint32_t upper() const throw();
+
+  /**
+   * Returns the size of the range.  An empty or infinite range returns 0.
+   * The method isEmpty() or a lower() return value of 0 can be used to
+   * distinguish between the two cases when size() returns 0.
+   */
+  uint32_t size() const throw();
+
+
+private:
+
+  /**
+   * True if this range is empty, else false.
+   */
+  bool m_isEmpty;
+
+  /**
+   * The inclusive lower bound of the range.
+   */
+  uint32_t m_lower;
+
+  /**
+   * The inclusive upper bound of the range.  A value of 0 means infinity.
+   */
+  uint32_t m_upper;
+};
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
+
+/**
+ * ostream << operator for cta::tapeserver::readtp::TapeFseqRange
+ */
+std::ostream &operator<<(std::ostream &os,
+  const cta::tapeserver::readtp::TapeFseqRange &value);
+
diff --git a/tapeserver/readtp/TapeFseqRangeListSequence.cpp b/tapeserver/readtp/TapeFseqRangeListSequence.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..479ffd6cb259b051e73dca8b5d5ba3a9c4d7c153
--- /dev/null
+++ b/tapeserver/readtp/TapeFseqRangeListSequence.cpp
@@ -0,0 +1,174 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tapeserver/readtp/TapeFseqRange.hpp"
+#include "tapeserver/readtp/TapeFseqRangeListSequence.hpp"
+#include "common/exception/InvalidArgument.hpp"
+#include "common/exception/Exception.hpp"
+
+#include <getopt.h>
+#include <ostream>
+
+#include <list>
+#include <errno.h>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+TapeFseqRangeListSequence::TapeFseqRangeListSequence()
+   {
+  reset(NULL);
+}
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+TapeFseqRangeListSequence::TapeFseqRangeListSequence(
+  const TapeFseqRangeList *const list)  {
+  reset(list);
+}
+
+
+//------------------------------------------------------------------------------
+// reset
+//------------------------------------------------------------------------------
+void TapeFseqRangeListSequence::reset(
+  const TapeFseqRangeList *const list)  {
+  m_list = list;
+
+  if(m_list == NULL) {
+    m_isFinite  = true;
+    m_totalSize = 0;
+  } else {
+    m_rangeItor  = list->begin();
+    m_nbSequence = (*(list->begin()));
+
+    // Determine the values of m_isFinite and m_totalSize
+    m_isFinite  = true; // Initial guess
+    m_totalSize = 0;    // Initial guess
+    for(TapeFseqRangeList::const_iterator itor=list->begin();
+      itor != list->end(); itor++) {
+      const TapeFseqRange &range = *itor;
+
+      // If upper bound of range is infinity
+      if(range.upper() == 0) {
+        m_isFinite  = false;
+        m_totalSize = 0;
+
+        // No need to continue counting
+        break;
+
+      // Else the upper bound is finite
+      } else {
+        m_totalSize += range.size();
+      }
+    }
+  }
+}
+
+
+//------------------------------------------------------------------------------
+// hasMore
+//------------------------------------------------------------------------------
+bool TapeFseqRangeListSequence::hasMore() const throw() {
+  if(m_list != NULL) {
+    return m_nbSequence.hasMore();
+  } else {
+    return false;
+  }
+}
+
+
+//------------------------------------------------------------------------------
+// next
+//------------------------------------------------------------------------------
+uint32_t TapeFseqRangeListSequence::next()
+   {
+
+  if(!hasMore()) {
+    exception::Exception ex;
+
+    ex.getMessage()
+      << "Invalid operation: Sequence::next() called after end of sequence";
+
+    throw ex;
+  }
+
+  uint32_t tmp = m_nbSequence.next();
+
+  // If the end of the current range sequence has been reached
+  if(!m_nbSequence.hasMore()) {
+
+    // Move on to the next if there is one
+    m_rangeItor++;
+    if(m_rangeItor != m_list->end()) {
+      m_nbSequence = *m_rangeItor;
+    }
+  }
+
+  return tmp;
+}
+
+
+//------------------------------------------------------------------------------
+// isFinite
+//------------------------------------------------------------------------------
+bool TapeFseqRangeListSequence::isFinite() const throw() {
+  return m_isFinite;
+}
+
+
+//------------------------------------------------------------------------------
+// totalSize
+//------------------------------------------------------------------------------
+uint32_t TapeFseqRangeListSequence::totalSize()
+  const throw() {
+  return m_totalSize;
+}
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
+
+//------------------------------------------------------------------------------
+// ostream << operator for castor::tape::tpcp::TapeFseqRangeList
+//------------------------------------------------------------------------------
+std::ostream &operator<<(std::ostream &os,
+  const cta::tapeserver::readtp::TapeFseqRangeList &value) {
+
+  os << '{';
+
+  for(cta::tapeserver::readtp::TapeFseqRangeList::const_iterator itor =
+    value.begin(); itor != value.end(); itor++) {
+
+    // Write a separating comma if not the first item in the list
+    if(itor!=value.begin()) {
+      os << ",";
+    }
+
+    os << *itor;
+  }
+
+  os << '}';
+
+  return os;
+}
diff --git a/tapeserver/readtp/TapeFseqRangeListSequence.hpp b/tapeserver/readtp/TapeFseqRangeListSequence.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7ce698f802b5ddb594b81faf193b14f227aeba77
--- /dev/null
+++ b/tapeserver/readtp/TapeFseqRangeListSequence.hpp
@@ -0,0 +1,135 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "TapeFseqRange.hpp"
+#include "TapeFseqRangeSequence.hpp"
+
+#include <list>
+#include <ostream>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+/**
+ * A list of tape file sequence ranges.
+ */
+class TapeFseqRangeList: public  std::list<TapeFseqRange> {
+}; // class TapeFseqRangeList
+
+/**
+ * Generates a sequence of tape file sequence numbers from a list of tape file
+ * sequence ranges.
+ */
+class TapeFseqRangeListSequence {
+public:
+
+  /**
+   * Constructor.
+   *
+   * Creates an empty sequence, in other word hasMore() will always return
+   * false.
+   */
+  TapeFseqRangeListSequence() ;
+
+  /**
+   * Constructor.
+   *
+   * @param list The list of tape file sequence ranges from which the sequence
+   * of tape file sequence numbers is to be generated.
+   */
+  TapeFseqRangeListSequence(const TapeFseqRangeList *const list)
+    ;
+
+  /**
+   * Resets the sequence.
+   *
+   * @param list The list of tape file sequence ranges from which the sequence
+   * of tape file sequence numbers is to be generated.
+   */
+  void reset(const TapeFseqRangeList *const list)
+    ;
+
+  /**
+   * Returns true if there is another tape file sequence number in the
+   * sequence.
+   */
+  bool hasMore() const throw();
+
+  /**
+   * Returns the next  tape file sequence number in the sequence, or throws an
+   * exception if there isn't one.
+   */
+  uint32_t next() ;
+
+  /**
+   * Returns true if the sequence is finite, else false if it is infinite.
+   */
+  bool isFinite() const throw();
+
+  /**
+   * Returns the total number of values the sequence could ever generate.  The
+   * value returned by this method is not affected by calls to next().  This
+   * method returns 0 if the total number of values is 0 or infinity.  The
+   * isFinite() method can be used to distinguish between the two cases.
+   */
+  uint32_t totalSize() const throw();
+
+
+private:
+
+  /**
+   * The list of tape file sequence ranges.
+   */
+  const TapeFseqRangeList *m_list;
+
+  /**
+   * Iterator pointing to the current range of tape file sequence numbers.
+   */
+  TapeFseqRangeList::const_iterator m_rangeItor;
+
+  /**
+   * True if the sequence is finite, else false if it is infinite.
+   */
+  bool m_isFinite;
+
+  /**
+   * The total number of values the sequence could ever generate.  The
+   * value returned by this method is not affected by calls to next().  This
+   * method returns 0 if the total number of values is 0 or infinity.  The
+   * isFinite() method can be used to distinguish between the two cases.
+   */
+  uint32_t m_totalSize;
+
+  /**
+   * The current sequence of the tape file sequence numbers.
+   */
+  TapeFseqRangeSequence m_nbSequence;
+
+}; // class TapeFseqRangeListSequence
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
+
+/**
+ * ostream << operator for cta::tapeserver::readtp::TapeFseqRangeList
+ */
+std::ostream &operator<<(std::ostream &os,
+  const cta::tapeserver::readtp::TapeFseqRangeList &value);
diff --git a/tapeserver/readtp/TapeFseqRangeSequence.cpp b/tapeserver/readtp/TapeFseqRangeSequence.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..de7c65ed20013bab3fc956b1f18c964edd956855
--- /dev/null
+++ b/tapeserver/readtp/TapeFseqRangeSequence.cpp
@@ -0,0 +1,122 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "tapeserver/readtp/TapeFseqRangeSequence.hpp"
+#include "tapeserver/readtp/TapeFseqRange.hpp"
+#include "common/exception/Exception.hpp"
+
+#include <getopt.h>
+#include <ostream>
+
+#include <list>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+TapeFseqRangeSequence::TapeFseqRangeSequence() throw() {
+  reset();
+}
+
+
+//------------------------------------------------------------------------------
+// constructor
+//------------------------------------------------------------------------------
+TapeFseqRangeSequence::TapeFseqRangeSequence(
+  const TapeFseqRange &range) throw() {
+  reset(range);
+}
+
+
+//------------------------------------------------------------------------------
+// reset
+//------------------------------------------------------------------------------
+void TapeFseqRangeSequence::reset() throw() {
+
+  // Reset the range to be empty
+  m_range.reset();
+
+  m_next = 0; // Ignored
+}
+
+
+//------------------------------------------------------------------------------
+// reset
+//------------------------------------------------------------------------------
+void TapeFseqRangeSequence::reset(
+  const TapeFseqRange &range) throw() {
+  m_range = range;
+
+  if(range.isEmpty()) {
+    m_next = 0; // Ignored
+  } else {
+    m_next = m_range.lower();
+  }
+}
+
+
+//------------------------------------------------------------------------------
+// hasMore
+//------------------------------------------------------------------------------
+bool TapeFseqRangeSequence::hasMore() const throw() {
+
+  if(m_range.isEmpty()) {
+
+    return false;
+
+  } else {
+
+    // Infinity is represented by range.upper() == 0
+    return m_range.upper() == 0 || m_next <= m_range.upper();
+  }
+}
+
+
+//------------------------------------------------------------------------------
+// next
+//------------------------------------------------------------------------------
+uint32_t TapeFseqRangeSequence::next()
+   {
+
+  if(!hasMore()) {
+    exception::Exception ex;
+
+    ex.getMessage()
+      << "Sequence::next() called after end of sequence";
+
+    throw ex;
+  }
+
+  return m_next++;
+}
+
+
+//------------------------------------------------------------------------------
+// range
+//------------------------------------------------------------------------------
+const TapeFseqRange
+  &TapeFseqRangeSequence::range() const throw() {
+  return m_range;
+}
+
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
\ No newline at end of file
diff --git a/tapeserver/readtp/TapeFseqRangeSequence.hpp b/tapeserver/readtp/TapeFseqRangeSequence.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..ae068dfd0a68bc570711f93c733eb9b36331c7cd
--- /dev/null
+++ b/tapeserver/readtp/TapeFseqRangeSequence.hpp
@@ -0,0 +1,100 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "TapeFseqRange.hpp"
+
+#include <list>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+/**
+ * Generates a sequence of tape file sequence numbers from a range of tape file
+ * sequence numbers.
+ */
+class TapeFseqRangeSequence {
+public:
+
+  /**
+   * Constructor.
+   *
+   * Constructs an empty sequence.
+   */
+  TapeFseqRangeSequence() throw();
+
+  /**
+   * Constructor.
+   *
+   * @param range The range from which the sequence is generated.
+   */
+  TapeFseqRangeSequence(const TapeFseqRange &range) throw();
+
+  /**
+   * Resets the sequence to empty.
+   */
+  void reset() throw();
+
+  /**
+   * Resets the sequence using the specified range.
+   *
+   * @param range The range from which the sequence is generated.
+   */
+  void reset(const TapeFseqRange &range) throw();
+
+  /**
+   * Returns true if there is another tape file sequence number in the
+   * sequence.
+   */
+  bool hasMore() const throw();
+
+  /**
+   * Returns the next tape file sequence number in the sequence, or throws
+   * NoValue exception if there isn't one.
+   */
+  uint32_t next() ;
+
+  /**
+   * Returns the number of values generated by the sequence so far.
+   */
+  uint32_t nbGeneratedValues() const throw();
+
+  /**
+   * Returns the range used by this sequence.
+   */
+  const TapeFseqRange &range() const throw();
+
+
+private:
+
+  /**
+   * The range from which the sequence is generated.
+   */
+  TapeFseqRange m_range;
+
+  /**
+   * The value to be returned by a call to next().
+   */
+  uint32_t m_next;
+
+}; // class TapeFseqRangeSequence
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
\ No newline at end of file
diff --git a/tapeserver/readtp/TapeFseqSequenceParser.cpp b/tapeserver/readtp/TapeFseqSequenceParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8e4d9a47c1547b30ed042a13bf1747056b453c1f
--- /dev/null
+++ b/tapeserver/readtp/TapeFseqSequenceParser.cpp
@@ -0,0 +1,150 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "common/exception/InvalidArgument.hpp"
+#include "tapeserver/readtp/TapeFseqSequenceParser.hpp"
+#include "common/utils/utils.hpp"
+
+#include <list>
+#include <string>
+#include <vector>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+//------------------------------------------------------------------------------
+// parseTapeFileSequence
+//------------------------------------------------------------------------------
+TapeFseqRangeList TapeFileSequenceParser::parse(char *const str)
+{
+  TapeFseqRangeList tapeFseqRanges;
+  std::vector<std::string> rangeStrs;
+  
+  // Range strings are separated by commas
+  utils::splitString(str, ',', rangeStrs);
+
+  // For each range string
+  for(std::vector<std::string>::const_iterator itor=rangeStrs.begin();
+    itor!=rangeStrs.end(); itor++) {
+
+    std::vector<std::string> boundaryStrs;
+
+    // Lower and upper boundary strings are separated by a dash ('-')
+    utils::splitString(*itor, '-', boundaryStrs);
+
+    int nbBoundaries = boundaryStrs.size();
+
+    switch(nbBoundaries) {
+    case 1: // Range string = "n"
+      if(!utils::isValidUInt(boundaryStrs[0].c_str())) {
+        exception::InvalidArgument ex;
+        ex.getMessage() << "Invalid range string: '" << boundaryStrs[0]
+          << "': Expecting an unsigned integer";
+        throw ex;
+      }
+
+      {
+        const uint32_t upperLower = atoi(boundaryStrs[0].c_str());
+        tapeFseqRanges.push_back(TapeFseqRange(upperLower, upperLower));
+      }
+      break;
+
+    case 2: // Range string = "m-n" or "-n" or "m-" or "-"
+
+      // If "-n" or "-" then the range string is invalid
+      if(boundaryStrs[0] == "") {
+        exception::InvalidArgument ex;
+        ex.getMessage() << "Invalid range string: '" << *itor
+          << "': Strings of the form '-n' or '-' are invalid";
+        throw ex;
+      }
+
+      // At this point the range string must be either "m-n" or "m-"
+
+      // Parse the "m" of "m-n" or "m-"
+      if(!utils::isValidUInt(boundaryStrs[0].c_str())) {
+        exception::InvalidArgument ex;
+        ex.getMessage() << "Invalid range string: '" << *itor
+          << "': The lower boundary should be an unsigned integer";
+        throw ex;
+      }
+
+      {
+        const uint32_t lower = atoi(boundaryStrs[0].c_str());
+
+        if(lower == 0) {
+          exception::InvalidArgument ex;
+          ex.getMessage() << "Invalid range string: '" << *itor
+            << "': The lower boundary can not be '0'";
+          throw ex;
+        }
+
+        // If "m-"
+        if(boundaryStrs[1] == "") {
+
+          // Infinity (or until the end of tape) is represented by 0
+          tapeFseqRanges.push_back(TapeFseqRange(lower, 0));
+
+        // Else "m-n"
+        } else {
+
+          // Parse the "n" of "m-n"
+          if(!utils::isValidUInt(boundaryStrs[1].c_str())) {
+            exception::InvalidArgument ex;
+            ex.getMessage() << "Invalid range string: '" << *itor
+              << "': The upper boundary should be an unsigned integer";
+            throw ex;
+          }
+
+          const uint32_t upper = atoi(boundaryStrs[1].c_str());
+
+          if(upper == 0){
+            exception::InvalidArgument ex;
+            ex.getMessage() << "Invalid range string: '" << *itor
+              << "': The upper boundary can not be '0'";
+            throw ex;
+          }
+
+          if(lower > upper){
+            exception::InvalidArgument ex;
+            ex.getMessage() << "Invalid range string: '" << *itor
+              << "': The lower boundary cannot be greater than the upper "
+              "boundary";
+            throw ex;
+          }
+
+          tapeFseqRanges.push_back(TapeFseqRange(lower, upper));
+        } // Else "m-n"
+      }
+
+
+      break;
+
+    default: // Range string is invalid
+      exception::InvalidArgument ex;
+      ex.getMessage() << "Invalid range string: '" << *itor
+        << "': A range string can only contain one or no dashes ('-')";
+      throw ex;
+    }
+  }
+  return tapeFseqRanges;
+}
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
\ No newline at end of file
diff --git a/tapeserver/readtp/TapeFseqSequenceParser.hpp b/tapeserver/readtp/TapeFseqSequenceParser.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d413ca27963e3fe1b0949e43eaf4d8a9695bbcde
--- /dev/null
+++ b/tapeserver/readtp/TapeFseqSequenceParser.hpp
@@ -0,0 +1,58 @@
+/*
+ * @project        The CERN Tape Archive (CTA)
+ * @copyright      Copyright(C) 2015-2021 CERN
+ * @license        This program is free software: you can redistribute it and/or modify
+ *                 it under the terms of the GNU General Public License as published by
+ *                 the Free Software Foundation, either version 3 of the License, or
+ *                 (at your option) any later version.
+ *
+ *                 This program is distributed in the hope that it will be useful,
+ *                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *                 GNU General Public License for more details.
+ *
+ *                 You should have received a copy of the GNU General Public License
+ *                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "common/exception/Exception.hpp"
+#include "tapeserver/readtp/TapeFseqRangeListSequence.hpp"
+
+#include <list>
+
+namespace cta {
+namespace tapeserver {
+namespace readtp {
+
+/**
+ * Helper class to parse tape file sequence parameter strings.
+ */
+class TapeFileSequenceParser {
+public:
+
+  /**
+   * Parse the specified tape file sequence parameter string and store the
+   * resulting ranges into m_parsedCommandLine.tapeFseqRanges.
+   *
+   * The syntax rules for a tape file sequence specification are:
+   * <ul>
+   *  <li>  f1            File f1.
+   *  <li>  f1-f2         Files f1 to f2 included.
+   *  <li>  f1-           Files from f1 to the last file of the tape.
+   *  <li>  f1-f2,f4,f6-  Series of ranges "," separated.
+   * </ul>
+   *
+   * @param str The string received as an argument for the TapeFileSequence
+   * option.
+   * @return The resulting list of tape file sequence ranges.
+   */
+  static TapeFseqRangeList parse(char *const str)
+    ;
+
+}; // class TapeFileSequenceParser
+
+} // namespace readtp
+} // namespace tapeserver
+} // namespace cta
\ No newline at end of file
diff --git a/tapeserver/readtp/cta-readtp.1cta b/tapeserver/readtp/cta-readtp.1cta
new file mode 100644
index 0000000000000000000000000000000000000000..cba3f3363f2719da2b2edd1c18f8f48690955eb0
--- /dev/null
+++ b/tapeserver/readtp/cta-readtp.1cta
@@ -0,0 +1,53 @@
+.\" @project        The CERN Tape Archive (CTA)
+.\" @copyright      Copyright(C) 2019-2021 CERN
+.\" @license        This program is free software: you can redistribute it and/or modify
+.\"                 it under the terms of the GNU General Public License as published by
+.\"                 the Free Software Foundation, either version 3 of the License, or
+.\"                 (at your option) any later version.
+.\"
+.\"                 This program is distributed in the hope that it will be useful,
+.\"                 but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\"                 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+.\"                 GNU General Public License for more details.
+.\"
+.\"                 You should have received a copy of the GNU General Public License
+.\"                 along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+.TH CTA-READTP 1CTA "August 2021" CTA CTA
+.SH NAME
+cta-readtp \- Read files from a tape
+.SH SYNOPSIS
+.BI "cta-readtp VID SEQUENCE [OPTIONS]"
+
+.SH DESCRIPTION
+\fBcta-readtp\fP is a command-line tool for reading files from tape and validating their checksums.
+
+The  tape  to  be read is specified by the \fBVID\fP argument.  The tape files to be read are specified as a \fBSEQUENCE\fP of tape file sequence numbers.  The
+syntax used to specify the sequence is as follows:
+
+    f1-f2          Files f1 to f2 inclusive.
+    f1-            Files f1 to the last file on the tape.
+    f1-f2,f4,f6-   A series of non-consecutive ranges of files.
+
+.SH OPTIONS
+.TP
+.TP
+\fB\-h, \-\-help
+Prints the usage message.
+.TP
+\fB\-f, \-\-destination_files
+Path to a file containing a list of URLs the read files will be written to. If not specified, read files will be written to file:///dev/null.
+If there are more read files than destination files, the remaining read files will be written to file:///dev/null
+.TP
+\fB\-p, \-\-xroot_private_key
+Path to the xroot private key file. Necessary if any destination file URL is for xroot.
+.
+
+.SH RETURN VALUE
+Zero on success and non-zero on failure.
+.SH EXAMPLES
+.br
+cta-readtp V01007 10002,10004-10006,10008-
+
+.SH AUTHOR
+\fBCTA\fP Team
diff --git a/xroot_plugins/XrdCtaTapeFileLs.hpp b/xroot_plugins/XrdCtaTapeFileLs.hpp
index a90582ebfa3419cea7e735ed6071fdce597063ca..ca813935ca409d01424f53514348b619e70aba8a 100644
--- a/xroot_plugins/XrdCtaTapeFileLs.hpp
+++ b/xroot_plugins/XrdCtaTapeFileLs.hpp
@@ -94,8 +94,7 @@ TapeFileLsStream::TapeFileLsStream(const RequestMessage &requestMsg,
     }
     searchCriteria.diskFileIds->push_back(std::to_string(fid));
   }
-  // Disk instance on its own does not give a valid set of search criteria (no &has_any)
-  searchCriteria.diskInstance = requestMsg.getOptional(OptionString::INSTANCE);
+  searchCriteria.diskInstance = requestMsg.getOptional(OptionString::INSTANCE, &has_any);
 
   searchCriteria.archiveFileId = requestMsg.getOptional(OptionUInt64::ARCHIVE_FILE_ID, &has_any);
 
diff --git a/xroot_plugins/XrdCtaVirtualOrganizationLs.hpp b/xroot_plugins/XrdCtaVirtualOrganizationLs.hpp
index 8bf8e52bb97af9fba5d58e813a8fa71e5188b8ff..df59a73646c487bbd2ba3d74a3c8214af6737939 100644
--- a/xroot_plugins/XrdCtaVirtualOrganizationLs.hpp
+++ b/xroot_plugins/XrdCtaVirtualOrganizationLs.hpp
@@ -77,6 +77,7 @@ int VirtualOrganizationLsStream::fillBuffer(XrdSsiPb::OStreamBuffer<Data> *strea
     vo_item->set_name(vo.name);
     vo_item->set_read_max_drives(vo.readMaxDrives);
     vo_item->set_write_max_drives(vo.writeMaxDrives);
+    vo_item->set_max_file_size(vo.maxFileSize);
     vo_item->mutable_creation_log()->set_username(vo.creationLog.username);
     vo_item->mutable_creation_log()->set_host(vo.creationLog.host);
     vo_item->mutable_creation_log()->set_time(vo.creationLog.time);
diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.cpp b/xroot_plugins/XrdSsiCtaRequestMessage.cpp
index 5ed7a836baa8e54fe8907454f6823cd9a710e95b..41c60c3f4af9ccae61df808f77c920fe384ff51f 100644
--- a/xroot_plugins/XrdSsiCtaRequestMessage.cpp
+++ b/xroot_plugins/XrdSsiCtaRequestMessage.cpp
@@ -282,6 +282,10 @@ void RequestMessage::process(const cta::xrd::Request &request, cta::xrd::Respons
            case cmd_pair(AdminCmd::CMD_RECYCLETAPEFILE, AdminCmd::SUBCMD_LS):
                processRecycleTapeFile_Ls(response,stream);
                break;
+           case cmd_pair(AdminCmd::CMD_RECYCLETAPEFILE, AdminCmd::SUBCMD_RESTORE):
+               processRecycleTapeFile_Restore(response);
+               break;
+
             default:
                throw PbException("Admin command pair <" +
                      AdminCmd_Cmd_Name(request.admincmd().cmd()) + ", " +
@@ -467,10 +471,12 @@ void RequestMessage::processCLOSEW(const cta::eos::Notification &notification, c
       throw PbException("File is in fail_on_closew_test storage class, which always fails.");
    }
 
+   auto storageClass = m_catalogue.getStorageClass(storageClassItor->second);
+
    // Disallow archival of files above the specified limit
-   if(notification.file().size() > m_archiveFileMaxSize) {
+   if(storageClass.vo.maxFileSize && notification.file().size() > storageClass.vo.maxFileSize) {
       throw exception::UserError("Archive request rejected: file size (" + std::to_string(notification.file().size()) +
-                                 " bytes) exceeds maximum allowed size (" + std::to_string(m_archiveFileMaxSize) + " bytes)");
+                                 " bytes) exceeds maximum allowed size (" + std::to_string(storageClass.vo.maxFileSize) + " bytes)");
    }
 
    cta::common::dataStructures::ArchiveRequest request;
@@ -1833,7 +1839,7 @@ void RequestMessage::processTapeFile_Rm(cta::xrd::Response &response)
   } else if (diskFileId) {
     if (!instance) {
       throw exception::UserError(std::string("--fxid requires that --instance is specified"));
-    } 
+    }
     m_catalogue.deleteTapeFileCopy(vid, diskFileId.value(), instance.value(), reason);
     response.set_type(cta::xrd::Response::RSP_SUCCESS);
   } else {
@@ -1999,6 +2005,7 @@ void RequestMessage::processVirtualOrganization_Add(cta::xrd::Response &response
   const auto &readMaxDrives = getRequired(OptionUInt64::READ_MAX_DRIVES);
   const auto &writeMaxDrives = getRequired(OptionUInt64::WRITE_MAX_DRIVES);
   const auto &comment = getRequired(OptionString::COMMENT);
+  const auto &maxFileSizeOpt = getOptional(OptionUInt64::MAX_FILE_SIZE);
 
   cta::common::dataStructures::VirtualOrganization vo;
   vo.name = name;
@@ -2006,6 +2013,12 @@ void RequestMessage::processVirtualOrganization_Add(cta::xrd::Response &response
   vo.writeMaxDrives = writeMaxDrives;
   vo.comment = comment;
 
+  if (maxFileSizeOpt) {
+    vo.maxFileSize = maxFileSizeOpt.value();
+  } else {
+    vo.maxFileSize = m_archiveFileMaxSize;
+  }
+
   m_catalogue.createVirtualOrganization(m_cliIdentity,vo);
 
   response.set_type(cta::xrd::Response::RSP_SUCCESS);
@@ -2018,6 +2031,7 @@ void RequestMessage::processVirtualOrganization_Ch(cta::xrd::Response &response)
   const auto readMaxDrives = getOptional(OptionUInt64::READ_MAX_DRIVES);
   const auto writeMaxDrives = getOptional(OptionUInt64::WRITE_MAX_DRIVES);
   const auto comment = getOptional(OptionString::COMMENT);
+  const auto maxFileSize = getOptional(OptionUInt64::MAX_FILE_SIZE);
 
   if(comment)
     m_catalogue.modifyVirtualOrganizationComment(m_cliIdentity,name,comment.value());
@@ -2028,6 +2042,9 @@ void RequestMessage::processVirtualOrganization_Ch(cta::xrd::Response &response)
   if(writeMaxDrives)
     m_catalogue.modifyVirtualOrganizationWriteMaxDrives(m_cliIdentity,name,writeMaxDrives.value());
 
+  if(maxFileSize)
+    m_catalogue.modifyVirtualOrganizationMaxFileSize(m_cliIdentity,name,maxFileSize.value());
+
   response.set_type(cta::xrd::Response::RSP_SUCCESS);
 }
 
@@ -2147,4 +2164,39 @@ void RequestMessage::processRecycleTapeFile_Ls(cta::xrd::Response &response, Xrd
   response.set_type(cta::xrd::Response::RSP_SUCCESS);
 }
 
+void RequestMessage::processRecycleTapeFile_Restore(cta::xrd::Response& response) {
+   response.set_type(cta::xrd::Response::RSP_SUCCESS);
+   using namespace cta::admin;
+
+  bool has_any = false;
+  cta::catalogue::RecycleTapeFileSearchCriteria searchCriteria;
+
+  searchCriteria.vid = getOptional(OptionString::VID, &has_any);
+  auto diskFileId = getOptional(OptionString::FXID, &has_any);
+  searchCriteria.diskFileIds = getOptional(OptionStrList::FILE_ID, &has_any);
+
+  if(diskFileId){
+    // single option on the command line we need to do the conversion ourselves.
+    if(!searchCriteria.diskFileIds) searchCriteria.diskFileIds = std::vector<std::string>();
+
+    auto fid = strtol(diskFileId->c_str(), nullptr, 16);
+    if(fid < 1 || fid == LONG_MAX) {
+       throw cta::exception::UserError(*diskFileId + " is not a valid file ID");
+    }
+
+    searchCriteria.diskFileIds->push_back(std::to_string(fid));
+  }
+  // Disk instance on its own does not give a valid set of search criteria (no &has_any)
+  searchCriteria.diskInstance = getOptional(OptionString::INSTANCE);
+  searchCriteria.archiveFileId = getOptional(OptionUInt64::ARCHIVE_FILE_ID, &has_any);
+  // Copy number on its own does not give a valid set of search criteria (no &has_any)
+  searchCriteria.copynb = getOptional(OptionUInt64::COPY_NUMBER);
+
+  if(!has_any){
+    throw cta::exception::UserError("Must specify at least one search option");
+  }
+   m_catalogue.restoreFilesInRecycleLog(searchCriteria);
+  response.set_type(cta::xrd::Response::RSP_SUCCESS);
+}
+
 }} // namespace cta::xrd
diff --git a/xroot_plugins/XrdSsiCtaRequestMessage.hpp b/xroot_plugins/XrdSsiCtaRequestMessage.hpp
index fb9b2f4f27b2eda48cb1a1db3992f2010c1c35e3..616516bcffb2c4851334ba0f580e9f2f2388eaca 100644
--- a/xroot_plugins/XrdSsiCtaRequestMessage.hpp
+++ b/xroot_plugins/XrdSsiCtaRequestMessage.hpp
@@ -208,6 +208,7 @@ private:
   void processVirtualOrganization_Add(cta::xrd::Response &response);
   void processVirtualOrganization_Ch(cta::xrd::Response &response);
   void processVirtualOrganization_Rm(cta::xrd::Response &response);
+  void processRecycleTapeFile_Restore(cta::xrd::Response &response);
   
   /*!
    * Process AdminCmd events which can return a stream response
diff --git a/xroot_plugins/XrdSsiCtaServiceProvider.cpp b/xroot_plugins/XrdSsiCtaServiceProvider.cpp
index df4cc19b2cffb7033735d7b3c9a3f6ddab3c2d02..ededf3116c4f71909a09d4d909c55d66e195cf65 100644
--- a/xroot_plugins/XrdSsiCtaServiceProvider.cpp
+++ b/xroot_plugins/XrdSsiCtaServiceProvider.cpp
@@ -153,7 +153,7 @@ void XrdSsiCtaServiceProvider::ExceptionThrowingInit(XrdSsiLogger *logP, XrdSsiC
 
    // Initialise the Frontend
    auto archiveFileMaxSize = config.getOptionValueInt("cta.archivefile.max_size_gb");
-   m_archiveFileMaxSize = archiveFileMaxSize.first ? archiveFileMaxSize.second : 2048; // GB
+   m_archiveFileMaxSize = archiveFileMaxSize.first ? archiveFileMaxSize.second : 0; // GB
    m_archiveFileMaxSize *= 1024*1024*1024; // bytes
 
    // Get the repack buffer URL
diff --git a/xrootd-ssi-protobuf-interface b/xrootd-ssi-protobuf-interface
index 2f8068955f6622f26e6373a70cfcb4f16435d7ea..533402d24924f0450924d4f07d0b8450398ab203 160000
--- a/xrootd-ssi-protobuf-interface
+++ b/xrootd-ssi-protobuf-interface
@@ -1 +1 @@
-Subproject commit 2f8068955f6622f26e6373a70cfcb4f16435d7ea
+Subproject commit 533402d24924f0450924d4f07d0b8450398ab203