mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-23 16:25:22 +03:00
FirmwareCache: memory footprint and UI improvements
This commit is contained in:
parent
caef8dbf3c
commit
54bdd2da14
2 changed files with 105 additions and 59 deletions
|
@ -24,16 +24,19 @@
|
||||||
/**
|
/**
|
||||||
* @typedef {object} CacheItem
|
* @typedef {object} CacheItem
|
||||||
* @property {Descriptor} release
|
* @property {Descriptor} release
|
||||||
* @property {string} [hexdata]
|
* @property {string} hexdata
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages caching of downloaded firmware files
|
* Manages caching of downloaded firmware files
|
||||||
*/
|
*/
|
||||||
let FirmwareCache = (function() {
|
let FirmwareCache = (function () {
|
||||||
|
|
||||||
let MetadataStorage = (function() {
|
let onPutToCacheCallback,
|
||||||
let CACHEKEY = "firmware-cache-metadata";
|
onRemoveFromCacheCallback;
|
||||||
|
|
||||||
|
let JournalStorage = (function () {
|
||||||
|
let CACHEKEY = "firmware-cache-journal";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Array} data LRU key-value pairs
|
* @param {Array} data LRU key-value pairs
|
||||||
|
@ -62,25 +65,33 @@ let FirmwareCache = (function() {
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
let metadataCache = new LRUMap(100);
|
let journal = new LRUMap(100),
|
||||||
let metadataLoaded = false;
|
journalLoaded = false;
|
||||||
|
|
||||||
metadataCache.shift = function() {
|
journal.shift = function () {
|
||||||
// remove hexdata for oldest release
|
// remove cached data for oldest release
|
||||||
let oldest = LRUMap.prototype.shift.call(this);
|
let oldest = LRUMap.prototype.shift.call(this);
|
||||||
if (oldest !== undefined) {
|
if (oldest === undefined) {
|
||||||
/** @type {CacheItem} */
|
return undefined;
|
||||||
let cached = oldest[1];
|
|
||||||
let hexdataKey = withHexdataPrefix(keyOf(cached.release));
|
|
||||||
chrome.storage.local.remove(hexdataKey,
|
|
||||||
() => console.debug("Hex data removed: " + hexdataKey));
|
|
||||||
}
|
}
|
||||||
|
let key = oldest[0];
|
||||||
|
let cacheKey = withCachePrefix(key);
|
||||||
|
chrome.storage.local.get(cacheKey, obj => {
|
||||||
|
/** @type {CacheItem} */
|
||||||
|
let cached = typeof obj === "object" && obj.hasOwnProperty(cacheKey)
|
||||||
|
? obj[cacheKey]
|
||||||
|
: null;
|
||||||
|
chrome.storage.local.remove(cacheKey, () => {
|
||||||
|
onRemoveFromCache(cached.release);
|
||||||
|
console.debug("Cache data removed: " + cacheKey);
|
||||||
|
});
|
||||||
|
});
|
||||||
return oldest;
|
return oldest;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Descriptor} release
|
* @param {Descriptor} release
|
||||||
* @returns {string} A key used for caching the metadata for a release
|
* @returns {string} A key used to store a release in the journal
|
||||||
*/
|
*/
|
||||||
function keyOf(release) {
|
function keyOf(release) {
|
||||||
return release.file;
|
return release.file;
|
||||||
|
@ -88,10 +99,10 @@ let FirmwareCache = (function() {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @returns {string} A key for storing the hex data for a release
|
* @returns {string} A key for storing cached data for a release
|
||||||
*/
|
*/
|
||||||
function withHexdataPrefix(key) {
|
function withCachePrefix(key) {
|
||||||
return "hex:" + key;
|
return "cache:" + key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,11 +110,11 @@ let FirmwareCache = (function() {
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
function has(release) {
|
function has(release) {
|
||||||
if (!metadataLoaded) {
|
if (!journalLoaded) {
|
||||||
console.warn("Cache not yet loaded");
|
console.warn("Cache not yet loaded");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return metadataCache.has(keyOf(release));
|
return journal.has(keyOf(release));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,48 +122,68 @@ let FirmwareCache = (function() {
|
||||||
* @param {string} hexdata
|
* @param {string} hexdata
|
||||||
*/
|
*/
|
||||||
function put(release, hexdata) {
|
function put(release, hexdata) {
|
||||||
if (!metadataLoaded) {
|
if (!journalLoaded) {
|
||||||
console.warn("Cache not yet loaded");
|
console.warn("Cache journal not yet loaded");
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (has(release)) {
|
|
||||||
console.debug("Firmware is already cached: " + keyOf(release));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let key = keyOf(release);
|
let key = keyOf(release);
|
||||||
let hexdataKey = withHexdataPrefix(key);
|
if (has(release)) {
|
||||||
metadataCache.set(key, {
|
console.debug("Firmware is already cached: " + key);
|
||||||
release: release,
|
return;
|
||||||
});
|
}
|
||||||
MetadataStorage.persist(metadataCache.toJSON());
|
journal.set(key, true);
|
||||||
|
JournalStorage.persist(journal.toJSON());
|
||||||
let obj = {};
|
let obj = {};
|
||||||
obj[hexdataKey] = hexdata;
|
obj[withCachePrefix(key)] = {
|
||||||
chrome.storage.local.set(obj);
|
release: release,
|
||||||
|
hexdata: hexdata,
|
||||||
|
};
|
||||||
|
chrome.storage.local.set(obj, () => {
|
||||||
|
console.info("Release put to cache: " + key);
|
||||||
|
onPutToCache(release);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Descriptor} release
|
* @param {Descriptor} release
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
* @returns {(CacheItem|undefined)}
|
|
||||||
*/
|
*/
|
||||||
function get(release, callback) {
|
function get(release, callback) {
|
||||||
if (!metadataLoaded) {
|
if (!journalLoaded) {
|
||||||
console.warn("Cache not yet loaded");
|
console.warn("Cache journal not yet loaded");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
let key = keyOf(release);
|
let key = keyOf(release);
|
||||||
|
if (!has(release)) {
|
||||||
|
console.debug("Firmware is not cached: " + key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let cacheKey = withCachePrefix(key);
|
||||||
|
chrome.storage.local.get(cacheKey, obj => {
|
||||||
/** @type {CacheItem} */
|
/** @type {CacheItem} */
|
||||||
let cached = metadataCache.get(key);
|
let cached = typeof obj === "object" && obj.hasOwnProperty(cacheKey)
|
||||||
if (cached !== undefined) {
|
? obj[cacheKey]
|
||||||
let hexdataKey = withHexdataPrefix(key);
|
|
||||||
chrome.storage.local.get(hexdataKey, function(obj) {
|
|
||||||
cached.hexdata = typeof obj === "object" && obj.hasOwnProperty(hexdataKey)
|
|
||||||
? obj[hexdataKey]
|
|
||||||
: null;
|
: null;
|
||||||
callback(cached);
|
callback(cached);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return cached;
|
|
||||||
|
/**
|
||||||
|
* @param {Descriptor} release
|
||||||
|
*/
|
||||||
|
function onPutToCache(release) {
|
||||||
|
if (typeof onPutToCacheCallback === "function") {
|
||||||
|
onPutToCacheCallback(release);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Descriptor} release
|
||||||
|
*/
|
||||||
|
function onRemoveFromCache(release) {
|
||||||
|
if (typeof onRemoveFromCacheCallback === "function") {
|
||||||
|
onRemoveFromCacheCallback(release);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -163,21 +194,23 @@ let FirmwareCache = (function() {
|
||||||
for (let entry of entries) {
|
for (let entry of entries) {
|
||||||
pairs.push([entry.key, entry.value]);
|
pairs.push([entry.key, entry.value]);
|
||||||
}
|
}
|
||||||
metadataCache.assign(pairs);
|
journal.assign(pairs);
|
||||||
metadataLoaded = true;
|
journalLoaded = true;
|
||||||
console.info("Firmware cache loaded; number of entries: " + entries.length);
|
console.info("Firmware cache journal loaded; number of entries: " + entries.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
has: has,
|
has: has,
|
||||||
put: put,
|
put: put,
|
||||||
get: get,
|
get: get,
|
||||||
|
onPutToCache: callback => onPutToCacheCallback = callback,
|
||||||
|
onRemoveFromCache: callback => onRemoveFromCacheCallback = callback,
|
||||||
load: () => {
|
load: () => {
|
||||||
MetadataStorage.load(onEntriesLoaded);
|
JournalStorage.load(onEntriesLoaded);
|
||||||
},
|
},
|
||||||
flush: () => {
|
flush: () => {
|
||||||
MetadataStorage.persist(metadataCache.toJSON());
|
JournalStorage.persist(journal.toJSON());
|
||||||
metadataCache.clear();
|
journal.clear();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -16,8 +16,22 @@ TABS.firmware_flasher.initialize = function (callback) {
|
||||||
var intel_hex = false, // standard intel hex in string format
|
var intel_hex = false, // standard intel hex in string format
|
||||||
parsed_hex = false; // parsed raw hex in array format
|
parsed_hex = false; // parsed raw hex in array format
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change boldness of firmware option depending on cache status
|
||||||
|
*
|
||||||
|
* @param {Descriptor} release
|
||||||
|
*/
|
||||||
|
function onFirmwareCacheUpdate(release) {
|
||||||
|
$("option[value='{0}']".format(release.version))
|
||||||
|
.css("font-weight", FirmwareCache.has(release)
|
||||||
|
? "bold"
|
||||||
|
: "normal");
|
||||||
|
}
|
||||||
|
|
||||||
$('#content').load("./tabs/firmware_flasher.html", function () {
|
$('#content').load("./tabs/firmware_flasher.html", function () {
|
||||||
FirmwareCache.load();
|
FirmwareCache.load();
|
||||||
|
FirmwareCache.onPutToCache(onFirmwareCacheUpdate);
|
||||||
|
FirmwareCache.onRemoveFromCache(onFirmwareCacheUpdate);
|
||||||
|
|
||||||
function parse_hex(str, callback) {
|
function parse_hex(str, callback) {
|
||||||
// parsing hex in different thread
|
// parsing hex in different thread
|
||||||
|
@ -41,7 +55,6 @@ TABS.firmware_flasher.initialize = function (callback) {
|
||||||
if (parsed_hex) {
|
if (parsed_hex) {
|
||||||
if (!FirmwareCache.has(summary)) {
|
if (!FirmwareCache.has(summary)) {
|
||||||
FirmwareCache.put(summary, intel_hex);
|
FirmwareCache.put(summary, intel_hex);
|
||||||
console.info("Release put to cache: " + summary.file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var url;
|
var url;
|
||||||
|
@ -213,7 +226,7 @@ TABS.firmware_flasher.initialize = function (callback) {
|
||||||
))
|
))
|
||||||
.css("font-weight", FirmwareCache.has(descriptor)
|
.css("font-weight", FirmwareCache.has(descriptor)
|
||||||
? "bold"
|
? "bold"
|
||||||
: null
|
: "normal"
|
||||||
)
|
)
|
||||||
.data('summary', descriptor);
|
.data('summary', descriptor);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue