gwaldron / osgearth

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

about BlackList #2618

Closed HerryJessica closed 3 weeks ago

HerryJessica commented 2 months ago

What is the usage of "TileBlacklist"?

if (img.valid() && options().featherPixels() == true) { ImageUtils::featherAlphaRegions( img.get() ); }

if (img == 0L)
{
    if ( progress == 0L || !progress->isCanceled() )
    {
        source->getBlacklist()->add( key );
    }
} 

When requesting the key again, it returns invalid because the first request failed and it will be added to the blacklist. Or how to continue to request this TileKey if the first request fails

gwaldron commented 2 months ago

TileBlacklist is part of the OLD TileSource framework that is no longer used in osgEarth 3.x. I recommend that you upgrade to a more modern version.

The idea of a blacklist is that if you get an unrecoverable error trying to access a resource, you don't try to access it again.

HerryJessica commented 2 months ago

If I want to request a resource again after the first request fails

I have multiple ImageLayers but I only want to re-request the one that failed. What should I do?

I try to call progress->cancel(); this causes all layers on this TileKey to re-request

gwaldron commented 2 months ago

We really need more information to have a chance at helping you. What version of osgEarth are you using? What are you trying to do at a high level? Do you have a code snippet? In osgEarth 3.x, a blacklist is only applied to URI requests, and a request only gets blacklisted if it is deemed unrecoverable (like an HTTP 404).

HerryJessica commented 2 months ago

GeoImage OnImageLayer::createImageImplementation(const TileKey& key, ProgressCallback progress) const { osg::Image img=requestImage(key); return GeoImage(img,key.getExtent()); }

osg::Image* OnImageLayer::requestImage(const TileKey& key) {

osg::Image * img=NULL;
std::string location = _url;

unsigned x,y,z;
key.getTileXY(x,y);
z = key.getLevelOfDetail();
if(key.getProfile()->getProfileType()==Profile::TYPE_GEODETIC)
{
    z++;
}

// support OpenLayers template style:
replaceIn( location, "${x}", Stringify() << x );
replaceIn( location, "${y}", Stringify() << y );
replaceIn( location, "${z}", Stringify() << z );

// failing that, legacy osgearth style:
replaceIn( location, "{x}", Stringify() << x );
replaceIn( location, "{y}", Stringify() << y );
replaceIn( location, "{z}", Stringify() << z );

unsigned recode=0;
HTTPRequest request(location);

HTTPResponse respose=HTTPClient::get(request);
recode=respose.getCode();
if(recode!=200)
    return img;
std::string dataStr;
if(respose.isOK())
{
    if(respose.getNumParts() > 0)
    {
        dataStr = respose.getPartAsString(0);
    }
}
if(dataStr.size())
{
    std::istringstream inputStream(dataStr);
    img=ImageUtils::readStream(inputStream,NULL);
}
return img;

}

When the “recode” return value is 0, it may be that the request has timed out. At this time, I want to request again one or more times. I mean re-calling createImageImplementation osgEarth verison3.2

gwaldron commented 1 month ago

You are better off just using the URI API and passing in the ProgressCallback. No need to use the HTTPClient directly. That way, if the request times out, the callback will be set to cancel and will automatically retry later. (At least, that's the behavior in 3.5/3.6.)

URI uri(location);
return uri.getImage(options, progress);