Ticket #11193: expires-version1-v6.patch

File expires-version1-v6.patch, 8.7 KB (added by wiktorn, 11 years ago)

fixed redownloads of no-tile-at-this-level, so they are not requeried from server

  • src/org/openstreetmap/gui/jmapviewer/OsmFileCacheTileLoader.java

     
    4848
    4949    private static final Charset TAGS_CHARSET = Charset.forName("UTF-8");
    5050
    51     public static final long FILE_AGE_ONE_DAY = 1000 * 60 * 60 * 24;
    52     public static final long FILE_AGE_ONE_WEEK = FILE_AGE_ONE_DAY * 7;
     51    private static final long DEFAULT_EXPIRES_TIME = 1000 * 60 * 60 * 24 * 7;
     52
    5353
    5454    protected String cacheDirBase;
    5555
    5656    protected final Map<TileSource, File> sourceCacheDirMap;
    5757
    5858    protected long maxCacheFileAge = Long.MAX_VALUE;  // max. age not limited
    59     protected long recheckAfter = FILE_AGE_ONE_WEEK;
    6059
    6160    public static File getDefaultCacheDir() throws SecurityException {
    6261        String tempDir = null;
     
    6665        } catch (SecurityException e) {
    6766            log.log(Level.WARNING,
    6867                    "Failed to access system property ''java.io.tmpdir'' for security reasons. Exception was: "
    69                     + e.toString());
     68                            + e.toString());
    7069            throw e; // rethrow
    7170        }
    7271        try {
     
    156155            now = System.currentTimeMillis();
    157156            tileCacheDir = getSourceCacheDir(tile.getSource());
    158157
    159             if (loadTileFromFile(recheckAfter)) {
     158            loadTagsFromFile();
     159
     160            if (isTileFileValid() && (isNoTileAtZoom() || loadTileFromFile())) {
    160161                log.log(Level.FINE, "TMS - found in tile cache: {0}", tile);
    161162                tile.setLoaded(true);
    162163                listener.tileLoadingFinished(tile, true);
    163164                return;
    164165            }
     166
    165167            TileJob job = new TileJob() {
    166168
    167169                @Override
     
    171173                        listener.tileLoadingFinished(tile, true);
    172174                    } else {
    173175                        // failed to download - use old cache file if available
    174                         if (loadTileFromFile(maxCacheFileAge)) {
     176                        if (isNoTileAtZoom() || loadTileFromFile()) {
    175177                            tile.setLoaded(true);
    176178                            tile.error = false;
    177179                            listener.tileLoadingFinished(tile, true);
     
    242244                    default:
    243245                        break;
    244246                    }
    245                     if (loadTileFromFile(maxCacheFileAge)) {
    246                         tileFile.setLastModified(now);
    247                         return true;
    248                     }
     247                    loadTileFromFile();
     248                    tileFile.setLastModified(now);
     249                    return true;
    249250                }
    250251
    251252                loadTileMetadata(tile, urlConn);
     
    285286            return false;
    286287        }
    287288
    288         protected boolean loadTileFromFile(long maxAge) {
     289        protected boolean isTileFileValid() {
     290            Long expires = null;
    289291            try {
    290                 tileFile = getTileFile();
    291                 if (!tileFile.exists())
    292                     return false;
    293                 loadTagsFromFile();
     292                expires = Long.parseLong(tile.getValue("expires"));
     293            } catch (NumberFormatException e) {}
    294294
    295                 fileMtime = tileFile.lastModified();
    296                 if (now - fileMtime > maxAge)
     295            if(expires != null && !expires.equals(0L)) {
     296                // check by expire date set by server
     297                if (now > expires) {
     298                    log.log(Level.FINE, "TMS - Tile has expired -> not valid {0}", tile);
    297299                    return false;
    298 
    299                 if ("no-tile".equals(tile.getValue("tile-info"))) {
    300                     tile.setError("No tile at this zoom level");
    301                     if (tileFile.exists()) {
    302                         tileFile.delete();
    303                     }
    304                     tileFile = null;
    305                 } else {
    306                     try (FileInputStream fin = new FileInputStream(tileFile)) {
    307                         if (fin.available() == 0)
    308                             throw new IOException("File empty");
    309                         tile.loadImage(fin);
     300                }
     301            } else {
     302                // check by file modification date
     303                if (tileFile.exists()) {
     304                    // check for modification date only when tile file exists
     305                    // so handle properly the case, when only tags file exists
     306                    fileMtime = tileFile.lastModified();
     307                    if (now - fileMtime > DEFAULT_EXPIRES_TIME) {
     308                        log.log(Level.FINE, "TMS - Tile has expired, maximum file age reached {0}", tile);
     309                        return false;
    310310                    }
    311311                }
     312            }
     313            return true;
     314        }
     315
     316        protected boolean isNoTileAtZoom() {
     317            if ("no-tile".equals(tile.getValue("tile-info"))) {
     318                // do not remove file - keep the information, that there is no tile, for further requests
     319                // the code above will check, if this information is still valid
     320                log.log(Level.FINE, "TMS - Tile valid, but no file, as no tiles at this level {0}", tile);
     321                tile.setError("No tile at this zoom level");
    312322                return true;
     323            }
     324            return false;
     325        }
    313326
     327        protected boolean loadTileFromFile() {
     328            if (!tileFile.exists())
     329                return false;
     330
     331            try (FileInputStream fin = new FileInputStream(tileFile)) {
     332                if (fin.available() == 0)
     333                    throw new IOException("File empty");
     334                tile.loadImage(fin);
     335                return true;
    314336            } catch (Exception e) {
    315337                log.log(Level.WARNING, "TMS - Error while loading image from tile cache: {0}; {1}", new Object[]{e.getMessage(), tile});
    316338                tileFile.delete();
     339                File tileMetaData = getTagsFile();
     340                if (tileMetaData.exists())
     341                    tileMetaData.delete();
    317342                tileFile = null;
    318343                fileMtime = null;
    319344            }
     
    405430            File file = getTileFile();
    406431            file.getParentFile().mkdirs();
    407432            try (
    408                 FileOutputStream f = new FileOutputStream(file)
    409             ) {
     433                    FileOutputStream f = new FileOutputStream(file)
     434                    ) {
    410435                f.write(rawData);
    411436            } catch (Exception e) {
    412437                log.log(Level.SEVERE, "Failed to save tile content: {0}", e.getLocalizedMessage());
     
    429454            }
    430455        }
    431456
    432         protected void loadTagsFromFile() {
     457        protected boolean loadTagsFromFile() {
     458            tileFile = getTileFile();
    433459            File tagsFile = getTagsFile();
    434460            try (BufferedReader f = new BufferedReader(new InputStreamReader(new FileInputStream(tagsFile), TAGS_CHARSET))) {
    435461                for (String line = f.readLine(); line != null; line = f.readLine()) {
     
    444470            } catch (Exception e) {
    445471                System.err.println("Failed to load tile tags: " + e.getLocalizedMessage());
    446472            }
     473
     474            return true;
    447475        }
    448476    }
    449477
  • src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java

     
    108108        if (str != null) {
    109109            tile.putValue("tile-info", str);
    110110        }
     111
     112        Long lng = urlConn.getExpiration();
     113        if (lng.equals(0L)) {
     114            try {
     115                str = urlConn.getHeaderField("Cache-Control");
     116                if (str != null) {
     117                    for (String token: str.split(",")) {
     118                        if (token.startsWith("max-age=")) {
     119                            lng = Math.min(
     120                                    Long.parseLong(token.substring(8)),
     121                                    86400 * 31 // cap max-age at one month
     122                                    ) * 1000 +
     123                                    System.currentTimeMillis();
     124
     125                        }
     126                    }
     127                }
     128            } catch (NumberFormatException e) {} //ignore malformed Cache-Control headers
     129        }
     130        if (!lng.equals(0)) {
     131            tile.putValue("expires", lng.toString());
     132        }
    111133    }
    112134
    113135    protected void prepareHttpUrlConnection(HttpURLConnection urlConn) {