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: