PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/scripts/util/time_sync.py

http://github.com/sirikata/sirikata
Python | 106 lines | 78 code | 18 blank | 10 comment | 14 complexity | 2bed8c7c01e4b34ca0f532e7fd387c0b MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #!/usr/bin/python
  2. import sys
  3. import threading
  4. import time
  5. import subprocess
  6. import re
  7. import errno
  8. # Settings
  9. ntp_interval = 30.0
  10. heartbeat_interval = 60.0
  11. # signals if we're done
  12. done = False;
  13. def set_done():
  14. global done
  15. done = True
  16. last_heartbeat = time.time()
  17. def heartbeat():
  18. global last_heartbeat
  19. last_heartbeat = time.time()
  20. def check_heartbeat():
  21. global last_heartbeat
  22. global heartbeat_interval
  23. if (time.time() - last_heartbeat > heartbeat_interval):
  24. sys.stderr.write('Heartbeat signal lost\n')
  25. sys.exit(-1)
  26. # Regex to match the offset info
  27. float_regex_str = '[-+]?[0-9]*\.?[0-9]+'
  28. offset_regex_str = 'offset ' + float_regex_str
  29. float_re = re.compile(float_regex_str)
  30. offset_re = re.compile(offset_regex_str)
  31. # monitors stdin, watching for a signal to stop
  32. class MonitorStdInThread(threading.Thread):
  33. def __init__(self):
  34. threading.Thread.__init__(self)
  35. self.daemon = True
  36. def run(self):
  37. try:
  38. data = sys.stdin.read(1)
  39. if len(data) == 0:
  40. sys.stderr.write('Monitor read error\n')
  41. set_done()
  42. sys.exit(-1)
  43. elif (data == 'h'):
  44. heartbeat()
  45. elif (data == 'k'):
  46. set_done()
  47. except IOError, e:
  48. if e.errno == errno.EPIPE:
  49. sys.stderr.write('Broken monitor pipe\n')
  50. set_done()
  51. sys.exit(-1)
  52. class MonitorHeartbeatThread(threading.Thread):
  53. def __init__(self):
  54. threading.Thread.__init__(self)
  55. self.daemon = True
  56. def run(self):
  57. global heartbeat_interval
  58. while(True):
  59. check_heartbeat()
  60. time.sleep(heartbeat_interval / 4)
  61. # Main code
  62. server_name = sys.argv[1]
  63. # Monitor std in waiting for signal to stop
  64. monitor = MonitorStdInThread()
  65. monitor.start()
  66. heartbeat()
  67. monitor_heartbeat = MonitorHeartbeatThread()
  68. monitor_heartbeat.start()
  69. # Just loop checking and transmiting values
  70. while (done == False):
  71. ntp_process = subprocess.Popen(["ntpdate", "-q", "-p", "8", server_name], stdout=subprocess.PIPE)
  72. output = ntp_process.communicate()[0]
  73. results = ntp_process.returncode
  74. match = offset_re.search(output)
  75. offset_match = float_re.search(match.group())
  76. try:
  77. print offset_match.group()
  78. sys.stdout.flush()
  79. except IOError, e:
  80. if e.errno == errno.EPIPE:
  81. set_done()
  82. break
  83. elif e.errno != errno.EPIPE:
  84. # if its EPIPE, the other process closed the pipe, ignore
  85. # otherwise, rethrow
  86. raise
  87. time.sleep(ntp_interval)
  88. sys.exit(0)