OcciConn.cpp 5.67 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 "common/exception/Exception.hpp"
20
21
22
23
#include "common/make_unique.hpp"
#include "rdbms/OcciConn.hpp"
#include "rdbms/OcciEnv.hpp"
#include "rdbms/OcciStmt.hpp"
24
25
26

#include <stdexcept>
#include <string>
27

28
namespace cta {
29
namespace rdbms {
30

31
32
33
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
34
OcciConn::OcciConn(oracle::occi::Environment *const env, oracle::occi::Connection *const conn):
35
  m_env(env),
Steven Murray's avatar
Steven Murray committed
36
  m_conn(conn) {
37
  if(nullptr == conn) {
38
    throw exception::Exception(std::string(__FUNCTION__) + " failed"
39
      ": The OCCI connection is a nullptr pointer");
Steven Murray's avatar
Steven Murray committed
40
  }
41
42
43
44
45
46
47

  try {
    const std::string sql = "ALTER SESSION SET recyclebin = OFF";
    executeNonQuery(sql, Stmt::AutocommitMode::OFF);
  } catch(exception::Exception &ex) {
    throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
  }
48
49
50
51
52
}

//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
53
OcciConn::~OcciConn() throw() {
54
55
56
57
58
59
60
61
62
63
  try {
    close(); // Idempotent close() mthod
  } catch(...) {
    // Destructor should not throw any exceptions
  }
}

//------------------------------------------------------------------------------
// close
//------------------------------------------------------------------------------
64
void OcciConn::close() {
65
66
  std::lock_guard<std::mutex> lock(m_mutex);

67
  if(m_conn != nullptr) {
68
    m_env->terminateConnection(m_conn);
69
    m_conn = nullptr;
70
71
72
73
74
75
  }
}

//------------------------------------------------------------------------------
// get
//------------------------------------------------------------------------------
76
oracle::occi::Connection *OcciConn::get() const {
77
78
79
80
81
82
  return m_conn;
}

//------------------------------------------------------------------------------
// operator->()
//------------------------------------------------------------------------------
83
oracle::occi::Connection *OcciConn::operator->() const {
84
85
86
87
88
89
  return get();
}

//------------------------------------------------------------------------------
// createStmt
//------------------------------------------------------------------------------
90
std::unique_ptr<Stmt> OcciConn::createStmt(const std::string &sql, Stmt::AutocommitMode autocommitMode) {
91
  try {
92
    return cta::make_unique<OcciStmt>(autocommitMode, sql, *this);
93
94
95
96
97
  } catch(exception::Exception &ex) {
    throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + sql + ": " +
      ex.getMessage().str());
  } catch(std::exception &se) {
    throw exception::Exception(std::string(__FUNCTION__) + " failed for SQL statement " + sql + ": " + se.what());
98
  }
99
}
100

101
102
103
104
//------------------------------------------------------------------------------
// commit
//------------------------------------------------------------------------------
void OcciConn::commit() {
105
106
107
108
109
  try {
    m_conn->commit();
  } catch(std::exception &se) {
    throw exception::Exception(std::string(__FUNCTION__) + " failed: " + se.what());
  }
110
111
112
}

//------------------------------------------------------------------------------
113
// rollback
114
115
//------------------------------------------------------------------------------
void OcciConn::rollback() {
116
117
118
119
120
  try {
    m_conn->rollback();
  } catch(std::exception &se) {
    throw exception::Exception(std::string(__FUNCTION__) + " failed: " + se.what());
  }
121
122
}

Steven Murray's avatar
Steven Murray committed
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//------------------------------------------------------------------------------
// getTableNames
//------------------------------------------------------------------------------
std::list<std::string> OcciConn::getTableNames() {
  try {
    std::list<std::string> names;
    const char *const sql =
      "SELECT "
        "TABLE_NAME "
      "FROM "
        "USER_TABLES "
      "ORDER BY "
        "TABLE_NAME";
    auto stmt = createStmt(sql, rdbms::Stmt::AutocommitMode::OFF);
    auto rset = stmt->executeQuery();
    while (rset->next()) {
      names.push_back(rset->columnString("TABLE_NAME"));
    }

    return names;
  } catch(exception::Exception &ex) {
    throw exception::Exception(std::string(__FUNCTION__) + " failed: " + ex.getMessage().str());
  }
}

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//------------------------------------------------------------------------------
// updateHealth
//------------------------------------------------------------------------------
void OcciConn::updateHealth(const oracle::occi::SQLException &ex) {
  using namespace oracle;

  // Error codes that identify an unhealthy connection
  // The majority of these error codes were learnt from CASTOR
  switch(ex.getErrorCode()) {
  case    28:
  case  1003:
  case  1008:
  case  1012:
  case  1033:
  case  1089:
  case  2392:
  case  2399:
  case  3113:
  case  3114:
  case  3135:
  case 12170:
  case 12541:
  case 12571:
  case 24338:
  case 12537:
  case 25401:
  case 25409:
  case 32102:
    setHealthy(false);
    break;
  default:
    break;
  };
}

183
} // namespace rdbms
184
} // namespace cta