Skip to content

Commit

Permalink
Moved Storage Out of Download Manager
Browse files Browse the repository at this point in the history
Move the use of storage engine out of download manager and back into
storage. Storage creates and manages the life of storage engine, so
it is easier for it to handle all storage functions.

Now, the callback that is given to download manager is used to pass
the downloaded array buffer back to storage so that it can be saved
into storage engine.

This moves all uses of storage engine into storage which will make it
easier to replace with Storage Muxer.

Issue #1248

Change-Id: I555788478af09d1d79c3db7534431e1d9daf4e20
  • Loading branch information
vaage authored and joeyparrish committed May 9, 2018
1 parent 488d295 commit cc3d6f1
Show file tree
Hide file tree
Showing 2 changed files with 130 additions and 147 deletions.
124 changes: 38 additions & 86 deletions lib/offline/download_manager.js
Expand Up @@ -17,42 +17,37 @@

goog.provide('shaka.offline.DownloadManager');

goog.require('goog.asserts');
goog.require('shaka.net.NetworkingEngine');
goog.require('shaka.offline.IStorageEngine');
goog.require('shaka.util.Error');
goog.require('shaka.util.IDestroyable');
goog.require('shaka.util.MapUtils');


/**
* @typedef {{
* request: shakaExtern.Request,
* estimatedSize: number,
* onStore: function(number)
* onDownloaded: function(!ArrayBuffer):!Promise
* }}
*
* @property {shakaExtern.Request}
* The network request that will give us the bytes we want to download.
* @property {number} estimatedSize
* The size of the segment as estimated by the bandwidth and segment duration.
* @property {function(number)} onStore
* A callback for when a segment has been added to the storage.
* @property {function(!ArrayBuffer):!Promise} onDownloaded
* A callback for when a request has been downloaded and can be used by
* the caller. Callback should return a promise so that downloading will
* not continue until we are done with the current response.
*/
shaka.offline.DownloadRequest;


/**
* This manages downloading segments and notifying the app of progress.
*
* @param {shaka.offline.IStorageEngine} storageEngine
* @param {!shaka.net.NetworkingEngine} netEngine
*
* @struct
* @constructor
* @implements {shaka.util.IDestroyable}
*/
shaka.offline.DownloadManager = function(storageEngine, netEngine) {
shaka.offline.DownloadManager = function() {
/**
* We sill store download requests in groups. The groups will be downloaded in
* parallel but the segments in each group will be done serially.
Expand All @@ -61,22 +56,6 @@ shaka.offline.DownloadManager = function(storageEngine, netEngine) {
*/
this.groups_ = {};

/**
* The IDs of the segments that have been stored for an in-progress
* download(). This is used for cleanup in destroy().
* @private {!Array.<number>}
*/
this.storedSegmentIds_ = [];

/** @private {shaka.offline.IStorageEngine} */
this.storageEngine_ = storageEngine;

/** @private {shaka.net.NetworkingEngine} */
this.netEngine_ = netEngine;

/** @private {?shakaExtern.ManifestDB} */
this.manifest_ = null;

/** @private {!Promise} */
this.promise_ = Promise.resolve();

Expand All @@ -86,6 +65,9 @@ shaka.offline.DownloadManager = function(storageEngine, netEngine) {
/** @private {number} */
this.downloadActual_ = 0;

/** @private {number} */
this.size_ = 0;

/** @private {!Array.<function(number, number)>} */
this.progressListeners_ = [];

Expand All @@ -104,28 +86,20 @@ shaka.offline.DownloadManager.prototype.followProgress = function(callback) {

/** @override */
shaka.offline.DownloadManager.prototype.destroy = function() {
let storage = this.storageEngine_;
let segments = this.storedSegmentIds_;

// Don't try to remove segments if there are none. That may trigger an error
// in storage if the DB connection was never created.
if (segments.length) {
this.promise_ = this.promise_.then(() => {
return storage.removeSegments(segments, null);
});
}
this.destroyed_ = true;

// Don't destroy() storageEngine since it is owned by Storage.
let p = this.promise_;
const noop = () => {};
let wait = this.promise_.catch(noop);

this.groups_ = {};
this.storedSegmentIds_ = [];
this.storageEngine_ = null;
this.netEngine_ = null;
this.manifest_ = null;
this.downloadActual_ = 0;
this.downloadExpected_ = 0;
this.progressListeners_ = [];
this.promise_ = Promise.resolve();
this.requests_ = [];
this.size_ = 0;
this.totalDownloaded_ = 0;

return p;
return wait;
};


Expand All @@ -136,35 +110,31 @@ shaka.offline.DownloadManager.prototype.destroy = function() {
* not exists, a new group will be created.
* @param {shakaExtern.Request} request
* @param {number} estimatedSize
* @param {function(number)} onStore
* A callback for when the segment has been saved to storage. The parameter
* will be the id the segment was saved under.
* @param {function(!ArrayBuffer):!Promise} onDownloaded
* A callback for when a request has been downloaded and can be used by
* the caller. Callback should return a promise so that downloading will
* not continue until we are done with the current response.
*/
shaka.offline.DownloadManager.prototype.queue = function(
group, request, estimatedSize, onStore) {
group, request, estimatedSize, onDownloaded) {
this.groups_[group] = this.groups_[group] || [];
this.groups_[group].push({
request: request,
estimatedSize: estimatedSize,
onStore: onStore
onDownloaded: onDownloaded
});
};


/**
* Downloads all the segments, stores them in the database, and stores the given
* manifest object.
*
* @param {shakaExtern.ManifestDB} manifest
* @param {!shaka.net.NetworkingEngine} net
* @return {!Promise.<number>}
*/
shaka.offline.DownloadManager.prototype.downloadAndStore = function(manifest) {
shaka.offline.DownloadManager.prototype.download = function(net) {
// Clear any old progress.
this.downloadExpected_ = 0;
this.downloadActual_ = 0;

this.manifest_ = manifest;

let groups = shaka.util.MapUtils.values(this.groups_);
this.groups_ = {}; // Clear the map to create a clean slate.

Expand All @@ -175,14 +145,7 @@ shaka.offline.DownloadManager.prototype.downloadAndStore = function(manifest) {
/** @type {!Promise.<number>} */
let p = Promise.resolve().then(() => {
this.checkDestroyed_();
return Promise.all(groups.map((group) => this.downloadGroup_(group)));
}).then(() => {
this.checkDestroyed_();
return this.storageEngine_.addManifest(manifest);
}).then((id) => {
this.checkDestroyed_();
this.storedSegmentIds_ = [];
return id;
return Promise.all(groups.map((group) => this.downloadGroup_(net, group)));
});

// Amend our new promise chain to our internal promise so that when we destroy
Expand All @@ -194,17 +157,18 @@ shaka.offline.DownloadManager.prototype.downloadAndStore = function(manifest) {


/**
* @param {!shaka.net.NetworkingEngine} net
* @param {!Array.<shaka.offline.DownloadRequest>} group
* @return {!Promise}
* @private
*/
shaka.offline.DownloadManager.prototype.downloadGroup_ = function(group) {
shaka.offline.DownloadManager.prototype.downloadGroup_ = function(net, group) {
let p = Promise.resolve();

group.forEach((segment) => {
p = p.then(() => {
this.checkDestroyed_();
return this.downloadSegment_(segment);
return this.downloadSegment_(net, segment);
});
});

Expand All @@ -213,30 +177,25 @@ shaka.offline.DownloadManager.prototype.downloadGroup_ = function(group) {


/**
* @param {!shaka.net.NetworkingEngine} net
* @param {shaka.offline.DownloadRequest} segment
* @return {!Promise}
* @private
*/
shaka.offline.DownloadManager.prototype.downloadSegment_ = function(segment) {
shaka.offline.DownloadManager.prototype.downloadSegment_ = function(
net, segment) {
return Promise.resolve().then(() => {
this.checkDestroyed_();

let type = shaka.net.NetworkingEngine.RequestType.SEGMENT;
return this.netEngine_.request(type, segment.request).promise;
return net.request(type, segment.request).promise;
}).then((response) => {
this.checkDestroyed_();

this.markAsDone_(segment.estimatedSize, response.data.byteLength);
this.updateProgress_();

return this.storageEngine_.addSegment({
data: response.data
});
}).then((id) => {
this.checkDestroyed_();

this.storedSegmentIds_.push(id);
segment.onStore(id);
return segment.onDownloaded(response.data);
});
};

Expand Down Expand Up @@ -273,7 +232,7 @@ shaka.offline.DownloadManager.prototype.markAsPending_ = function(estimate) {
shaka.offline.DownloadManager.prototype.markAsDone_ = function(
estimate, actual) {
this.downloadActual_ += estimate;
this.manifest_.size += actual;
this.size_ += actual;
};


Expand All @@ -282,17 +241,10 @@ shaka.offline.DownloadManager.prototype.markAsDone_ = function(
* @private
*/
shaka.offline.DownloadManager.prototype.updateProgress_ = function() {
goog.asserts.assert(this.manifest_, 'Must not be destroyed');

/** @type {number} */
let progress = this.downloadExpected_ == 0 ?
0 :
(this.downloadActual_ / this.downloadExpected_);

/** @type {number} */
let size = this.manifest_.size;

this.progressListeners_.forEach(function(listener) {
listener(progress, size);
});
this.progressListeners_.forEach((listener) => listener(progress, this.size_));
};

0 comments on commit cc3d6f1

Please sign in to comment.