| 195 | } |
| 196 | |
| 197 | Connection* Manager::getConnection(thread_db* tdbb, const string& dataSource, |
| 198 | const string& user, const string& pwd, const string& role, TraScope tra_scope) |
| 199 | { |
| 200 | Attachment* att = tdbb->getAttachment(); |
| 201 | if (att->att_ext_call_depth >= MAX_CALLBACKS) |
| 202 | ERR_post(Arg::Gds(isc_exec_sql_max_call_exceeded)); |
| 203 | |
| 204 | string prvName; |
| 205 | PathName dbName; |
| 206 | splitDataSourceName(tdbb, dataSource, prvName, dbName); |
| 207 | |
| 208 | Provider* prv = getProvider(prvName); |
| 209 | |
| 210 | const bool isCurrentAtt = (prvName == INTERNAL_PROVIDER_NAME) && |
| 211 | isCurrentAccount(att->att_user, user, pwd, role); |
| 212 | |
| 213 | ClumpletWriter dpb(ClumpletReader::dpbList, MAX_DPB_SIZE); |
| 214 | if (!isCurrentAtt) |
| 215 | prv->generateDPB(tdbb, dpb, user, pwd, role); |
| 216 | |
| 217 | // look up at connections already bound to current attachment |
| 218 | Connection* conn = prv->getBoundConnection(tdbb, dbName, dpb, tra_scope, isCurrentAtt); |
| 219 | if (conn) |
| 220 | return conn; |
| 221 | |
| 222 | // if could be pooled, ask connections pool |
| 223 | |
| 224 | // Ensure pool is created |
| 225 | getConnPool(true); |
| 226 | |
| 227 | ULONG hash = 0; |
| 228 | |
| 229 | if (!isCurrentAtt) |
| 230 | { |
| 231 | CryptHash ch(att->att_crypt_callback); |
| 232 | hash = DefaultHash<UCHAR>::hash(dbName.c_str(), dbName.length(), MAX_ULONG) + |
| 233 | DefaultHash<UCHAR>::hash(dpb.getBuffer(), dpb.getBufferLength(), MAX_ULONG) + |
| 234 | (ch.isValid() ? DefaultHash<UCHAR>::hash(ch.getValue(), ch.getLength(), MAX_ULONG) : 0); |
| 235 | |
| 236 | while (true) |
| 237 | { |
| 238 | conn = m_connPool->getConnection(tdbb, prv, hash, dbName, dpb, ch); |
| 239 | if (!conn) |
| 240 | break; |
| 241 | |
| 242 | if (conn->validate(tdbb)) |
| 243 | { |
| 244 | prv->bindConnection(tdbb, conn); |
| 245 | conn->resetRedirect(att->att_crypt_callback); |
| 246 | break; |
| 247 | } |
| 248 | |
| 249 | // destroy invalid connection |
| 250 | m_connPool->delConnection(tdbb, conn, true); |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | if (!conn) |
no test coverage detected