OraVdqmSvc.cpp 103 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/******************************************************************************
 *
 * This file is part of the Castor project.
 * See http://castor.web.cern.ch/castor
 *
 * Copyright (C) 2003  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 2
 * 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 *
20
 * @author Castor Dev team, castor-dev@cern.ch
21
22
 *****************************************************************************/

23
#include "castor/BaseAddress.hpp"
24
#include "castor/Constants.hpp"
25
26
#include "castor/IFactory.hpp"
#include "castor/SvcFactory.hpp"
27
#include "castor/db/DbCnvSvc.hpp"
28
#include "castor/exception/InvalidArgument.hpp"
29
30
#include "castor/db/ora/OraCnvSvc.hpp"
#include "castor/db/ora/OraStatement.hpp"
31
32
33
#include "castor/db/ora/OraVdqmSvc.hpp"
#include "castor/vdqm/ClientIdentification.hpp"
#include "castor/vdqm/VdqmTape.hpp"
34
35
#include "castor/vdqm/TapeAccessSpecification.hpp"
#include "castor/vdqm/DeviceGroupName.hpp"
36
#include "castor/vdqm/TapeDrive.hpp"
37
#include "castor/vdqm/TapeDriveCompatibility.hpp"
38
39
#include "castor/vdqm/TapeRequest.hpp"
#include "castor/vdqm/TapeServer.hpp"
40
41
42
43
#include "Cuuid.h"
#include "net.h"
#include "serrno.h"
#include "vdqm_constants.h"
44

45
#include <occi.h>
46
#include <errno.h>
47
#include <memory>
Steven Murray's avatar
Steven Murray committed
48
#include <string.h>
49
50
51
52
53


// -----------------------------------------------------------------------
// Instantiation of a static factory class
// -----------------------------------------------------------------------
54
55
static castor::SvcFactory<castor::db::ora::OraVdqmSvc>
  s_factoryOraVdqmSvc;
56

57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// -----------------------------------------------------------------------
// Static map of SQL statement strings
// -----------------------------------------------------------------------
castor::db::ora::OraVdqmSvc::StatementStringMap
  castor::db::ora::OraVdqmSvc::s_statementStrings;


// -----------------------------------------------------------------------
// StatementStringMap::StatementStringMap
// -----------------------------------------------------------------------
castor::db::ora::OraVdqmSvc::StatementStringMap::StatementStringMap() {
  addStmtStr(SELECT_TAPE_SQL_STMT,
    "SELECT id FROM VdqmTape WHERE vid = :1 FOR UPDATE");
  addStmtStr(SELECT_TAPE_SERVER_SQL_STMT,
    "SELECT id FROM TapeServer WHERE serverName = :1 FOR UPDATE");
  addStmtStr(CHECK_TAPE_REQUEST1_SQL_STMT,
    "SELECT"
    "  id "
    "FROM"
    "  ClientIdentification "
    "WHERE"
    "      ClientIdentification.machine = :1"
    "  AND userName = :2"
    "  AND port = :3"
    "  AND euid = :4"
    "  AND egid = :5"
    "  AND magic = :6");
  addStmtStr(CHECK_TAPE_REQUEST2_SQL_STMT,
    "SELECT"
    "  id "
    "FROM"
    "  TapeRequest "
    "WHERE"
    "      TapeRequest.tapeAccessSpecification = :1"
    "  AND TapeRequest.tape = :2"
    "  AND TapeRequest.requestedSrv = :3"
    "  AND TapeRequest.client = :4");
  addStmtStr(GET_QUEUE_POSITION_SQL_STMT,
    "SELECT"
    "  count(*) "
    "FROM"
    "  TapeRequest tr1,"
    "  TapeRequest tr2 "
    "WHERE"
    "      tr1.id = :1 "
    "  AND tr1.deviceGroupName = tr2.deviceGroupName"
    "  AND tr2.modificationTime <= tr1.modificationTime");
  addStmtStr(SET_VOL_PRIORITY_SQL_STMT,
    "BEGIN castorVdqm.setVolPriority(:1, :2, :3, :4, :5, :6, :7); END;");
  addStmtStr(DELETE_VOL_PRIORITY_SQL_STMT,
    "BEGIN castorVdqm.deleteVolPriority(:1, :2, :3, :4, :5, :6, :7, :8); END;");
108
109
  addStmtStr(DELETE_OLD_VOL_PRIORITIES_SQL_STMT,
    "BEGIN castorVdqm.deleteOldVolPriorities(:1, :2); END;");
110
  addStmtStr(GET_ALL_VOL_PRIORITIES_SQL_STMT,
111
112
113
114
115
116
117
118
119
120
121
122
    "SELECT"
    "  priority,"
    "  clientUID,"
    "  clientGID,"
    "  clientHost,"
    "  vid,"
    "  tpMode,"
    "  lifespanType,"
    "  id,"
    "  creationTime,"
    "  modificationTime "
    "FROM"
123
    "  VolumePriority "
124
    "ORDER BY"
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    "  vid, tpMode, lifespanType");
  addStmtStr(GET_EFFECTIVE_VOL_PRIORITIES_SQL_STMT,
    "SELECT"
    "  priority,"
    "  clientUID,"
    "  clientGID,"
    "  clientHost,"
    "  vid,"
    "  tpMode,"
    "  lifespanType,"
    "  id,"
    "  creationTime,"
    "  modificationTime "
    "FROM"
    "  EffectiveVolumePriority_VIEW "
    "ORDER BY"
    "  vid, tpMode");
  addStmtStr(GET_VOL_PRIORITIES_SQL_STMT,
    "SELECT"
    "  priority,"
    "  clientUID,"
    "  clientGID,"
    "  clientHost,"
    "  vid,"
    "  tpMode,"
    "  lifespanType,"
    "  id,"
    "  creationTime,"
    "  modificationTime "
    "FROM"
    "  VolumePriority "
    "WHERE"
    "  lifespanType = :1 "
    "ORDER BY"
    "  vid, tpMode, lifespanType");
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
  addStmtStr(SELECT_TAPE_DRIVE_SQL_STMT,
    "SELECT"
    "  id "
    "FROM"
    "  TapeDrive "
    "WHERE"
    "      driveName = :1"
    "  AND tapeServer = :2 "
    "FOR UPDATE");
  addStmtStr(DEDICATE_DRIVE_SQL_STMT,
    "BEGIN castorVdqm.dedicateDrive(:1, :2, :3, :4); END;");
  addStmtStr(DELETE_DRIVE_SQL_STMT,
    "BEGIN castorVdqm.deleteDrive(:1, :2, :3, :4); END;");
  addStmtStr(WRITE_RTCPD_JOB_SUBMISSION_SQL_STMT,
    "BEGIN castorVdqm.writeRTPCDJobSubmission(:1, :2, :3); END;");
  addStmtStr(WRITE_FAILED_RTCPD_JOB_SUBMISSION_SQL_STMT,
    "BEGIN castorVdqm.writeFailedRTPCDJobSubmission(:1, :2, :3); END;");
  addStmtStr(EXIST_TAPE_DRIVE_WITH_TAPE_IN_USE_SQL_STMT,
    "SELECT"
    "  td.id "
    "FROM"
    "  TapeDrive td,"
    "  TapeRequest tr,"
    "  VdqmTape "
    "WHERE"
    "      td.runningTapeReq = tr.id"
    "  AND tr.tape = VdqmTape.id"
    "  AND VdqmTape.vid = :1");
  addStmtStr(EXIST_TAPE_DRIVE_WITH_TAPE_MOUNTED_SQL_STMT,
    "SELECT"
    "  td.id "
    "FROM"
    "  TapeDrive td,"
    "  VdqmTape "
    "WHERE"
    "      td.tape = VdqmTape.id"
    "  AND VdqmTape.vid = :1");
  addStmtStr(SELECT_TAPE_BY_VID_SQL_STMT,
    "SELECT id FROM VdqmTape WHERE vid = :1");
  addStmtStr(SELECT_TAPE_REQ_FOR_MOUNTED_TAPE_SQL_STMT,
    "SELECT"
    "  id "
    "FROM"
    "  TapeRequest "
    "WHERE"
    "      tapeDrive = 0"
    "  AND tape = :1"
    "  AND (requestedSrv = :2"
    "   OR requestedSrv = 0) "
    "FOR UPDATE");
  addStmtStr(SELECT_TAPE_ACCESS_SPECIFICATION_SQL_STMT,
    "SELECT"
    "  id "
    "FROM"
    "  TapeAccessSpecification "
    "WHERE"
    "      accessMode = :1"
    "  AND density = :2"
    "  AND tapeModel = :3");
  addStmtStr(SELECT_DEVICE_GROUP_NAME_SQL_STMT,
    "SELECT id FROM DeviceGroupName WHERE dgName = :1");
221
  addStmtStr(SELECT_VOL_REQS_DGN_CREATION_TIME_ORDER_SQL_STMT,
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
    "SELECT"
    "  id,"
    "  driveName,"
    "  tapeDriveId,"
    "  priority,"
    "  clientPort,"
    "  clientEuid,"
    "  clientEgid,"
    "  accessMode,"
    "  creationTime,"
    "  clientMachine,"
    "  vid,"
    "  tapeServer,"
    "  dgName,"
    "  clientUsername "
    "FROM"
    "  tapeRequestShowqueues_VIEW "
    "WHERE"
    "      (:1 IS NULL OR :2 = dgName)"
241
242
    "  AND (:3 IS NULL OR :4 = tapeServer) "
    "ORDER BY"
243
    "  dgName ASC,"
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
    "  creationTime ASC");
  addStmtStr(SELECT_VOL_REQS_PRIORITY_ORDER_SQL_STMT,
    "SELECT"
    "  id,"
    "  driveName,"
    "  tapeDriveId,"
    "  priority,"
    "  clientPort,"
    "  clientEuid,"
    "  clientEgid,"
    "  accessMode,"
    "  creationTime,"
    "  clientMachine,"
    "  vid,"
    "  tapeServer,"
    "  dgName,"
    "  clientUsername,"
261
262
    "  volumePriority,"
    "  remoteCopyType "
263
264
265
266
267
268
269
270
271
    "FROM"
    "  tapeRequestShowqueues_VIEW "
    "WHERE"
    "      (:1 IS NULL OR :2 = dgName)"
    "  AND (:3 IS NULL OR :4 = tapeServer) "
    "ORDER BY"
    "  accessMode DESC,"
    "  volumePriority DESC,"
    "  creationTime ASC");
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
  addStmtStr(SELECT_TAPE_DRIVE_QUEUE_SQL_STMT,
    "SELECT"
    "  status,"
    "  id,"
    "  runningTapeReq,"
    "  jobId,"
    "  modificationTime,"
    "  resetTime,"
    "  useCount,"
    "  errCount,"
    "  transferredMB,"
    "  tapeAccessMode,"
    "  totalMB,"
    "  serverName,"
    "  vid,"
    "  driveName,"
    "  DGName,"
    "  dedicate "
    "FROM"
    "  TapeDriveShowqueues_VIEW "
    "WHERE"
    "      (:1 IS NULL OR :2 = DGName)"
    "  AND (:3 IS NULL OR :4 = serverName)");
295
296
  addStmtStr(SELECT_TAPE_REQUEST_SQL_STMT,
    "SELECT id FROM TapeRequest WHERE CAST(id AS INT) = :1");
297
298
  addStmtStr(SELECT_TAPE_REQUEST_FOR_UPDATE_SQL_STMT,
    "SELECT id FROM TapeRequest WHERE CAST(id AS INT) = :1 FOR UPDATE");
299
300
301
302
303
304
305
306
307
308
309
310
311
312
  addStmtStr(SELECT_COMPATIBILITIES_FOR_DRIVE_MODEL_SQL_STMT,
    "SELECT id FROM TapeDriveCompatibility WHERE tapeDriveModel = :1");
  addStmtStr(SELECT_TAPE_ACCESS_SPECIFICATIONS_SQL_STMT,
    "SELECT"
    "  id "
    "FROM"
    "  TapeAccessSpecification "
    "WHERE"
    "  tapeModel = :1 "
    "ORDER BY"
    "  accessMode DESC");
  addStmtStr(ALLOCATE_DRIVE_SQL_STMT,
    "BEGIN castorVdqm.allocateDrive(:1, :2, :3, :4, :5); END;");
  addStmtStr(REUSE_DRIVE_ALLOCATION_SQL_STMT,
313
    "BEGIN castorVdqm.reuseDriveAllocation(:1, :2, :3, :4, :5); END;");
314
315
  addStmtStr(REQUEST_TO_SUBMIT_SQL_STMT,
    "BEGIN castorVdqm.getRequestToSubmit(:1); END;");
316
317
318
319
320
321
  addStmtStr(REQUEST_SUBMITTED_SQL_STMT,
    "BEGIN castorVdqm.requestSubmitted(:1, :2, :3, :4, :5, :6, :7, :8, :9, "
    ":10, :11, :12, :13); END;");
  addStmtStr(RESET_DRIVE_AND_REQUEST_SQL_STMT,
    "BEGIN castorVdqm.resetDriveAndRequest(:1, :2, :3, :4, :5, :6, :7, :8, "
    ":9, :10, :11, :12); END;");
322
323
324
325
326
327
328
329
330
331
}


