Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c2bf66f
commit b7cd999
Showing
9 changed files
with
209 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
.nyc_output | ||
build | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
"<!(node -e \"require('nan')\")" | ||
], | ||
"sources": [ | ||
"src/monitor.cc", | ||
"src/binding.cc" | ||
] | ||
}] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
'use strict' | ||
|
||
const bindings = require('bindings')('resetdatecache') | ||
var bindings = require('bindings')('resetdatecache'); | ||
|
||
module.exports = bindings.reset | ||
module.exports = bindings.reset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
#include "monitor.h" | ||
|
||
static const uint64_t kDebounceDelay = 500; | ||
|
||
void TimeZoneMonitor::_asyncWorkCb(uv_async_t *work) { | ||
TimeZoneMonitor *monitor = static_cast<TimeZoneMonitor *>(work->data); | ||
monitor->ThreadedCallback(); | ||
monitor->DebouncedNotify(); | ||
} | ||
|
||
void TimeZoneMonitor::tzDelayExpired(uv_timer_t* handle) { | ||
TimeZoneMonitor *monitor = static_cast<TimeZoneMonitor *>(handle->data); | ||
monitor->Notify(); | ||
} | ||
|
||
TimeZoneMonitor::TimeZoneMonitor() { | ||
uv_async_init(uv_default_loop(), &_asyncWork, _asyncWorkCb); | ||
uv_timer_init(uv_default_loop(), &_debouncer); | ||
_asyncWork.data = this; | ||
_debouncer.data = this; | ||
|
||
uv_unref((uv_handle_t*)&_asyncWork); | ||
uv_unref((uv_handle_t*)&_debouncer); | ||
} | ||
|
||
void TimeZoneMonitor::ThreadedNotify() { | ||
uv_async_send(&_asyncWork); | ||
} | ||
|
||
void TimeZoneMonitor::DebouncedNotify() { | ||
//Some platforms write the file instead of symlinking it, add a small delay just to be sure | ||
uv_timer_start(&_debouncer, TimeZoneMonitor::tzDelayExpired, kDebounceDelay, 0); | ||
} | ||
|
||
#ifdef _WIN32 | ||
# include "monitor_windows.cc" | ||
#elif __ANDROID__ | ||
# include "monitor_android.cc" | ||
#elif __APPLE__ | ||
# include "monitor_unix.cc" | ||
#elif __unix__ | ||
# include "monitor_unix.cc" | ||
#else | ||
// static | ||
TimeZoneMonitor *TimeZoneMonitor::Create() { | ||
return new TimeZoneMonitor(); | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
|
||
#ifndef _TZD_MONITOR_H | ||
#define _TZD_MONITOR_H | ||
#include <uv.h> | ||
|
||
class TimeZoneMonitor { | ||
public: | ||
// Returns a new TimeZoneMonitor object specific to the platform. | ||
static TimeZoneMonitor *Create(); | ||
void Notify(); | ||
protected: | ||
TimeZoneMonitor(); //Creation can only occur through create. | ||
void DebouncedNotify(); | ||
void ThreadedNotify(); | ||
virtual void ThreadedCallback() {} | ||
private: | ||
static void tzDelayExpired(uv_timer_t* handle); | ||
static void _asyncWorkCb(uv_async_t *work); | ||
uv_async_t _asyncWork; | ||
uv_timer_t _debouncer; | ||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
//TODO: We should catch the TIMEZONE_CHANGED intent and fire ThreadedNotify | ||
//Unfortunatly, it looks like this part requires some jni magic which may not work from inside a module | ||
//Lets disable the notifications for now... | ||
|
||
// static | ||
TimeZoneMonitor *TimeZoneMonitor::Create() { | ||
return new TimeZoneMonitor(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#include <uv.h> | ||
#include <string.h> | ||
#include "monitor.h" | ||
|
||
|
||
// There is no true standard for where time zone information is actually | ||
// stored. glibc uses /etc/localtime, uClibc uses /etc/TZ, and some older | ||
// systems store the name of the time zone file within /usr/share/zoneinfo | ||
// in /etc/timezone. Different libraries and custom builds may mean that | ||
// still more paths are used. Just watch all three of these paths, because | ||
// false positives are harmless, assuming the false positive rate is | ||
// reasonable. | ||
static const char* kFilesToWatch[] = { | ||
"localtime", | ||
"timezone", | ||
"TZ", | ||
}; | ||
// libuv seems to have some troubles when monitoring symlinks. | ||
//It does however work if we monitor the parent folder non-recursively | ||
static const char* kWatchFolder = "/etc/"; | ||
|
||
class TimeZoneMonitorUnix : public TimeZoneMonitor { | ||
public: | ||
TimeZoneMonitorUnix(); | ||
private: | ||
static void tzChange(uv_fs_event_t *handle, const char *filename, int events, int status); | ||
uv_fs_event_t fileWatcher; | ||
}; | ||
|
||
|
||
void TimeZoneMonitorUnix::tzChange(uv_fs_event_t *handle, const char *filename, int events, int status) { | ||
TimeZoneMonitorUnix *monitor = static_cast<TimeZoneMonitorUnix *>(handle->data); | ||
for (size_t i = 0; i < sizeof(kFilesToWatch)/sizeof(kFilesToWatch[0]); i++) { | ||
if(strcmp(kFilesToWatch[i], filename) == 0) { | ||
monitor->DebouncedNotify(); //Debounce the notification (sometimes multiple files change) | ||
return; | ||
} | ||
} | ||
} | ||
|
||
TimeZoneMonitorUnix::TimeZoneMonitorUnix() | ||
{ | ||
uv_fs_event_init(uv_default_loop(), &fileWatcher); | ||
fileWatcher.data = this; | ||
uv_unref((uv_handle_t*)&fileWatcher); | ||
|
||
uv_fs_event_start(&fileWatcher, TimeZoneMonitorUnix::tzChange, kWatchFolder, 0); | ||
} | ||
|
||
// static | ||
TimeZoneMonitor *TimeZoneMonitor::Create() { | ||
return new TimeZoneMonitorUnix(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#include "monitor.h" | ||
|
||
static const DWORD dwFilter = REG_NOTIFY_CHANGE_LAST_SET; | ||
|
||
class TimeZoneMonitorWindows : public TimeZoneMonitor { | ||
public: | ||
TimeZoneMonitorWindows(); | ||
protected: | ||
void ThreadedCallback(); | ||
private: | ||
void Notify(); | ||
void SetUp(void); | ||
static void TimeZoneChangeThreadedCallback(PVOID context, BOOLEAN timeout); | ||
HANDLE hTZEvent; | ||
HKEY hRegKey; | ||
}; | ||
|
||
|
||
void TimeZoneMonitorWindows::ThreadedCallback() { | ||
//Setup only causes notify to be called once | ||
SetUp(); | ||
} | ||
|
||
void TimeZoneMonitorWindows::SetUp() { | ||
ResetEvent(hTZEvent); | ||
// Watch the registry key for a change of value, must be run on main thread | ||
RegNotifyChangeKeyValue(hRegKey, TRUE, | ||
dwFilter, hTZEvent, TRUE); | ||
} | ||
|
||
TimeZoneMonitorWindows::TimeZoneMonitorWindows() { | ||
|
||
HANDLE hWait; | ||
LONG lErrorCode; | ||
lErrorCode = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation", 0, KEY_NOTIFY, &hRegKey); | ||
if (lErrorCode != ERROR_SUCCESS) return; | ||
|
||
// Create an event. | ||
hTZEvent = CreateEvent(NULL, TRUE, FALSE, NULL); | ||
if (hTZEvent == NULL) return; | ||
|
||
SetUp(); | ||
|
||
//Invoke the TimeZoneChangeThreadedCallback upon a change | ||
RegisterWaitForSingleObject( | ||
&hWait, hTZEvent, TimeZoneChangeThreadedCallback, | ||
this, INFINITE, WT_EXECUTEINWAITTHREAD | ||
); | ||
} | ||
|
||
//static | ||
void TimeZoneMonitorWindows::TimeZoneChangeThreadedCallback(PVOID context, BOOLEAN timeout) { | ||
TimeZoneMonitorWindows *monitor = static_cast<TimeZoneMonitorWindows *>(context); | ||
monitor->ThreadedNotify(); //First enter the main eventloop, then debounce the notify | ||
} | ||
|
||
// static | ||
TimeZoneMonitor *TimeZoneMonitor::Create() { | ||
return new TimeZoneMonitorWindows(); | ||
} |