mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 784575 - Part 1: NetworkStatsService Modification. r=gene, r=acperez
This commit is contained in:
parent
d8d69c1253
commit
375f2e3953
@ -23,6 +23,9 @@ const TOPIC_INTERFACE_UNREGISTERED = "network-interface-unregistered";
|
||||
const NET_TYPE_WIFI = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
|
||||
const NET_TYPE_MOBILE = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
|
||||
|
||||
// The maximum traffic amount can be saved in the |cachedAppStats|.
|
||||
const MAX_CACHED_TRAFFIC = 500 * 1000 * 1000; // 500 MB
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIDBManager",
|
||||
"@mozilla.org/dom/indexeddb/manager;1",
|
||||
"nsIIndexedDatabaseManager");
|
||||
@ -35,6 +38,10 @@ XPCOMUtils.defineLazyServiceGetter(this, "networkManager",
|
||||
"@mozilla.org/network/manager;1",
|
||||
"nsINetworkManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
let myGlobal = this;
|
||||
|
||||
this.NetworkStatsService = {
|
||||
@ -74,6 +81,10 @@ this.NetworkStatsService = {
|
||||
this.timer.initWithCallback(this, this._db.sampleRate,
|
||||
Ci.nsITimer.TYPE_REPEATING_PRECISE);
|
||||
|
||||
// App stats are firstly stored in the cached.
|
||||
this.cachedAppStats = Object.create(null);
|
||||
this.cachedAppStatsDate = new Date();
|
||||
|
||||
this.updateQueue = [];
|
||||
this.isQueueRunning = false;
|
||||
},
|
||||
@ -164,15 +175,38 @@ this.NetworkStatsService = {
|
||||
* In order to return updated stats, first is performed a call to
|
||||
* updateAllStats function, which will get last stats from netd
|
||||
* and update the database.
|
||||
* Then, depending on the request (stats per interface or total stats)
|
||||
* Then, depending on the request (stats per appId or total stats)
|
||||
* it retrieve them from database and return to the manager.
|
||||
*/
|
||||
getStats: function getStats(mm, msg) {
|
||||
this.updateAllStats(function onStatsUpdated(aResult, aMessage) {
|
||||
|
||||
let options = msg.data;
|
||||
let data = msg.data;
|
||||
|
||||
let options = { appId: 0,
|
||||
connectionType: data.connectionType,
|
||||
start: data.start,
|
||||
end: data.end };
|
||||
|
||||
let manifestURL = data.manifestURL;
|
||||
if (manifestURL) {
|
||||
let appId = appsService.getAppLocalIdByManifestURL(manifestURL);
|
||||
if (DEBUG) {
|
||||
debug("get appId: " + appId + " from manifestURL: " + manifestURL);
|
||||
}
|
||||
|
||||
if (!appId) {
|
||||
mm.sendAsyncMessage("NetworkStats:Get:Return",
|
||||
{ id: msg.id, error: "Invalid manifestURL", result: null });
|
||||
return;
|
||||
}
|
||||
|
||||
options.appId = appId;
|
||||
options.manifestURL = manifestURL;
|
||||
}
|
||||
|
||||
if (DEBUG) {
|
||||
debug("getstats for: - " + options.connectionType + " -");
|
||||
debug("getStats for options: " + JSON.stringify(options));
|
||||
}
|
||||
|
||||
if (!options.connectionType || options.connectionType.length == 0) {
|
||||
@ -207,6 +241,9 @@ this.NetworkStatsService = {
|
||||
},
|
||||
|
||||
updateAllStats: function updateAllStats(callback) {
|
||||
// Update |cachedAppStats|.
|
||||
this.updateCachedAppStats();
|
||||
|
||||
let elements = [];
|
||||
let lastElement;
|
||||
|
||||
@ -356,10 +393,11 @@ this.NetworkStatsService = {
|
||||
return;
|
||||
}
|
||||
|
||||
let stats = { connectionType: this._connectionTypes[connType].name,
|
||||
let stats = { appId: 0,
|
||||
connectionType: this._connectionTypes[connType].name,
|
||||
date: date,
|
||||
rxBytes: txBytes,
|
||||
txBytes: rxBytes};
|
||||
rxBytes: rxBytes,
|
||||
txBytes: txBytes };
|
||||
|
||||
if (DEBUG) {
|
||||
debug("Update stats for " + stats.connectionType + ": rx=" + stats.rxBytes +
|
||||
@ -377,6 +415,130 @@ this.NetworkStatsService = {
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
* Function responsible for receiving per-app stats.
|
||||
*/
|
||||
saveAppStats: function saveAppStats(aAppId, aConnectionType, aTimeStamp, aRxBytes, aTxBytes, aCallback) {
|
||||
if (DEBUG) {
|
||||
debug("saveAppStats: " + aAppId + " " + aConnectionType + " " +
|
||||
aTimeStamp + " " + aRxBytes + " " + aTxBytes);
|
||||
}
|
||||
|
||||
// |aAppId| can not be 0 or null in this case.
|
||||
if (!aAppId) {
|
||||
return;
|
||||
}
|
||||
|
||||
let stats = { appId: aAppId,
|
||||
connectionType: this._connectionTypes[aConnectionType].name,
|
||||
date: new Date(aTimeStamp),
|
||||
rxBytes: aRxBytes,
|
||||
txBytes: aTxBytes };
|
||||
|
||||
// Generate an unique key from |appId| and |connectionType|,
|
||||
// which is used to retrieve data in |cachedAppStats|.
|
||||
let key = stats.appId + stats.connectionType;
|
||||
|
||||
// |cachedAppStats| only keeps the data with the same date.
|
||||
// If the incoming date is different from |cachedAppStatsDate|,
|
||||
// both |cachedAppStats| and |cachedAppStatsDate| will get updated.
|
||||
let diff = (this._db.normalizeDate(stats.date) -
|
||||
this._db.normalizeDate(this.cachedAppStatsDate)) /
|
||||
this._db.sampleRate;
|
||||
if (diff != 0) {
|
||||
this.updateCachedAppStats(function onUpdated(success, message) {
|
||||
this.cachedAppStatsDate = stats.date;
|
||||
this.cachedAppStats[key] = stats;
|
||||
|
||||
if (!aCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
aCallback.notify(false, message);
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback.notify(true, "ok");
|
||||
}.bind(this));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to find the matched row in the cached by |appId| and |connectionType|.
|
||||
// If not found, save the incoming data into the cached.
|
||||
let appStats = this.cachedAppStats[key];
|
||||
if (!appStats) {
|
||||
this.cachedAppStats[key] = stats;
|
||||
return;
|
||||
}
|
||||
|
||||
// Find matched row, accumulate the traffic amount.
|
||||
appStats.rxBytes += stats.rxBytes;
|
||||
appStats.txBytes += stats.txBytes;
|
||||
|
||||
// If new rxBytes or txBytes exceeds MAX_CACHED_TRAFFIC
|
||||
// the corresponding row will be saved to indexedDB.
|
||||
// Then, the row will be removed from the cached.
|
||||
if (appStats.rxBytes > MAX_CACHED_TRAFFIC ||
|
||||
appStats.txBytes > MAX_CACHED_TRAFFIC) {
|
||||
this._db.saveStats(appStats,
|
||||
function (error, result) {
|
||||
if (DEBUG) {
|
||||
debug("Application stats inserted in indexedDB");
|
||||
}
|
||||
}
|
||||
);
|
||||
delete this.cachedAppStats[key];
|
||||
}
|
||||
},
|
||||
|
||||
updateCachedAppStats: function updateCachedAppStats(callback) {
|
||||
if (DEBUG) {
|
||||
debug("updateCachedAppStats: " + this.cachedAppStatsDate);
|
||||
}
|
||||
|
||||
let stats = Object.keys(this.cachedAppStats);
|
||||
if (stats.length == 0) {
|
||||
// |cachedAppStats| is empty, no need to update.
|
||||
return;
|
||||
}
|
||||
|
||||
let index = 0;
|
||||
this._db.saveStats(this.cachedAppStats[stats[index]],
|
||||
function onSavedStats(error, result) {
|
||||
if (DEBUG) {
|
||||
debug("Application stats inserted in indexedDB");
|
||||
}
|
||||
|
||||
// Clean up the |cachedAppStats| after updating.
|
||||
if (index == stats.length - 1) {
|
||||
this.cachedAppStats = Object.create(null);
|
||||
|
||||
if (!callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
callback(false, error);
|
||||
return;
|
||||
}
|
||||
|
||||
callback(true, "ok");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update is not finished, keep updating.
|
||||
index += 1;
|
||||
this._db.saveStats(this.cachedAppStats[stats[index]],
|
||||
onSavedStats.bind(this, error, result));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
get maxCachedTraffic () {
|
||||
return MAX_CACHED_TRAFFIC;
|
||||
},
|
||||
|
||||
logAllRecords: function logAllRecords() {
|
||||
this._db.logAllRecords(function onResult(error, result) {
|
||||
if (error) {
|
||||
|
Loading…
Reference in New Issue
Block a user