BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / apps / musiccollection / FileMonitor.cpp
blob620ded5a6b0146c69fcfa326b6a1514104dd7140
1 /*
2 * Copyright 2011, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Clemens Zeidler <haiku@clemens-zeidler.de>
7 */
9 #include "FileMonitor.h"
11 #include <Looper.h>
13 #include <Messenger.h>
14 #include <NodeMonitor.h>
17 FileMonitor::FileMonitor(EntryViewInterface* listener)
19 fListener(listener),
20 fCurrentReadList(NULL),
21 fCurrentReadIndex(0)
27 FileMonitor::~FileMonitor()
29 Reset();
33 void
34 FileMonitor::SetReadThread(ReadThread* readThread)
36 fReadThread = readThread;
40 void
41 FileMonitor::Reset()
43 fWatchedFileList.clear();
44 stop_watching(this);
46 BMessenger messenger(this);
47 messenger.SendMessage(kMsgCleared);
49 if (fCurrentReadList != NULL)
50 fCurrentReadIndex = fCurrentReadList->size();
54 void
55 FileMonitor::MessageReceived(BMessage* msg)
57 switch (msg->what) {
58 case kMsgAddRefs:
60 if (fCurrentReadList == NULL)
61 fCurrentReadList = fReadThread->ReadRefList();
62 uint32 terminate = fCurrentReadIndex + 50;
63 for (; fCurrentReadIndex < terminate; fCurrentReadIndex++) {
64 if (fCurrentReadIndex >= fCurrentReadList->size()) {
65 fCurrentReadList = NULL;
66 fCurrentReadIndex = 0;
67 fReadThread->ReadDone();
68 break;
71 entry_ref& entry = (*fCurrentReadList)[fCurrentReadIndex];
72 node_ref nodeRef;
73 BNode node(&entry);
74 if (node.GetNodeRef(&nodeRef) != B_OK)
75 continue;
77 EntryCreated(entry.name, entry.directory, entry.device,
78 nodeRef.node);
80 if (fCurrentReadList)
81 Looper()->PostMessage(kMsgAddRefs, this);
83 break;
86 case kMsgCleared:
87 fListener->EntriesCleared();
88 break;
90 default:
91 NodeMonitorHandler::MessageReceived(msg);
96 void
97 FileMonitor::EntryCreated(const char *name, ino_t directory, dev_t device,
98 ino_t node)
100 WatchedFile file;
101 NodeMonitorHandler::make_node_ref(device, node, &file.node);
102 if (fWatchedFileList.find(file.node) != fWatchedFileList.end())
103 return;
105 NodeMonitorHandler::make_entry_ref(device, directory, name, &file.entry);
106 fWatchedFileList[file.node] = file;
108 watch_node(&file.node, B_WATCH_NAME | B_WATCH_STAT | B_WATCH_ATTR, this);
109 fListener->EntryCreated(&fWatchedFileList[file.node]);
113 void
114 FileMonitor::EntryRemoved(const char *name, ino_t directory, dev_t device,
115 ino_t node)
117 WatchedFile* file = _FindFile(device, node);
118 if (file == NULL)
119 return;
121 fListener->EntryRemoved(file);
122 fWatchedFileList.erase(file->node);
126 void
127 FileMonitor::EntryMoved(const char *name, const char *fromName,
128 ino_t fromDirectory, ino_t toDirectory, dev_t device, ino_t node,
129 dev_t nodeDevice)
131 WatchedFile* file = _FindFile(device, node);
132 if (file == NULL)
133 return;
134 NodeMonitorHandler::make_entry_ref(device, toDirectory, name, &file->entry);
135 NodeMonitorHandler::make_node_ref(device, node, &file->node);
136 fListener->EntryMoved(file);
140 void
141 FileMonitor::StatChanged(ino_t node, dev_t device, int32 statFields)
143 WatchedFile* file = _FindFile(device, node);
144 if (file == NULL)
145 return;
146 fListener->StatChanged(file);
150 void
151 FileMonitor::AttrChanged(ino_t node, dev_t device)
153 WatchedFile* file = _FindFile(device, node);
154 if (file == NULL)
155 return;
156 fListener->AttrChanged(file);
160 WatchedFile*
161 FileMonitor::_FindFile(dev_t device, ino_t node)
163 node_ref nodeRef;
164 NodeMonitorHandler::make_node_ref(device, node, &nodeRef);
166 WatchedFileList::iterator it = fWatchedFileList.find(nodeRef);
167 if (it == fWatchedFileList.end())
168 return NULL;
170 return &it->second;
174 int32
175 ReadThreadFunction(void *data)
177 ReadThread* that = (ReadThread*)data;
178 return that->Process();
182 ReadThread::ReadThread(FileMonitor* target)
184 fTarget(target),
185 fReading(false),
186 fStopped(false),
187 fThreadId(-1),
188 fNReaded(0),
189 fRunning(false)
191 fWriteRefList = &fRefList1;
192 fReadRefList = &fRefList2;
196 status_t
197 ReadThread::Run()
199 if (fThreadId >= 0)
200 return B_ERROR;
202 fStopped = false;
203 fThreadId = spawn_thread(ReadThreadFunction, "file reader", B_LOW_PRIORITY,
204 this);
205 fRunning = true;
206 status_t status = resume_thread(fThreadId);
207 if (status != B_OK)
208 fRunning = false;
209 return status;
213 bool
214 ReadThread::Running()
216 return fRunning;
220 status_t
221 ReadThread::Wait()
223 status_t exitValue;
224 return wait_for_thread(fThreadId, &exitValue);
228 void
229 ReadThread::Stop()
231 fStopped = true;
235 bool
236 ReadThread::Stopped()
238 return fStopped;
242 RefList*
243 ReadThread::ReadRefList()
245 return fReadRefList;
249 void
250 ReadThread::ReadDone()
252 fReadRefList->clear();
253 // and release the list
254 fReading = false;
256 if (!fRunning && fWriteRefList->size() != 0) {
257 BMessenger messenger(fTarget);
258 _PublishEntrys(messenger);
263 int32
264 ReadThread::Process()
266 BMessenger messenger(fTarget);
268 entry_ref entry;
269 while (ReadNextEntry(entry)) {
270 if (Stopped()) {
271 fWriteRefList->clear();
272 break;
275 fWriteRefList->push_back(entry);
277 fNReaded++;
278 if (fNReaded >= 50)
279 _PublishEntrys(messenger);
282 fRunning = false;
284 _PublishEntrys(messenger);
286 fThreadId = -1;
287 return B_OK;
291 void
292 ReadThread::_SwapLists()
294 RefList* lastReadList = fReadRefList;
295 fReadRefList = fWriteRefList;
296 fWriteRefList = lastReadList;
300 void
301 ReadThread::_PublishEntrys(BMessenger& messenger)
303 if (fReading || Stopped())
304 return;
305 _SwapLists();
306 fReading = true;
307 fNReaded = 0;
308 messenger.SendMessage(kMsgAddRefs);