gwaldron / osgearth

3D Maps for OpenSceneGraph / C++14
https://www.pelicanmapping.com/home-1/opensource
Other
1.5k stars 779 forks source link

FileSystemCacheBin crashes if reader/writer for extension osgb cannot be loaded #585

Closed hwiesmann closed 9 years ago

hwiesmann commented 9 years ago

In the constructor _rw is assigned to the reader/writer of the extension osgb. Afterwards, there are no checks whether _rw contains a non null pointer value. Therefore, the program will crash when using _rw.

Hartwig

gwaldron commented 9 years ago

patched; please check and report bank. Thanks.

hwiesmann commented 9 years ago

Your fix is not working: in TerrainLayer::getCacheBin(const Profile* profile, const std::string& binId) metadata is read. If the read fails metadata is created and written (see below).

        // attempt to read the cache metadata:
        CacheBinMetadata meta( newBin->readMetadata() );

        if ( meta.isValid() ) // cache exists and is valid.
        {
            // verify that the cache if compatible with the tile source:
            if ( tileSource && getProfile() )
            {
                //todo: check the profile too
                if ( *meta._sourceDriver != tileSource->getOptions().getDriver() )
                {
                    OE_WARN << LC << "Cache has an incompatible driver or profile... disabling"
                        << std::endl;
                    setCachePolicy( CachePolicy::NO_CACHE );
                    return 0L;
                }
            }   

            else if ( isCacheOnly() && !_profile.valid() )
            {
                // in cacheonly mode, create a profile from the first cache bin accessed
                // (they SHOULD all be the same...)
                _profile = Profile::create( *meta._sourceProfile );
                _tileSize = *meta._sourceTileSize;
            }
        }

        else
        {
            // cache does not exist, so try to create it. A valid TileSource is necessary
            // for this.
            if ( tileSource && getProfile() )
            {
                // no existing metadata; create some.
                meta._cacheBinId      = binId;
                meta._sourceName      = this->getName();
                meta._sourceDriver    = tileSource->getOptions().getDriver();
                meta._sourceTileSize  = getTileSize();
                meta._sourceProfile   = getProfile()->toProfileOptions();
                meta._cacheProfile    = profile->toProfileOptions();
                meta._cacheCreateTime = DateTime().asTimeStamp();

                // store it in the cache bin.
                newBin->writeMetadata( meta.getConfig() );
            }
            else if ( isCacheOnly() )
            {
                OE_WARN << LC <<
                    "Failed to open a cache for layer "
                    "because cache_only policy is in effect and bin [" << binId << "] "
                    "could not be located."
                    << std::endl;
                return 0L;
            }
            else
            {
                OE_WARN << LC <<
                    "Failed to create cache bin [" << binId << "] "
                    "because there is no valid tile source."
                    << std::endl;
                return 0L;
            }
        }

Unfortunately, the failed read operation blocks any further operation. Therefore, also writing the metadata fails. This has the consequence that no new file system cache can be created.

Regards, Hartwig

gwaldron commented 9 years ago

I tried to patch this up differently; please give it a quick try. Didn't test it yet myself.

hwiesmann commented 9 years ago

Seems to work!