// -----------------------------------------------------------------------
// StatementStringMap::addStmtStr
// -----------------------------------------------------------------------
void castor::db::ora::OraVdqmSvc::StatementStringMap::addStmtStr(
  const StatementId stmtId, const char *stmt) {
  insert(std::make_pair(stmtId, stmt));
}
332

333
334
335
336
337

// -----------------------------------------------------------------------
// OraVdqmSvc
// -----------------------------------------------------------------------
castor::db::ora::OraVdqmSvc::OraVdqmSvc(const std::string name) :
338
  BaseSvc(name), DbBaseObj(0) {
339
  registerToCnvSvc(this);
340
341
342
343
344
345
346
}


// -----------------------------------------------------------------------
// ~OraVdqmSvc
// -----------------------------------------------------------------------
castor::db::ora::OraVdqmSvc::~OraVdqmSvc() throw() {
347
  unregisterFromCnvSvc(this);
348
349
350
351
352
353
  reset();
}

// -----------------------------------------------------------------------
// id
// -----------------------------------------------------------------------
354
unsigned int castor::db::ora::OraVdqmSvc::id() const {
355
356
357
358
359
360
  return ID();
}

// -----------------------------------------------------------------------
// ID
// -----------------------------------------------------------------------
361
unsigned int castor::db::ora::OraVdqmSvc::ID() {
362
363
364
365
366
367
368
  return castor::SVC_ORAVDQMSVC;
}

