Annotation of parser3/src/main/pa_sql_driver_manager.C, revision 1.2
1.1 paf 1: /** @file
2: Parser: sql driver manager implementation.
3:
4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
5:
6: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
7:
1.2 ! paf 8: $Id: pa_sql_driver_manager.C,v 1.1 2001/04/04 10:53:57 paf Exp $
1.1 paf 9: */
10:
11: #include "pa_config_includes.h"
12: #include "ltdl.h"
13: #include "pa_sql_driver_manager.h"
1.2 ! paf 14: #include "pa_sql_connection.h"
1.1 paf 15: #include "pa_exception.h"
16: #include "pa_common.h"
17:
18: // globals
19:
20: SQL_Driver_manager *SQL_driver_manager;
21:
22: // consts
23:
24: const int MAX_PROTOCOL=20;
25: const char *LIBRARY_CREATE_FUNC_NAME="create";
26:
27: // url:
28: // protocol://user:pass@host:port/database
29: // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is driver-dependent
30: SQL_Connection& SQL_Driver_manager::get_connection(const String& url,
31: Table *protocol2library) {
32: SYNCHRONIZED(true);
33:
34: Pool& pool=url.pool(); // request pool
35:
36: // we have table for locating protocol's library
37: if(!protocol2library)
38: PTHROW(0, 0,
39: &url,
40: "SQL:drivers table must be defined");
41:
42: // first trying to get cached connection
43: if(SQL_Connection *result=get_connection_from_cache(url))
44: return *result;
45: // no cached connection
46:
47: int pos=url.pos("://", 3);
48: if(pos<0)
49: PTHROW(0, 0,
50: &url,
51: "no protocol specified"); // NOTE: not THROW, but PTHROW
52:
53: // make url string on global pool
54: char *url_cstr=(char *)malloc(MAX_STRING);
55: strncpy(url_cstr, url.cstr(String::UL_AS_IS), MAX_STRING);
56:
57: char *protocol_cstr=lsplit(&url_cstr, ':');
58: String& protocol=*new(this->pool()) String(this->pool(), protocol_cstr);
59:
60: // skip // after :
61: while(*url_cstr=='/')
62: url_cstr++;
63:
64: SQL_Driver *driver;
65: // first trying to get cached driver
66: if(!(driver=get_driver_from_cache(protocol))) {
67: // no cached
68: const String *library=0;
69: if(protocol2library->locate(0, protocol)) {
1.2 ! paf 70: if(!(library=protocol2library->item(1)) || library->size()==0)
1.1 paf 71: PTHROW(0, 0,
72: protocol2library->origin_string(),
73: "library column for protocol '%s' is empty", protocol_cstr);
74: } else
75: PTHROW(0, 0,
1.2 ! paf 76: &url,
! 77: "undefined protocol '%s'", protocol_cstr);
1.1 paf 78:
79: const char *filename=library->cstr(String::UL_FILE_NAME);
1.2 ! paf 80: lt_dlhandle handle=lt_dlopen(filename);
1.1 paf 81: if (!handle)
82: PTHROW(0, 0,
83: library,
84: "can not open the module, %s", lt_dlerror());
85:
86: SQL_Driver_create_func create=(SQL_Driver_create_func)lt_dlsym(handle,
87: LIBRARY_CREATE_FUNC_NAME);
88: if(!create)
89: PTHROW(0, 0,
90: library,
91: "function '%s' was not found", LIBRARY_CREATE_FUNC_NAME);
92:
1.2 ! paf 93: // create library-driver!
1.1 paf 94: driver=(*create)();
95:
96: // validate driver api version
97: int driver_api_version=driver->api_version();
1.2 ! paf 98: if(driver_api_version<SQL_API_VERSION)
1.1 paf 99: PTHROW(0, 0,
100: library,
101: "driver API version is 0x%04X while current minimum is 0x%04X",
102: driver_api_version, SQL_API_VERSION);
103:
104: // cache it
105: put_driver_to_cache(protocol, *driver);
106: }
107:
108: return *new(this->pool()) SQL_Connection(url.pool(), //< associate with request
1.2 ! paf 109: *driver, url_cstr, url);
1.1 paf 110: }
111:
112: void SQL_Driver_manager::close_connection(const String& url,
113: SQL_Connection& connection) {
114: SYNCHRONIZED(true);
115:
116: connection.set_pool(0); // deassociate from request
117: put_connection_to_cache(url, connection);
118: }
119:
120:
121: // driver cache
122:
123: SQL_Driver *SQL_Driver_manager::get_driver_from_cache(const String& protocol) {
124: if(SQL_Driver *result=static_cast<SQL_Driver *>(driver_cache.get(protocol)))
125: return result;
126:
127: return 0;
128: }
129:
130: void SQL_Driver_manager::put_driver_to_cache(const String& protocol,
131: SQL_Driver& driver) {
132: driver_cache.put(protocol, &driver);
133: }
134:
135: // connection cache
136:
137: SQL_Connection *SQL_Driver_manager::get_connection_from_cache(const String& url) {
138: if(Stack *connections=static_cast<Stack *>(connection_cache.get(url)))
139: if(connections->size()) // there are cached connections to that 'url'
140: return static_cast<SQL_Connection *>(connections->pop());
141:
142: return 0;
143: }
144:
1.2 ! paf 145: /// @todo cache expiration[use SQL_Driver::disconnect], pinging.
1.1 paf 146: void SQL_Driver_manager::put_connection_to_cache(const String& url,
147: SQL_Connection& connection) {
148: Stack *connections;
149: if(!(connections=static_cast<Stack *>(connection_cache.get(url)))) {
150: // there are no cached connections to that 'url' yet
151: connections=NEW Stack(pool()); // NOTE: never freed up!
152: connection_cache.put(url, connections);
153: }
154: connections->push(&connection);
155: }
E-mail: