Line data Source code
1 : /****************************************************************************** 2 : * File : PostGISRasterDriver.cpp 3 : * Project: PostGIS Raster driver 4 : * Purpose: Implements PostGIS Raster driver class methods 5 : * Author: Jorge Arevalo, jorge.arevalo@deimos-space.com 6 : * 7 : * Last changes: $Id$ 8 : * 9 : ****************************************************************************** 10 : * Copyright (c) 2010, Jorge Arevalo, jorge.arevalo@deimos-space.com 11 : * Copyright (c) 2013, Even Rouault 12 : * 13 : * Permission is hereby granted, free of charge, to any person obtaining a 14 : * copy of this software and associated documentation files (the "Software"), 15 : * to deal in the Software without restriction, including without limitation 16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense, 17 : * and/or sell copies of the Software, and to permit persons to whom the 18 : * Software is furnished to do so, subject to the following conditions: 19 : * 20 : * The above copyright notice and this permission notice shall be included 21 : * in all copies or substantial portions of the Software. 22 : * 23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 29 : * DEALINGS IN THE SOFTWARE. 30 : ******************************************************************************/ 31 : #include "postgisraster.h" 32 : #include "cpl_multiproc.h" 33 : 34 : PostGISRasterDriver *PostGISRasterDriver::gpoPostGISRasterDriver = nullptr; 35 : 36 : /************************ 37 : * \brief Constructor 38 : ************************/ 39 7 : PostGISRasterDriver::PostGISRasterDriver() 40 : { 41 7 : gpoPostGISRasterDriver = this; 42 7 : } 43 : 44 : /************************ 45 : * \brief Destructor 46 : ************************/ 47 8 : PostGISRasterDriver::~PostGISRasterDriver() 48 : { 49 4 : gpoPostGISRasterDriver = nullptr; 50 4 : if (hMutex != nullptr) 51 0 : CPLDestroyMutex(hMutex); 52 4 : std::map<CPLString, PGconn *>::iterator oIter = oMapConnection.begin(); 53 4 : for (; oIter != oMapConnection.end(); ++oIter) 54 0 : PQfinish(oIter->second); 55 8 : } 56 : 57 : /*************************************************************************** 58 : * \brief Create a PQconn object and store it in a list 59 : * 60 : * The PostGIS Raster driver keeps the connection with the PostgreSQL database 61 : * server for as long it leaves. Following PostGISRasterDataset instance 62 : * can re-use the existing connection as long it used the same database, 63 : * same host, port and user name. 64 : * 65 : * The PostGIS Raster driver will keep a list of all the successful 66 : * connections so, when connection is requested and it does not exist 67 : * on the list a new one will be instantiated, added to the list and 68 : * returned to the caller. 69 : * 70 : * All connection will be destroyed when the PostGISRasterDriver is destroyed. 71 : * 72 : ***************************************************************************/ 73 2 : PGconn *PostGISRasterDriver::GetConnection(const char *pszConnectionString, 74 : const char *pszServiceIn, 75 : const char *pszDbnameIn, 76 : const char *pszHostIn, 77 : const char *pszPortIn, 78 : const char *pszUserIn) 79 : { 80 2 : PGconn *poConn = nullptr; 81 : 82 2 : if (pszHostIn == nullptr) 83 0 : pszHostIn = "(null)"; 84 2 : if (pszPortIn == nullptr) 85 0 : pszPortIn = "(null)"; 86 2 : if (pszUserIn == nullptr) 87 0 : pszUserIn = "(null)"; 88 4 : CPLString osKey = (pszServiceIn == nullptr) ? pszDbnameIn : pszServiceIn; 89 2 : osKey += "-"; 90 2 : osKey += pszHostIn; 91 2 : osKey += "-"; 92 2 : osKey += pszPortIn; 93 2 : osKey += "-"; 94 2 : osKey += pszUserIn; 95 2 : osKey += "-"; 96 2 : osKey += CPLSPrintf(CPL_FRMT_GIB, CPLGetPID()); 97 : 98 : /** 99 : * Look for an existing connection in the map 100 : **/ 101 4 : CPLMutexHolderD(&hMutex); 102 2 : std::map<CPLString, PGconn *>::iterator oIter = oMapConnection.find(osKey); 103 2 : if (oIter != oMapConnection.end()) 104 1 : return oIter->second; 105 : 106 : /** 107 : * There's no existing connection. Create a new one. 108 : **/ 109 1 : poConn = PQconnectdb(pszConnectionString); 110 1 : if (poConn == nullptr || PQstatus(poConn) == CONNECTION_BAD) 111 : { 112 0 : CPLError(CE_Failure, CPLE_AppDefined, "PQconnectdb failed: %s\n", 113 : PQerrorMessage(poConn)); 114 0 : PQfinish(poConn); 115 0 : return nullptr; 116 : } 117 : 118 : /** 119 : * Save connection in the connection map. 120 : **/ 121 1 : oMapConnection[osKey] = poConn; 122 1 : return poConn; 123 : }