OSDN Git Service

7fdd135507ef37c6cfc17be8fecdfae2e53d77ee
[neighbornote/NeighborNote.git] / src / cx / fbn / nevernote / threads / SaveRunner.java
1 /*\r
2  * This file is part of NeverNote \r
3  * Copyright 2009 Randy Baumgarte\r
4  * \r
5  * This file may be licensed under the terms of of the\r
6  * GNU General Public License Version 2 (the ``GPL'').\r
7  *\r
8  * Software distributed under the License is distributed\r
9  * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either\r
10  * express or implied. See the GPL for the specific language\r
11  * governing rights and limitations.\r
12  *\r
13  * You should have received a copy of the GPL along with this\r
14  * program. If not, go to http://www.gnu.org/licenses/gpl.html\r
15  * or write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
17  *\r
18 */\r
19 \r
20 package cx.fbn.nevernote.threads;\r
21 \r
22 import java.util.GregorianCalendar;\r
23 import java.util.List;\r
24 import java.util.concurrent.LinkedBlockingQueue;\r
25 \r
26 import com.evernote.edam.type.Resource;\r
27 import com.trolltech.qt.core.QMutex;\r
28 import com.trolltech.qt.core.QObject;\r
29 \r
30 import cx.fbn.nevernote.Global;\r
31 import cx.fbn.nevernote.evernote.EnmlConverter;\r
32 import cx.fbn.nevernote.sql.DatabaseConnection;\r
33 import cx.fbn.nevernote.utilities.ApplicationLogger;\r
34 import cx.fbn.nevernote.utilities.Pair;\r
35 \r
36 public class SaveRunner extends QObject implements Runnable {\r
37          \r
38         private final ApplicationLogger         logger;\r
39         private volatile boolean                        keepRunning;\r
40         public QMutex                                           threadLock;\r
41         private final DatabaseConnection        conn;\r
42         private boolean                                         idle;\r
43         private final int                                       threadID;\r
44 \r
45         private volatile LinkedBlockingQueue<Pair<String, String>> workQueue = new LinkedBlockingQueue<Pair<String, String>>();\r
46         \r
47         \r
48         //*********************************************\r
49         //* Constructor                               *\r
50         //*********************************************\r
51         public SaveRunner(String logname) {\r
52                 logger = new ApplicationLogger(logname);\r
53                 threadID = Global.saveThreadId;\r
54                 conn = new DatabaseConnection(logger, threadID);\r
55                 threadLock = new QMutex();\r
56                 keepRunning = true;\r
57         }\r
58         \r
59         \r
60         \r
61         //*********************************************\r
62         //* Run unit                                  *\r
63         //*********************************************\r
64         @Override\r
65         public void run() {\r
66                 thread().setPriority(Thread.MIN_PRIORITY);\r
67                 boolean keepRunning = true;\r
68                 \r
69                 while(keepRunning) {\r
70                         try {\r
71                                 Pair<String, String> content;\r
72                                 idle = true;\r
73                                 content = workQueue.take();\r
74                                 if (!content.getFirst().equalsIgnoreCase("stop")) {                                             \r
75                                         idle = false;\r
76                                         \r
77                                         // This is a bit of a hack.  It causes this thread to pause for 0.2 seconds.\r
78                                         // This helps make sure that the main thread gets to the\r
79                                         // database first when switching notes, othrewise it really \r
80                                         // slows things down when fetching new notes.\r
81                                         GregorianCalendar now = new GregorianCalendar();\r
82                                         long prev = now.getTimeInMillis();\r
83                                         prev = prev+200;\r
84                                         while (prev>now.getTimeInMillis()) {\r
85                                                 now = new GregorianCalendar();                                          \r
86                                         }\r
87                                         \r
88                                         updateNoteContent(content.getFirst(), content.getSecond());\r
89                                 } else {\r
90                                         return;\r
91                                 }\r
92                                 threadLock.unlock();\r
93                         } catch (InterruptedException e) { }\r
94                 }\r
95         }\r
96         \r
97         \r
98         public synchronized void addWork(String guid, String content) {\r
99                 while(workQueue.size() > 0) {}\r
100                 Pair<String, String> pair = new Pair<String, String>(guid, content);\r
101                 workQueue.offer(pair);\r
102         }\r
103         \r
104         public synchronized void release(String guid, String content) {\r
105                 Pair<String, String> pair = new Pair<String, String>(guid, content);\r
106                 workQueue.add(pair);\r
107         }\r
108         \r
109         public synchronized int getWorkQueueSize() {\r
110                 return workQueue.size();\r
111         }\r
112 \r
113         \r
114         //*********************************************\r
115         //* Getter & Setter method to tell the thread *\r
116         //* to keep running.                          *\r
117         //*********************************************\r
118         public void setKeepRunning(boolean b) {\r
119                 keepRunning = b;\r
120         }\r
121         public boolean keepRunning() {\r
122                 return keepRunning;\r
123         }\r
124         \r
125         public boolean isIdle() {\r
126                 return idle;\r
127         }\r
128         \r
129         \r
130         //*********************************************\r
131         //* Do the actual work                                *\r
132         //*********************************************\r
133         public void updateNoteContent(String guid, String content) {\r
134                 logger.log(logger.HIGH, "Entering ListManager.updateNoteContent");\r
135                 \r
136                 // Actually save the content\r
137                 EnmlConverter enml = new EnmlConverter(logger);\r
138                 String newContent = enml.convert(guid, content);\r
139                 String fixedContent = enml.fixEnXMLCrap(newContent);\r
140                 conn.getNoteTable().updateNoteContent(guid, fixedContent);\r
141 \r
142 \r
143                 logger.log(logger.EXTREME, "Saving new note resources");\r
144                 List<Resource> oldResources = conn.getNoteTable().noteResourceTable.getNoteResources(guid, false);\r
145                 List<String> newResources = enml.getResources();\r
146                 removeObsoleteResources(oldResources, newResources);\r
147                 \r
148                 logger.log(logger.HIGH, "Leaving ListManager.updateNoteContent");\r
149         }\r
150         \r
151         // Remove resources that are no longer needed\r
152         private void removeObsoleteResources(List<Resource> oldResources, List<String> newResources) {\r
153                 if (oldResources == null || oldResources.size() == 0)\r
154                         return;\r
155                 if (newResources == null || newResources.size() == 0) {\r
156                         for (int i=0; i<oldResources.size(); i++) {\r
157                                 conn.getNoteTable().noteResourceTable.expungeNoteResource(oldResources.get(i).getGuid());\r
158                         }\r
159                 }\r
160                 for (int i=0; i<oldResources.size(); i++) {\r
161                         boolean matchFound = false;\r
162                         for (int j=0; j<newResources.size(); j++) {\r
163                                 if (newResources.get(j).equalsIgnoreCase(oldResources.get(i).getGuid())) \r
164                                         matchFound = true;\r
165                                 if (Global.resourceMap.get(newResources.get(j))!= null) {\r
166                                         if (Global.resourceMap.get(newResources.get(j)).equalsIgnoreCase(oldResources.get(i).getGuid())) \r
167                                                 matchFound = true;\r
168                                 }\r
169                                 if (matchFound)\r
170                                         j = newResources.size();\r
171                         }\r
172                         if (!matchFound)\r
173                                 conn.getNoteTable().noteResourceTable.expungeNoteResource(oldResources.get(i).getGuid());\r
174                 }\r
175         }\r
176 }\r