Changeset 1caf3e7


Ignore:
Timestamp:
Apr 21, 2015 2:22:05 PM (5 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
b67bbd70
Parents:
fd82fff
Message:

Router timestamper:

  • Add country-to-continent mapping
  • Add continent pool.ntp.org zones as first fallback, this will improve time service for countries that don't have a zone
  • Don't start threads in constructors
  • Fix logging, better prevention of initialization loops
  • Log severe errors to wrapper log also

continent.txt file from http://dev.maxmind.com/geoip/legacy/codes/country_continent/
Creative Commons Attribution-ShareAlike? 3.0 Unported License
http://dev.maxmind.com/geoip/legacy/geolite/
Terms already met in LICENSE.txt

Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • build.xml

    rfd82fff r1caf3e7  
    14061406        <!-- small enough to include for now -->
    14071407        <copy file="installer/resources/geoipv6.dat.gz" todir="pkg-temp/geoip/" />
     1408        <copy file="installer/resources/continents.txt" todir="pkg-temp/geoip/" />
    14081409    </target>
    14091410
     
    14231424        <copy file="installer/resources/geoipv6.dat.gz" todir="pkg-temp/geoip/" />
    14241425        <copy file="installer/resources/countries.txt" todir="pkg-temp/geoip/" />
     1426        <copy file="installer/resources/continents.txt" todir="pkg-temp/geoip/" />
    14251427    </target>
    14261428
  • router/java/src/net/i2p/router/RouterClock.java

    rfd82fff r1caf3e7  
    4141    private long _lastChanged;
    4242    private int _lastStratum;
    43     private final Timestamper _timeStamper;
     43    private final RouterTimestamper _timeStamper;
    4444
    4545    /**
     
    5454    private volatile long _lastShiftNanos;
    5555
     56    /**
     57     *  Does not start. Caller MUST call start()
     58     */
    5659    public RouterClock(RouterContext context) {
    5760        super(context);
     
    6164        _lastShiftNanos = System.nanoTime();
    6265        _timeStamper = new RouterTimestamper(context, this);
     66    }
     67
     68    /**
     69     *  Cannot be stopped, but RouterTimestamper registers a shutdown task.
     70     *  @since 0.9.20
     71     */
     72    public void start() {
     73        _timeStamper.startTimestamper();
    6374    }
    6475
  • router/java/src/net/i2p/router/RouterContext.java

    rfd82fff r1caf3e7  
    484484    protected void initializeClock() {
    485485        synchronized (_lock1) {
    486             if (_clock == null)
    487                 _clock = new RouterClock(this);
     486            if (_clock == null) {
     487                RouterClock rc = new RouterClock(this);
     488                rc.start();
     489                _clock = rc;
     490            }
    488491            _clockInitialized = true;
    489492        }
  • router/java/src/net/i2p/router/time/RouterTimestamper.java

    rfd82fff r1caf3e7  
    2121public class RouterTimestamper extends Timestamper {
    2222    private final I2PAppContext _context;
     23    // warning, may be null
    2324    private Log _log;
    2425    private final List<String> _servers;
    25     private List<String> _priorityServers;
     26    private List<List<String>> _priorityServers;
    2627    private final List<UpdateListener> _listeners;
    2728    private int _queryFrequency;
     
    3435    private volatile boolean _isRunning;
    3536    private Thread _timestamperThread;
     37    private final Zones _zones;
    3638   
    3739    private static final int MIN_QUERY_FREQUENCY = 5*60*1000;
    3840    private static final int DEFAULT_QUERY_FREQUENCY = 11*60*1000;
    3941    private static final String DEFAULT_SERVER_LIST = "0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org";
    40     private static final String DEFAULT_DISABLED = "true";
     42    private static final boolean DEFAULT_DISABLED = true;
    4143    /** how many times do we have to query if we are changing the clock? */
    4244    private static final int DEFAULT_CONCURRING_SERVERS = 3;
     
    5254    private static final int MAX_VARIANCE = 10*1000;
    5355       
     56    /**
     57     *  Does not start. Caller MUST call startTimestamper()
     58     */
    5459    public RouterTimestamper(I2PAppContext ctx) {
    5560        this(ctx, null, true);
    5661    }
    5762   
     63    /**
     64     *  Does not start. Caller MUST call startTimestamper()
     65     */
    5866    public RouterTimestamper(I2PAppContext ctx, UpdateListener lsnr) {
    5967        this(ctx, lsnr, true);
    6068    }
     69
     70    /**
     71     *  Does not start. Caller MUST call startTimestamper()
     72     */
    6173    public RouterTimestamper(I2PAppContext ctx, UpdateListener lsnr, boolean daemon) {
    6274        super();
     
    7284        // so the property must be set at startup.
    7385        // We still need to be instantiated since the router calls clock().getTimestamper().waitForInitialization()
    74         String disabled = ctx.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
    75         if (Boolean.parseBoolean(disabled)) {
     86        _disabled = ctx.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
     87        if (_disabled) {
    7688            _initialized = true;
     89            _zones = null;
     90            System.out.println("Warning: NTP is disabled");
    7791            return;
    7892        }
    7993        if (lsnr != null)
    8094            _listeners.add(lsnr);
     95        _zones = new Zones(ctx);
    8196        updateConfig();
    82         startTimestamper();
    8397    }
    8498   
     
    111125    }
    112126   
    113     private void startTimestamper() {
     127    public void startTimestamper() {
     128        if (_disabled || _initialized)
     129            return;
    114130        _timestamperThread = new I2PThread(this, "Timestamper", _daemon);
    115131        _timestamperThread.setPriority(I2PThread.MIN_PRIORITY);
     
    150166    @Override
    151167    public void run() {
    152         try { Thread.sleep(1000); } catch (InterruptedException ie) {}
    153         _log = _context.logManager().getLog(Timestamper.class);
    154         if (_log.shouldLog(Log.INFO))
    155             _log.info("Starting timestamper");
    156168        boolean lastFailed = false;
    157169        try {
    158170            while (_isRunning) {
     171                // NOTE: _log is null the first time through, to prevent problems and stack overflows
    159172                updateConfig();
    160173                if (!_disabled) {
    161                     // first the servers for our country, if we know what country we're in...
     174                    // first the servers for our country and continent, we know what country we're in...
    162175                    if (_priorityServers != null) {
    163                         if (_log.shouldLog(Log.DEBUG))
    164                             _log.debug("Querying servers " + _priorityServers);
    165                         try {
    166                             lastFailed = !queryTime(_priorityServers.toArray(new String[_priorityServers.size()]));
    167                         } catch (IllegalArgumentException iae) {
    168                             if ( (!lastFailed) && (_log.shouldLog(Log.WARN)) )
    169                                 _log.warn("Unable to reach country-specific NTP servers");
    170                             lastFailed = true;
     176                        for (List<String> servers : _priorityServers) {
     177                            if (_log != null && _log.shouldDebug())
     178                                _log.debug("Querying servers " + servers);
     179                            try {
     180                                lastFailed = !queryTime(servers.toArray(new String[servers.size()]));
     181                            } catch (IllegalArgumentException iae) {
     182                                if (!lastFailed && _log != null && _log.shouldWarn())
     183                                    _log.warn("Unable to reach any regional NTP servers: " + servers);
     184                                lastFailed = true;
     185                            }
     186                            if (!lastFailed)
     187                                break;
    171188                        }
    172189                    }
    173190                    // ... and then the global list, if that failed
    174191                    if (_priorityServers == null || lastFailed) {
    175                         if (_log.shouldLog(Log.DEBUG))
     192                        if (_log != null && _log.shouldDebug())
    176193                            _log.debug("Querying servers " + _servers);
    177194                        try {
    178195                            lastFailed = !queryTime(_servers.toArray(new String[_servers.size()]));
    179196                        } catch (IllegalArgumentException iae) {
    180                             if ( (!_initialized) && (_log.shouldLog(Log.ERROR)) ) {
    181                                 List<String> all = new ArrayList<String>();
    182                                 if (_priorityServers != null)
    183                                     all.addAll(_priorityServers);
    184                                 all.addAll(_servers);
    185                                 _log.error("Unable to reach any of the NTP servers " + all + " - network disconnected? Or set time.sntpServerList=myserver1.com,myserver2.com in advanced configuration.");
    186                             }
    187197                            lastFailed = true;
    188198                        }
     
    190200                }
    191201               
    192                 _initialized = true;
     202                boolean wasInitialized = _initialized;
     203                if (!wasInitialized)
     204                    _initialized = true;
    193205                synchronized (this) { notifyAll(); }
     206                if (!wasInitialized) {
     207                    // let the log manager get initialized
     208                    try { Thread.sleep(10*1000); } catch (InterruptedException ie) {}
     209                    // NOW we set up logging
     210                    _log = _context.logManager().getLog(RouterTimestamper.class);
     211                    if (lastFailed) {
     212                        List<String> all = new ArrayList<String>(9);
     213                        if (_priorityServers != null) {
     214                            for (List<String> servers : _priorityServers) {
     215                                all.addAll(servers);
     216                            }
     217                        }
     218                        all.addAll(_servers);
     219                        String msg = "Unable to reach any of the NTP servers " + all +
     220                                     " - network disconnected? Or set time.sntpServerList=myserver1.com,myserver2.com in advanced configuration.";
     221                        _log.logAlways(Log.WARN, msg);
     222                        System.out.println("Warning: " + msg);
     223                    } else if (_log.shouldDebug()) {
     224                        _log.debug("NTP initialization successful");
     225                        int i = 1;
     226                        if (_priorityServers != null) {
     227                            for (List<String> servers : _priorityServers) {
     228                                _log.debug("NTP Server list " + (i++) + ": " + servers);
     229                            }
     230                        }
     231                        _log.debug("NTP Server list " + i + ": " + _servers);
     232                    }
     233                }
    194234                long sleepTime;
    195235                if (lastFailed) {
     
    207247            }
    208248        } catch (Throwable t) {
    209             _log.log(Log.CRIT, "Timestamper died!", t);
    210249            synchronized (this) { notifyAll(); }
     250            if (_log != null)
     251                _log.log(Log.CRIT, "Timestamper died!", t);
     252            t.printStackTrace();
    211253        }
    212254    }
     
    233275            if (i == 0) {
    234276                if (Math.abs(delta) < MAX_VARIANCE) {
    235                     if (_log.shouldLog(Log.INFO))
     277                    if (_log != null && _log.shouldInfo())
    236278                        _log.info("a single SNTP query was within the tolerance (" + delta + "ms)");
    237279                    // If less than a half second on the first try, we're in good shape
     
    244286            } else {
    245287                if (Math.abs(delta - expectedDelta) > MAX_VARIANCE) {
    246                     if (_log.shouldLog(Log.ERROR)) {
     288                    if (_log != null && _log.shouldError()) {
    247289                        StringBuilder err = new StringBuilder(96);
    248290                        err.append("SNTP client variance exceeded at query ").append(i);
     
    261303        }
    262304        stampTime(now, stratum);
    263         if (_log.shouldLog(Log.DEBUG)) {
     305        if (_log != null && _log.shouldDebug()) {
    264306            StringBuilder buf = new StringBuilder(64);
    265307            buf.append("Deltas: ");
     
    281323             lsnr.setNow(now, stratum);
    282324        }
    283         if (_log.shouldLog(Log.DEBUG))
     325        if (_log != null && _log.shouldDebug())
    284326            _log.debug("Stamped the time as " + now + " (delta=" + (now-before) + ")");
    285327    }
    286328 
    287329    /**
    288      * Reload all the config elements from the appContext
    289      *
     330     * Reload all the config elements from the appContext.
     331     * No logging allowed here
    290332     */
    291333    private void updateConfig() {
     
    299341                    country = country.toLowerCase(Locale.US);
    300342            }
    301             if (country != null &&  country.length() > 0) {
    302                 _priorityServers = new ArrayList<String>(3);
    303                 for (int i = 0; i < 3; i++)
    304                      _priorityServers.add(i + "." + country + ".pool.ntp.org");
     343            if (country != null &&  country.length() > 0 &&
     344                !country.equals("a1") && !country.equals("a2")) {
     345                _priorityServers = new ArrayList<List<String>>(2);
     346                List<String> p1 = new ArrayList<String>(3);
     347                for (int i = 0; i < 3; i++) {
     348                     p1.add(i + "." + country + ".pool.ntp.org");
     349                }
     350                _priorityServers.add(p1);
     351                String zone = _zones.getZone(country);
     352                if (zone != null) {
     353                    List<String> p2 = new ArrayList<String>(3);
     354                    for (int i = 0; i < 3; i++) {
     355                        p2.add(i + "." + zone + ".pool.ntp.org");
     356                    }
     357                    _priorityServers.add(p2);
     358                }
    305359            } else {
    306360                _priorityServers = null;
     
    321375                                   _context.getProperty(PROP_QUERY_FREQUENCY, DEFAULT_QUERY_FREQUENCY));
    322376       
    323         String disabled = _context.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
    324         _disabled = Boolean.parseBoolean(disabled);
     377        _disabled = _context.getProperty(PROP_DISABLED, DEFAULT_DISABLED);
    325378       
    326379        _concurringServers = Math.min(4, Math.max(1,
  • router/java/src/net/i2p/router/transport/GeoIP.java

    rfd82fff r1caf3e7  
    7474    static final String PROP_GEOIP_ENABLED = "routerconsole.geoip.enable";
    7575    public static final String PROP_GEOIP_DIR = "geoip.dir";
    76     static final String GEOIP_DIR_DEFAULT = "geoip";
     76    public static final String GEOIP_DIR_DEFAULT = "geoip";
    7777    static final String GEOIP_FILE_DEFAULT = "geoip.txt";
    7878    static final String COUNTRY_FILE_DEFAULT = "countries.txt";
Note: See TracChangeset for help on using the changeset viewer.