You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
4.2 KiB
153 lines
4.2 KiB
/**
|
|
* Copyright (c) 2013 Yahoo! Inc. All rights reserved.
|
|
*
|
|
* Copyrights licensed under the MIT License. See the accompanying LICENSE file
|
|
* for terms.
|
|
*/
|
|
|
|
|
|
var events = require('events');
|
|
var Path = require('./Path.js');
|
|
var Event = require('./Event.js');
|
|
|
|
function WatcherManager() {
|
|
this.dataWatchers = {};
|
|
this.childWatchers = {};
|
|
this.existenceWatchers = {};
|
|
}
|
|
|
|
function registerWatcher(self, type, path, watcher) {
|
|
var watchers = self[type + 'Watchers'],
|
|
watcherExists = false;
|
|
|
|
Path.validate(path);
|
|
|
|
if (typeof watcher !== 'function') {
|
|
throw new Error('watcher must be a valid function.');
|
|
}
|
|
|
|
watchers[path] = watchers[path] || new events.EventEmitter();
|
|
watcherExists = watchers[path].listeners('notification').some(function (l) {
|
|
// This is rather hacky since node.js wraps the listeners using an
|
|
// internal function.
|
|
return l === watcher || l.listener === watcher;
|
|
});
|
|
|
|
if (!watcherExists) {
|
|
watchers[path].once('notification', watcher);
|
|
}
|
|
}
|
|
|
|
function getWatcherPaths(self, type) {
|
|
var watchers = self[type + 'Watchers'],
|
|
result = [];
|
|
|
|
Object.keys(watchers).forEach(function (path) {
|
|
if (watchers[path].listeners('notification').length > 0) {
|
|
result.push(path);
|
|
}
|
|
});
|
|
|
|
return result;
|
|
}
|
|
|
|
WatcherManager.prototype.registerDataWatcher = function (path, watcher) {
|
|
registerWatcher(this, 'data', path, watcher);
|
|
};
|
|
|
|
WatcherManager.prototype.getDataWatcherPaths = function () {
|
|
return getWatcherPaths(this, 'data');
|
|
};
|
|
|
|
WatcherManager.prototype.registerChildWatcher = function (path, watcher) {
|
|
registerWatcher(this, 'child', path, watcher);
|
|
};
|
|
|
|
WatcherManager.prototype.getChildWatcherPaths = function () {
|
|
return getWatcherPaths(this, 'child');
|
|
};
|
|
|
|
WatcherManager.prototype.registerExistenceWatcher = function (path, watcher) {
|
|
registerWatcher(this, 'existence', path, watcher);
|
|
};
|
|
|
|
WatcherManager.prototype.getExistenceWatcherPaths = function () {
|
|
return getWatcherPaths(this, 'existence');
|
|
};
|
|
|
|
WatcherManager.prototype.emit = function (watcherEvent) {
|
|
if (!watcherEvent) {
|
|
throw new Error('watcherEvent must be a valid object.');
|
|
}
|
|
|
|
var emitters = [],
|
|
event;
|
|
|
|
switch (watcherEvent.type) {
|
|
case Event.NODE_DATA_CHANGED:
|
|
case Event.NODE_CREATED:
|
|
if (this.dataWatchers[watcherEvent.path]) {
|
|
emitters.push(this.dataWatchers[watcherEvent.path]);
|
|
delete this.dataWatchers[watcherEvent.path];
|
|
}
|
|
|
|
if (this.existenceWatchers[watcherEvent.path]) {
|
|
emitters.push(this.existenceWatchers[watcherEvent.path]);
|
|
delete this.existenceWatchers[watcherEvent.path];
|
|
}
|
|
break;
|
|
case Event.NODE_CHILDREN_CHANGED:
|
|
if (this.childWatchers[watcherEvent.path]) {
|
|
emitters.push(this.childWatchers[watcherEvent.path]);
|
|
delete this.childWatchers[watcherEvent.path];
|
|
}
|
|
break;
|
|
case Event.NODE_DELETED:
|
|
if (this.dataWatchers[watcherEvent.path]) {
|
|
emitters.push(this.dataWatchers[watcherEvent.path]);
|
|
delete this.dataWatchers[watcherEvent.path];
|
|
}
|
|
if (this.childWatchers[watcherEvent.path]) {
|
|
emitters.push(this.childWatchers[watcherEvent.path]);
|
|
delete this.childWatchers[watcherEvent.path];
|
|
}
|
|
break;
|
|
default:
|
|
throw new Error('Unknown event type: ' + watcherEvent.type);
|
|
}
|
|
|
|
if (emitters.length < 1) {
|
|
return;
|
|
}
|
|
|
|
event = Event.create(watcherEvent);
|
|
|
|
emitters.forEach(function (emitter) {
|
|
emitter.emit('notification', event);
|
|
});
|
|
};
|
|
|
|
WatcherManager.prototype.isEmpty = function () {
|
|
var empty = true,
|
|
watchers,
|
|
paths,
|
|
i,
|
|
j;
|
|
|
|
watchers = [this.dataWatchers, this.existenceWatchers, this.childWatchers];
|
|
|
|
for (i = 0; i < watchers.length; i += 1) {
|
|
paths = Object.keys(watchers[i]);
|
|
|
|
for (j = 0; j < paths.length; j += 1) {
|
|
if (watchers[i][paths[j]].listeners('notification').length > 0) {
|
|
empty = false;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return empty;
|
|
};
|
|
|
|
module.exports = WatcherManager;
|
|
|