RdbmsCatalogue.cpp 190 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/*
 * The CERN Tape Archive (CTA) project
 * Copyright (C) 2015  CERN
 *
 * 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/>.
 */

19
#include "catalogue/ArchiveFileRow.hpp"
20
#include "catalogue/RdbmsArchiveFileItorImpl.hpp"
21
#include "catalogue/RdbmsCatalogue.hpp"
22
#include "catalogue/retryOnLostConnection.hpp"
23
#include "catalogue/SqliteCatalogueSchema.hpp"
24
25
#include "catalogue/UserSpecifiedANonEmptyTape.hpp"
#include "catalogue/UserSpecifiedANonExistentTape.hpp"
26
27
28
#include "catalogue/UserSpecifiedAnEmptyStringComment.hpp"
#include "catalogue/UserSpecifiedAnEmptyStringTapePoolName.hpp"
#include "catalogue/UserSpecifiedAnEmptyStringVo.hpp"
29
#include "common/dataStructures/TapeFile.hpp"
30
#include "common/exception/Exception.hpp"
31
#include "common/exception/UserError.hpp"
32
#include "common/make_unique.hpp"
33
#include "common/threading/MutexLocker.hpp"
34
#include "common/Timer.hpp"
35
#include "common/utils/utils.hpp"
36
#include "rdbms/AutoRollback.hpp"
37

38
#include <ctype.h>
39
40
#include <memory>
#include <time.h>
41
#include <common/exception/LostDatabaseConnection.hpp>
42