//------------------------------------------------------------------------------
// reset
//------------------------------------------------------------------------------
void castor::db::ora::OraVdqmSvc::reset() throw() {
369
370
  // Call upper level reset
  this->castor::BaseSvc::reset();
371
372
  this->castor::db::DbBaseObj::reset();

373
  // Here we attempt to delete the statements correctly
374
  // If something goes wrong, we just ignore it
375
376
377
378
  for(std::map<int, oracle::occi::Statement *>::iterator itor =
    m_statements.begin(); itor != m_statements.end(); itor++) {
    try {
      deleteStatement(itor->second);
379
    } catch(castor::exception::Exception &e) {
380
381
382
383
384
      // Do nothing
    }
  }
  // Reset the stored statements
  m_statements.clear();
385
386
387
}


388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
// -----------------------------------------------------------------------
// commit
// -----------------------------------------------------------------------
void castor::db::ora::OraVdqmSvc::commit() {
  DbBaseObj::commit();
}


// -----------------------------------------------------------------------
// rollback
// -----------------------------------------------------------------------
void castor::db::ora::OraVdqmSvc::rollback() {
  DbBaseObj::rollback();
}


404
// -----------------------------------------------------------------------
Steven Murray's avatar
Steven Murray committed
405
// selectOrCreateTape
406
407
// -----------------------------------------------------------------------
castor::vdqm::VdqmTape*
408
castor::db::ora::OraVdqmSvc::selectOrCreateTape(const std::string vid)
409
   {
410
411
412

  // Get the Statement object, creating one if necessary
  oracle::occi::Statement *stmt = NULL;
413
414
  const StatementId stmtId = SELECT_TAPE_SQL_STMT;
  try {
415
416
    if(!(stmt = getStatement(stmtId))) {
      stmt = createStatement(s_statementStrings[stmtId]);
417
      stmt->setAutoCommit(false);
418
419
      storeStatement(stmtId, stmt);
    }
420
421
  } catch(oracle::occi::SQLException &oe) {
    handleException(oe);
422
    castor::exception::Exception ie;
423
424
425
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << oe.getMessage();
    throw ie;
426
  } catch(castor::exception::Exception& e) {
427
    castor::exception::Exception ie;
428
429
430
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << e.getMessage().str();
    throw ie;
431
  }
432

433
  // Execute statement and get result
434
  u_signed64 id;
435
  try {
436
437
    stmt->setString(1, vid);
    oracle::occi::ResultSet *rset = stmt->executeQuery();
438
    if (oracle::occi::ResultSet::END_OF_FETCH == rset->next()) {
439
      stmt->closeResultSet(rset);
440
441
442
443
444
445
446
447
448
449
      // we found nothing, so let's create the tape

      castor::vdqm::VdqmTape* tape = new castor::vdqm::VdqmTape();
      tape->setVid(vid);
      castor::BaseAddress ad;
      ad.setCnvSvcName("DbCnvSvc");
      ad.setCnvSvcType(castor::SVC_DBCNV);
      try {
        cnvSvc()->createRep(&ad, tape, false);
        return tape;
450
      } catch (castor::exception::Exception& e) {
451
        delete tape;
452
453
        // XXX  Change createRep in CodeGenerator to forward the oracle
        // errorcode 
454
455
456
457
458
459
460
        if ( e.getMessage().str().find("ORA-00001", 0) != std::string::npos ) {
          // if violation of unique constraint, ie means that
          // some other thread was quicker than us on the insertion
          // So let's select what was inserted
       
          // set again the parameters

461
          rset = stmt->executeQuery();
462
463
          if (oracle::occi::ResultSet::END_OF_FETCH == rset->next()) {
            // Still nothing ! Here it's a real error
464
            stmt->closeResultSet(rset);
465
            castor::exception::Exception ex;
466
467
468
469
470
471
472
473
            ex.getMessage()
              << "Unable to select tape while inserting "
              << "violated unique constraint :"
              << std::endl << e.getMessage().str();
            throw ex;
          }
        } else {
	  // Else, "standard" error, throw exception
474
	  castor::exception::Exception ex;
475
	  ex.getMessage()
476
	    << "Exception while inserting new tape in the DB:"
477
478
479
480
481
482
483
	    << std::endl << e.getMessage().str();
	  throw ex;
	}
      }
    }
    // If we reach this point, then we selected successfully
    // a tape and it's id is in rset
484
    id = (u_signed64)rset->getDouble(1);
485
    stmt->closeResultSet(rset);
486
487
  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
488
    castor::exception::Exception ie;
489
    ie.getMessage()
490
      << "Unable to select tape by vid :"
491
492
      << std::endl << oe.getMessage();
    throw ie;
493
494
495
496
497
498
499
  }
  // Now get the tape from its id
  try {
    castor::BaseAddress ad;
    ad.setTarget(id);
    ad.setCnvSvcName("DbCnvSvc");
    ad.setCnvSvcType(castor::SVC_DBCNV);
500
    ad.setObjType(castor::OBJ_VdqmTape);
501
502
503
504
    castor::IObject* obj = cnvSvc()->createObj(&ad);
    castor::vdqm::VdqmTape* tape =
      dynamic_cast<castor::vdqm::VdqmTape*> (obj);
    if (0 == tape) {
505
      castor::exception::Exception e;
506
507
508
509
510
511
      e.getMessage() << "createObj return unexpected type "
                     << obj->type() << " for id " << id;
      delete obj;
      throw e;
    }
    return tape;
512
513
  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
514
    castor::exception::Exception ie;
515
516
517
518
    ie.getMessage()
      << "Unable to select tape for id " << id << " :"
      << std::endl << oe.getMessage();
    throw ie;
519
520
521
522
  }
  // We should never reach this point
}

