| 1 | // $Id: oraclebackend.cc,v 1.1 2002/11/27 15:35:52 ahu Exp $ |
|---|
| 2 | |
|---|
| 3 | #include <string> |
|---|
| 4 | #include <map> |
|---|
| 5 | #include <unistd.h> |
|---|
| 6 | #include <stdlib.h> |
|---|
| 7 | #include <ctype.h> |
|---|
| 8 | #include <sys/time.h> |
|---|
| 9 | |
|---|
| 10 | using namespace std; |
|---|
| 11 | |
|---|
| 12 | #include "dns.hh" |
|---|
| 13 | #include "dnsbackend.hh" |
|---|
| 14 | #include "ahuexception.hh" |
|---|
| 15 | #include "logger.hh" |
|---|
| 16 | #include "oraclebackend.hh" |
|---|
| 17 | |
|---|
| 18 | #include <oci.h> |
|---|
| 19 | |
|---|
| 20 | static const char *kDefaultQueries[kNumQueries] = |
|---|
| 21 | { |
|---|
| 22 | // ForwardQuery |
|---|
| 23 | "select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from Records where name = :name and type = :type", |
|---|
| 24 | |
|---|
| 25 | // ForwardQueryByZone |
|---|
| 26 | |
|---|
| 27 | "select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from records where name = :name and type = :type and ZoneId = :id", |
|---|
| 28 | |
|---|
| 29 | // ForwardAnyQuery |
|---|
| 30 | |
|---|
| 31 | "select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from records where name = :name", |
|---|
| 32 | |
|---|
| 33 | // ForwardWildcardQuery |
|---|
| 34 | |
|---|
| 35 | "select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from records where name like :name and type = :type", |
|---|
| 36 | |
|---|
| 37 | // ForwardWildcardAnyQuery |
|---|
| 38 | "select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate,0) from records where name like :name", |
|---|
| 39 | |
|---|
| 40 | // ListQuery |
|---|
| 41 | "select content, TimeToLive, Priority, type, ZoneId, nvl(ChangeDate, 0), name from records where ZoneId = :id" |
|---|
| 42 | }; |
|---|
| 43 | |
|---|
| 44 | static const char* kModuleId = "[OracleBackend] "; |
|---|
| 45 | |
|---|
| 46 | OracleBackend::OracleBackend(const string &suffix) |
|---|
| 47 | { |
|---|
| 48 | setArgPrefix(string("oracle")+suffix); |
|---|
| 49 | dsword err; |
|---|
| 50 | |
|---|
| 51 | if (!getArg("home").empty() && setenv("ORACLE_HOME", getArg("home").c_str(), 1) == -1) { |
|---|
| 52 | throw OracleException("Cannot set ORACLE_HOME"); |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | if (!getArg("sid").empty() && setenv("ORACLE_SID", getArg("sid").c_str(), 1) == -1) { |
|---|
| 56 | throw OracleException("Cannot set ORACLE_SID"); |
|---|
| 57 | } |
|---|
| 58 | |
|---|
| 59 | // |
|---|
| 60 | // Initialize everything in a known state |
|---|
| 61 | // |
|---|
| 62 | |
|---|
| 63 | mEnvironmentHandle = NULL; |
|---|
| 64 | mErrorHandle = NULL; |
|---|
| 65 | mServiceContextHandle = NULL; |
|---|
| 66 | |
|---|
| 67 | for (int i = 0; i < kNumQueries; i++) { |
|---|
| 68 | mStatementHandles[i] = NULL; |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | // Process configuration options |
|---|
| 72 | |
|---|
| 73 | mQueries[0] = getArg("forward-query").c_str(); |
|---|
| 74 | mQueries[1] = getArg("forward-query-by-zone").c_str(); |
|---|
| 75 | mQueries[2] = getArg("forward-any-query").c_str(); |
|---|
| 76 | mQueries[3] = getArg("forward-wildcard-query").c_str(); |
|---|
| 77 | mQueries[4] = getArg("forward-wildcard-any-query").c_str(); |
|---|
| 78 | mQueries[5] = getArg("list-query").c_str(); |
|---|
| 79 | |
|---|
| 80 | mUpperCase = mustDo("uppercase"); |
|---|
| 81 | mDebugQueries = mustDo("debug-queries"); |
|---|
| 82 | mTimeQueries = mustDo("time-queries"); |
|---|
| 83 | |
|---|
| 84 | if (mTimeQueries == true) { |
|---|
| 85 | mTimeQueriesFile = getArg("time-queries"); |
|---|
| 86 | L << Logger::Error << kModuleId << "Logging SQL query statistics to: " << mTimeQueriesFile << endl; |
|---|
| 87 | mTimeQueriesStream.open(mTimeQueriesFile.c_str(), ios::out | ios::app); |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | try |
|---|
| 91 | { |
|---|
| 92 | // Initialize and create the environment |
|---|
| 93 | |
|---|
| 94 | err = OCIInitialize(OCI_THREADED, 0, NULL, NULL, NULL); |
|---|
| 95 | if (err) { |
|---|
| 96 | throw OracleException("OCIInitialize"); |
|---|
| 97 | } |
|---|
| 98 | |
|---|
| 99 | err = OCIEnvInit(&mEnvironmentHandle, OCI_DEFAULT, 0, 0); |
|---|
| 100 | if (err) { |
|---|
| 101 | throw OracleException("OCIEnvInit"); |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | // Allocate an error handle |
|---|
| 105 | |
|---|
| 106 | err = OCIHandleAlloc(mEnvironmentHandle, (dvoid**) &mErrorHandle, OCI_HTYPE_ERROR, 0, NULL); |
|---|
| 107 | if (err) { |
|---|
| 108 | throw OracleException("OCIHandleAlloc"); |
|---|
| 109 | } |
|---|
| 110 | |
|---|
| 111 | // Logon to the database |
|---|
| 112 | |
|---|
| 113 | const char *username = getArg("username").c_str(); |
|---|
| 114 | const char *password = getArg("password").c_str(); |
|---|
| 115 | const char *database = getArg("database").c_str(); |
|---|
| 116 | |
|---|
| 117 | err = OCILogon(mEnvironmentHandle, mErrorHandle, &mServiceContextHandle, (OraText*) username, strlen(username), |
|---|
| 118 | (OraText*) password, strlen(password), (OraText*) database, strlen(database)); |
|---|
| 119 | |
|---|
| 120 | if (err) { |
|---|
| 121 | throw OracleException(mErrorHandle); |
|---|
| 122 | } |
|---|
| 123 | |
|---|
| 124 | // Allocate the statement handles, and prepare the statements |
|---|
| 125 | |
|---|
| 126 | for (int i = 0; i < kNumQueries; i++) |
|---|
| 127 | { |
|---|
| 128 | err = OCIHandleAlloc(mEnvironmentHandle, (dvoid **) &mStatementHandles[i], OCI_HTYPE_STMT, 0, NULL); |
|---|
| 129 | |
|---|
| 130 | if (err) { |
|---|
| 131 | throw OracleException(mErrorHandle); |
|---|
| 132 | } |
|---|
| 133 | |
|---|
| 134 | err = OCIStmtPrepare(mStatementHandles[i], mErrorHandle, (text*) mQueries[i], strlen(mQueries[i]), |
|---|
| 135 | OCI_NTV_SYNTAX, OCI_DEFAULT); |
|---|
| 136 | |
|---|
| 137 | if (err) { |
|---|
| 138 | throw OracleException(mErrorHandle); |
|---|
| 139 | } |
|---|
| 140 | |
|---|
| 141 | // Bind query arguments |
|---|
| 142 | OCIBind *theBindHandle = NULL; |
|---|
| 143 | |
|---|
| 144 | // Only the kListQuery and kForwardQueryByZone have an :id field |
|---|
| 145 | |
|---|
| 146 | if (i == kListQuery || i == kForwardQueryByZone) |
|---|
| 147 | { |
|---|
| 148 | err = OCIBindByName(mStatementHandles[i], &theBindHandle, mErrorHandle, (OraText*) ":id", strlen(":id"), |
|---|
| 149 | (ub1 *) &mQueryId, sizeof(mQueryId), SQLT_INT, NULL, NULL, 0, 0, NULL, OCI_DEFAULT); |
|---|
| 150 | |
|---|
| 151 | if (err) { |
|---|
| 152 | throw OracleException(mErrorHandle); |
|---|
| 153 | } |
|---|
| 154 | } |
|---|
| 155 | |
|---|
| 156 | // For all the other queries, except for kList Query we have more complex bindings |
|---|
| 157 | |
|---|
| 158 | if (i != kListQuery) |
|---|
| 159 | { |
|---|
| 160 | // All queries have a name: field. |
|---|
| 161 | |
|---|
| 162 | if (i < kListQuery) |
|---|
| 163 | { |
|---|
| 164 | err = OCIBindByName(mStatementHandles[i], &theBindHandle, mErrorHandle, (OraText*) ":name", strlen(":name"), |
|---|
| 165 | (ub1 *) mQueryName, sizeof(mQueryName), SQLT_STR, NULL, NULL, 0, 0, NULL, OCI_DEFAULT); |
|---|
| 166 | |
|---|
| 167 | if (err) { |
|---|
| 168 | throw OracleException(mErrorHandle); |
|---|
| 169 | } |
|---|
| 170 | } |
|---|
| 171 | |
|---|
| 172 | // Only these queries have a type: field |
|---|
| 173 | |
|---|
| 174 | if (i == kForwardQuery || i == kForwardQueryByZone || i == kForwardWildcardQuery ) |
|---|
| 175 | { |
|---|
| 176 | err = OCIBindByName(mStatementHandles[i], &theBindHandle, mErrorHandle, (OraText*) ":type", strlen(":type"), |
|---|
| 177 | (ub1 *) mQueryType, sizeof(mQueryType), SQLT_STR, NULL, NULL, 0, 0, NULL, OCI_DEFAULT); |
|---|
| 178 | |
|---|
| 179 | if (err) { |
|---|
| 180 | throw OracleException(mErrorHandle); |
|---|
| 181 | } |
|---|
| 182 | } |
|---|
| 183 | } |
|---|
| 184 | |
|---|
| 185 | // Define the output |
|---|
| 186 | OCIDefine *theDefineHandle; |
|---|
| 187 | |
|---|
| 188 | mResultContentIndicator = mResultTTLIndicator = mResultPriorityIndicator = mResultTypeIndicator |
|---|
| 189 | = mResultDomainIdIndicator = mResultChangeDateIndicator = 0; |
|---|
| 190 | |
|---|
| 191 | theDefineHandle = NULL; |
|---|
| 192 | err = OCIDefineByPos(mStatementHandles[i], &theDefineHandle, mErrorHandle, 1, mResultContent, |
|---|
| 193 | sizeof(mResultContent) - 1, SQLT_STR, (dvoid*) &mResultContentIndicator, NULL, NULL, OCI_DEFAULT); |
|---|
| 194 | |
|---|
| 195 | if (err) { |
|---|
| 196 | throw OracleException(mErrorHandle); |
|---|
| 197 | } |
|---|
| 198 | |
|---|
| 199 | theDefineHandle = NULL; |
|---|
| 200 | err = OCIDefineByPos(mStatementHandles[i], &theDefineHandle, mErrorHandle, 2, &mResultTTL, |
|---|
| 201 | sizeof(mResultTTL), SQLT_INT, (dvoid*) &mResultTTLIndicator, NULL, NULL, OCI_DEFAULT); |
|---|
| 202 | |
|---|
| 203 | if (err) { |
|---|
| 204 | throw OracleException(mErrorHandle); |
|---|
| 205 | } |
|---|
| 206 | theDefineHandle = NULL; |
|---|
| 207 | err = OCIDefineByPos(mStatementHandles[i], &theDefineHandle, mErrorHandle, 3, &mResultPriority, |
|---|
| 208 | sizeof(mResultPriority), SQLT_INT, (dvoid*) &mResultPriorityIndicator, NULL, NULL, OCI_DEFAULT); |
|---|
| 209 | |
|---|
| 210 | if (err) { |
|---|
| 211 | throw OracleException(mErrorHandle); |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | theDefineHandle = NULL; |
|---|
| 215 | err = OCIDefineByPos(mStatementHandles[i], &theDefineHandle, mErrorHandle, 4, mResultType, |
|---|
| 216 | sizeof(mResultType) - 1, SQLT_STR, (dvoid*) &mResultTypeIndicator, NULL, NULL, OCI_DEFAULT); |
|---|
| 217 | |
|---|
| 218 | if (err) { |
|---|
| 219 | throw OracleException(mErrorHandle); |
|---|
| 220 | } |
|---|
| 221 | |
|---|
| 222 | theDefineHandle = NULL; |
|---|
| 223 | err = OCIDefineByPos(mStatementHandles[i], &theDefineHandle, mErrorHandle, 5, &mResultDomainId, |
|---|
| 224 | sizeof(mResultDomainId), SQLT_INT, (dvoid*) &mResultDomainIdIndicator, NULL, NULL, OCI_DEFAULT); |
|---|
| 225 | |
|---|
| 226 | if (err) { |
|---|
| 227 | throw OracleException(mErrorHandle); |
|---|
| 228 | } |
|---|
| 229 | |
|---|
| 230 | theDefineHandle = NULL; |
|---|
| 231 | err = OCIDefineByPos(mStatementHandles[i], &theDefineHandle, mErrorHandle, 6, &mResultChangeDate, |
|---|
| 232 | sizeof(mResultChangeDate), SQLT_INT, (dvoid*) &mResultChangeDateIndicator, NULL, NULL, OCI_DEFAULT); |
|---|
| 233 | |
|---|
| 234 | if (err) { |
|---|
| 235 | throw OracleException(mErrorHandle); |
|---|
| 236 | } |
|---|
| 237 | |
|---|
| 238 | if (i == kListQuery) |
|---|
| 239 | { |
|---|
| 240 | theDefineHandle = NULL; |
|---|
| 241 | err = OCIDefineByPos(mStatementHandles[i], &theDefineHandle, mErrorHandle, 7, mResultName, |
|---|
| 242 | sizeof(mResultName) - 1, SQLT_STR, (dvoid*) &mResultNameIndicator, NULL, NULL, OCI_DEFAULT); |
|---|
| 243 | |
|---|
| 244 | if (err) { |
|---|
| 245 | throw OracleException(mErrorHandle); |
|---|
| 246 | } |
|---|
| 247 | } |
|---|
| 248 | } |
|---|
| 249 | |
|---|
| 250 | } |
|---|
| 251 | |
|---|
| 252 | catch (OracleException &theException) |
|---|
| 253 | { |
|---|
| 254 | L << Logger::Error << kModuleId << "Connection to database failed: " << theException.Reason() << endl; |
|---|
| 255 | // Cleanup(); |
|---|
| 256 | throw AhuException("Unable to create a connection: " + theException.Reason()); |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | L << Logger::Warning << kModuleId << "Oracle Backend up and running" << endl; |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | OracleBackend::~OracleBackend() |
|---|
| 263 | { |
|---|
| 264 | L << Logger::Warning << kModuleId << "Destructing Oracle Backend" << endl; |
|---|
| 265 | Cleanup(); |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | void OracleBackend::lookup(const QType &qtype,const string &qname, DNSPacket *pkt_p, int zoneId) |
|---|
| 269 | { |
|---|
| 270 | // |
|---|
| 271 | // Choose the right query |
|---|
| 272 | // |
|---|
| 273 | |
|---|
| 274 | int theQueryType = -1; |
|---|
| 275 | |
|---|
| 276 | if (qname[0] == '%') { |
|---|
| 277 | if (qtype.getCode() == 255) { |
|---|
| 278 | theQueryType = kForwardWildcardAnyQuery; |
|---|
| 279 | } else { |
|---|
| 280 | theQueryType = kForwardWildcardQuery; |
|---|
| 281 | } |
|---|
| 282 | } else { |
|---|
| 283 | if (qtype.getCode() == 255) { |
|---|
| 284 | theQueryType = kForwardAnyQuery; |
|---|
| 285 | } else { |
|---|
| 286 | if (zoneId != -1) { |
|---|
| 287 | theQueryType = kForwardQueryByZone; |
|---|
| 288 | } else { |
|---|
| 289 | theQueryType = kForwardQuery; |
|---|
| 290 | } |
|---|
| 291 | } |
|---|
| 292 | } |
|---|
| 293 | |
|---|
| 294 | |
|---|
| 295 | // Fill in the correct query parameters |
|---|
| 296 | |
|---|
| 297 | if (mDebugQueries) { |
|---|
| 298 | printf(">>> executing query: %s\n", mQueries[theQueryType]); |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | switch (theQueryType) |
|---|
| 302 | { |
|---|
| 303 | case kForwardQuery: |
|---|
| 304 | case kForwardWildcardQuery: |
|---|
| 305 | strncpy(mQueryName, qname.c_str(), sizeof(mQueryName)); |
|---|
| 306 | strncpy(mQueryType, qtype.getName().c_str(), sizeof(mQueryType)); |
|---|
| 307 | if (mDebugQueries) { |
|---|
| 308 | printf(">>> :name = '%s' :type = '%s'\n", mQueryName, mQueryType); |
|---|
| 309 | } |
|---|
| 310 | break; |
|---|
| 311 | |
|---|
| 312 | case kForwardQueryByZone: |
|---|
| 313 | strncpy(mQueryName, qname.c_str(), sizeof(mQueryName)); |
|---|
| 314 | strncpy(mQueryType, qtype.getName().c_str(), sizeof(mQueryType)); |
|---|
| 315 | mQueryId = zoneId; |
|---|
| 316 | if (mDebugQueries) { |
|---|
| 317 | printf(">>> :name = '%s' :type = '%s' :id = '%d'\n", mQueryName, mQueryType, mQueryId); |
|---|
| 318 | } |
|---|
| 319 | break; |
|---|
| 320 | |
|---|
| 321 | case kForwardAnyQuery: |
|---|
| 322 | case kForwardWildcardAnyQuery: |
|---|
| 323 | strncpy(mQueryName, qname.c_str(), sizeof(mQueryName)); |
|---|
| 324 | if (mDebugQueries) { |
|---|
| 325 | printf(">>> :name = '%s'\n", mQueryName); |
|---|
| 326 | } |
|---|
| 327 | break; |
|---|
| 328 | |
|---|
| 329 | } |
|---|
| 330 | |
|---|
| 331 | if(mUpperCase == true) { |
|---|
| 332 | char *p = mQueryName; |
|---|
| 333 | while (*p != 0x00) { |
|---|
| 334 | *p++ = std::toupper(*p); |
|---|
| 335 | } |
|---|
| 336 | } |
|---|
| 337 | |
|---|
| 338 | // Execute the query |
|---|
| 339 | |
|---|
| 340 | struct timeval theStartTime; |
|---|
| 341 | |
|---|
| 342 | if (mTimeQueries == true) { |
|---|
| 343 | gettimeofday(&theStartTime, NULL); |
|---|
| 344 | } |
|---|
| 345 | |
|---|
| 346 | try |
|---|
| 347 | { |
|---|
| 348 | mActiveQuery = theQueryType; |
|---|
| 349 | |
|---|
| 350 | mQueryResult = OCIStmtExecute(mServiceContextHandle, mStatementHandles[theQueryType], mErrorHandle, 1, 0, |
|---|
| 351 | (OCISnapshot *)NULL, (OCISnapshot*) NULL, OCI_DEFAULT); |
|---|
| 352 | |
|---|
| 353 | if (mQueryResult != OCI_SUCCESS && mQueryResult != OCI_SUCCESS_WITH_INFO && mQueryResult != OCI_NO_DATA) { |
|---|
| 354 | throw OracleException(mErrorHandle); |
|---|
| 355 | } |
|---|
| 356 | } |
|---|
| 357 | |
|---|
| 358 | catch (OracleException &theException) |
|---|
| 359 | { |
|---|
| 360 | L << Logger::Error << kModuleId << "Execute failed: " << theException.Reason() << endl; |
|---|
| 361 | throw AhuException("Execute failed: " + theException.Reason()); |
|---|
| 362 | } |
|---|
| 363 | |
|---|
| 364 | if (mTimeQueries == true) |
|---|
| 365 | { |
|---|
| 366 | struct timeval theTime; |
|---|
| 367 | |
|---|
| 368 | gettimeofday(&theTime, NULL); |
|---|
| 369 | |
|---|
| 370 | double theDifference = theTime.tv_sec - theStartTime.tv_sec |
|---|
| 371 | + (theTime.tv_usec - theStartTime.tv_usec) / 1000000.0; |
|---|
| 372 | |
|---|
| 373 | mTimeQueriesStream << theTime.tv_sec << "." << theTime.tv_sec << "\t" << theQueryType << "\t" |
|---|
| 374 | << theDifference << endl; |
|---|
| 375 | } |
|---|
| 376 | } |
|---|
| 377 | |
|---|
| 378 | bool OracleBackend::list(int domain_id) |
|---|
| 379 | { |
|---|
| 380 | mQueryId = domain_id; |
|---|
| 381 | |
|---|
| 382 | if (mDebugQueries) { |
|---|
| 383 | printf(">>> executing query: %s\n", mQueries[kListQuery]); |
|---|
| 384 | printf(">>> :id = '%d'\n", mQueryId); |
|---|
| 385 | } |
|---|
| 386 | |
|---|
| 387 | mActiveQuery = kListQuery; |
|---|
| 388 | |
|---|
| 389 | try |
|---|
| 390 | { |
|---|
| 391 | mQueryResult = OCIStmtExecute(mServiceContextHandle, mStatementHandles[kListQuery], mErrorHandle, 1, 0, |
|---|
| 392 | (OCISnapshot *)NULL, (OCISnapshot*) NULL, OCI_DEFAULT); |
|---|
| 393 | |
|---|
| 394 | if (mQueryResult != OCI_SUCCESS && mQueryResult != OCI_SUCCESS_WITH_INFO && mQueryResult != OCI_NO_DATA) { |
|---|
| 395 | throw OracleException(mErrorHandle); |
|---|
| 396 | } |
|---|
| 397 | } |
|---|
| 398 | |
|---|
| 399 | catch (OracleException &theException) |
|---|
| 400 | { |
|---|
| 401 | L << Logger::Error << kModuleId << "Execute failed: " << theException.Reason() << endl; |
|---|
| 402 | throw AhuException("Execute failed: " + theException.Reason()); |
|---|
| 403 | } |
|---|
| 404 | |
|---|
| 405 | return true; |
|---|
| 406 | } |
|---|
| 407 | |
|---|
| 408 | bool OracleBackend::get(DNSResourceRecord &theRecord) |
|---|
| 409 | { |
|---|
| 410 | if (mQueryResult == OCI_NO_DATA) |
|---|
| 411 | return false; |
|---|
| 412 | |
|---|
| 413 | theRecord.content = mResultContent; |
|---|
| 414 | theRecord.ttl = mResultTTL; |
|---|
| 415 | theRecord.priority = mResultPriority; |
|---|
| 416 | theRecord.qtype = mResultType; |
|---|
| 417 | theRecord.domain_id = mResultDomainId; |
|---|
| 418 | theRecord.last_modified = mResultChangeDate; |
|---|
| 419 | |
|---|
| 420 | // use this to distinguish between select with 'name' field (list()) and one without |
|---|
| 421 | |
|---|
| 422 | if (mActiveQuery != kListQuery) { |
|---|
| 423 | theRecord.qname = mQueryName; |
|---|
| 424 | } else { |
|---|
| 425 | theRecord.qname = mResultName; |
|---|
| 426 | } |
|---|
| 427 | |
|---|
| 428 | // Try to fetch the next one. We look at the result the next time we're being |
|---|
| 429 | // called. |
|---|
| 430 | |
|---|
| 431 | try |
|---|
| 432 | { |
|---|
| 433 | mQueryResult = OCIStmtFetch(mStatementHandles[mActiveQuery], mErrorHandle, 1, 0, 0); |
|---|
| 434 | if (mQueryResult != OCI_SUCCESS && mQueryResult != OCI_SUCCESS_WITH_INFO && mQueryResult != OCI_NO_DATA) { |
|---|
| 435 | new OracleException(mErrorHandle); // ? - ahu |
|---|
| 436 | } |
|---|
| 437 | } |
|---|
| 438 | catch (OracleException &theException) |
|---|
| 439 | { |
|---|
| 440 | L << Logger::Error << kModuleId << "Fetch failed: " << theException.Reason() << endl; |
|---|
| 441 | throw AhuException("Execute failed: " + theException.Reason()); |
|---|
| 442 | } |
|---|
| 443 | |
|---|
| 444 | return true; |
|---|
| 445 | } |
|---|
| 446 | |
|---|
| 447 | void OracleBackend::Cleanup() |
|---|
| 448 | { |
|---|
| 449 | sword theError; |
|---|
| 450 | |
|---|
| 451 | L << Logger::Warning << kModuleId << "Cleaning up Oracle Backend" << endl; |
|---|
| 452 | |
|---|
| 453 | if (mTimeQueries == true) { |
|---|
| 454 | mTimeQueriesStream.close(); |
|---|
| 455 | } |
|---|
| 456 | |
|---|
| 457 | for (int i = 0; i < kNumQueries; i++) { |
|---|
| 458 | if (mStatementHandles[i] != NULL) { |
|---|
| 459 | OCIHandleFree(mStatementHandles[i], OCI_HTYPE_STMT); |
|---|
| 460 | mStatementHandles[i] = NULL; |
|---|
| 461 | } |
|---|
| 462 | } |
|---|
| 463 | |
|---|
| 464 | if (mServiceContextHandle != NULL) { |
|---|
| 465 | theError = OCILogoff(mServiceContextHandle, mErrorHandle); |
|---|
| 466 | if (theError != 0) { |
|---|
| 467 | L << Logger::Warning << kModuleId << "OCILogoff returned a error (" << theError << ")" << endl; |
|---|
| 468 | } |
|---|
| 469 | } |
|---|
| 470 | |
|---|
| 471 | /* |
|---|
| 472 | #if DITHOEFTNIETMEERNAEENOCILOGOFF |
|---|
| 473 | if (mServiceContextHandle != NULL) { |
|---|
| 474 | OCIHandleFree(mServiceContextHandle, OCI_HTYPE_SVCCTX); |
|---|
| 475 | mServiceContextHandle = NULL; |
|---|
| 476 | } |
|---|
| 477 | #endif |
|---|
| 478 | */ |
|---|
| 479 | |
|---|
| 480 | if (mErrorHandle != NULL) { |
|---|
| 481 | OCIHandleFree(mErrorHandle, OCI_HTYPE_ERROR); |
|---|
| 482 | mErrorHandle = NULL; |
|---|
| 483 | } |
|---|
| 484 | |
|---|
| 485 | if (mEnvironmentHandle != NULL) { |
|---|
| 486 | OCIHandleFree(mEnvironmentHandle, OCI_HTYPE_ENV); |
|---|
| 487 | mEnvironmentHandle = NULL; |
|---|
| 488 | } |
|---|
| 489 | } |
|---|
| 490 | |
|---|
| 491 | |
|---|
| 492 | class OracleFactory : public BackendFactory |
|---|
| 493 | { |
|---|
| 494 | public: |
|---|
| 495 | OracleFactory() : BackendFactory("oracle") {} |
|---|
| 496 | |
|---|
| 497 | void declareArguments(const string &suffix="") |
|---|
| 498 | { |
|---|
| 499 | declare(suffix,"debug-queries","Debugging output","no"); |
|---|
| 500 | declare(suffix,"time-queries","Output query timings to a file","no"); |
|---|
| 501 | declare(suffix,"uppercase","Uppercase database","no"); |
|---|
| 502 | declare(suffix,"database","Database to connect to","powerdns"); |
|---|
| 503 | declare(suffix,"username","Username to connect as","powerdns"); |
|---|
| 504 | declare(suffix,"password","Password to connect with",""); |
|---|
| 505 | declare(suffix,"home","Set and override ORACLE_HOME from within PDNS",""); |
|---|
| 506 | declare(suffix,"sid","Set and override ORACLE_SID from within PDNS",""); |
|---|
| 507 | |
|---|
| 508 | declare(suffix, "forward-query", "", kDefaultQueries[0]); |
|---|
| 509 | declare(suffix, "forward-query-by-zone", "", kDefaultQueries[1]); |
|---|
| 510 | declare(suffix, "forward-any-query", "", kDefaultQueries[2]); |
|---|
| 511 | declare(suffix, "forward-wildcard-query", "", kDefaultQueries[3]); |
|---|
| 512 | declare(suffix, "forward-wildcard-any-query", "", kDefaultQueries[4]); |
|---|
| 513 | declare(suffix, "list-query", "", kDefaultQueries[5]); |
|---|
| 514 | } |
|---|
| 515 | |
|---|
| 516 | DNSBackend *make(const string &suffix="") |
|---|
| 517 | { |
|---|
| 518 | try { |
|---|
| 519 | return new OracleBackend(suffix); |
|---|
| 520 | } |
|---|
| 521 | catch(...) {} |
|---|
| 522 | return 0; |
|---|
| 523 | } |
|---|
| 524 | }; |
|---|
| 525 | |
|---|
| 526 | |
|---|
| 527 | //! Magic class that is activated when the dynamic library is loaded |
|---|
| 528 | class OracleLoader |
|---|
| 529 | { |
|---|
| 530 | public: |
|---|
| 531 | |
|---|
| 532 | //! This reports us to the main UeberBackend class |
|---|
| 533 | |
|---|
| 534 | OracleLoader() |
|---|
| 535 | { |
|---|
| 536 | BackendMakers().report(new OracleFactory); |
|---|
| 537 | L << Logger::Warning << kModuleId << "Oracle Backend loaded." << endl; |
|---|
| 538 | } |
|---|
| 539 | |
|---|
| 540 | }; |
|---|
| 541 | static OracleLoader loader; |
|---|