43
44
45
namespace cta {
namespace catalogue {

46
47
48
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
49
RdbmsCatalogue::RdbmsCatalogue(
50
  log::Logger &log,
51
  const rdbms::Login &login,
52
  const uint64_t nbConns,
53
54
  const uint64_t nbArchiveFileListingConns,
  const uint32_t maxTriesToConnect):
55
  m_log(log),
56
  m_connPool(login, nbConns),
57
  m_archiveFileListingConnPool(login, nbArchiveFileListingConns),
Steven Murray's avatar
Steven Murray committed
58
59
60
61
  m_maxTriesToConnect(maxTriesToConnect),
  m_tapeCopyToPoolCache(10),
  m_groupMountPolicyCache(10),
  m_userMountPolicyCache(10),
62
63
  m_expectedNbArchiveRoutesCache(10),
  m_isAdminCache(10) {
64
65
66
67
68
}

//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
69
RdbmsCatalogue::~RdbmsCatalogue() {
70
71
72
73
74
}

//------------------------------------------------------------------------------
// createAdminUser
//------------------------------------------------------------------------------
75
void RdbmsCatalogue::createAdminUser(
Steven Murray's avatar
Steven Murray committed
76
  const common::dataStructures::SecurityIdentity &admin,
77
  const std::string &username,
78
  const std::string &comment) {
Steven Murray's avatar
Steven Murray committed
79
  try {
80
    auto conn = m_connPool.getConn();
81
    if (adminUserExists(conn, username)) {
82
      throw exception::UserError(std::string("Cannot create admin user " + username +
83
84
        " because an admin user with the same name already exists"));
    }
85
    const uint64_t now = time(nullptr);
Steven Murray's avatar
Steven Murray committed
86
87
88
89
90
91
92
93
94
95
96
97
98
    const char *const sql =
      "INSERT INTO ADMIN_USER("
        "ADMIN_USER_NAME,"

        "USER_COMMENT,"

        "CREATION_LOG_USER_NAME,"
        "CREATION_LOG_HOST_NAME,"
        "CREATION_LOG_TIME,"

        "LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME)"
99
      "VALUES("
Steven Murray's avatar
Steven Murray committed
100
101
102
103
104
105
106
107
        ":ADMIN_USER_NAME,"

        ":USER_COMMENT,"

        ":CREATION_LOG_USER_NAME,"
        ":CREATION_LOG_HOST_NAME,"
        ":CREATION_LOG_TIME,"

108
109
110
        ":LAST_UPDATE_USER_NAME,"
        ":LAST_UPDATE_HOST_NAME,"
        ":LAST_UPDATE_TIME)";
111
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
Steven Murray's avatar
Steven Murray committed
112

113
    stmt.bindString(":ADMIN_USER_NAME", username);
Steven Murray's avatar
Steven Murray committed
114

115
    stmt.bindString(":USER_COMMENT", comment);
Steven Murray's avatar
Steven Murray committed
116

117
118
119
    stmt.bindString(":CREATION_LOG_USER_NAME", admin.username);
    stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host);
    stmt.bindUint64(":CREATION_LOG_TIME", now);
Steven Murray's avatar
Steven Murray committed
120

121
122
123
    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
    stmt.bindUint64(":LAST_UPDATE_TIME", now);
124

125
    stmt.executeNonQuery();
126
127
128
129
  } catch(exception::UserError &) {
    throw;
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
130
131
132
133
134
135
136
    throw;
  }
}

//------------------------------------------------------------------------------
// adminUserExists
//------------------------------------------------------------------------------
137
bool RdbmsCatalogue::adminUserExists(rdbms::Conn &conn, const std::string adminUsername) const {
138
139
140
141
142
143
144
  try {
    const char *const sql =
      "SELECT "
        "ADMIN_USER_NAME AS ADMIN_USER_NAME "
      "FROM "
        "ADMIN_USER "
      "WHERE "
145
        "ADMIN_USER_NAME = :ADMIN_USER_NAME";
146
147
148
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindString(":ADMIN_USER_NAME", adminUsername);
    auto rset = stmt.executeQuery();
149
    return rset.next();
150
151
  } catch(exception::UserError &) {
    throw;
152
153
154
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
Steven Murray's avatar
Steven Murray committed
155
  }
156
157
158
159
160
}

//------------------------------------------------------------------------------
// deleteAdminUser
//------------------------------------------------------------------------------
161
void RdbmsCatalogue::deleteAdminUser(const std::string &username) {
162
  try {
163
    const char *const sql = "DELETE FROM ADMIN_USER WHERE ADMIN_USER_NAME = :ADMIN_USER_NAME";
164
    auto conn = m_connPool.getConn();
165
166
167
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
    stmt.bindString(":ADMIN_USER_NAME", username);
    stmt.executeNonQuery();
168

169
    if(0 == stmt.getNbAffectedRows()) {
170
      throw exception::UserError(std::string("Cannot delete admin-user ") + username + " because they do not exist");
171
    }
172
173
174
175
  } catch(exception::UserError &) {
    throw;
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
176
177
    throw;
  }
Steven Murray's avatar
Steven Murray committed
178
}
179
180
181
182

//------------------------------------------------------------------------------
// getAdminUsers
//------------------------------------------------------------------------------
183
std::list<common::dataStructures::AdminUser> RdbmsCatalogue::getAdminUsers() const {
Steven Murray's avatar
Steven Murray committed
184
185
186
187
188
  try {
    std::list<common::dataStructures::AdminUser> admins;
    const char *const sql =
      "SELECT "
        "ADMIN_USER_NAME AS ADMIN_USER_NAME,"
189

Steven Murray's avatar
Steven Murray committed
190
        "USER_COMMENT AS USER_COMMENT,"
191

192
193
194
        "CREATION_LOG_USER_NAME AS CREATION_LOG_USER_NAME,"
        "CREATION_LOG_HOST_NAME AS CREATION_LOG_HOST_NAME,"
        "CREATION_LOG_TIME AS CREATION_LOG_TIME,"
195

196
197
198
        "LAST_UPDATE_USER_NAME AS LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME AS LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME AS LAST_UPDATE_TIME "
199
      "FROM "
200
201
202
        "ADMIN_USER "
      "ORDER BY "
        "ADMIN_USER_NAME";
203
    auto conn = m_connPool.getConn();
204
205
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    auto rset = stmt.executeQuery();
206
    while (rset.next()) {
Steven Murray's avatar
Steven Murray committed
207
      common::dataStructures::AdminUser admin;
208

209
210
211
212
213
214
215
216
      admin.name = rset.columnString("ADMIN_USER_NAME");
      admin.comment = rset.columnString("USER_COMMENT");
      admin.creationLog.username = rset.columnString("CREATION_LOG_USER_NAME");
      admin.creationLog.host = rset.columnString("CREATION_LOG_HOST_NAME");
      admin.creationLog.time = rset.columnUint64("CREATION_LOG_TIME");
      admin.lastModificationLog.username = rset.columnString("LAST_UPDATE_USER_NAME");
      admin.lastModificationLog.host = rset.columnString("LAST_UPDATE_HOST_NAME");
      admin.lastModificationLog.time = rset.columnUint64("LAST_UPDATE_TIME");
217

Steven Murray's avatar
Steven Murray committed
218
219
      admins.push_back(admin);
    }
220

Steven Murray's avatar
Steven Murray committed
221
    return admins;
222
223
  } catch(exception::UserError &) {
    throw;
224
225
226
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
Steven Murray's avatar
Steven Murray committed
227
  }
228
229
230
231
232
}

//------------------------------------------------------------------------------
// modifyAdminUserComment
//------------------------------------------------------------------------------
Steven Murray's avatar
Steven Murray committed
233
void RdbmsCatalogue::modifyAdminUserComment(const common::dataStructures::SecurityIdentity &admin,
234
235
236
237
238
239
240
241
242
  const std::string &username, const std::string &comment) {
  try {
    const time_t now = time(nullptr);
    const char *const sql =
      "UPDATE ADMIN_USER SET "
        "USER_COMMENT = :USER_COMMENT,"
        "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME = :LAST_UPDATE_TIME "
243
      "WHERE "
244
245
        "ADMIN_USER_NAME = :ADMIN_USER_NAME";
    auto conn = m_connPool.getConn();
246
247
248
249
250
251
252
253
254
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
    stmt.bindString(":USER_COMMENT", comment);
    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
    stmt.bindUint64(":LAST_UPDATE_TIME", now);
    stmt.bindString(":ADMIN_USER_NAME", username);
    stmt.executeNonQuery();

    if(0 == stmt.getNbAffectedRows()) {
255
256
257
258
      throw exception::UserError(std::string("Cannot modify admin user ") + username + " because they do not exist");
    }
  } catch(exception::UserError &) {
    throw;
259
260
261
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
262
  }
Steven Murray's avatar
Steven Murray committed
263
}
264
265
266
267

//------------------------------------------------------------------------------
// createStorageClass
//------------------------------------------------------------------------------
268
void RdbmsCatalogue::createStorageClass(
Steven Murray's avatar
Steven Murray committed
269
  const common::dataStructures::SecurityIdentity &admin,
270
  const common::dataStructures::StorageClass &storageClass) {
Steven Murray's avatar
Steven Murray committed
271
  try {
272
    auto conn = m_connPool.getConn();
273
    if(storageClassExists(conn, storageClass.diskInstance, storageClass.name)) {
274
275
      throw exception::UserError(std::string("Cannot create storage class ") + storageClass.diskInstance + ":" +
        storageClass.name + " because it already exists");
276
    }
277
    const uint64_t storageClassId = getNextStorageClassId(conn);
278
    const time_t now = time(nullptr);
Steven Murray's avatar
Steven Murray committed
279
280
    const char *const sql =
      "INSERT INTO STORAGE_CLASS("
281
        "STORAGE_CLASS_ID,"
282
        "DISK_INSTANCE_NAME,"
Steven Murray's avatar
Steven Murray committed
283
284
285
286
287
288
289
290
291
292
293
294
        "STORAGE_CLASS_NAME,"
        "NB_COPIES,"

        "USER_COMMENT,"

        "CREATION_LOG_USER_NAME,"
        "CREATION_LOG_HOST_NAME,"
        "CREATION_LOG_TIME,"

        "LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME)"
295
      "VALUES("
296
        ":STORAGE_CLASS_ID,"
297
        ":DISK_INSTANCE_NAME,"
Steven Murray's avatar
Steven Murray committed
298
299
300
301
302
303
304
305
306
        ":STORAGE_CLASS_NAME,"
        ":NB_COPIES,"

        ":USER_COMMENT,"

        ":CREATION_LOG_USER_NAME,"
        ":CREATION_LOG_HOST_NAME,"
        ":CREATION_LOG_TIME,"

307
308
309
        ":LAST_UPDATE_USER_NAME,"
        ":LAST_UPDATE_HOST_NAME,"
        ":LAST_UPDATE_TIME)";
310
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
Steven Murray's avatar
Steven Murray committed
311

312
    stmt.bindUint64(":STORAGE_CLASS_ID", storageClassId);
313
314
315
    stmt.bindString(":DISK_INSTANCE_NAME", storageClass.diskInstance);
    stmt.bindString(":STORAGE_CLASS_NAME", storageClass.name);
    stmt.bindUint64(":NB_COPIES", storageClass.nbCopies);
Steven Murray's avatar
Steven Murray committed
316

317
    stmt.bindString(":USER_COMMENT", storageClass.comment);
Steven Murray's avatar
Steven Murray committed
318

319
320
321
    stmt.bindString(":CREATION_LOG_USER_NAME", admin.username);
    stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host);
    stmt.bindUint64(":CREATION_LOG_TIME", now);
Steven Murray's avatar
Steven Murray committed
322

323
324
325
    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
    stmt.bindUint64(":LAST_UPDATE_TIME", now);
326

327
    stmt.executeNonQuery();
328
  } catch(exception::UserError &) {
329
    throw;
330
331
332
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
333
334
335
336
337
338
  }
}