523

524
525
526
527
// -----------------------------------------------------------------------
// selectTapeServer
// -----------------------------------------------------------------------
castor::vdqm::TapeServer* 
528
529
  castor::db::ora::OraVdqmSvc::selectOrCreateTapeServer(
  const std::string serverName, bool withTapeDrives)
530
   {
531
532
533

  // Check if the parameter is empty 
  if(serverName == "") {
534
    return NULL;
535
  }
536
537
538

  // Get the Statement object, creating one if necessary
  oracle::occi::Statement *stmt = NULL;
539
540
  const StatementId stmtId = SELECT_TAPE_SERVER_SQL_STMT;
  try {
541
542
    if(!(stmt = getStatement(stmtId))) {
      stmt = createStatement(s_statementStrings[stmtId]);
543
      stmt->setAutoCommit(false);
544
545
      storeStatement(stmtId, stmt);
    }
546
547
  } catch(oracle::occi::SQLException &oe) {
    handleException(oe);
548
    castor::exception::Exception ie;
549
550
551
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << oe.getMessage();
    throw ie;
552
  } catch(castor::exception::Exception& e) {
553
    castor::exception::Exception ie;
554
555
556
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << e.getMessage().str();
    throw ie;
557
558
  }

559
  // Execute statement and get result
560
  u_signed64 id;
561
  try {
562
563
    stmt->setString(1, serverName);
    oracle::occi::ResultSet *rset = stmt->executeQuery();
564
565
    
    if (oracle::occi::ResultSet::END_OF_FETCH == rset->next()) {
566
      stmt->closeResultSet(rset);
567
      
Matthias Braeger's avatar
Matthias Braeger committed
568
      // we found nothing, so let's create the tape sever
569
570
571
      castor::vdqm::TapeServer* tapeServer = new castor::vdqm::TapeServer();
      tapeServer->setServerName(serverName);
      castor::BaseAddress ad;
572
573
      ad.setCnvSvcName("DbCnvSvc");
      ad.setCnvSvcType(castor::SVC_DBCNV);
574
575
576
      try {
        cnvSvc()->createRep(&ad, tapeServer, false);
        return tapeServer;
577
578
      } catch (oracle::occi::SQLException &oe) {
        handleException(oe);
579
        delete tapeServer;
580
        if (1 == oe.getErrorCode()) {
581
582
583
          // if violation of unique constraint, ie means that
          // some other thread was quicker than us on the insertion
          // So let's select what was inserted
584
          rset = stmt->executeQuery();
585
586
          if (oracle::occi::ResultSet::END_OF_FETCH == rset->next()) {
            // Still nothing ! Here it's a real error
587
            stmt->closeResultSet(rset);
588
            castor::exception::Exception ex;
589
590
591
            ex.getMessage()
              << "Unable to select tapeServer while inserting "
              << "violated unique constraint :"
592
              << std::endl << oe.getMessage();
593
594
595
            throw ex;
          }
        }
596
        stmt->closeResultSet(rset);
597
        // Else, "standard" error, throw exception
598
        castor::exception::Exception ex;
599
600
        ex.getMessage()
          << "Exception while inserting new tapeServer in the DB :"
601
          << std::endl << oe.getMessage();
602
603
604
605
606
607
        throw ex;
      }
    }
    
    // If we reach this point, then we selected successfully
    // a tapeServer and it's id is in rset
608
    id = (u_signed64)rset->getDouble(1);
609
    stmt->closeResultSet(rset);
610
611
  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
612
    castor::exception::Exception ie;
613
    ie.getMessage()
614
      << "Unable to select tapeServer by vid, side and tpmode :"
615
616
      << std::endl << oe.getMessage();
    throw ie;
617
618
619
620
621
622
  }
  
  // Now get the tapeServer from its id
  try {
    castor::BaseAddress ad;
    ad.setTarget(id);
623
624
    ad.setCnvSvcName("DbCnvSvc");
    ad.setCnvSvcType(castor::SVC_DBCNV);
625
    ad.setObjType(castor::OBJ_TapeServer);
626
627
628
629
630
    castor::IObject* obj = cnvSvc()->createObj(&ad);
    
    castor::vdqm::TapeServer* tapeServer =
      dynamic_cast<castor::vdqm::TapeServer*> (obj);
    if (0 == tapeServer) {
631
      castor::exception::Exception e;
632
633
634
635
636
      e.getMessage() << "createObj return unexpected type "
                     << obj->type() << " for id " << id;
      delete obj;
      throw e;
    }
637
    
Matthias Braeger's avatar
Matthias Braeger committed
638
    if ( withTapeDrives ) {
639
640
      cnvSvc()->fillObj(&ad, obj, castor::OBJ_TapeDrive);
          
641
642
643
644
      // For existing TapeDrives, we want also the corresponding TapeRequest
      for (std::vector<castor::vdqm::TapeDrive*>::iterator it =
        tapeServer->tapeDrives().begin(); it != tapeServer->tapeDrives().end();
        it++) {
645
646
647
648
        if ((*it) != NULL) {
          cnvSvc()->fillObj(&ad, (*it), castor::OBJ_TapeRequest);
        }
      }
Matthias Braeger's avatar
Matthias Braeger committed
649
    }
650
    
651
    // Reset Pointer
652
653
    obj = 0;
    
654
    return tapeServer;
655
656
  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
657
    castor::exception::Exception ie;
658
    ie.getMessage()
659
      << "Unable to select tapeServer for id " << id  << " :"
660
661
      << std::endl << oe.getMessage();
    throw ie;
662
663
  }
  // We should never reach this point
664
665
666
667
668
669
}


