OSDN Git Service

Alter sync logic to examine new notes as they arrive rather than doing a full reload...
[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 \r
44         private volatile LinkedBlockingQueue<Pair<String, String>> workQueue = new LinkedBlockingQueue<Pair<String, String>>();\r
45         \r
46         \r
47         //*********************************************\r
48         //* Constructor                               *\r
49         //*********************************************\r
50         public SaveRunner(String logname, String u, String uid, String pswd, String cpswd) {\r
51                 logger = new ApplicationLogger(logname);\r
52                 conn = new DatabaseConnection(logger, u, uid, pswd, cpswd);\r
53                 threadLock = new QMutex();\r
54                 keepRunning = true;\r
55         }\r
56         \r
57         \r
58         \r
59         //*********************************************\r
60         //* Run unit                                  *\r
61         //*********************************************\r
62         @Override\r
63         public void run() {\r
64                 thread().setPriority(Thread.MIN_PRIORITY);\r
65                 boolean keepRunning = true;\r
66                 \r
67                 while(keepRunning) {\r
68                         try {\r
69                                 Pair<String, String> content;\r
70                                 idle = true;\r
71                                 content = workQueue.take();\r
72                                 if (!content.getFirst().equalsIgnoreCase("stop")) {                                             \r
73                                         idle = false;\r
74                                         \r
75                                         // This is a bit of a hack.  It causes this thread to pause for 0.2 seconds.\r
76                                         // This helps make sure that the main thread gets to the\r
77                                         // database first when switching notes, othrewise it really \r
78                                         // slows things down when fetching new notes.\r
79                                         GregorianCalendar now = new GregorianCalendar();\r
80                                         long prev = now.getTimeInMillis();\r
81                                         prev = prev+200;\r
82                                         while (prev>now.getTimeInMillis()) {\r
83                                                 now = new GregorianCalendar();                                          \r
84                                         }\r
85                                         \r
86                                         updateNoteContent(content.getFirst(), content.getSecond());\r
87                                 } else {\r
88                                         return;\r
89                                 }\r
90                                 threadLock.unlock();\r
91                         } catch (InterruptedException e) { }\r
92                 }\r
93                 conn.dbShutdown();\r
94         }\r
95         \r
96         \r
97         public synchronized void addWork(String guid, String content) {\r
98                 while(workQueue.size() > 0) {}\r
99                 Pair<String, String> pair = new Pair<String, String>(guid, content);\r
100                 workQueue.offer(pair);\r
101         }\r
102         \r
103         public synchronized void release(String guid, String content) {\r
104                 Pair<String, String> pair = new Pair<String, String>(guid, content);\r
105                 workQueue.add(pair);\r
106         }\r
107         \r
108         public synchronized int getWorkQueueSize() {\r
109                 return workQueue.size();\r
110         }\r
111 \r
112         \r
113         //*********************************************\r
114         //* Getter & Setter method to tell the thread *\r
115         //* to keep running.                          *\r
116         //*********************************************\r
117         public void setKeepRunning(boolean b) {\r
118                 keepRunning = b;\r
119         }\r
120         public boolean keepRunning() {\r
121                 return keepRunning;\r
122         }\r
123         \r
124         public boolean isIdle() {\r
125                 return idle;\r
126         }\r
127         \r
128         \r
129         //*********************************************\r
130         //* Do the actual work                                *\r
131         //*********************************************\r
132         public void updateNoteContent(String guid, String content) {\r
133                 logger.log(logger.HIGH, "Entering ListManager.updateNoteContent");\r
134                 \r
135                 // Actually save the content\r
136                 EnmlConverter enml = new EnmlConverter(logger);\r
137                 String newContent = enml.convert(guid, content);\r
138                 String fixedContent = enml.fixEnXMLCrap(newContent);\r
139                 conn.getNoteTable().updateNoteContent(guid, fixedContent);\r
140 \r
141 \r
142                 logger.log(logger.EXTREME, "Saving new note resources");\r
143                 List<Resource> oldResources = conn.getNoteTable().noteResourceTable.getNoteResources(guid, false);\r
144                 List<String> newResources = enml.getResources();\r
145                 removeObsoleteResources(oldResources, newResources);\r
146                 \r
147                 logger.log(logger.HIGH, "Leaving ListManager.updateNoteContent");\r
148         }\r
149         \r
150         // Remove resources that are no longer needed\r
151         private void removeObsoleteResources(List<Resource> oldResources, List<String> newResources) {\r
152                 if (oldResources == null || oldResources.size() == 0)\r
153                         return;\r
154                 if (newResources == null || newResources.size() == 0) {\r
155                         for (int i=0; i<oldResources.size(); i++) {\r
156                                 conn.getNoteTable().noteResourceTable.expungeNoteResource(oldResources.get(i).getGuid());\r
157                         }\r
158                 }\r
159                 for (int i=0; i<oldResources.size(); i++) {\r
160                         boolean matchFound = false;\r
161                         for (int j=0; j<newResources.size(); j++) {\r
162                                 if (newResources.get(j).equalsIgnoreCase(oldResources.get(i).getGuid())) \r
163                                         matchFound = true;\r
164                                 if (Global.resourceMap.get(newResources.get(j))!= null) {\r
165                                         if (Global.resourceMap.get(newResources.get(j)).equalsIgnoreCase(oldResources.get(i).getGuid())) \r
166                                                 matchFound = true;\r
167                                 }\r
168                                 if (matchFound)\r
169                                         j = newResources.size();\r
170                         }\r
171                         if (!matchFound)\r
172                                 conn.getNoteTable().noteResourceTable.expungeNoteResource(oldResources.get(i).getGuid());\r
173                 }\r
174         }\r
175 }\r