//------------------------------------------------------------------------------
// storageClassExists
//------------------------------------------------------------------------------
339
bool RdbmsCatalogue::storageClassExists(rdbms::Conn &conn, const std::string &diskInstanceName,
340
  const std::string &storageClassName) const {
341
342
343
  try {
    const char *const sql =
      "SELECT "
344
        "DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME, "
345
346
347
348
        "STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME "
      "FROM "
        "STORAGE_CLASS "
      "WHERE "
349
        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
350
        "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
351
352
353
354
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName);
    stmt.bindString(":STORAGE_CLASS_NAME", storageClassName);
    auto rset = stmt.executeQuery();
355
    return rset.next();
356
357
  } catch(exception::UserError &) {
    throw;
358
359
360
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
Steven Murray's avatar
Steven Murray committed
361
  }
362
363
364
365
366
}

//------------------------------------------------------------------------------
// deleteStorageClass
//------------------------------------------------------------------------------
367
void RdbmsCatalogue::deleteStorageClass(const std::string &diskInstanceName, const std::string &storageClassName) {
368
369
370
371
372
  try {
    const char *const sql =
      "DELETE FROM "
        "STORAGE_CLASS "
      "WHERE "
373
        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
374
        "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
375
    auto conn = m_connPool.getConn();
376
    auto stmt = conn.createStmt(sql,rdbms::AutocommitMode::ON);
377

378
379
    stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName);
    stmt.bindString(":STORAGE_CLASS_NAME", storageClassName);
380

381
382
    stmt.executeNonQuery();
    if(0 == stmt.getNbAffectedRows()) {
383
384
      throw exception::UserError(std::string("Cannot delete storage-class ") + diskInstanceName + ":" +
        storageClassName + " because it does not exist");
385
    }
386
  } catch(exception::UserError &) {
387
    throw;
388
389
390
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
391
  }
Steven Murray's avatar
Steven Murray committed
392
}
393
394
395
396

