2 * Copyright 2011, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Clemens Zeidler <haiku@clemens-zeidler.de>
9 #include "FileMonitor.h"
13 #include <Messenger.h>
14 #include <NodeMonitor.h>
17 FileMonitor::FileMonitor(EntryViewInterface
* listener
)
20 fCurrentReadList(NULL
),
27 FileMonitor::~FileMonitor()
34 FileMonitor::SetReadThread(ReadThread
* readThread
)
36 fReadThread
= readThread
;
43 fWatchedFileList
.clear();
46 BMessenger
messenger(this);
47 messenger
.SendMessage(kMsgCleared
);
49 if (fCurrentReadList
!= NULL
)
50 fCurrentReadIndex
= fCurrentReadList
->size();
55 FileMonitor::MessageReceived(BMessage
* msg
)
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();
71 entry_ref
& entry
= (*fCurrentReadList
)[fCurrentReadIndex
];
74 if (node
.GetNodeRef(&nodeRef
) != B_OK
)
77 EntryCreated(entry
.name
, entry
.directory
, entry
.device
,
81 Looper()->PostMessage(kMsgAddRefs
, this);
87 fListener
->EntriesCleared();
91 NodeMonitorHandler::MessageReceived(msg
);
97 FileMonitor::EntryCreated(const char *name
, ino_t directory
, dev_t device
,
101 NodeMonitorHandler::make_node_ref(device
, node
, &file
.node
);
102 if (fWatchedFileList
.find(file
.node
) != fWatchedFileList
.end())
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
]);
114 FileMonitor::EntryRemoved(const char *name
, ino_t directory
, dev_t device
,
117 WatchedFile
* file
= _FindFile(device
, node
);
121 fListener
->EntryRemoved(file
);
122 fWatchedFileList
.erase(file
->node
);
127 FileMonitor::EntryMoved(const char *name
, const char *fromName
,
128 ino_t fromDirectory
, ino_t toDirectory
, dev_t device
, ino_t node
,
131 WatchedFile
* file
= _FindFile(device
, node
);
134 NodeMonitorHandler::make_entry_ref(device
, toDirectory
, name
, &file
->entry
);
135 NodeMonitorHandler::make_node_ref(device
, node
, &file
->node
);
136 fListener
->EntryMoved(file
);
141 FileMonitor::StatChanged(ino_t node
, dev_t device
, int32 statFields
)
143 WatchedFile
* file
= _FindFile(device
, node
);
146 fListener
->StatChanged(file
);
151 FileMonitor::AttrChanged(ino_t node
, dev_t device
)
153 WatchedFile
* file
= _FindFile(device
, node
);
156 fListener
->AttrChanged(file
);
161 FileMonitor::_FindFile(dev_t device
, ino_t node
)
164 NodeMonitorHandler::make_node_ref(device
, node
, &nodeRef
);
166 WatchedFileList::iterator it
= fWatchedFileList
.find(nodeRef
);
167 if (it
== fWatchedFileList
.end())
175 ReadThreadFunction(void *data
)
177 ReadThread
* that
= (ReadThread
*)data
;
178 return that
->Process();
182 ReadThread::ReadThread(FileMonitor
* target
)
191 fWriteRefList
= &fRefList1
;
192 fReadRefList
= &fRefList2
;
203 fThreadId
= spawn_thread(ReadThreadFunction
, "file reader", B_LOW_PRIORITY
,
206 status_t status
= resume_thread(fThreadId
);
214 ReadThread::Running()
224 return wait_for_thread(fThreadId
, &exitValue
);
236 ReadThread::Stopped()
243 ReadThread::ReadRefList()
250 ReadThread::ReadDone()
252 fReadRefList
->clear();
253 // and release the list
256 if (!fRunning
&& fWriteRefList
->size() != 0) {
257 BMessenger
messenger(fTarget
);
258 _PublishEntrys(messenger
);
264 ReadThread::Process()
266 BMessenger
messenger(fTarget
);
269 while (ReadNextEntry(entry
)) {
271 fWriteRefList
->clear();
275 fWriteRefList
->push_back(entry
);
279 _PublishEntrys(messenger
);
284 _PublishEntrys(messenger
);
292 ReadThread::_SwapLists()
294 RefList
* lastReadList
= fReadRefList
;
295 fReadRefList
= fWriteRefList
;
296 fWriteRefList
= lastReadList
;
301 ReadThread::_PublishEntrys(BMessenger
& messenger
)
303 if (fReading
|| Stopped())
308 messenger
.SendMessage(kMsgAddRefs
);