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 : * 8 : ****************************************************************************** 9 : * Copyright (c) 2010, Jorge Arevalo, jorge.arevalo@deimos-space.com 10 : * Copyright (c) 2013, Even Rouault 11 : * 12 : * SPDX-License-Identifier: MIT 13 : ******************************************************************************/ 14 : #include "postgisraster.h" 15 : #include "cpl_multiproc.h" 16 : 17 : PostGISRasterDriver *PostGISRasterDriver::gpoPostGISRasterDriver = nullptr; 18 : 19 : /************************ 20 : * \brief Constructor 21 : ************************/ 22 9 : PostGISRasterDriver::PostGISRasterDriver() 23 : { 24 9 : gpoPostGISRasterDriver = this; 25 9 : } 26 : 27 : /************************ 28 : * \brief Destructor 29 : ************************/ 30 10 : PostGISRasterDriver::~PostGISRasterDriver() 31 : { 32 5 : gpoPostGISRasterDriver = nullptr; 33 5 : if (hMutex != nullptr) 34 0 : CPLDestroyMutex(hMutex); 35 5 : std::map<CPLString, PGconn *>::iterator oIter = oMapConnection.begin(); 36 5 : for (; oIter != oMapConnection.end(); ++oIter) 37 0 : PQfinish(oIter->second); 38 10 : } 39 : 40 : /*************************************************************************** 41 : * \brief Create a PQconn object and store it in a list 42 : * 43 : * The PostGIS Raster driver keeps the connection with the PostgreSQL database 44 : * server for as long it leaves. Following PostGISRasterDataset instance 45 : * can re-use the existing connection as long it used the same database, 46 : * same host, port and user name. 47 : * 48 : * The PostGIS Raster driver will keep a list of all the successful 49 : * connections so, when connection is requested and it does not exist 50 : * on the list a new one will be instantiated, added to the list and 51 : * returned to the caller. 52 : * 53 : * All connection will be destroyed when the PostGISRasterDriver is destroyed. 54 : * 55 : ***************************************************************************/ 56 2 : PGconn *PostGISRasterDriver::GetConnection(const char *pszConnectionString, 57 : const char *pszServiceIn, 58 : const char *pszDbnameIn, 59 : const char *pszHostIn, 60 : const char *pszPortIn, 61 : const char *pszUserIn) 62 : { 63 2 : PGconn *poConn = nullptr; 64 : 65 2 : if (pszHostIn == nullptr) 66 0 : pszHostIn = "(null)"; 67 2 : if (pszPortIn == nullptr) 68 0 : pszPortIn = "(null)"; 69 2 : if (pszUserIn == nullptr) 70 0 : pszUserIn = "(null)"; 71 4 : CPLString osKey = (pszServiceIn == nullptr) ? pszDbnameIn : pszServiceIn; 72 2 : osKey += "-"; 73 2 : osKey += pszHostIn; 74 2 : osKey += "-"; 75 2 : osKey += pszPortIn; 76 2 : osKey += "-"; 77 2 : osKey += pszUserIn; 78 2 : osKey += "-"; 79 2 : osKey += CPLSPrintf(CPL_FRMT_GIB, CPLGetPID()); 80 : 81 : /** 82 : * Look for an existing connection in the map 83 : **/ 84 4 : CPLMutexHolderD(&hMutex); 85 2 : std::map<CPLString, PGconn *>::iterator oIter = oMapConnection.find(osKey); 86 2 : if (oIter != oMapConnection.end()) 87 1 : return oIter->second; 88 : 89 : /** 90 : * There's no existing connection. Create a new one. 91 : **/ 92 1 : poConn = PQconnectdb(pszConnectionString); 93 1 : if (poConn == nullptr || PQstatus(poConn) == CONNECTION_BAD) 94 : { 95 0 : CPLError(CE_Failure, CPLE_AppDefined, "PQconnectdb failed: %s\n", 96 : PQerrorMessage(poConn)); 97 0 : PQfinish(poConn); 98 0 : return nullptr; 99 : } 100 : 101 : /** 102 : * Save connection in the connection map. 103 : **/ 104 1 : oMapConnection[osKey] = poConn; 105 1 : return poConn; 106 : }