//------------------------------------------------------------------------------
// getStorageClasses
//------------------------------------------------------------------------------
397
std::list<common::dataStructures::StorageClass> RdbmsCatalogue::getStorageClasses() const {
Steven Murray's avatar
Steven Murray committed
398
399
400
401
  try {
    std::list<common::dataStructures::StorageClass> storageClasses;
    const char *const sql =
      "SELECT "
402
        "DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME,"
Steven Murray's avatar
Steven Murray committed
403
        "STORAGE_CLASS_NAME AS STORAGE_CLASS_NAME,"
404
        "NB_COPIES AS NB_COPIES,"
Steven Murray's avatar
Steven Murray committed
405
406
407

        "USER_COMMENT AS USER_COMMENT,"

408
409
410
        "CREATION_LOG_USER_NAME AS CREATION_LOG_USER_NAME,"
        "CREATION_LOG_HOST_NAME AS CREATION_LOG_HOST_NAME,"
        "CREATION_LOG_TIME AS CREATION_LOG_TIME,"
Steven Murray's avatar
Steven Murray committed
411

412
413
414
        "LAST_UPDATE_USER_NAME AS LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME AS LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME AS LAST_UPDATE_TIME "
415
      "FROM "
416
417
418
        "STORAGE_CLASS "
      "ORDER BY "
        "DISK_INSTANCE_NAME, STORAGE_CLASS_NAME";
419
    auto conn = m_connPool.getConn();
420
421
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    auto rset = stmt.executeQuery();
422
    while (rset.next()) {
Steven Murray's avatar
Steven Murray committed
423
424
      common::dataStructures::StorageClass storageClass;

425
426
427
428
429
430
431
432
433
434
      storageClass.diskInstance = rset.columnString("DISK_INSTANCE_NAME");
      storageClass.name = rset.columnString("STORAGE_CLASS_NAME");
      storageClass.nbCopies = rset.columnUint64("NB_COPIES");
      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");
Steven Murray's avatar
Steven Murray committed
435
436

      storageClasses.push_back(storageClass);
437
438
    }

Steven Murray's avatar
Steven Murray committed
439
    return storageClasses;
440
441
  } catch(exception::UserError &) {
    throw;
442
443
444
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
445
446
447
448
449
450
  }
}

//------------------------------------------------------------------------------
// modifyStorageClassNbCopies
//------------------------------------------------------------------------------
Steven Murray's avatar
Steven Murray committed
451
void RdbmsCatalogue::modifyStorageClassNbCopies(const common::dataStructures::SecurityIdentity &admin,
452
453
454
455
456
457
458
459
460
  const std::string &instanceName, const std::string &name, const uint64_t nbCopies) {
  try {
    const time_t now = time(nullptr);
    const char *const sql =
      "UPDATE STORAGE_CLASS SET "
        "NB_COPIES = :NB_COPIES,"
        "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME = :LAST_UPDATE_TIME "
461
      "WHERE "
462
463
464
        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
        "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
    auto conn = m_connPool.getConn();
465
466
467
468
469
470
471
472
473
474
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
    stmt.bindUint64(":NB_COPIES", nbCopies);
    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
    stmt.bindUint64(":LAST_UPDATE_TIME", now);
    stmt.bindString(":DISK_INSTANCE_NAME", instanceName);
    stmt.bindString(":STORAGE_CLASS_NAME", name);
    stmt.executeNonQuery();

    if(0 == stmt.getNbAffectedRows()) {
475
476
477
478
479
      throw exception::UserError(std::string("Cannot modify storage class ") + instanceName + ":" + name +
        " because it does not exist");
    }
  } catch(exception::UserError &) {
    throw;
480
481
482
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
483
  }
Steven Murray's avatar
Steven Murray committed
484
}
485
486
487
488

//------------------------------------------------------------------------------
// modifyStorageClassComment
//------------------------------------------------------------------------------
Steven Murray's avatar
Steven Murray committed
489
void RdbmsCatalogue::modifyStorageClassComment(const common::dataStructures::SecurityIdentity &admin,
490
491
492
493
494
495
496
497
498
  const std::string &instanceName, const std::string &name, const std::string &comment) {
  try {
    const time_t now = time(nullptr);
    const char *const sql =
      "UPDATE STORAGE_CLASS SET "
        "USER_COMMENT = :USER_COMMENT,"
        "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME = :LAST_UPDATE_TIME "
499
      "WHERE "
500
501
502
        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
        "STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME";
    auto conn = m_connPool.getConn();
503
504
505
506
507
508
509
510
511
512
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
    stmt.bindString(":USER_COMMENT", comment);
    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
    stmt.bindUint64(":LAST_UPDATE_TIME", now);
    stmt.bindString(":DISK_INSTANCE_NAME", instanceName);
    stmt.bindString(":STORAGE_CLASS_NAME", name);
    stmt.executeNonQuery();

    if(0 == stmt.getNbAffectedRows()) {
513
514
515
516
517
      throw exception::UserError(std::string("Cannot modify storage class ") + instanceName + ":" + name +
        " because it does not exist");
    }
  } catch(exception::UserError &) {
    throw;
518
519
520
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
521
  }
Steven Murray's avatar
Steven Murray committed
522
}
523
524
525
526