// -----------------------------------------------------------------------
// checkTapeRequest
// -----------------------------------------------------------------------
670
bool castor::db::ora::OraVdqmSvc::checkTapeRequest(
671
  const castor::vdqm::TapeRequest *const newTapeRequest) 
672
   {
673

674
675
676
  // Get the Statement objects, creating them if necessary
  oracle::occi::Statement *stmt1 = NULL;
  const StatementId stmtId1 = CHECK_TAPE_REQUEST1_SQL_STMT;
677
  try {
678
679
    if(!(stmt1 = getStatement(stmtId1))) {
      stmt1 = createStatement(s_statementStrings[stmtId1]);
680
      stmt1->setAutoCommit(false);
681
      storeStatement(stmtId1, stmt1);
682
    }
683
684
  } catch(oracle::occi::SQLException &oe) {
    handleException(oe);
685
    castor::exception::Exception ie;
686
687
688
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId1 << ": " << oe.getMessage();
    throw ie;
689
  } catch(castor::exception::Exception& e) {
690
    castor::exception::Exception ie;
691
692
693
694
695
696
697
698
699
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId1 << ": " << e.getMessage().str();
    throw ie;
  }
  oracle::occi::Statement *stmt2 = NULL;
  const StatementId stmtId2 = CHECK_TAPE_REQUEST2_SQL_STMT;
  try {
    if(!(stmt2 = getStatement(stmtId2))) {
      stmt2 = createStatement(s_statementStrings[stmtId2]);
700
      stmt2->setAutoCommit(false);
701
      storeStatement(stmtId2, stmt2);
702
    }
703
704
  } catch(oracle::occi::SQLException &oe) {
    handleException(oe);
705
    castor::exception::Exception ie;
706
707
708
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId2 << ": " << oe.getMessage();
    throw ie;
709
  } catch(castor::exception::Exception& e) {
710
    castor::exception::Exception ie;
711
712
713
714
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId2 << ": " << e.getMessage().str();
    throw ie;
  }
715

716
  try {
717
    castor::vdqm::ClientIdentification *client = newTapeRequest->client();
718
    
719
720
721
722
723
724
    stmt1->setString(1, client->machine());
    stmt1->setString(2, client->userName());
    stmt1->setInt(3, client->port());
    stmt1->setInt(4, client->euid());
    stmt1->setInt(5, client->egid());
    stmt1->setInt(6, client->magic());
725
726
727
    client = 0;
    
    // execute the statement
728
    oracle::occi::ResultSet *rset = stmt1->executeQuery();
729
    if (oracle::occi::ResultSet::END_OF_FETCH == rset->next()) {
730
      // Nothing found
731
      stmt1->closeResultSet(rset);
732
      return true;
733
    }
734
    
735
736
737
738
    // For every found ClientIdentification has to be checked whether
    // a tape request can be found, with the matching values. If yes, 
    // we return false, because we don't want to queue twice the same
    // request!
739
    
740
741
742
743
    stmt2->setDouble(1, newTapeRequest->tapeAccessSpecification()->id());
    stmt2->setDouble(2, newTapeRequest->tape()->id());
    stmt2->setDouble(3, newTapeRequest->requestedSrv() ==
      0 ? 0 : newTapeRequest->requestedSrv()->id());
744
    
745
746
747
    oracle::occi::ResultSet *rset2 = NULL;
    u_signed64 clientId = 0;
    do {
748
749
750
751
      // If we reach this point, then we selected successfully
      // a ClientIdentification and it's id is in rset
      clientId = (u_signed64)rset->getDouble(1);
      
752
753
      stmt2->setDouble(4, clientId);
      rset2 = stmt2->executeQuery();
754
755
      if (oracle::occi::ResultSet::END_OF_FETCH == rset2->next()) {
        // Nothing found
756
        stmt2->closeResultSet(rset2);
757
758
759
      }
      else {
        // We found the same request in the database!
760
761
        stmt1->closeResultSet(rset);
        stmt2->closeResultSet(rset2);
762
763
        return false;
      } 
764
    } while (oracle::occi::ResultSet::END_OF_FETCH != rset->next());
765
    
766
767
    // If we are here, the request doesn't yet exist.
    stmt1->closeResultSet(rset);
768
    return true;
769
770
  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
771
    castor::exception::Exception ie;
772
    ie.getMessage()
773
      << "Error caught in checkTapeRequest."
774
775
      << std::endl << oe.what();
    throw ie;
776
777
778
779
780
781
782
783
784
785
786
  }
  // We should never reach this point.
    
  return true;
}


