Changeset 24699


Ignore:
Timestamp:
Jul 23, 2012, 3:13:29 AM (11 years ago)
Author:
Even Rouault
Message:

OSM: fix logic to detect if in-memory temporary file exceeds allowed size; reserve memory from the beginning of the reading to avoid virtual memory space exhaustion on 32bit OS

Location:
trunk/gdal/ogr/ogrsf_frmts/osm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/gdal/ogr/ogrsf_frmts/osm/ogr_osm.h

    r24697 r24699  
    234234    OGRGeometry*        BuildGeometryCollection(OSMRelation* psRelation, int bMultiLineString);
    235235
     236    int                 TransferToDiskIfNecesserary();
     237
    236238  public:
    237239                        OGROSMDataSource();
  • trunk/gdal/ogr/ogrsf_frmts/osm/ogrosmdatasource.cpp

    r24697 r24699  
    10521052    int rc;
    10531053    int bIsExisting = FALSE;
     1054    int bSuccess = FALSE;
    10541055
    10551056#ifdef HAVE_SQLITE_VFS
     
    10571058    if ( pszExistingTmpFile != NULL )
    10581059    {
     1060        bSuccess = TRUE;
    10591061        bIsExisting = TRUE;
    10601062        rc = sqlite3_open_v2( pszExistingTmpFile, &hDB,
     
    10641066    else
    10651067    {
    1066         bInMemoryTmpDB = TRUE;
    10671068        osTmpDBName.Printf("/vsimem/osm_importer/osm_temp_%p.sqlite", this);
    1068         pMyVFS = OGRSQLiteCreateVFS(NULL, this);
    1069         sqlite3_vfs_register(pMyVFS, 0);
    1070         rc = sqlite3_open_v2( osTmpDBName.c_str(), &hDB,
    1071                             SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX,
    1072                             pMyVFS->zName );
    1073     }
    1074 #else
    1075     osTmpDBName = CPLGenerateTempFilename("osm_tmp");
    1076     rc = sqlite3_open( osTmpDBName.c_str(), &hDB );
    1077 
    1078     /* On Unix filesystems, you can remove a file even if it */
    1079     /* opened */
    1080     if( rc == SQLITE_OK )
    1081     {
    1082         const char* pszVal = CPLGetConfigOption("OSM_UNLINK_TMPFILE", "YES");
    1083         if( EQUAL(pszVal, "YES") )
    1084         {
     1069
     1070        /* On 32 bit, the virtual memory space is scarce, so we need to reserve it right now */
     1071        /* Won't hurt on 64 bit either. */
     1072        VSILFILE* fp = VSIFOpenL(osTmpDBName, "wb");
     1073        if( fp )
     1074        {
     1075            GIntBig nSize = (GIntBig)nMaxSizeForInMemoryDBInMB * 1024 * 1024;
     1076            if (nSize < 0 || (GIntBig)(size_t)nSize != nSize)
     1077            {
     1078                CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for OSM_MAX_TMPFILE_SIZE. Using 100 instead.");
     1079                nMaxSizeForInMemoryDBInMB = 100;
     1080                nSize = (GIntBig)nMaxSizeForInMemoryDBInMB * 1024 * 1024;
     1081            }
     1082
    10851083            CPLPushErrorHandler(CPLQuietErrorHandler);
    1086             bMustUnlink = VSIUnlink( osTmpDBName ) != 0;
     1084            bSuccess = VSIFSeekL(fp, (vsi_l_offset) nSize, SEEK_SET) == 0;
    10871085            CPLPopErrorHandler();
     1086
     1087            if( bSuccess )
     1088                 VSIFTruncateL(fp, 0);
     1089
     1090            VSIFCloseL(fp);
     1091
     1092            if( !bSuccess )
     1093            {
     1094                CPLDebug("OSM", "Not enough memory for in-memory file. Using disk temporary file instead.");
     1095                VSIUnlink(osTmpDBName);
     1096            }
     1097        }
     1098
     1099        if( bSuccess )
     1100        {
     1101            bInMemoryTmpDB = TRUE;
     1102            pMyVFS = OGRSQLiteCreateVFS(NULL, this);
     1103            sqlite3_vfs_register(pMyVFS, 0);
     1104            rc = sqlite3_open_v2( osTmpDBName.c_str(), &hDB,
     1105                                SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_NOMUTEX,
     1106                                pMyVFS->zName );
    10881107        }
    10891108    }
    10901109#endif
     1110
     1111    if( !bSuccess )
     1112    {
     1113        osTmpDBName = CPLGenerateTempFilename("osm_tmp");
     1114        rc = sqlite3_open( osTmpDBName.c_str(), &hDB );
     1115
     1116        /* On Unix filesystems, you can remove a file even if it */
     1117        /* opened */
     1118        if( rc == SQLITE_OK )
     1119        {
     1120            const char* pszVal = CPLGetConfigOption("OSM_UNLINK_TMPFILE", "YES");
     1121            if( EQUAL(pszVal, "YES") )
     1122            {
     1123                CPLPushErrorHandler(CPLQuietErrorHandler);
     1124                bMustUnlink = VSIUnlink( osTmpDBName ) != 0;
     1125                CPLPopErrorHandler();
     1126            }
     1127        }
     1128    }
    10911129
    10921130    if( rc != SQLITE_OK )
     
    16361674            return FALSE;
    16371675        }
    1638         else if( bFeatureAdded )
    1639             break;
    1640     }
    1641 
     1676        else
     1677        {
     1678            if( bInMemoryTmpDB )
     1679            {
     1680                if( !TransferToDiskIfNecesserary() )
     1681                    return FALSE;
     1682            }
     1683
     1684            if( bFeatureAdded )
     1685                break;
     1686        }
     1687    }
     1688
     1689    return TRUE;
     1690}
     1691
     1692/************************************************************************/
     1693/*                    TransferToDiskIfNecesserary()                     */
     1694/************************************************************************/
     1695
     1696int OGROSMDataSource::TransferToDiskIfNecesserary()
     1697{
    16421698    if( bInMemoryTmpDB )
    16431699    {
Note: See TracChangeset for help on using the changeset viewer.