//------------------------------------------------------------------------------
// createTapePool
//------------------------------------------------------------------------------
527
void RdbmsCatalogue::createTapePool(
Steven Murray's avatar
Steven Murray committed
528
  const common::dataStructures::SecurityIdentity &admin,
529
  const std::string &name,
530
  const std::string &vo,
531
532
533
  const uint64_t nbPartialTapes,
  const bool encryptionValue,
  const std::string &comment) {
Steven Murray's avatar
Steven Murray committed
534
  try {
535
536
537
538
539
540
541
542
543
544
545
546
547
548
    if(name.empty()) {
      throw UserSpecifiedAnEmptyStringTapePoolName("Cannot create tape pool because the tape pool name is an empty string");
    }

    if(vo.empty()) {
      throw UserSpecifiedAnEmptyStringVo(std::string("Cannot create tape pool ") + name +
        " because the VO is an empty string");
    }

    if(comment.empty()) {
      throw UserSpecifiedAnEmptyStringComment(std::string("Cannot create tape pool ") + name +
        " because the comment is an empty string");
    }

549
    auto conn = m_connPool.getConn();
550

551
    if(tapePoolExists(conn, name)) {
552
      throw exception::UserError(std::string("Cannot create tape pool ") + name +
553
554
        " because a tape pool with the same name already exists");
    }
555
    const time_t now = time(nullptr);
Steven Murray's avatar
Steven Murray committed
556
557
558
    const char *const sql =
      "INSERT INTO TAPE_POOL("
        "TAPE_POOL_NAME,"
559
        "VO,"
Steven Murray's avatar
Steven Murray committed
560
561
562
563
564
565
566
567
568
569
570
571
        "NB_PARTIAL_TAPES,"
        "IS_ENCRYPTED,"

        "USER_COMMENT,"

        "CREATION_LOG_USER_NAME,"
        "CREATION_LOG_HOST_NAME,"
        "CREATION_LOG_TIME,"

        "LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME)"
572
      "VALUES("
Steven Murray's avatar
Steven Murray committed
573
        ":TAPE_POOL_NAME,"
574
        ":VO,"
Steven Murray's avatar
Steven Murray committed
575
576
577
578
579
580
581
582
583
        ":NB_PARTIAL_TAPES,"
        ":IS_ENCRYPTED,"

        ":USER_COMMENT,"

        ":CREATION_LOG_USER_NAME,"
        ":CREATION_LOG_HOST_NAME,"
        ":CREATION_LOG_TIME,"

584
585
586
        ":LAST_UPDATE_USER_NAME,"
        ":LAST_UPDATE_HOST_NAME,"
        ":LAST_UPDATE_TIME)";
587
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
Steven Murray's avatar
Steven Murray committed
588

589
    stmt.bindString(":TAPE_POOL_NAME", name);
590
    stmt.bindString(":VO", vo);
591
592
    stmt.bindUint64(":NB_PARTIAL_TAPES", nbPartialTapes);
    stmt.bindBool(":IS_ENCRYPTED", encryptionValue);
Steven Murray's avatar
Steven Murray committed
593

594
    stmt.bindString(":USER_COMMENT", comment);
Steven Murray's avatar
Steven Murray committed
595

596
597
598
    stmt.bindString(":CREATION_LOG_USER_NAME", admin.username);
    stmt.bindString(":CREATION_LOG_HOST_NAME", admin.host);
    stmt.bindUint64(":CREATION_LOG_TIME", now);
Steven Murray's avatar
Steven Murray committed
599

600
601
602
    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
    stmt.bindUint64(":LAST_UPDATE_TIME", now);
603

604
    stmt.executeNonQuery();
605
  } catch(exception::UserError &) {
606
    throw;
607
608
609
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
610
611
612
613
614
615
616
617
618
619
  }
}

//------------------------------------------------------------------------------
// tapePoolExists
//------------------------------------------------------------------------------
bool RdbmsCatalogue::tapePoolExists(const std::string &tapePoolName) const {
  try {
    auto conn = m_connPool.getConn();
    return tapePoolExists(conn, tapePoolName);
620
621
  } catch(exception::UserError &) {
    throw;
622
623
624
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
Steven Murray's avatar
Steven Murray committed
625
  }
626
627
}

628
629
630
//------------------------------------------------------------------------------
// tapePoolExists
//------------------------------------------------------------------------------
631
bool RdbmsCatalogue::tapePoolExists(rdbms::Conn &conn, const std::string &tapePoolName) const {
632
633
634
635
636
637
638
  try {
    const char *const sql =
      "SELECT "
        "TAPE_POOL_NAME AS TAPE_POOL_NAME "
      "FROM "
        "TAPE_POOL "
      "WHERE "
639
        "TAPE_POOL_NAME = :TAPE_POOL_NAME";
640
641
642
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindString(":TAPE_POOL_NAME", tapePoolName);
    auto rset = stmt.executeQuery();
643
    return rset.next();
644
645
  } catch(exception::UserError &) {
    throw;
646
647
648
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
649
650
651
  }
}

