1/*
2 * Copyright 2010, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Clemens Zeidler <haiku@clemens-zeidler.de>
7 */
8#ifndef VOLUME_WATCHER_H
9#define VOLUME_WATCHER_H
10
11
12#include <vector>
13
14#include <Debug.h>
15#include <Handler.h>
16#include <NodeMonitorHandler.h>
17#include <Volume.h>
18
19#include <ObjectList.h>
20
21#include "AnalyserDispatcher.h"
22#include "CatchUpManager.h"
23#include "IndexServerAddOn.h"
24
25
26class VolumeWatcher;
27
28
29class WatchNameHandler : public NodeMonitorHandler {
30public:
31								WatchNameHandler(VolumeWatcher* volumeWatcher);
32
33			void				EntryCreated(const char *name, ino_t directory,
34									dev_t device, ino_t node);
35			void				EntryRemoved(const char *name, ino_t directory,
36									dev_t device, ino_t node);
37			void				EntryMoved(const char *name,
38									const char *fromName, ino_t from_directory,
39									ino_t to_directory, dev_t device,
40									ino_t node, dev_t nodeDevice);
41			void				StatChanged(ino_t node, dev_t device,
42									int32 statFields);
43
44			void				MessageReceived(BMessage* msg);
45private:
46			VolumeWatcher*		fVolumeWatcher;
47};
48
49
50typedef std::vector<entry_ref> EntryRefVector;
51
52
53class VolumeWatcher;
54
55
56const uint32 kTriggerWork = '&twk';	// what a bad message
57
58
59class VolumeWorker : public AnalyserDispatcher
60{
61public:
62								VolumeWorker(VolumeWatcher* watcher);
63
64			void				MessageReceived(BMessage *message);
65
66			bool				IsBusy();
67
68private:
69			void				_Work();
70
71			void				_SetBusy(bool busy = true);
72
73			VolumeWatcher*		fVolumeWatcher;
74			int32				fBusy;
75};
76
77
78class VolumeWatcherBase {
79public:
80								VolumeWatcherBase(const BVolume& volume);
81
82			const BVolume&		Volume() { return fVolume; }
83
84			bool				Enabled() { return fEnabled; }
85			bigtime_t			GetLastUpdated() { return fLastUpdated; }
86
87protected:
88			bool				ReadSettings();
89			bool				WriteSettings();
90
91			BVolume				fVolume;
92
93			bool				fEnabled;
94
95			bigtime_t			fLastUpdated;
96};
97
98
99/*! Used to thread safe exchange refs. While the watcher thread file the current
100list the worker thread can handle the second list. The worker thread gets his entries by calling SwapList while holding the watcher thread lock. */
101class SwapEntryRefVector {
102public:
103								SwapEntryRefVector();
104
105			EntryRefVector*		SwapList();
106			EntryRefVector*		CurrentList();
107private:
108			EntryRefVector		fFirstList;
109			EntryRefVector		fSecondList;
110			EntryRefVector*		fCurrentList;
111			EntryRefVector*		fNextList;
112};
113
114
115struct list_collection
116{
117			EntryRefVector*		createdList;
118			EntryRefVector*		deletedList;
119			EntryRefVector*		modifiedList;
120			EntryRefVector*		movedList;
121			EntryRefVector*		movedFromList;
122};
123
124
125/*! Watch a volume and delegate changed entries to a VolumeWorker. */
126class VolumeWatcher : public VolumeWatcherBase, public BLooper {
127public:
128								VolumeWatcher(const BVolume& volume);
129								~VolumeWatcher();
130
131			bool				StartWatching();
132			void				Stop();
133
134			//! thread safe
135			bool				AddAnalyser(FileAnalyser* analyser);
136			bool				RemoveAnalyser(const BString& name);
137
138			void				GetSecureEntries(list_collection& collection);
139
140			bool				FindEntryRef(ino_t node, dev_t device,
141									entry_ref& entry);
142
143private:
144	friend class WatchNameHandler;
145
146			void				_NewEntriesArrived();
147
148			bool				fWatching;
149
150			WatchNameHandler	fWatchNameHandler;
151
152			SwapEntryRefVector	fCreatedList;
153			SwapEntryRefVector	fDeleteList;
154			SwapEntryRefVector	fModifiedList;
155			SwapEntryRefVector	fMovedList;
156			SwapEntryRefVector	fMovedFromList;
157
158			VolumeWorker*		fVolumeWorker;
159			CatchUpManager		fCatchUpManager;
160};
161
162
163#endif
164