OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate ) { // First check if we have to do any work. int nLen = strlen(pszFilename); if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) || (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) ) return NULL; long hr; /* Check that the filename is really a directory, to avoid confusion with */ /* Garmin MapSource - gdb format which can be a problem when the FileGDB */ /* driver is loaded as a plugin, and loaded before the GPSBabel driver */ /* (http://trac.osgeo.org/osgeo4w/ticket/245) */ VSIStatBuf stat; if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) ) { return NULL; } Geodatabase* pGeoDatabase = NULL; FGdbDatabaseConnection* pConnection = oMapConnections[pszFilename]; if( pConnection != NULL ) { pGeoDatabase = pConnection->m_pGeodatabase; pConnection->m_nRefCount ++; CPLDebug("FileGDB", "ref_count of %s = %d now", pszFilename, pConnection->m_nRefCount); } else { pGeoDatabase = new Geodatabase; hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase); if (FAILED(hr) || pGeoDatabase == NULL) { delete pGeoDatabase; GDBErr(hr, "Failed to open Geodatabase"); return NULL; } CPLDebug("FileGDB", "Really opening %s", pszFilename); oMapConnections[pszFilename] = new FGdbDatabaseConnection(pGeoDatabase); } FGdbDataSource* pDS; pDS = new FGdbDataSource(this); if(!pDS->Open( pGeoDatabase, pszFilename, bUpdate ) ) { delete pDS; return NULL; } else return pDS; }
OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate ) { // First check if we have to do any work. if (!EQUAL(CPLGetExtension(pszFilename), "gdb")) return NULL; long hr; Geodatabase* pGeoDatabase = new Geodatabase; hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase); if (FAILED(hr) || pGeoDatabase == NULL) { delete pGeoDatabase; GDBErr(hr, "Failed to open Geodatabase"); return NULL; } FGdbDataSource* pDS; pDS = new FGdbDataSource(); if(!pDS->Open( pGeoDatabase, pszFilename, bUpdate ) ) { delete pDS; return NULL; } else return pDS; }
OGRDataSource* FGdbDriver::CreateDataSource( const char * conn, char **papszOptions) { long hr; Geodatabase *pGeodatabase; std::wstring wconn = StringToWString(conn); int bUpdate = TRUE; // If we're creating, we must be writing. VSIStatBuf stat; /* We don't support options yet, so warn if they send us some */ if ( papszOptions ) { /* TODO: warning, ignoring options */ } /* Only accept names of form "filename.gdb" and */ /* also .gdb.zip to be able to return FGDB with MapServer OGR output (#4199) */ const char* pszExt = CPLGetExtension(conn); if ( !(EQUAL(pszExt,"gdb") || EQUAL(pszExt, "zip")) ) { CPLError( CE_Failure, CPLE_AppDefined, "FGDB data source name must use 'gdb' extension.\n" ); return NULL; } /* Don't try to create on top of something already there */ if( CPLStat( conn, &stat ) == 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "%s already exists.\n", conn ); return NULL; } /* Try to create the geodatabase */ pGeodatabase = new Geodatabase; // Create on heap so we can store it in the Datasource hr = CreateGeodatabase(wconn, *pGeodatabase); /* Handle creation errors */ if ( S_OK != hr ) { const char *errstr = "Error creating geodatabase (%s).\n"; if ( hr == -2147220653 ) errstr = "File already exists (%s).\n"; delete pGeodatabase; CPLError( CE_Failure, CPLE_AppDefined, errstr, conn ); return NULL; } oMapConnections[conn] = new FGdbDatabaseConnection(pGeodatabase); /* Ready to embed the Geodatabase in an OGR Datasource */ FGdbDataSource* pDS = new FGdbDataSource(this); if ( ! pDS->Open(pGeodatabase, conn, bUpdate) ) { delete pDS; return NULL; } else return pDS; }
int FGdbDataSource::ReOpen() { CPLAssert(m_pGeodatabase == NULL); if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE1") || !m_pConnection->OpenGeodatabase(m_osFSName) ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s", m_osFSName.c_str()); return FALSE; } FGdbDataSource* pDS = new FGdbDataSource(m_poDriver, m_pConnection); if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE2") || !pDS->Open(m_osPublicName, TRUE, m_osFSName) ) { pDS->m_poDriver = NULL; delete pDS; CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s", m_osFSName.c_str()); return FALSE; } int bRet = TRUE; size_t count = m_layers.size(); for(size_t i = 0; i < count; ++i ) { FGdbLayer* pNewLayer = (FGdbLayer*)pDS->GetLayerByName(m_layers[i]->GetName()); if( pNewLayer && !EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL_REOPEN", ""), "CASE3") ) { m_layers[i]->m_pTable = pNewLayer->m_pTable; pNewLayer->m_pTable = NULL; m_layers[i]->m_pEnumRows = pNewLayer->m_pEnumRows; pNewLayer->m_pEnumRows = NULL; } else { CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen %s", m_layers[i]->GetName()); bRet = FALSE; } m_layers[i]->m_oMapOGRFIDToFGDBFID.clear(); m_layers[i]->m_oMapFGDBFIDToOGRFID.clear(); } m_pGeodatabase = pDS->m_pGeodatabase; pDS->m_pGeodatabase = NULL; pDS->m_poDriver = NULL; pDS->m_pConnection = NULL; delete pDS; return bRet; }
OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate ) { // First check if we have to do any work. int nLen = strlen(pszFilename); if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) || (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) ) return NULL; long hr; Geodatabase* pGeoDatabase = new Geodatabase; hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase); if (FAILED(hr) || pGeoDatabase == NULL) { delete pGeoDatabase; GDBErr(hr, "Failed to open Geodatabase"); return NULL; } FGdbDataSource* pDS; pDS = new FGdbDataSource(); if(!pDS->Open( pGeoDatabase, pszFilename, bUpdate ) ) { delete pDS; return NULL; } else return pDS; }
OGRDataSource *FGdbDriver::Open( const char* pszFilename, int bUpdate ) { // First check if we have to do any work. size_t nLen = strlen(pszFilename); if(! ((nLen >= 4 && EQUAL(pszFilename + nLen - 4, ".gdb")) || (nLen >= 5 && EQUAL(pszFilename + nLen - 5, ".gdb/"))) ) return NULL; long hr; /* Check that the filename is really a directory, to avoid confusion with */ /* Garmin MapSource - gdb format which can be a problem when the FileGDB */ /* driver is loaded as a plugin, and loaded before the GPSBabel driver */ /* (http://trac.osgeo.org/osgeo4w/ticket/245) */ VSIStatBuf stat; if( CPLStat( pszFilename, &stat ) != 0 || !VSI_ISDIR(stat.st_mode) ) { return NULL; } CPLMutexHolderD(&hMutex); FGdbDatabaseConnection* pConnection = oMapConnections[pszFilename]; if( pConnection != NULL ) { if( pConnection->IsFIDHackInProgress() ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot open geodatabase at the moment since it is in 'FID hack mode'"); return NULL; } pConnection->m_nRefCount ++; CPLDebug("FileGDB", "ref_count of %s = %d now", pszFilename, pConnection->m_nRefCount); } else { Geodatabase* pGeoDatabase = new Geodatabase; hr = ::OpenGeodatabase(StringToWString(pszFilename), *pGeoDatabase); if (FAILED(hr)) { delete pGeoDatabase; if( OGRGetDriverByName("OpenFileGDB") != NULL && bUpdate == FALSE ) { std::wstring fgdb_error_desc_w; std::string fgdb_error_desc("Unknown error"); fgdbError er; er = FileGDBAPI::ErrorInfo::GetErrorDescription(static_cast<fgdbError>(hr), fgdb_error_desc_w); if ( er == S_OK ) { fgdb_error_desc = WStringToString(fgdb_error_desc_w); } CPLDebug("FileGDB", "Cannot open %s with FileGDB driver: %s. Failing silently so OpenFileGDB can be tried", pszFilename, fgdb_error_desc.c_str()); } else { GDBErr(hr, "Failed to open Geodatabase"); } oMapConnections.erase(pszFilename); return NULL; } CPLDebug("FileGDB", "Really opening %s", pszFilename); pConnection = new FGdbDatabaseConnection(pszFilename, pGeoDatabase); oMapConnections[pszFilename] = pConnection; } FGdbDataSource* pDS; pDS = new FGdbDataSource(this, pConnection); if(!pDS->Open( pszFilename, bUpdate, NULL ) ) { delete pDS; return NULL; } else { OGRMutexedDataSource* poMutexedDS = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE); if( bUpdate ) return OGRCreateEmulatedTransactionDataSourceWrapper(poMutexedDS, this, TRUE, FALSE); else return poMutexedDS; } }
OGRErr FGdbDriver::RollbackTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS) { CPLMutexHolderOptionalLockD(hMutex); bOutHasReopenedDS = FALSE; OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut; FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource(); FGdbDatabaseConnection* pConnection = poDS->GetConnection(); if( !pConnection->IsLocked() ) { CPLError(CE_Failure, CPLE_NotSupported, "No transaction in progress"); return OGRERR_FAILURE; } bOutHasReopenedDS = TRUE; CPLString osName(poMutexedDS->GetName()); CPLString osNameOri(osName); if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' ) osName.resize(osName.size()-1); //int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction(); pConnection->m_nRefCount ++; delete poDSInOut; poDSInOut = NULL; poMutexedDS = NULL; poDS = NULL; pConnection->CloseGeodatabase(); CPLString osEditedName(osName); osEditedName += ".ogredited"; OGRErr eErr = OGRERR_NONE; if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || CPLUnlinkTree(osEditedName) != 0 ) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot remove %s. Manual cleanup required", osEditedName.c_str()); eErr = OGRERR_FAILURE; } pConnection->m_pGeodatabase = new Geodatabase; long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase)); if (EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || FAILED(hr)) { delete pConnection->m_pGeodatabase; pConnection->m_pGeodatabase = NULL; pConnection->SetLocked(FALSE); Release(osName); GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed"); return OGRERR_FAILURE; } FGdbDataSource* pDS = new FGdbDataSource(this, pConnection); pDS->Open(osNameOri, TRUE, NULL); //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction); poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE); pConnection->SetLocked(FALSE); return eErr; }
OGRErr FGdbDriver::CommitTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS) { CPLMutexHolderOptionalLockD(hMutex); bOutHasReopenedDS = FALSE; OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut; FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource(); FGdbDatabaseConnection* pConnection = poDS->GetConnection(); if( !pConnection->IsLocked() ) { CPLError(CE_Failure, CPLE_NotSupported, "No transaction in progress"); return OGRERR_FAILURE; } bOutHasReopenedDS = TRUE; CPLString osName(poMutexedDS->GetName()); CPLString osNameOri(osName); if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' ) osName.resize(osName.size()-1); #ifndef WIN32 int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction(); #endif pConnection->m_nRefCount ++; delete poDSInOut; poDSInOut = NULL; poMutexedDS = NULL; poDS = NULL; pConnection->CloseGeodatabase(); CPLString osEditedName(osName); osEditedName += ".ogredited"; #ifndef WIN32 if( bPerLayerCopyingForTransaction ) { int bError = FALSE; char** papszFiles; std::vector<CPLString> aosTmpFilesToClean; // Check for files present in original copy that are not in edited copy // That is to say deleted layers papszFiles = VSIReadDir(osName); for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter) { if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 ) continue; VSIStatBufL sStat; if( (*papszIter)[0] == 'a' && VSIStatL( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 ) { if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || VSIRename( CPLFormFilename(osName, *papszIter, NULL), CPLFormFilename(osName, *papszIter, "tmp") ) != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s", CPLFormFilename(osName, *papszIter, NULL), CPLFormFilename(osName, *papszIter, "tmp")); bError = TRUE; } else aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp")); } } CSLDestroy(papszFiles); // Move modified files from edited directory to main directory papszFiles = VSIReadDir(osEditedName); for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter) { if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 ) continue; struct stat sStat; if( lstat( CPLFormFilename(osEditedName, *papszIter, NULL), &sStat ) != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot stat %s", CPLFormFilename(osEditedName, *papszIter, NULL)); bError = TRUE; } else if( !S_ISLNK(sStat.st_mode) ) { // If there was such a file in original directory, first rename it // as a temporary file if( lstat( CPLFormFilename(osName, *papszIter, NULL), &sStat ) == 0 ) { if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || VSIRename( CPLFormFilename(osName, *papszIter, NULL), CPLFormFilename(osName, *papszIter, "tmp") ) != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s", CPLFormFilename(osName, *papszIter, NULL), CPLFormFilename(osName, *papszIter, "tmp")); bError = TRUE; } else aosTmpFilesToClean.push_back(CPLFormFilename(osName, *papszIter, "tmp")); } if( !bError ) { if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || CPLMoveFile( CPLFormFilename(osName, *papszIter, NULL), CPLFormFilename(osEditedName, *papszIter, NULL) ) != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot move %s to %s", CPLFormFilename(osEditedName, *papszIter, NULL), CPLFormFilename(osName, *papszIter, NULL)); bError = TRUE; } else CPLDebug("FileGDB", "Move %s to %s", CPLFormFilename(osEditedName, *papszIter, NULL), CPLFormFilename(osName, *papszIter, NULL)); } } } CSLDestroy(papszFiles); if( !bError ) { for(size_t i=0;i<aosTmpFilesToClean.size();i++) { if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE4") || VSIUnlink(aosTmpFilesToClean[i]) != 0 ) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot remove %s. Manual cleanup required", aosTmpFilesToClean[i].c_str()); } } } if( bError ) { CPLError(CE_Failure, CPLE_AppDefined, "An error occurred while moving files from %s back to %s. " "Manual cleaning must be done and dataset should be closed", osEditedName.c_str(), osName.c_str()); pConnection->SetLocked(FALSE); Release(osName); return OGRERR_FAILURE; } else if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE5") || CPLUnlinkTree(osEditedName) != 0 ) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot remove %s. Manual cleanup required", osEditedName.c_str()); } } else #endif { CPLString osTmpName(osName); osTmpName += ".ogrtmp"; /* Install the backup copy as the main database in 3 steps : */ /* first rename the main directory in .tmp */ /* then rename the edited copy under regular name */ /* and finally dispose the .tmp directory */ /* That way there's no risk definitely losing data */ if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || VSIRename(osName, osTmpName) != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s. Edited database during transaction is in %s" "Dataset should be closed", osName.c_str(), osTmpName.c_str(), osEditedName.c_str()); pConnection->SetLocked(FALSE); Release(osName); return OGRERR_FAILURE; } if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || VSIRename(osEditedName, osName) != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename %s to %s. The original geodatabase is in '%s'. " "Dataset should be closed", osEditedName.c_str(), osName.c_str(), osTmpName.c_str()); pConnection->SetLocked(FALSE); Release(osName); return OGRERR_FAILURE; } if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE3") || CPLUnlinkTree(osTmpName) != 0 ) { CPLError(CE_Warning, CPLE_AppDefined, "Cannot remove %s. Manual cleanup required", osTmpName.c_str()); } } pConnection->m_pGeodatabase = new Geodatabase; long hr = ::OpenGeodatabase(StringToWString(osName), *(pConnection->m_pGeodatabase)); if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE_REOPEN") || FAILED(hr)) { delete pConnection->m_pGeodatabase; pConnection->m_pGeodatabase = NULL; pConnection->SetLocked(FALSE); Release(osName); GDBErr(hr, "Failed to re-open Geodatabase. Dataset should be closed"); return OGRERR_FAILURE; } FGdbDataSource* pDS = new FGdbDataSource(this, pConnection); pDS->Open(osNameOri, TRUE, NULL); //pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction); poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE); pConnection->SetLocked(FALSE); return OGRERR_NONE; }
OGRErr FGdbDriver::StartTransaction(OGRDataSource*& poDSInOut, int& bOutHasReopenedDS) { CPLMutexHolderOptionalLockD(hMutex); bOutHasReopenedDS = FALSE; OGRMutexedDataSource* poMutexedDS = (OGRMutexedDataSource*)poDSInOut; FGdbDataSource* poDS = (FGdbDataSource* )poMutexedDS->GetBaseDataSource(); if( !poDS->GetUpdate() ) return OGRERR_FAILURE; FGdbDatabaseConnection* pConnection = poDS->GetConnection(); if( pConnection->GetRefCount() != 1 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot start transaction as database is opened in another connection"); return OGRERR_FAILURE; } if( pConnection->IsLocked() ) { CPLError(CE_Failure, CPLE_AppDefined, "Transaction is already in progress"); return OGRERR_FAILURE; } bOutHasReopenedDS = TRUE; CPLString osName(poMutexedDS->GetName()); CPLString osNameOri(osName); if( osName[osName.size()-1] == '/' || osName[osName.size()-1] == '\\' ) osName.resize(osName.size()-1); #ifndef WIN32 int bPerLayerCopyingForTransaction = poDS->HasPerLayerCopyingForTransaction(); #endif pConnection->m_nRefCount ++; delete poDSInOut; poDSInOut = NULL; poMutexedDS = NULL; poDS = NULL; pConnection->CloseGeodatabase(); CPLString osEditedName(osName); osEditedName += ".ogredited"; CPLPushErrorHandler(CPLQuietErrorHandler); CPL_IGNORE_RET_VAL(CPLUnlinkTree(osEditedName)); CPLPopErrorHandler(); OGRErr eErr = OGRERR_NONE; CPLString osDatabaseToReopen; #ifndef WIN32 if( bPerLayerCopyingForTransaction ) { int bError = FALSE; if( VSIMkdir( osEditedName, 0755 ) != 0 ) { CPLError( CE_Failure, CPLE_AppDefined, "Cannot create directory '%s'.", osEditedName.c_str() ); bError = TRUE; } // Only copy a0000000X.Y files with X >= 1 && X <= 8, gdb and timestamps // and symlink others char** papszFiles = VSIReadDir(osName); for(char** papszIter = papszFiles; !bError && *papszIter; ++papszIter) { if( strcmp(*papszIter, ".") == 0 || strcmp(*papszIter, "..") == 0 ) continue; if( ((*papszIter)[0] == 'a' && atoi((*papszIter)+1) >= 1 && atoi((*papszIter)+1) <= 8) || EQUAL(*papszIter, "gdb") || EQUAL(*papszIter, "timestamps") ) { if( CPLCopyFile(CPLFormFilename(osEditedName, *papszIter, NULL), CPLFormFilename(osName, *papszIter, NULL)) != 0 ) { bError = TRUE; CPLError(CE_Failure, CPLE_AppDefined, "Cannot copy %s", *papszIter); } } else { CPLString osSourceFile; if( CPLIsFilenameRelative(osName) ) osSourceFile = CPLFormFilename(CPLSPrintf("../%s", CPLGetFilename(osName.c_str())), *papszIter, NULL); else osSourceFile = osName; if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || CPLSymlink( osSourceFile, CPLFormFilename(osEditedName.c_str(), *papszIter, NULL), NULL ) != 0 ) { bError = TRUE; CPLError(CE_Failure, CPLE_AppDefined, "Cannot symlink %s", *papszIter); } } } CSLDestroy(papszFiles); if( bError ) { eErr = OGRERR_FAILURE; osDatabaseToReopen = osName; } else osDatabaseToReopen = osEditedName; } else #endif { if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE1") || CPLCopyTree( osEditedName, osName ) != 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot backup geodatabase"); eErr = OGRERR_FAILURE; osDatabaseToReopen = osName; } else osDatabaseToReopen = osEditedName; } pConnection->m_pGeodatabase = new Geodatabase; long hr = ::OpenGeodatabase(StringToWString(osDatabaseToReopen), *(pConnection->m_pGeodatabase)); if( EQUAL(CPLGetConfigOption("FGDB_SIMUL_FAIL", ""), "CASE2") || FAILED(hr)) { delete pConnection->m_pGeodatabase; pConnection->m_pGeodatabase = NULL; Release(osName); GDBErr(hr, CPLSPrintf("Failed to open %s. Dataset should be closed", osDatabaseToReopen.c_str())); return OGRERR_FAILURE; } FGdbDataSource* pDS = new FGdbDataSource(this, pConnection); pDS->Open(osDatabaseToReopen, TRUE, osNameOri); #ifndef WIN32 if( eErr == OGRERR_NONE && bPerLayerCopyingForTransaction ) { pDS->SetPerLayerCopyingForTransaction(bPerLayerCopyingForTransaction); pDS->SetSymlinkFlagOnAllLayers(); } #endif poDSInOut = new OGRMutexedDataSource(pDS, TRUE, hMutex, TRUE); if( eErr == OGRERR_NONE ) pConnection->SetLocked(TRUE); return eErr; }