// -----------------------------------------------------------------------
// getQueuePosition
// -----------------------------------------------------------------------
int castor::db::ora::OraVdqmSvc::getQueuePosition(
787
  const u_signed64 tapeRequestId)  {
788
    
789
790
791
  // Get the Statement object, creating one if necessary
  oracle::occi::Statement *stmt = NULL;
  const StatementId stmtId = GET_QUEUE_POSITION_SQL_STMT;
792
  try {
793
794
    if(!(stmt = getStatement(stmtId))) {
      stmt = createStatement(s_statementStrings[stmtId]);
795
      stmt->setAutoCommit(false);
796
      storeStatement(stmtId, stmt);
797
    }
798
799
  } catch(oracle::occi::SQLException &oe) {
    handleException(oe);
800
    castor::exception::Exception ie;
801
802
803
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << oe.getMessage();
    throw ie;
804
  } catch(castor::exception::Exception& e) {
805
    castor::exception::Exception ie;
806
807
808
809
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << e.getMessage().str();
    throw ie;
  }
810

811
812
  try {
    // Execute the statement
813
814
    stmt->setDouble(1, tapeRequestId);
    oracle::occi::ResultSet *rset = stmt->executeQuery();
815
816
    if (oracle::occi::ResultSet::END_OF_FETCH == rset->next()) {
      // Nothing found, return -1
817
      // Normally, the statement should always find something!
818
      stmt->closeResultSet(rset);
819
      return -1;
820
    }
821
822
    
    // Return the TapeRequest queue position
823
    int queuePosition = (int)rset->getInt(1);
824
    stmt->closeResultSet(rset);
825
    
826
    // XXX: Maybe in future the return value should be double!
827
828
    // -1 means not found
    return queuePosition == 0 ? -1 : queuePosition;
829
830
  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
831
    castor::exception::Exception ie;
832
833
834
    ie.getMessage() << "Error caught in getQueuePosition." << std::endl
      << oe.what();
    throw ie;
835
836
  }
  // We should never reach this point.
837
838
}

839

840
841
842
843
844
// -----------------------------------------------------------------------
// setVolPriority
// -----------------------------------------------------------------------
void castor::db::ora::OraVdqmSvc::setVolPriority(const int priority,
  const int clientUID, const int clientGID, const std::string clientHost,
845
  const std::string vid, const int tpMode, const int lifespanType)
846
   {
847

848
849
850
  // Get the Statement object, creating one if necessary
  oracle::occi::Statement *stmt = NULL;
  const StatementId stmtId = SET_VOL_PRIORITY_SQL_STMT;
851
  try {
852
853
    if(!(stmt = getStatement(stmtId))) {
      stmt = createStatement(s_statementStrings[stmtId]);
854
      stmt->setAutoCommit(false);
855
      storeStatement(stmtId, stmt);
856
    }
857
858
  } catch(oracle::occi::SQLException &oe) {
    handleException(oe);
859
    castor::exception::Exception ie;
860
861
862
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << oe.getMessage();
    throw ie;
863
  } catch(castor::exception::Exception& e) {
864
    castor::exception::Exception ie;
865
866
867
868
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << e.getMessage().str();
    throw ie;
  }
869

870
  try {
871
    // Execute the statement
872
873
874
875
876
877
878
879
880
    stmt->setInt(1, priority);
    stmt->setInt(2, clientUID);
    stmt->setInt(3, clientGID);
    stmt->setString(4, clientHost);
    stmt->setString(5, vid);
    stmt->setInt(6, tpMode);
    stmt->setInt(7, lifespanType);

    stmt->executeUpdate();
881
882
  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
883
    castor::exception::Exception ie;
884
885
886
    ie.getMessage() << "Error caught in setVolPriority." << std::endl
      << oe.what();
    throw ie;
887
  }
888
889
890
}