652
653
654
//------------------------------------------------------------------------------
// archiveFileExists
//------------------------------------------------------------------------------
655
bool RdbmsCatalogue::archiveFileIdExists(rdbms::Conn &conn, const uint64_t archiveFileId) const {
656
657
658
659
660
661
662
663
  try {
    const char *const sql =
      "SELECT "
        "ARCHIVE_FILE_ID AS ARCHIVE_FILE_ID "
      "FROM "
        "ARCHIVE_FILE "
      "WHERE "
        "ARCHIVE_FILE_ID = :ARCHIVE_FILE_ID";
664
665
666
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindUint64(":ARCHIVE_FILE_ID", archiveFileId);
    auto rset = stmt.executeQuery();
667
    return rset.next();
668
669
  } catch(exception::UserError &) {
    throw;
670
671
672
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
673
674
675
  }
}

676
677
678
//------------------------------------------------------------------------------
// diskFileIdExists
//------------------------------------------------------------------------------
679
bool RdbmsCatalogue::diskFileIdExists(rdbms::Conn &conn, const std::string &diskInstanceName,
680
681
682
683
684
685
686
687
688
689
690
  const std::string &diskFileId) const {
  try {
    const char *const sql =
      "SELECT "
        "DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME, "
        "DISK_FILE_ID AS DISK_FILE_ID "
      "FROM "
        "ARCHIVE_FILE "
      "WHERE "
        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
        "DISK_FILE_ID = :DISK_FILE_ID";
691
692
693
694
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName);
    stmt.bindString(":DISK_FILE_ID", diskFileId);
    auto rset = stmt.executeQuery();
695
    return rset.next();
696
697
  } catch(exception::UserError &) {
    throw;
698
699
700
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
701
702
703
  }
}

704
705
706
//------------------------------------------------------------------------------
// diskFilePathExists
//------------------------------------------------------------------------------
707
bool RdbmsCatalogue::diskFilePathExists(rdbms::Conn &conn, const std::string &diskInstanceName,
708
709
710
711
712
713
714
715
716
717
718
  const std::string &diskFilePath) const {
  try {
    const char *const sql =
      "SELECT "
        "DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME, "
        "DISK_FILE_PATH AS DISK_FILE_PATH "
      "FROM "
        "ARCHIVE_FILE "
      "WHERE "
        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
        "DISK_FILE_PATH = :DISK_FILE_PATH";
719
720
721
722
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName);
    stmt.bindString(":DISK_FILE_PATH", diskFilePath);
    auto rset = stmt.executeQuery();
723
    return rset.next();
724
725
  } catch(exception::UserError &) {
    throw;
726
727
728
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
729
730
731
  }
}

732
733
734
//------------------------------------------------------------------------------
// diskFileUserExists
//------------------------------------------------------------------------------
735
bool RdbmsCatalogue::diskFileUserExists(rdbms::Conn &conn, const std::string &diskInstanceName,
736
737
738
739
740
741
742
743
744
745
746
  const std::string &diskFileUser) const {
  try {
    const char *const sql =
      "SELECT "
        "DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME, "
        "DISK_FILE_USER AS DISK_FILE_USER "
      "FROM "
        "ARCHIVE_FILE "
      "WHERE "
        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
        "DISK_FILE_USER = :DISK_FILE_USER";
747
748
749
750
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName);
    stmt.bindString(":DISK_FILE_USER", diskFileUser);
    auto rset = stmt.executeQuery();
751
    return rset.next();
752
753
  } catch(exception::UserError &) {
    throw;
754
755
756
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
757
758
759
  }
}

760
761
762
//------------------------------------------------------------------------------
// diskFileGroupExists
//------------------------------------------------------------------------------
763
bool RdbmsCatalogue::diskFileGroupExists(rdbms::Conn &conn, const std::string &diskInstanceName,
764
765
766
767
768
769
770
771
772
773
774
  const std::string &diskFileGroup) const {
  try {
    const char *const sql =
      "SELECT "
        "DISK_INSTANCE_NAME AS DISK_INSTANCE_NAME, "
        "DISK_FILE_GROUP AS DISK_FILE_GROUP "
      "FROM "
        "ARCHIVE_FILE "
      "WHERE "
        "DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
        "DISK_FILE_GROUP = :DISK_FILE_GROUP";
775
776
777
778
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName);
    stmt.bindString(":DISK_FILE_GROUP", diskFileGroup);
    auto rset = stmt.executeQuery();
779
    return rset.next();
780
781
  } catch(exception::UserError &) {
    throw;
782
783
784
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
785
786
787
  }
}

