NtpTimeProvider.java
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 Google Inc.
00003  * 
00004  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
00005  * use this file except in compliance with the License. You may obtain a copy of
00006  * the License at
00007  * 
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  * 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
00013  * License for the specific language governing permissions and limitations under
00014  * the License.
00015  */
00016 
00017 package org.ros.time;
00018 
00019 import com.google.common.base.Preconditions;
00020 import com.google.common.collect.Lists;
00021 
00022 import org.apache.commons.logging.Log;
00023 import org.apache.commons.logging.LogFactory;
00024 import org.apache.commons.net.ntp.NTPUDPClient;
00025 import org.apache.commons.net.ntp.TimeInfo;
00026 import org.ros.math.CollectionMath;
00027 import org.ros.message.Duration;
00028 import org.ros.message.Time;
00029 
00030 import java.io.IOException;
00031 import java.net.InetAddress;
00032 import java.util.List;
00033 import java.util.concurrent.ScheduledExecutorService;
00034 import java.util.concurrent.ScheduledFuture;
00035 import java.util.concurrent.TimeUnit;
00036 
00042 public class NtpTimeProvider implements TimeProvider {
00043 
00044   private static final boolean DEBUG = false;
00045   private static final Log log = LogFactory.getLog(NtpTimeProvider.class);
00046 
00047   private static final int SAMPLE_SIZE = 11;
00048   
00049   private final InetAddress host;
00050   private final ScheduledExecutorService scheduledExecutorService;
00051   private final WallTimeProvider wallTimeProvider;
00052   private final NTPUDPClient ntpClient;
00053 
00054   private long offset;
00055   private ScheduledFuture<?> scheduledFuture;
00056 
00061   public NtpTimeProvider(InetAddress host, ScheduledExecutorService scheduledExecutorService) {
00062     this.host = host;
00063     this.scheduledExecutorService = scheduledExecutorService;
00064     wallTimeProvider = new WallTimeProvider();
00065     ntpClient = new NTPUDPClient();
00066     offset = 0;
00067     scheduledFuture = null;
00068   }
00069 
00075   public void updateTime() throws IOException {
00076     List<Long> offsets = Lists.newArrayList();
00077     for (int i = 0; i < SAMPLE_SIZE; i++) {
00078       offsets.add(computeOffset());
00079     }
00080     offset = CollectionMath.median(offsets);
00081     log.info(String.format("NTP time offset: %d ms", offset));
00082   }
00083 
00084   private long computeOffset() throws IOException {
00085     if (DEBUG) {
00086       log.info("Updating time offset from NTP server: " + host.getHostName());
00087     }
00088     TimeInfo time;
00089     try {
00090       time = ntpClient.getTime(host);
00091     } catch (IOException e) {
00092       log.error("Failed to read time from NTP server: " + host.getHostName(), e);
00093       throw e;
00094     }
00095     time.computeDetails();
00096     return time.getOffset();
00097   }
00098 
00114   public void startPeriodicUpdates(long period, TimeUnit unit) {
00115     scheduledFuture =
00116         scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
00117           @Override
00118           public void run() {
00119             try {
00120               updateTime();
00121             } catch (IOException e) {
00122               log.error("Periodic NTP update failed.", e);
00123             }
00124           }
00125         }, 0, period, unit);
00126   }
00127 
00131   public void stopPeriodicUpdates() {
00132     Preconditions.checkNotNull(scheduledFuture);
00133     scheduledFuture.cancel(true);
00134     scheduledFuture = null;
00135   }
00136 
00137   @Override
00138   public Time getCurrentTime() {
00139     Time currentTime = wallTimeProvider.getCurrentTime();
00140     return currentTime.add(Duration.fromMillis(offset));
00141   }
00142 }


rosjava_core
Author(s):
autogenerated on Wed Aug 26 2015 16:06:49