Annotation of parser3/src/main/pa_sql_driver_manager.C, revision 1.5
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.5 ! paf 8: $Id: pa_sql_driver_manager.C,v 1.4 2001/04/05 11:01: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:
1.3 paf 27:
28: /// Services_for_SQL_driver implementation
29: class Services_for_SQL_driver_impl : public Services_for_SQL_driver, public Pooled {
30: public:
31: Services_for_SQL_driver_impl(Pool& apool, const String& aurl) : Pooled(apool),
32: furl(aurl) {
33: }
34:
35: /// allocates some bytes on pool
36: void *malloc(size_t size) { return Pooled::malloc(size); }
37: /// allocates some bytes clearing them with zeros
38: void *calloc(size_t size) { return Pooled::calloc(size); }
39: /// throw exception
40: void _throw(const char *comment) {
41: THROW(0, 0,
42: &furl,
43: comment);
44: }
45:
46: private:
47: const String& furl;
48: };
49:
50: // SQL_Driver_manager
51:
1.1 paf 52: // url:
53: // protocol://user:pass@host:port/database
54: // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this is driver-dependent
55: SQL_Connection& SQL_Driver_manager::get_connection(const String& url,
56: Table *protocol2library) {
57: SYNCHRONIZED(true);
58:
59: Pool& pool=url.pool(); // request pool
60:
61: // we have table for locating protocol's library
62: if(!protocol2library)
63: PTHROW(0, 0,
64: &url,
65: "SQL:drivers table must be defined");
66:
67: // first trying to get cached connection
68: if(SQL_Connection *result=get_connection_from_cache(url))
1.5 ! paf 69: if(result->ping())
! 70: return *result;
! 71: else
! 72: result->disconnect(); // kill unpingabe=dead connection
1.1 paf 73: // no cached connection
74:
75: int pos=url.pos("://", 3);
76: if(pos<0)
77: PTHROW(0, 0,
78: &url,
79: "no protocol specified"); // NOTE: not THROW, but PTHROW
80:
81: // make url string on global pool
82: char *url_cstr=(char *)malloc(MAX_STRING);
83: strncpy(url_cstr, url.cstr(String::UL_AS_IS), MAX_STRING);
84:
85: char *protocol_cstr=lsplit(&url_cstr, ':');
86: String& protocol=*new(this->pool()) String(this->pool(), protocol_cstr);
87:
88: // skip // after :
89: while(*url_cstr=='/')
90: url_cstr++;
91:
92: SQL_Driver *driver;
93: // first trying to get cached driver
94: if(!(driver=get_driver_from_cache(protocol))) {
95: // no cached
96: const String *library=0;
97: if(protocol2library->locate(0, protocol)) {
1.2 paf 98: if(!(library=protocol2library->item(1)) || library->size()==0)
1.1 paf 99: PTHROW(0, 0,
100: protocol2library->origin_string(),
101: "library column for protocol '%s' is empty", protocol_cstr);
102: } else
103: PTHROW(0, 0,
1.2 paf 104: &url,
105: "undefined protocol '%s'", protocol_cstr);
1.1 paf 106:
107: const char *filename=library->cstr(String::UL_FILE_NAME);
1.2 paf 108: lt_dlhandle handle=lt_dlopen(filename);
1.1 paf 109: if (!handle)
110: PTHROW(0, 0,
111: library,
112: "can not open the module, %s", lt_dlerror());
113:
114: SQL_Driver_create_func create=(SQL_Driver_create_func)lt_dlsym(handle,
115: LIBRARY_CREATE_FUNC_NAME);
116: if(!create)
117: PTHROW(0, 0,
118: library,
119: "function '%s' was not found", LIBRARY_CREATE_FUNC_NAME);
120:
1.2 paf 121: // create library-driver!
1.1 paf 122: driver=(*create)();
123:
124: // validate driver api version
125: int driver_api_version=driver->api_version();
1.3 paf 126: if(driver_api_version<SQL_DRIVER_API_VERSION)
1.1 paf 127: PTHROW(0, 0,
128: library,
129: "driver API version is 0x%04X while current minimum is 0x%04X",
1.3 paf 130: driver_api_version, SQL_DRIVER_API_VERSION);
1.1 paf 131:
132: // cache it
133: put_driver_to_cache(protocol, *driver);
134: }
135:
1.4 paf 136: // services associated with request
1.3 paf 137: Services_for_SQL_driver_impl& services=
138: *new(pool) Services_for_SQL_driver_impl(pool, url);
139:
1.4 paf 140: // allocate in global pool
141: // associate with services[request], deassociates at close
1.3 paf 142: SQL_Connection& result=
143: *new(this->pool()) SQL_Connection(this->pool(), url, *driver, services, url_cstr);
144:
145: return result;
1.1 paf 146: }
147:
148: void SQL_Driver_manager::close_connection(const String& url,
149: SQL_Connection& connection) {
150: SYNCHRONIZED(true);
151:
152: put_connection_to_cache(url, connection);
153: }
154:
155:
156: // driver cache
157:
158: SQL_Driver *SQL_Driver_manager::get_driver_from_cache(const String& protocol) {
159: if(SQL_Driver *result=static_cast<SQL_Driver *>(driver_cache.get(protocol)))
160: return result;
161:
162: return 0;
163: }
164:
165: void SQL_Driver_manager::put_driver_to_cache(const String& protocol,
166: SQL_Driver& driver) {
167: driver_cache.put(protocol, &driver);
168: }
169:
170: // connection cache
171:
172: SQL_Connection *SQL_Driver_manager::get_connection_from_cache(const String& url) {
173: if(Stack *connections=static_cast<Stack *>(connection_cache.get(url)))
174: if(connections->size()) // there are cached connections to that 'url'
175: return static_cast<SQL_Connection *>(connections->pop());
176:
177: return 0;
178: }
179:
1.2 paf 180: /// @todo cache expiration[use SQL_Driver::disconnect], pinging.
1.1 paf 181: void SQL_Driver_manager::put_connection_to_cache(const String& url,
182: SQL_Connection& connection) {
183: Stack *connections;
184: if(!(connections=static_cast<Stack *>(connection_cache.get(url)))) {
185: // there are no cached connections to that 'url' yet
186: connections=NEW Stack(pool()); // NOTE: never freed up!
187: connection_cache.put(url, connections);
188: }
189: connections->push(&connection);
190: }
E-mail: