summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2018-11-06 00:24:27 +0100
committerGitHub <noreply@github.com>2018-11-06 00:24:27 +0100
commitf350f2e3ec0bb9b06c7c585db0b9e33266f43021 (patch)
treeb39798124523f5c78956c1db805d65d5e4078071
parentcd31bea2b7abdd17995160fe279c3a6ae8b3105c (diff)
parent1fa6e0be23f0684ce76de3311c52e01495a4de7e (diff)
downloadnextcloud-server-f350f2e3ec0bb9b06c7c585db0b9e33266f43021.tar.gz
nextcloud-server-f350f2e3ec0bb9b06c7c585db0b9e33266f43021.zip
Merge pull request #12128 from tomasz-grobelny/fix_file_move
Fix file move operation for large number of files
-rw-r--r--apps/files/js/filelist.js47
-rw-r--r--apps/files/tests/js/filelistSpec.js117
2 files changed, 106 insertions, 58 deletions
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index 8b12cce51d1..9459a266ce9 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -989,7 +989,7 @@
});
}
- this.move(_.pluck(files, 'name'), targetPath);
+ var movePromise = this.move(_.pluck(files, 'name'), targetPath);
// re-enable td elements to be droppable
// sometimes the filename drop handler is still called after re-enable,
@@ -997,6 +997,8 @@
setTimeout(function() {
self.$el.find('td.filename.ui-droppable').droppable('enable');
}, 10);
+
+ return movePromise;
},
/**
@@ -2162,7 +2164,31 @@
if (!_.isArray(fileNames)) {
fileNames = [fileNames];
}
- _.each(fileNames, function(fileName) {
+
+ function Semaphore(max) {
+ var counter = 0;
+ var waiting = [];
+
+ this.acquire = function() {
+ if(counter < max) {
+ counter++;
+ return new Promise(function(resolve) { resolve(); });
+ } else {
+ return new Promise(function(resolve) { waiting.push(resolve); });
+ }
+ };
+
+ this.release = function() {
+ counter--;
+ if (waiting.length > 0 && counter < max) {
+ counter++;
+ var promise = waiting.shift();
+ promise();
+ }
+ };
+ }
+
+ var moveFileFunction = function(fileName) {
var $tr = self.findFileEl(fileName);
self.showFileBusyState($tr, true);
if (targetPath.charAt(targetPath.length - 1) !== '/') {
@@ -2170,7 +2196,7 @@
// not overwrite it
targetPath = targetPath + '/';
}
- self.filesClient.move(dir + fileName, targetPath + fileName)
+ return self.filesClient.move(dir + fileName, targetPath + fileName)
.done(function() {
// if still viewing the same directory
if (OC.joinPaths(self.getCurrentDirectory(), '/') === dir) {
@@ -2201,11 +2227,24 @@
.always(function() {
self.showFileBusyState($tr, false);
});
+ };
+
+ var mcSemaphore = new Semaphore(10);
+ var counter = 0;
+ var promises = _.map(fileNames, function(arg) {
+ return mcSemaphore.acquire().then(function(){
+ moveFileFunction(arg).then(function(){
+ mcSemaphore.release();
+ counter++;
+ });
+ });
+ });
+
+ return Promise.all(promises).then(function(){
if (callback) {
callback();
}
});
-
},
/**
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index 961761c3e86..85fc31f8c0e 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -838,84 +838,91 @@ describe('OCA.Files.FileList tests', function() {
moveStub.restore();
});
- it('Moves single file to target folder', function() {
- fileList.move('One.txt', '/somedir');
+ it('Moves single file to target folder', function(done) {
+ return fileList.move('One.txt', '/somedir').then(function(){
- expect(moveStub.calledOnce).toEqual(true);
- expect(moveStub.getCall(0).args[0]).toEqual('/subdir/One.txt');
- expect(moveStub.getCall(0).args[1]).toEqual('/somedir/One.txt');
+ expect(moveStub.calledOnce).toEqual(true);
+ expect(moveStub.getCall(0).args[0]).toEqual('/subdir/One.txt');
+ expect(moveStub.getCall(0).args[1]).toEqual('/somedir/One.txt');
- deferredMove.resolve(201);
+ deferredMove.resolve(201);
- expect(fileList.findFileEl('One.txt').length).toEqual(0);
+ expect(fileList.findFileEl('One.txt').length).toEqual(0);
- // folder size has increased
- expect(fileList.findFileEl('somedir').data('size')).toEqual(262);
- expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B');
+ // folder size has increased
+ expect(fileList.findFileEl('somedir').data('size')).toEqual(262);
+ expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B');
- expect(notificationStub.notCalled).toEqual(true);
+ expect(notificationStub.notCalled).toEqual(true);
+ done();
+ });
});
- it('Moves list of files to target folder', function() {
+ it('Moves list of files to target folder', function(done) {
var deferredMove1 = $.Deferred();
var deferredMove2 = $.Deferred();
moveStub.onCall(0).returns(deferredMove1.promise());
moveStub.onCall(1).returns(deferredMove2.promise());
- fileList.move(['One.txt', 'Two.jpg'], '/somedir');
+ return fileList.move(['One.txt', 'Two.jpg'], '/somedir').then(function(){
- expect(moveStub.calledTwice).toEqual(true);
- expect(moveStub.getCall(0).args[0]).toEqual('/subdir/One.txt');
- expect(moveStub.getCall(0).args[1]).toEqual('/somedir/One.txt');
- expect(moveStub.getCall(1).args[0]).toEqual('/subdir/Two.jpg');
- expect(moveStub.getCall(1).args[1]).toEqual('/somedir/Two.jpg');
+ expect(moveStub.calledTwice).toEqual(true);
+ expect(moveStub.getCall(0).args[0]).toEqual('/subdir/One.txt');
+ expect(moveStub.getCall(0).args[1]).toEqual('/somedir/One.txt');
+ expect(moveStub.getCall(1).args[0]).toEqual('/subdir/Two.jpg');
+ expect(moveStub.getCall(1).args[1]).toEqual('/somedir/Two.jpg');
- deferredMove1.resolve(201);
+ deferredMove1.resolve(201);
- expect(fileList.findFileEl('One.txt').length).toEqual(0);
+ expect(fileList.findFileEl('One.txt').length).toEqual(0);
- // folder size has increased during move
- expect(fileList.findFileEl('somedir').data('size')).toEqual(262);
- expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B');
+ // folder size has increased during move
+ expect(fileList.findFileEl('somedir').data('size')).toEqual(262);
+ expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('262 B');
- deferredMove2.resolve(201);
+ deferredMove2.resolve(201);
- expect(fileList.findFileEl('Two.jpg').length).toEqual(0);
+ expect(fileList.findFileEl('Two.jpg').length).toEqual(0);
- // folder size has increased
- expect(fileList.findFileEl('somedir').data('size')).toEqual(12311);
- expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('12 KB');
+ // folder size has increased
+ expect(fileList.findFileEl('somedir').data('size')).toEqual(12311);
+ expect(fileList.findFileEl('somedir').find('.filesize').text()).toEqual('12 KB');
- expect(notificationStub.notCalled).toEqual(true);
+ expect(notificationStub.notCalled).toEqual(true);
+ done();
+ });
});
- it('Shows notification if a file could not be moved', function() {
- fileList.move('One.txt', '/somedir');
+ it('Shows notification if a file could not be moved', function(done) {
+ return fileList.move('One.txt', '/somedir').then(function(){
- expect(moveStub.calledOnce).toEqual(true);
+ expect(moveStub.calledOnce).toEqual(true);
- deferredMove.reject(409);
+ deferredMove.reject(409);
- expect(fileList.findFileEl('One.txt').length).toEqual(1);
+ expect(fileList.findFileEl('One.txt').length).toEqual(1);
- expect(notificationStub.calledOnce).toEqual(true);
- expect(notificationStub.getCall(0).args[0]).toEqual('Could not move "One.txt"');
+ expect(notificationStub.calledOnce).toEqual(true);
+ expect(notificationStub.getCall(0).args[0]).toEqual('Could not move "One.txt"');
+ done();
+ });
});
it('Restores thumbnail if a file could not be moved', function() {
- fileList.move('One.txt', '/somedir');
+ return fileList.move('One.txt', '/somedir').then(function(){
- expect(fileList.findFileEl('One.txt').find('.thumbnail').parent().attr('class'))
- .toContain('icon-loading-small');
+ expect(fileList.findFileEl('One.txt').find('.thumbnail').parent().attr('class'))
+ .toContain('icon-loading-small');
- expect(moveStub.calledOnce).toEqual(true);
+ expect(moveStub.calledOnce).toEqual(true);
- deferredMove.reject(409);
+ deferredMove.reject(409);
- expect(fileList.findFileEl('One.txt').length).toEqual(1);
+ expect(fileList.findFileEl('One.txt').length).toEqual(1);
- expect(notificationStub.calledOnce).toEqual(true);
- expect(notificationStub.getCall(0).args[0]).toEqual('Could not move "One.txt"');
+ expect(notificationStub.calledOnce).toEqual(true);
+ expect(notificationStub.getCall(0).args[0]).toEqual('Could not move "One.txt"');
- expect(OC.TestUtil.getImageUrl(fileList.findFileEl('One.txt').find('.thumbnail')))
- .toEqual(OC.imagePath('core', 'filetypes/text.svg'));
+ expect(OC.TestUtil.getImageUrl(fileList.findFileEl('One.txt').find('.thumbnail')))
+ .toEqual(OC.imagePath('core', 'filetypes/text.svg'));
+ });
});
});
@@ -1757,7 +1764,7 @@ describe('OCA.Files.FileList tests', function() {
expect(changeDirStub.getCall(0).args[0]).toEqual('/subdir/two/three with space');
changeDirStub.restore();
});
- it('dropping files on breadcrumb calls move operation', function() {
+ it('dropping files on breadcrumb calls move operation', function(done) {
var testDir = '/subdir/two/three with space/four/five';
var moveStub = sinon.stub(filesClient, 'move').returns($.Deferred().promise());
fileList.changeDirectory(testDir);
@@ -1775,14 +1782,16 @@ describe('OCA.Files.FileList tests', function() {
$('<tr data-file="Two.jpg" data-dir="' + testDir + '"></tr>')
]);
// simulate drop event
- fileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui);
+ return fileList._onDropOnBreadCrumb(new $.Event('drop', {target: $crumb}), ui).then(function(){
- expect(moveStub.callCount).toEqual(2);
- expect(moveStub.getCall(0).args[0]).toEqual(testDir + '/One.txt');
- expect(moveStub.getCall(0).args[1]).toEqual('/subdir/two/three with space/One.txt');
- expect(moveStub.getCall(1).args[0]).toEqual(testDir + '/Two.jpg');
- expect(moveStub.getCall(1).args[1]).toEqual('/subdir/two/three with space/Two.jpg');
- moveStub.restore();
+ expect(moveStub.callCount).toEqual(2);
+ expect(moveStub.getCall(0).args[0]).toEqual(testDir + '/One.txt');
+ expect(moveStub.getCall(0).args[1]).toEqual('/subdir/two/three with space/One.txt');
+ expect(moveStub.getCall(1).args[0]).toEqual(testDir + '/Two.jpg');
+ expect(moveStub.getCall(1).args[1]).toEqual('/subdir/two/three with space/Two.jpg');
+ moveStub.restore();
+ done();
+ });
});
it('dropping files on same dir breadcrumb does nothing', function() {
var testDir = '/subdir/two/three with space/four/five';