891
892
893
// -----------------------------------------------------------------------
// deleteVolPriority
// -----------------------------------------------------------------------
894
895
u_signed64 castor::db::ora::OraVdqmSvc::deleteVolPriority(
  const std::string vid, const int tpMode, const int lifespanType,
896
  int *const priority, int *const clientUID, int *const clientGID,
897
  std::string *const clientHost)  {
898

899
900
901
  u_signed64 id = 0;


902
903
904
  // Get the Statement object, creating one if necessary
  oracle::occi::Statement *stmt = NULL;
  const StatementId stmtId = DELETE_VOL_PRIORITY_SQL_STMT;
905
  try {
906
907
908
909
910
911
912
913
    if(!(stmt = getStatement(stmtId))) {
      stmt = createStatement(s_statementStrings[stmtId]);
      stmt->registerOutParam(4, oracle::occi::OCCIDOUBLE); // returnVar
      stmt->registerOutParam(5, oracle::occi::OCCIINT); // priorityVar
      stmt->registerOutParam(6, oracle::occi::OCCIINT); // clientUIDVar
      stmt->registerOutParam(7, oracle::occi::OCCIINT); // clientGIDVar
      stmt->registerOutParam(8, oracle::occi::OCCISTRING,
        2048); // clientHostVar
914
      stmt->setAutoCommit(false);
915
      storeStatement(stmtId, stmt);
916
    }
917
918
  } catch(oracle::occi::SQLException &oe) {
    handleException(oe);
919
    castor::exception::Exception ie;
920
921
922
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << oe.getMessage();
    throw ie;
923
  } catch(castor::exception::Exception& e) {
924
    castor::exception::Exception ie;
925
926
927
928
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << e.getMessage().str();
    throw ie;
  }
929

930
  try {
931
    // Execute the statement
932
933
934
    stmt->setString(1, vid);
    stmt->setInt(2, tpMode);
    stmt->setInt(3, lifespanType);
935

936
    stmt->executeUpdate();
937

938
939
940
941
942
    id          = (u_signed64)stmt->getDouble(4);
    *priority   = stmt->getInt(5);
    *clientUID  = stmt->getInt(6);
    *clientGID  = stmt->getInt(7);
    *clientHost = stmt->getString(8);
943

944
945
  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
946
    castor::exception::Exception ie;
947
948
949
    ie.getMessage() << "Error caught in deleteVolPriority." << std::endl
      << oe.what();
    throw ie;
950
  }
951
952

  return id;
953
954
955
}


956
957
958
959
// -----------------------------------------------------------------------
// deleteOldVolPriorities
// -----------------------------------------------------------------------
unsigned int castor::db::ora::OraVdqmSvc::deleteOldVolPriorities(
960
  const unsigned int maxAge)  {
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976

  unsigned int prioritiesDeletedVar = 0;


  // Get the Statement object, creating one if necessary
  oracle::occi::Statement *stmt = NULL;
  const StatementId stmtId = DELETE_OLD_VOL_PRIORITIES_SQL_STMT;
  try {
    if(!(stmt = getStatement(stmtId))) {
      stmt = createStatement(s_statementStrings[stmtId]);
      stmt->registerOutParam(2, oracle::occi::OCCIINT); // prioritiesDeletedVar
      stmt->setAutoCommit(false);
      storeStatement(stmtId, stmt);
    }
  } catch(oracle::occi::SQLException &oe) {
    handleException(oe);
977
    castor::exception::Exception ie;
978
979
980
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << oe.getMessage();
    throw ie;
981
  } catch(castor::exception::Exception& e) {
982
    castor::exception::Exception ie;
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
    ie.getMessage() << "Failed to get statement object with ID: "
      << stmtId << ": " << e.getMessage().str();
    throw ie;
  }

  try {
    // Execute the statement
    stmt->setInt(1, maxAge);

    stmt->executeUpdate();

    prioritiesDeletedVar = stmt->getInt(2);

  } catch (oracle::occi::SQLException &oe) {
    handleException(oe);
998
    castor::exception::Exception ie;
999
1000
    ie.getMessage() << "Error caught in deleteVolPriority." << std::endl
      << oe.what();
For faster browsing, not all history is shown. View entire blame