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 26 class VolumeWatcher; 27 28 29 class WatchNameHandler : public NodeMonitorHandler { 30 public: 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); 45 private: 46 VolumeWatcher* fVolumeWatcher; 47 }; 48 49 50 typedef std::vector<entry_ref> EntryRefVector; 51 52 53 class VolumeWatcher; 54 55 56 const uint32 kTriggerWork = '&twk'; // what a bad message 57 58 59 class VolumeWorker : public AnalyserDispatcher 60 { 61 public: 62 VolumeWorker(VolumeWatcher* watcher); 63 64 void MessageReceived(BMessage *message); 65 66 bool IsBusy(); 67 68 private: 69 void _Work(); 70 71 void _SetBusy(bool busy = true); 72 73 VolumeWatcher* fVolumeWatcher; 74 vint32 fBusy; 75 }; 76 77 78 class VolumeWatcherBase { 79 public: 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 87 protected: 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 100 list the worker thread can handle the second list. The worker thread gets his entries by calling SwapList while holding the watcher thread lock. */ 101 class SwapEntryRefVector { 102 public: 103 SwapEntryRefVector(); 104 105 EntryRefVector* SwapList(); 106 EntryRefVector* CurrentList(); 107 private: 108 EntryRefVector fFirstList; 109 EntryRefVector fSecondList; 110 EntryRefVector* fCurrentList; 111 EntryRefVector* fNextList; 112 }; 113 114 115 struct 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. */ 126 class VolumeWatcher : public VolumeWatcherBase, public BLooper { 127 public: 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 143 private: 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