788
789
790
//------------------------------------------------------------------------------
// archiveRouteExists
//------------------------------------------------------------------------------
791
bool RdbmsCatalogue::archiveRouteExists(rdbms::Conn &conn, const std::string &diskInstanceName,
792
793
794
795
  const std::string &storageClassName, const uint64_t copyNb) const {
  try {
    const char *const sql =
      "SELECT "
796
797
        "ARCHIVE_ROUTE.STORAGE_CLASS_ID AS STORAGE_CLASS_ID,"
        "ARCHIVE_ROUTE.COPY_NB AS COPY_NB "
798
799
      "FROM "
        "ARCHIVE_ROUTE "
800
801
      "INNER JOIN STORAGE_CLASS ON "
        "ARCHIVE_ROUTE.STORAGE_CLASS_ID = STORAGE_CLASS.STORAGE_CLASS_ID "
802
      "WHERE "
803
804
805
        "STORAGE_CLASS.DISK_INSTANCE_NAME = :DISK_INSTANCE_NAME AND "
        "STORAGE_CLASS.STORAGE_CLASS_NAME = :STORAGE_CLASS_NAME AND "
        "ARCHIVE_ROUTE.COPY_NB = :COPY_NB";
806
807
808
809
810
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    stmt.bindString(":DISK_INSTANCE_NAME", diskInstanceName);
    stmt.bindString(":STORAGE_CLASS_NAME", storageClassName);
    stmt.bindUint64(":COPY_NB", copyNb);
    auto rset = stmt.executeQuery();
811
    return rset.next();
812
813
  } catch(exception::UserError &) {
    throw;
814
815
816
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
817
818
819
  }
}

820
821
822
//------------------------------------------------------------------------------
// deleteTapePool
//------------------------------------------------------------------------------
823
void RdbmsCatalogue::deleteTapePool(const std::string &name) {
824
  try {
825
    const char *const sql = "DELETE FROM TAPE_POOL WHERE TAPE_POOL_NAME = :TAPE_POOL_NAME";
826
    auto conn = m_connPool.getConn();
827
828
829
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
    stmt.bindString(":TAPE_POOL_NAME", name);
    stmt.executeNonQuery();
830

831
    if(0 == stmt.getNbAffectedRows()) {
832
      throw exception::UserError(std::string("Cannot delete tape-pool ") + name + " because it does not exist");
833
    }
834
  } catch(exception::UserError &) {
835
    throw;
836
837
838
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
839
  }
Steven Murray's avatar
Steven Murray committed
840
}
841
842
843
844

//------------------------------------------------------------------------------
// getTapePools
//------------------------------------------------------------------------------
845
std::list<TapePool> RdbmsCatalogue::getTapePools() const {
Steven Murray's avatar
Steven Murray committed
846
  try {
847
    std::list<TapePool> pools;
Steven Murray's avatar
Steven Murray committed
848
849
    const char *const sql =
      "SELECT "
850
        "TAPE_POOL.TAPE_POOL_NAME AS TAPE_POOL_NAME,"
851
        "COALESCE(TAPE_POOL.VO, 'NONE') AS VO," // TBD Remove COALESCE
852
853
        "TAPE_POOL.NB_PARTIAL_TAPES AS NB_PARTIAL_TAPES,"
        "TAPE_POOL.IS_ENCRYPTED AS IS_ENCRYPTED,"
Steven Murray's avatar
Steven Murray committed
854

855
        "COALESCE(COUNT(TAPE.VID), 0) AS NB_TAPES,"
856
857
        "COALESCE(SUM(CAPACITY_IN_BYTES), 0) AS CAPACITY_IN_BYTES,"
        "COALESCE(SUM(DATA_IN_BYTES), 0) AS DATA_IN_BYTES,"
Steven Murray's avatar
Steven Murray committed
858

859
        "TAPE_POOL.USER_COMMENT AS USER_COMMENT,"
Steven Murray's avatar
Steven Murray committed
860

861
862
863
864
865
866
867
        "TAPE_POOL.CREATION_LOG_USER_NAME AS CREATION_LOG_USER_NAME,"
        "TAPE_POOL.CREATION_LOG_HOST_NAME AS CREATION_LOG_HOST_NAME,"
        "TAPE_POOL.CREATION_LOG_TIME AS CREATION_LOG_TIME,"

        "TAPE_POOL.LAST_UPDATE_USER_NAME AS LAST_UPDATE_USER_NAME,"
        "TAPE_POOL.LAST_UPDATE_HOST_NAME AS LAST_UPDATE_HOST_NAME,"
        "TAPE_POOL.LAST_UPDATE_TIME AS LAST_UPDATE_TIME "
868
      "FROM "
869
        "TAPE_POOL "
870
871
872
873
      "LEFT OUTER JOIN TAPE ON "
        "TAPE_POOL.TAPE_POOL_NAME = TAPE.TAPE_POOL_NAME "
      "GROUP BY "
        "TAPE_POOL.TAPE_POOL_NAME,"
874
        "TAPE_POOL.VO,"
875
876
877
878
879
880
881
882
883
        "TAPE_POOL.NB_PARTIAL_TAPES,"
        "TAPE_POOL.IS_ENCRYPTED,"
        "TAPE_POOL.USER_COMMENT,"
        "TAPE_POOL.CREATION_LOG_USER_NAME,"
        "TAPE_POOL.CREATION_LOG_HOST_NAME,"
        "TAPE_POOL.CREATION_LOG_TIME,"
        "TAPE_POOL.LAST_UPDATE_USER_NAME,"
        "TAPE_POOL.LAST_UPDATE_HOST_NAME,"
        "TAPE_POOL.LAST_UPDATE_TIME "
884
885
      "ORDER BY "
        "TAPE_POOL_NAME";
886

887
    auto conn = m_connPool.getConn();
888
889
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::OFF);
    auto rset = stmt.executeQuery();
890
    while (rset.next()) {
891
      TapePool pool;
Steven Murray's avatar
Steven Murray committed
892

893
      pool.name = rset.columnString("TAPE_POOL_NAME");
894
      pool.vo = rset.columnString("VO");
895
896
      pool.nbPartialTapes = rset.columnUint64("NB_PARTIAL_TAPES");
      pool.encryption = rset.columnBool("IS_ENCRYPTED");
897
      pool.nbTapes = rset.columnUint64("NB_TAPES");
898
899
      pool.capacityBytes = rset.columnUint64("CAPACITY_IN_BYTES");
      pool.dataBytes = rset.columnUint64("DATA_IN_BYTES");
900
901
902
903
904
905
906
      pool.comment = rset.columnString("USER_COMMENT");
      pool.creationLog.username = rset.columnString("CREATION_LOG_USER_NAME");
      pool.creationLog.host = rset.columnString("CREATION_LOG_HOST_NAME");
      pool.creationLog.time = rset.columnUint64("CREATION_LOG_TIME");
      pool.lastModificationLog.username = rset.columnString("LAST_UPDATE_USER_NAME");
      pool.lastModificationLog.host = rset.columnString("LAST_UPDATE_HOST_NAME");
      pool.lastModificationLog.time = rset.columnUint64("LAST_UPDATE_TIME");
Steven Murray's avatar
Steven Murray committed
907
908

      pools.push_back(pool);
909
910
    }

Steven Murray's avatar
Steven Murray committed
911
    return pools;
912
913
  } catch(exception::UserError &) {
    throw;
914
915
916
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
917
918
919
  }
}

