diff options
author | alexei.trebounskikh | 2018-06-14 19:18:00 +0000 |
---|---|---|
committer | Sam Davis | 2018-06-22 20:13:50 +0000 |
commit | 501815298751560cc2776f061f97cedbea102322 (patch) | |
tree | e7829260b34b129b82f9db8f38fb1e5343cc1eac | |
parent | 69394d2e008d2f1139993f4b42f8622df2a61378 (diff) | |
download | org.eclipse.mylyn.tasks-e_4_7_m_3_23_x.tar.gz org.eclipse.mylyn.tasks-e_4_7_m_3_23_x.tar.xz org.eclipse.mylyn.tasks-e_4_7_m_3_23_x.zip |
535879: [performance] Loading a large tasklist.xml takes a long timeR_3_23_3e_4_7_m_3_23_x
Changed the order the tasks are added to the task list to prevent
unnecessary removals from UnmatchedTaskContainer when loading
tasklist.xml.
Change-Id: I1931578f3c9cdd3e47fc5f2324577ec83874fc27
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=535879
Signed-off-by: alexei.trebounskikh <alexei.trebounskikh@tasktop.com>
(cherry picked from commit 3e12a215f3e68d8cf11ccf84196afb42178f2cfa)
3 files changed, 218 insertions, 3 deletions
diff --git a/org.eclipse.mylyn.tasks.core.tests/src/org/eclipse/mylyn/internal/tasks/core/externalization/LazyTransferListTest.java b/org.eclipse.mylyn.tasks.core.tests/src/org/eclipse/mylyn/internal/tasks/core/externalization/LazyTransferListTest.java new file mode 100644 index 000000000..c66e67797 --- /dev/null +++ b/org.eclipse.mylyn.tasks.core.tests/src/org/eclipse/mylyn/internal/tasks/core/externalization/LazyTransferListTest.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2018 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.core.externalization; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + +import org.eclipse.mylyn.internal.tasks.core.AbstractTask; +import org.eclipse.mylyn.internal.tasks.core.ITransferList; +import org.eclipse.mylyn.internal.tasks.core.TaskList; +import org.eclipse.mylyn.internal.tasks.core.TaskTask; +import org.junit.Before; +import org.junit.Test; + +public class LazyTransferListTest { + + private ITransferList taskList; + + private LazyTransferList lazyList; + + @Before + public void setUp() throws Exception { + taskList = mock(TaskList.class); + lazyList = new LazyTransferList(taskList); + } + + @Test + public void addUnmatchedTask() { + AbstractTask task = spy(new TaskTask("kind", "repoUrl", "id")); + + // add to unmatched + lazyList.addTask(task); + + // should not add task to task list + verify(taskList, never()).addTask(task); + verify(taskList, never()).addTask(eq(task), any()); + + // commit should add the task to task list + lazyList.commit(); + verify(taskList).addTask(task); + + // subsequent commit should not add task again + lazyList.commit(); + verifyNoMoreInteractions(taskList); + } + + @Test + public void addSubTask() { + AbstractTask task = spy(new TaskTask("kind", "repoUrl", "parent")); + AbstractTask subTask = spy(new TaskTask("kind", "repoUrl", "child")); + + // add subtask to a task container + lazyList.addTask(subTask); + lazyList.addTask(task); + lazyList.addTask(subTask, task); + + // should add task and subtask to task list + verify(taskList).addTask(task); + verify(taskList).addTask(subTask, task); + verifyNoMoreInteractions(taskList); + + // commit should not add anything to task list + lazyList.commit(); + verifyNoMoreInteractions(taskList); + } + +} diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/LazyTransferList.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/LazyTransferList.java new file mode 100644 index 000000000..a1a9604f9 --- /dev/null +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/LazyTransferList.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * Copyright (c) 2018 Tasktop Technologies and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.core.externalization; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import org.eclipse.mylyn.internal.tasks.core.AbstractTask; +import org.eclipse.mylyn.internal.tasks.core.AbstractTaskCategory; +import org.eclipse.mylyn.internal.tasks.core.AbstractTaskContainer; +import org.eclipse.mylyn.internal.tasks.core.ITransferList; +import org.eclipse.mylyn.internal.tasks.core.RepositoryQuery; +import org.eclipse.mylyn.internal.tasks.core.TaskCategory; +import org.eclipse.mylyn.internal.tasks.core.UnmatchedTaskContainer; +import org.eclipse.mylyn.tasks.core.ITask; + +/** + * This class delegates the calls to underlying {@link ITransferList} while altering behavior of {@link #addTask(ITask)} + * and {@link #addTask(ITask, category)} methods to avoid adding tasks being loaded to task list's + * {@link UnmatchedTaskContainer} if they belong to a different task container. Instead, tasks added with + * {@link #addTask(ITask)} method are stored internally, and only pushed to underlying {@link ITransferList} during + * subsequent calls to {@link #addTask(ITask, category)} or on final {@link #commit(void)}. + * <p> + * <b>Usage</b> + * <p> + * The caller can call {@link #addTask(ITask)} and {@link #addTask(ITask, category)} methods to load task list as usual. + * <p> + * The caller is expected to call {@link #commit(void)} to add the remaining uncategorized tasks to task list. + * + * @see {@link #addTask(ITask)} + * @see {@link #addTask(ITask, AbstractTaskContainer)} + * @see {@link #commit()} + */ +class LazyTransferList implements ITransferList { + + private final Map<String, ITask> untransferedTasks = new HashMap<>(); + + private final ITransferList taskList; + + LazyTransferList(ITransferList taskList) { + this.taskList = taskList; + } + + public void addCategory(TaskCategory category) { + taskList.addCategory(category); + } + + public void addQuery(RepositoryQuery query) { + taskList.addQuery(query); + } + + public void addTask(ITask task) { + untransferedTasks.put(task.getHandleIdentifier(), task); + } + + public boolean addTask(ITask task, AbstractTaskContainer parentContainer) { + boolean result = taskList.addTask(task, commit(parentContainer)); + untransferedTasks.remove(task.getHandleIdentifier()); + return result; + } + + public AbstractTaskCategory getContainerForHandle(String handle) { + return taskList.getContainerForHandle(handle); + } + + public Collection<AbstractTask> getAllTasks() { + return taskList.getAllTasks(); + } + + public Set<AbstractTaskCategory> getCategories() { + return taskList.getCategories(); + } + + public Set<RepositoryQuery> getQueries() { + return taskList.getQueries(); + } + + public AbstractTask getTask(String handleIdentifier) { + AbstractTask task = (AbstractTask) untransferedTasks.get(handleIdentifier); + + if (task == null) { + task = taskList.getTask(handleIdentifier); + } + + return task; + } + + public ITask getTask(String repositoryUrl, String taskId) { + return taskList.getTask(repositoryUrl, taskId); + } + + /** + * If the container is an {@link ITask}, pushes it to task list + * + * @param container + */ + private AbstractTaskContainer commit(AbstractTaskContainer container) { + if (container instanceof ITask) { + AbstractTask task = (AbstractTask) untransferedTasks.get(container.getHandleIdentifier()); + + if (task != null) { + taskList.addTask(task); + untransferedTasks.remove(container.getHandleIdentifier()); + } + } + + return container; + } + + /** + * Pushes the remaining tasks to task list + */ + public void commit() { + for (ITask task : untransferedTasks.values()) { + taskList.addTask(task); + } + untransferedTasks.clear(); + } +}
\ No newline at end of file diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListHandler.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListHandler.java index 394d02ec7..7a1e38b6d 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListHandler.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/externalization/SaxTaskListHandler.java @@ -34,7 +34,7 @@ import com.google.common.collect.Multimap; public class SaxTaskListHandler extends DefaultHandler { - private final ITransferList taskList; + private final LazyTransferList taskList; private final RepositoryModel repositoryModel; @@ -52,7 +52,7 @@ public class SaxTaskListHandler extends DefaultHandler { public SaxTaskListHandler(ITransferList taskList, RepositoryModel repositoryModel, IRepositoryManager repositoryManager) throws CoreException { - this.taskList = taskList; + this.taskList = new LazyTransferList(taskList); this.repositoryModel = repositoryModel; this.repositoryManager = repositoryManager; @@ -151,7 +151,7 @@ public class SaxTaskListHandler extends DefaultHandler { applyContainmentToTaskList(subTasks); applyContainmentToTaskList(queryResults); applyContainmentToTaskList(categorizedTasks); - + commitUntransferedTasksToTaskList(); break; default: break; @@ -161,6 +161,10 @@ public class SaxTaskListHandler extends DefaultHandler { } + private void commitUntransferedTasksToTaskList() { + taskList.commit(); + } + private <T extends IRepositoryElement> void recordHit(Attributes attributes, Multimap<T, String> hitMap, SaxTaskListElementBuilder<T> builder) { String handle = attributes.getValue(TaskListExternalizationConstants.KEY_HANDLE); |