Ignore:
Timestamp:
2013-04-07T17:07:27+02:00 (12 years ago)
Author:
akks
Message:

JOSM/ImageryCache: updated MapDB (no more deadlocks, Java 1.6 compatible), less crashes, multiple-JOSM support

Location:
applications/editors/josm/plugins/imagerycache/src/org/openstreetmap/josm/plugins/imagerycache
Files:
3 added
2 edited

Legend:

Unmodified
Added
Removed
  • applications/editors/josm/plugins/imagerycache/src/org/openstreetmap/josm/plugins/imagerycache/ImageryCachePlugin.java

    r29363 r29484  
    1717        public OsmTileLoader makeTileLoader(TileLoaderListener listener) {
    1818            String cachePath = TMSLayer.PROP_TILECACHE_DIR.get();
     19            try {
     20                new File(cachePath).mkdirs();
     21            } catch (Exception e) {
     22                cachePath=".";
     23            }
     24           
    1925            if (cachePath != null && !cachePath.isEmpty()) {
    2026                return new OsmDBTilesLoader(listener, new File(cachePath));
     
    2935    }
    3036   
     37    public static void main(String[] args) {
     38        System.out.println("Debugging code for ImageryAdjust plugin");
     39    }
    3140}
  • applications/editors/josm/plugins/imagerycache/src/org/openstreetmap/josm/plugins/imagerycache/OsmDBTilesLoader.java

    r29368 r29484  
    66import java.io.IOException;
    77import java.io.InputStream;
    8 import java.io.Serializable;
    98import java.net.HttpURLConnection;
    109import java.net.URL;
    1110import java.net.URLConnection;
    12 import java.util.HashMap;
    1311import java.util.Map;
    1412import java.util.Random;
    15 import org.mapdb.DB;
    16 import org.mapdb.DBMaker;
    1713import org.openstreetmap.gui.jmapviewer.JobDispatcher;
    1814import org.openstreetmap.gui.jmapviewer.OsmTileLoader;
     
    2218import org.openstreetmap.gui.jmapviewer.interfaces.TileSource;
    2319import org.openstreetmap.gui.jmapviewer.interfaces.TileSource.TileUpdate;
     20import org.openstreetmap.josm.Main;
    2421import org.openstreetmap.josm.data.preferences.BooleanProperty;
    2522
     
    3532   
    3633    public static final boolean debug = new BooleanProperty("imagerycache.debug", false).get();
    37 
    38     static class TileDAOMapDB {
    39         protected HashMap<String, DB> dbs = new HashMap<String, DB>();
    40         protected HashMap<String, Map<Long,DBTile>> storages  = new HashMap<String, Map<Long,DBTile>>();
    41         private final File cacheFolder;
    42        
    43         /**
    44          * Lazy creation of DB object associated to * @param source
    45          * or returning from cache
    46          */
    47         private synchronized DB getDB(String source) {
    48             DB db = dbs.get(source);
    49             if (db==null) {
    50                 try {
    51                 db = DBMaker
    52                     .newFileDB(new File(cacheFolder, "tiles_"+source.replaceAll("[\\\\/:*?\"<>| ]", "_")))
    53                     .randomAccessFileEnableIfNeeded()
    54                     .journalDisable()
    55                     .closeOnJvmShutdown()
    56                     .make();
    57                 dbs.put(source, db);
    58                 } catch (Exception e) {
    59                     System.out.println("Error: Can not create MapDB file");
    60                     e.printStackTrace(System.out);
    61                 }
    62             }
    63             return db;
    64         }
    65 
    66         private synchronized Map<Long,DBTile> getStorage(String source) {
    67             Map<Long, DBTile> m = storages.get(source);
    68             if (m == null) {
    69                 try {
    70                     DB d = getDB(source);
    71                     m = d.getHashMap("tiles");
    72                     storages.put(source, m);
    73                     if (debug) System.out.println("Created storage "+source);
    74                 } catch (Exception e) {
    75                     System.out.println("Error: Can not create HashMap in MapDB storage");
    76                     e.printStackTrace(System.out);
    77                 }
    78             }
    79             return m;
    80         }
    81        
    82         public TileDAOMapDB(File cacheFolder) {
    83             this.cacheFolder = cacheFolder;
    84         }
    85        
    86                
    87         DBTile getById(String source, long id) {
    88             return getStorage(source).get(id);
    89         }
    90 
    91         protected void updateModTime(String source, long id, DBTile dbTile) {
    92             if (debug) System.out.println("Tile "+id+": Updating modification time");
    93             getStorage(source).put(id, dbTile);
    94         }
    95 
    96         protected void updateTile(String source, long id, DBTile dbTile) {
    97             if (debug) System.out.println("Tile "+id+": Updating tile in base");
    98             getStorage(source).put(id, dbTile);
    99         }
    100 
    101         protected void deleteTile(String source, long id) {
    102             getStorage(source).remove(id);
    103         }
    104 
    105 
    106     }
    10734           
    10835    TileDAOMapDB dao;
    109                        
    11036   
    11137    protected long maxCacheFileAge = FILE_AGE_ONE_WEEK;
     
    11541    public OsmDBTilesLoader(TileLoaderListener smap, File cacheFolder) {
    11642        super(smap);
    117         dao = new TileDAOMapDB(cacheFolder);
     43        dao = TileDAOMapDB.getInstance();
     44        dao.setCacheFolder(cacheFolder);
    11845    }
    11946   
     
    12249        return new DatabaseLoadJob(tile);
    12350    }
    124    
    125     static class DBTile implements Serializable {
    126         byte data[];
    127         Map<String, String> metaData;
    128         long lastModified;
    129     }
    13051
    13152    protected class DatabaseLoadJob implements TileJob {
     
    13354        private final Tile tile;
    13455        File tileCacheDir;
     56       
     57        /**
     58         * Stores the tile loaded from database, null if nothing found.
     59         */
    13560        DBTile dbTile = null;
    13661        long fileAge = 0;
    137         boolean fileTilePainted = false;
    13862       
    13963        long id;
     
    16185                return;
    16286            }
    163             if (fileTilePainted) {
     87            if (dbTile != null) {
    16488                TileJob job = new TileJob() {
    165                     public void run() {
    166                         loadOrUpdateTile();
    167                     }
    168                     public Tile getTile() {
     89                    @Override public void run() {
     90                        loadOrUpdateTileFromServer();
     91                    }
     92                    @Override public Tile getTile() {
    16993                        return tile;
    17094                    }
     
    17296                JobDispatcher.getInstance().addJob(job);
    17397            } else {
    174                 loadOrUpdateTile();
    175             }
    176         }
    177 
     98                loadOrUpdateTileFromServer();
     99            }
     100        }
     101
     102        /**
     103         * Loads tile from database.
     104         * There can be dbTile != null but the tile is outdated and reload is still needed
     105         * @return true if no loading from server is needed.
     106         */
    178107        private boolean loadTileFromFile() {
    179108            ByteArrayInputStream bin = null;
     
    182111               
    183112                if (dbTile == null) return false;
     113               
     114                loadMetadata();
     115                if (debug) System.out.println(id+": found in cache, metadata ="+dbTile.metaData);
    184116
    185117                if ("no-tile".equals(tile.getValue("tile-info")))
    186118                {
    187119                    tile.setError("No tile at this zoom level");
    188                     if (dbTile!=null) {
    189                         dao.deleteTile(sourceName, id);
    190                     }
     120                    dao.deleteTile(sourceName, id);
    191121                } else {
    192122                    bin = new ByteArrayInputStream(dbTile.data);
     
    202132                    tile.setLoaded(true);
    203133                    listener.tileLoadingFinished(tile, true);
    204                     fileTilePainted = true;
    205                     return true;
    206                 }
    207                 listener.tileLoadingFinished(tile, true);
    208                 fileTilePainted = true;
     134                    return true; // tile loaded
     135                } else {
     136                    listener.tileLoadingFinished(tile, true);
     137                    return false; // Tile is loaded, but too old. Should be reloaded from server
     138                }
    209139            } catch (Exception e) {
     140                System.out.println("Error: Can not load tile from database: "+sourceName+":"+id);
     141                e.printStackTrace(System.out);
    210142                try {
    211143                    if (bin != null) {
     
    213145                        dao.deleteTile(sourceName, id);
    214146                    }
    215                 } catch (Exception e1) {
    216                 }
     147                } catch (Exception e1) {   }
    217148                dbTile = null;
    218149                fileAge = 0;
    219             }
    220             return false;
     150                return false; // tile is not because of some error (corrupted database, etc.)
     151            } catch (Error e) { // this is bad, bat MapDB throws it
     152                System.out.println("Serious database error: Can not load tile from database: "+sourceName+":"+id);
     153                e.printStackTrace(System.out);
     154                dbTile = null;  fileAge = 0;  return false;                                           
     155            }
    221156        }
    222157
     
    225160        }
    226161               
    227         private void loadOrUpdateTile() {
     162        private void loadOrUpdateTileFromServer() {
    228163           
    229164            try {
     
    231166                final TileUpdate tileUpdate = tile.getSource().getTileUpdate();
    232167                if (dbTile != null) {
     168                    // MapDB wants simmutable entities
     169                    dbTile = new DBTile(dbTile);
    233170                    switch (tileUpdate) {
    234171                    case IfModifiedSince:   // (1)
     
    276213                loadTileMetadata(tile, urlConn);
    277214                dbTile.metaData = tile.getMetadata();
    278 
     215               
    279216                if ("no-tile".equals(tile.getValue("tile-info")))
    280217                {
     
    305242                listener.tileLoadingFinished(tile, false);
    306243                try {
    307                     System.out.println("Tile "+id+": Error: Failed loading from "+tile.getUrl());
     244                    System.out.println("Error: Tile "+id+" can not be loaded from"+tile.getUrl());
    308245                    e.printStackTrace(System.out);
    309246                } catch(IOException i) {
     
    381318        }
    382319
     320        /**
     321         * Loads attribute map from dbTile to tile
     322         */
     323        private void loadMetadata() {
     324            Map<String,String> m = dbTile.metaData;
     325            if (m==null) return;
     326            for (String k: m.keySet()) {
     327                tile.putValue(k, m.get(k));
     328            }
     329        }
    383330    }
    384    
    385331}
Note: See TracChangeset for help on using the changeset viewer.