Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 198241 - Mylyn never lets the JobManager be idle
Summary: Mylyn never lets the JobManager be idle
Status: RESOLVED FIXED
Alias: None
Product: z_Archived
Classification: Eclipse Foundation
Component: Mylyn (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P2 minor (vote)
Target Milestone: 3.0   Edit
Assignee: Robert Elves CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-07-30 06:26 EDT by Stefanos Zachariadis CLA
Modified: 2009-04-08 08:11 EDT (History)
3 users (show)

See Also:


Attachments
patch for the TasklistSaveManager (6.10 KB, patch)
2007-07-30 06:26 EDT, Stefanos Zachariadis CLA
no flags Details | Diff
Patch for OffLineCachingStorage (5.37 KB, patch)
2007-07-30 06:32 EDT, Stefanos Zachariadis CLA
no flags Details | Diff
second stab for the TasklistSaveManager (6.12 KB, patch)
2007-10-04 09:55 EDT, Stefanos Zachariadis CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Stefanos Zachariadis CLA 2007-07-30 06:26:03 EDT
I'm trying to integrate mylyn with my eclipse application; however, it never lets the job manager be idle. I know this, because when running PDE unit tests, I use this method on my setUp() to make sure that eclipse is ready to be used:

public static void waitForJobs() throws Exception {
while (!Job.getJobManager().isIdle()) { delay(1000);
}
}

(delay waits for x ms, while letting the ui process events). This was
worked quite well in a number of eclipse projects I've worked on, with
multiple plugins.


When running mylyn, the jobmanager is never idle. Running this through a
debugger, it looks like the Flush Cache Job and the Task List Saver
always run. Indeed, looking at CacheFlushJob, which is nested inside
org.eclipse.mylyn.internal.tasks.ui.OfflineCachingStorage, it seems to
be in a while(true) loop. The exact same is true for TaskListSaverJob,
which is inside
org.eclipse.mylyn.internal.tasks.ui.util.TaskListSaveManager

I'm attaching patches for both files that fix these issues. Both Jobs are instantiated & scheduled only iff there are actions to execute. A lock is used to ensure that a job is not instantiated twice.
Comment 1 Stefanos Zachariadis CLA 2007-07-30 06:26:52 EDT
Created attachment 74911 [details]
patch for the TasklistSaveManager
Comment 2 Stefanos Zachariadis CLA 2007-07-30 06:32:35 EDT
Created attachment 74913 [details]
Patch for OffLineCachingStorage
Comment 3 Robert Elves CLA 2007-07-30 15:31:54 EDT
 (In reply to comment #1)
> Created an attachment (id=74911)
> patch for the TasklistSaveManager
The general approach looks good, but this patch results in the tasklist not being saved. The saveTaskList method isn't pushing a save request under some conditions. Open a local task make some changes to the notes.... will not be saved.  Ideally we'd also like to see unit test coverage of this.
Comment 4 Eugene Kuleshov CLA 2007-09-10 20:45:30 EDT
Stefanos, are you planning to continue working on this issue?
Comment 5 Mik Kersten CLA 2007-09-10 22:51:20 EDT
Rob: if we don't hear back from Stefanos please review again post 2.1 to see if this can be applied.

Stefanos: as per Eugene's comment, let us know if you are able to contribute a test and fix.
Comment 6 Stefanos Zachariadis CLA 2007-09-11 20:02:43 EDT
i'd be happy to continue on this; could you please let me know under which conditions the saveTaskList method isn't pushing a save request?
Comment 7 Robert Elves CLA 2007-09-12 01:12:08 EDT
 It's great you are able to continue working on this Stefanos. When you have a revised patch ready, append [patch] to the summary of this bug and it will get our attention much faster. To answer your question, the TaskListSaveManager.saveRequested() contract was that, if called, the task list would be saved upon next run of the BackgroundSaveTimer (held by the TaskListSaveManager). Your patch alters this slightly and jobs are only being added to the queue currently when  saveContext=true is being passed to TaskListSaveManager.saveTaskList(...).  So when actions take place that result in TaskListManager.containersChanged() being called, a save doesn't happen as part of the subsequent BackgroundSaveTimer save request.
Comment 8 Stefanos Zachariadis CLA 2007-09-17 12:40:22 EDT
Hi,

My apologies for my delay in communicating. Things should hopefully improve.

I may be have this wrong, but I'm slightly confused by the contract, at least as expressed in version 1.26 of TaskListSaveManager.java.

According to that version, TaskListSaveManager.containersChanged() calls saveTaskList() with saveContext=false and async=true.

Following the saveTaskList() logic, this bit will get executed:

if (async) {
  if (saveContext) {
    for (AbstractTask task : taskListManager.getTaskList().getActiveTasks()) {
      taskListSaverJob.addTaskContext(task);
    }
  }
  taskListSaverJob.requestSave();
}

since saveContext == false, the tasks to save will not end up in the queue in taskListSaverJob. However the job will still be scheduled, so this will run:

while (!taskQueue.isEmpty()) {
  AbstractTask task = taskQueue.poll();
  if (task != null) {
    contextManager.saveContext(task.getHandleIdentifier());
  }
}
internalSaveTaskList();

The while loop will not be executed, as the taskQueue is empty. However, the internalSaveTaskList() method will be called.

I'm sorry for being pedantic, but I found the class a bit difficult to follow. If I understand correctly, the only difference between my patch and the current head, is that if saveContext=false, then internalSaveTaskList() will not be run. Is this correct? If so, you'll have the new patch very soon :)
Comment 9 Mik Kersten CLA 2007-09-17 21:56:17 EDT
Stefanos: fyi Rob is away on vacation until Monday, and he'll look over this when he returns.
Comment 10 Robert Elves CLA 2007-09-28 14:00:53 EDT
Sorry for the delay Stefanos.
 (In reply to comment #8)
> I'm sorry for being pedantic, but I found the class a bit difficult to follow.

 This is tricky code and always takes me a minute or two to sort things out... which I guess is a good indicator that we need to refactor this. 

> If I understand correctly, the only difference between my patch and the current
> head, is that if saveContext=false, then internalSaveTaskList() will not be run.
> Is this correct? If so, you'll have the new patch very soon :)

Yes, is my understanding. Where once the code resulted in a call to taskListSaverJob.requestSave(); after your patch the same code doesn't result in effectively requesting a save here when saveContext=false:

public void saveTaskList(boolean saveContext, boolean async) {
		if (TasksUiPlugin.getDefault() != null && TasksUiPlugin.getDefault().isInitialized()) {
			TaskListManager taskListManager = TasksUiPlugin.getTaskListManager();
			if (async) {
				if (saveContext) {
					for (AbstractTask task : taskListManager.getTaskList().getActiveTasks()) {
						taskQueue.add(task);
					}
				}
				jobLock.lock();
				try {
					if(!taskQueue.isEmpty()) {
						TaskListSaverJob job = new TaskListSaverJob(taskQueue);
						job.schedule();
					}
				} finally {
					jobLock.unlock();
				}
Comment 11 Stefanos Zachariadis CLA 2007-10-04 09:55:55 EDT
Created attachment 79722 [details]
second stab for the TasklistSaveManager

will now schedule execution of internalSaveTasklist() even if the taskQueue is empty
Comment 12 Robert Elves CLA 2007-10-25 16:54:54 EDT
Reviewed patch, here are my notes:
* calling internalSaveTaskList() directly from within if(async) can't be done since internalSaveTaskList() is synchronous and could result in blocked ui if called from ui thread
* I think a fundamental problem here may also be that running of the save is dependent on the queue being populated. The queue is only populated a) when true is passed for save context, and b) when there is an active task.  A better way to look at this is perhaps to rename the queue to taskContextQueue since this is simply the queue of task contexts to save -along- with the saving of the tasklist itself. So when save is called a) the active task should be added to the queue if context=true, b) a request to save the tasklist should be registered (we were using a boolean). Then it becomes the job of the BackgroundSaveTimer to actually invoke the save. For an immediate save and flush of the context save queue, save called with asynch = false.

How does this sound?
Comment 13 Max Rydahl Andersen CLA 2008-05-19 11:49:31 EDT
Any chance this will looked into ?
Never idle taskmanager is a pain when trying to do testing...
Comment 14 Steffen Pingel CLA 2008-05-20 13:13:21 EDT
Rob, this has been addressed with the recent changes to the externalization jobs, right?
Comment 15 Robert Elves CLA 2008-06-03 12:56:06 EDT
Fixed.