920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
//------------------------------------------------------------------------------
// modifyTapePoolVO
//------------------------------------------------------------------------------
void RdbmsCatalogue::modifyTapePoolVo(const common::dataStructures::SecurityIdentity &admin,
  const std::string &name, const std::string &vo) {
  try {
    if(vo.empty()) {
      throw UserSpecifiedAnEmptyStringVo(std::string("Cannot modify tape pool ") + name +
        " because the new VO is an empty string");
    }

    const time_t now = time(nullptr);
    const char *const sql =
      "UPDATE TAPE_POOL SET "
        "VO = :VO,"
        "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME = :LAST_UPDATE_TIME "
      "WHERE "
        "TAPE_POOL_NAME = :TAPE_POOL_NAME";
    auto conn = m_connPool.getConn();
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
    stmt.bindString(":VO", vo);
    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
    stmt.bindUint64(":LAST_UPDATE_TIME", now);
    stmt.bindString(":TAPE_POOL_NAME", name);
    stmt.executeNonQuery();

    if(0 == stmt.getNbAffectedRows()) {
      throw exception::UserError(std::string("Cannot modify tape pool ") + name + " because it does not exist");
    }
  } catch(exception::UserError &) {
    throw;
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
  }
}

960
961
962
//------------------------------------------------------------------------------
// modifyTapePoolNbPartialTapes
//------------------------------------------------------------------------------
Steven Murray's avatar
Steven Murray committed
963
void RdbmsCatalogue::modifyTapePoolNbPartialTapes(const common::dataStructures::SecurityIdentity &admin,
964
965
966
967
968
969
970
971
972
973
974
975
  const std::string &name, const uint64_t nbPartialTapes) {
  try {
    const time_t now = time(nullptr);
    const char *const sql =
      "UPDATE TAPE_POOL SET "
        "NB_PARTIAL_TAPES = :NB_PARTIAL_TAPES,"
        "LAST_UPDATE_USER_NAME = :LAST_UPDATE_USER_NAME,"
        "LAST_UPDATE_HOST_NAME = :LAST_UPDATE_HOST_NAME,"
        "LAST_UPDATE_TIME = :LAST_UPDATE_TIME "
      "WHERE "
        "TAPE_POOL_NAME = :TAPE_POOL_NAME";
    auto conn = m_connPool.getConn();
976
977
978
979
980
981
982
983
984
    auto stmt = conn.createStmt(sql, rdbms::AutocommitMode::ON);
    stmt.bindUint64(":NB_PARTIAL_TAPES", nbPartialTapes);
    stmt.bindString(":LAST_UPDATE_USER_NAME", admin.username);
    stmt.bindString(":LAST_UPDATE_HOST_NAME", admin.host);
    stmt.bindUint64(":LAST_UPDATE_TIME", now);
    stmt.bindString(":TAPE_POOL_NAME", name);
    stmt.executeNonQuery();

    if(0 == stmt.getNbAffectedRows()) {
985
986
987
988
      throw exception::UserError(std::string("Cannot modify tape pool ") + name + " because it does not exist");
    }
  } catch(exception::UserError &) {
    throw;
989
990
991
  } catch(exception::Exception &ex) {
    ex.getMessage().str(std::string(__FUNCTION__) + ": " + ex.getMessage().str());
    throw;
992
  }
Steven Murray's avatar
Steven Murray committed
993
}
994
995
996
997

//------------------------------------------------------------------------------
// modifyTapePoolComment
//------------------------------------------------------------------------------
998
999
void RdbmsCatalogue::modifyTapePoolComment(const common::dataStructures::SecurityIdentity &admin,
  const std::string &name, const std::string &comment) {
1000
  try {
For faster browsing, not all history is shown. View entire blame