xref: /haiku/src/add-ons/kernel/file_systems/netfs/server/VolumeManager.cpp (revision ebb21bd1486152acf792f4b069339d14ef6e1896)
15a1d355fSStephan Aßmus // VolumeManager.cpp
25a1d355fSStephan Aßmus 
35a1d355fSStephan Aßmus #include "VolumeManager.h"
45a1d355fSStephan Aßmus 
55a1d355fSStephan Aßmus #include <new>
65a1d355fSStephan Aßmus 
75a1d355fSStephan Aßmus #include <sys/stat.h>
85a1d355fSStephan Aßmus 
95a1d355fSStephan Aßmus #include <AutoDeleter.h>
105a1d355fSStephan Aßmus #include <Entry.h>
115a1d355fSStephan Aßmus #include <fs_info.h>
125a1d355fSStephan Aßmus #include <fs_query.h>
135a1d355fSStephan Aßmus #include <HashMap.h>
145a1d355fSStephan Aßmus #include <NodeMonitor.h>
155a1d355fSStephan Aßmus #include <Volume.h>
165a1d355fSStephan Aßmus 
175a1d355fSStephan Aßmus #include "ClientVolume.h"
185a1d355fSStephan Aßmus #include "DebugSupport.h"
195a1d355fSStephan Aßmus #include "Directory.h"
205a1d355fSStephan Aßmus #include "Entry.h"
215a1d355fSStephan Aßmus #include "FDManager.h"
225a1d355fSStephan Aßmus #include "NodeHandle.h"
235a1d355fSStephan Aßmus #include "Path.h"
245a1d355fSStephan Aßmus #include "QueryDomain.h"
255a1d355fSStephan Aßmus #include "Volume.h"
265a1d355fSStephan Aßmus 
275a1d355fSStephan Aßmus // TODO: We should filter recent events at some point. Otherwise we'll end up
285a1d355fSStephan Aßmus // with one event of each kind for each entry/node.
295a1d355fSStephan Aßmus 
305a1d355fSStephan Aßmus const bigtime_t kRecentEventLifeTime = 100000;	// 0.1 s
315a1d355fSStephan Aßmus 
325a1d355fSStephan Aßmus // QueryHandler
335a1d355fSStephan Aßmus class VolumeManager::QueryHandler : public BHandler, public QueryListener,
345a1d355fSStephan Aßmus 	public BReferenceable {
355a1d355fSStephan Aßmus public:
QueryHandler(NodeMonitorListener * listener,QueryDomain * queryDomain,QueryHandle * handle)365a1d355fSStephan Aßmus 	QueryHandler(NodeMonitorListener* listener, QueryDomain* queryDomain,
375a1d355fSStephan Aßmus 		QueryHandle* handle)
385a1d355fSStephan Aßmus 		:
395a1d355fSStephan Aßmus 		BHandler(),
405a1d355fSStephan Aßmus 		QueryListener(),
4188e38c17SIngo Weinhold 		BReferenceable(),
425a1d355fSStephan Aßmus 		fListener(listener),
435a1d355fSStephan Aßmus 		fQueryDomain(queryDomain),
445a1d355fSStephan Aßmus 		fHandle(handle)
455a1d355fSStephan Aßmus 	{
465a1d355fSStephan Aßmus 	}
475a1d355fSStephan Aßmus 
GetQueryDomain() const485a1d355fSStephan Aßmus 	QueryDomain* GetQueryDomain() const
495a1d355fSStephan Aßmus 	{
505a1d355fSStephan Aßmus 		return fQueryDomain;
515a1d355fSStephan Aßmus 	}
525a1d355fSStephan Aßmus 
GetQueryHandle() const535a1d355fSStephan Aßmus 	QueryHandle* GetQueryHandle() const
545a1d355fSStephan Aßmus 	{
555a1d355fSStephan Aßmus 		return fHandle;
565a1d355fSStephan Aßmus 	}
575a1d355fSStephan Aßmus 
MessageReceived(BMessage * message)585a1d355fSStephan Aßmus 	virtual void MessageReceived(BMessage* message)
595a1d355fSStephan Aßmus 	{
605a1d355fSStephan Aßmus 		switch (message->what) {
615a1d355fSStephan Aßmus 			case B_QUERY_UPDATE:
625a1d355fSStephan Aßmus 			{
635a1d355fSStephan Aßmus 				NodeMonitoringEvent* event = NULL;
645a1d355fSStephan Aßmus 				int32 opcode;
655a1d355fSStephan Aßmus 				if (message->FindInt32("opcode", &opcode) == B_OK) {
665a1d355fSStephan Aßmus 					switch (opcode) {
675a1d355fSStephan Aßmus 						case B_ENTRY_CREATED:
685a1d355fSStephan Aßmus 							event = new(std::nothrow) EntryCreatedEvent;
695a1d355fSStephan Aßmus 							break;
705a1d355fSStephan Aßmus 						case B_ENTRY_REMOVED:
715a1d355fSStephan Aßmus 							event = new(std::nothrow) EntryRemovedEvent;
725a1d355fSStephan Aßmus 							break;
735a1d355fSStephan Aßmus 						case B_ENTRY_MOVED:
745a1d355fSStephan Aßmus 							event = new(std::nothrow) EntryMovedEvent;
755a1d355fSStephan Aßmus 							break;
765a1d355fSStephan Aßmus 					}
775a1d355fSStephan Aßmus 				}
785a1d355fSStephan Aßmus 				if (event) {
795a1d355fSStephan Aßmus 					event->queryHandler = this;
8088e38c17SIngo Weinhold 					AcquireReference();
815a1d355fSStephan Aßmus 					if (event->Init(message) == B_OK)
825a1d355fSStephan Aßmus 						fListener->ProcessNodeMonitoringEvent(event);
835a1d355fSStephan Aßmus 					else
845a1d355fSStephan Aßmus 						delete event;
855a1d355fSStephan Aßmus 				}
865a1d355fSStephan Aßmus 				break;
875a1d355fSStephan Aßmus 			}
885a1d355fSStephan Aßmus 			default:
895a1d355fSStephan Aßmus 				BHandler::MessageReceived(message);
905a1d355fSStephan Aßmus 		}
915a1d355fSStephan Aßmus 	}
925a1d355fSStephan Aßmus 
QueryHandleClosed(QueryHandle * handle)935a1d355fSStephan Aßmus 	virtual void QueryHandleClosed(QueryHandle* handle)
945a1d355fSStephan Aßmus 	{
955a1d355fSStephan Aßmus 		BLooper* looper = Looper();
965a1d355fSStephan Aßmus 		if (looper && looper->Lock()) {
975a1d355fSStephan Aßmus 			looper->RemoveHandler(this);
985a1d355fSStephan Aßmus 			looper->Unlock();
995a1d355fSStephan Aßmus 		}
1005a1d355fSStephan Aßmus 		handle->SetQueryListener(NULL);
10188e38c17SIngo Weinhold 		ReleaseReference();
1025a1d355fSStephan Aßmus 	}
1035a1d355fSStephan Aßmus 
1045a1d355fSStephan Aßmus private:
1055a1d355fSStephan Aßmus 	NodeMonitorListener*	fListener;
1065a1d355fSStephan Aßmus 	QueryDomain*			fQueryDomain;
1075a1d355fSStephan Aßmus 	QueryHandle*			fHandle;
1085a1d355fSStephan Aßmus };
1095a1d355fSStephan Aßmus 
1105a1d355fSStephan Aßmus // VolumeMap
1115a1d355fSStephan Aßmus struct VolumeManager::VolumeMap : HashMap<HashKey32<dev_t>, Volume*> {
1125a1d355fSStephan Aßmus };
1135a1d355fSStephan Aßmus 
1145a1d355fSStephan Aßmus // ClientVolumeMap
1155a1d355fSStephan Aßmus struct VolumeManager::ClientVolumeMap
1165a1d355fSStephan Aßmus 	: HashMap<HashKey32<int32>, ClientVolume*> {
1175a1d355fSStephan Aßmus };
1185a1d355fSStephan Aßmus 
1195a1d355fSStephan Aßmus // private BeOS syscalls to set the FD and node monitor slot limits
1205a1d355fSStephan Aßmus extern "C" int _kset_fd_limit_(int num);
1215a1d355fSStephan Aßmus extern "C" int _kset_mon_limit_(int num);
1225a1d355fSStephan Aßmus 
1235a1d355fSStephan Aßmus 
1245a1d355fSStephan Aßmus // EntryCreatedEventMap
1255a1d355fSStephan Aßmus struct VolumeManager::EntryCreatedEventMap
1265a1d355fSStephan Aßmus 	: HashMap<EntryRef, EntryCreatedEvent*> {
1275a1d355fSStephan Aßmus };
1285a1d355fSStephan Aßmus 
1295a1d355fSStephan Aßmus // EntryRemovedEventMap
1305a1d355fSStephan Aßmus struct VolumeManager::EntryRemovedEventMap
1315a1d355fSStephan Aßmus 	: HashMap<EntryRef, EntryRemovedEvent*> {
1325a1d355fSStephan Aßmus };
1335a1d355fSStephan Aßmus 
1345a1d355fSStephan Aßmus // EntryMovedEventKey
1355a1d355fSStephan Aßmus struct EntryMovedEventKey : public EntryRef {
EntryMovedEventKeyEntryMovedEventKey1365a1d355fSStephan Aßmus 	EntryMovedEventKey()
1375a1d355fSStephan Aßmus 	{
1385a1d355fSStephan Aßmus 	}
1395a1d355fSStephan Aßmus 
EntryMovedEventKeyEntryMovedEventKey1405a1d355fSStephan Aßmus 	EntryMovedEventKey(dev_t volumeID, ino_t fromDirectory,
1415a1d355fSStephan Aßmus 		const char* fromName, ino_t toDirectory, const char* toName)
1425a1d355fSStephan Aßmus 		: EntryRef(volumeID, fromDirectory, fromName),
1435a1d355fSStephan Aßmus 		  toDirectory(toDirectory),
1445a1d355fSStephan Aßmus 		  toName(toName)
1455a1d355fSStephan Aßmus 	{
1465a1d355fSStephan Aßmus 
1475a1d355fSStephan Aßmus 	}
1485a1d355fSStephan Aßmus 
GetHashCodeEntryMovedEventKey1495a1d355fSStephan Aßmus 	uint32 GetHashCode() const
1505a1d355fSStephan Aßmus 	{
1515a1d355fSStephan Aßmus 		uint32 hash = EntryRef::GetHashCode();
1525a1d355fSStephan Aßmus 		hash = 17 * hash + (uint32)(toDirectory >> 32);
1535a1d355fSStephan Aßmus 		hash = 17 * hash + (uint32)toDirectory;
1545a1d355fSStephan Aßmus 		hash = 17 * hash + string_hash(toName.GetString());
1555a1d355fSStephan Aßmus 		return hash;
1565a1d355fSStephan Aßmus 	}
1575a1d355fSStephan Aßmus 
operator ==EntryMovedEventKey1585a1d355fSStephan Aßmus 	bool operator==(const EntryMovedEventKey& other) const
1595a1d355fSStephan Aßmus 	{
1605a1d355fSStephan Aßmus 		return (*(const EntryRef*)this) == other
1615a1d355fSStephan Aßmus 			&& toDirectory == other.toDirectory
1625a1d355fSStephan Aßmus 			&& toName == other.toName;
1635a1d355fSStephan Aßmus 	}
1645a1d355fSStephan Aßmus 
operator !=EntryMovedEventKey1655a1d355fSStephan Aßmus 	bool operator!=(const EntryMovedEventKey& other) const
1665a1d355fSStephan Aßmus 	{
1675a1d355fSStephan Aßmus 		return !(*this == other);
1685a1d355fSStephan Aßmus 	}
1695a1d355fSStephan Aßmus 
1705a1d355fSStephan Aßmus 	ino_t		toDirectory;
1715a1d355fSStephan Aßmus 	HashString	toName;
1725a1d355fSStephan Aßmus };
1735a1d355fSStephan Aßmus 
1745a1d355fSStephan Aßmus // EntryMovedEventMap
1755a1d355fSStephan Aßmus struct VolumeManager::EntryMovedEventMap : HashMap<EntryRef, EntryMovedEvent*> {
1765a1d355fSStephan Aßmus };
1775a1d355fSStephan Aßmus 
1785a1d355fSStephan Aßmus // NodeStatChangedEventMap
1795a1d355fSStephan Aßmus struct VolumeManager::NodeStatChangedEventMap
1805a1d355fSStephan Aßmus 	: HashMap<NodeRef, StatChangedEvent*> {
1815a1d355fSStephan Aßmus };
1825a1d355fSStephan Aßmus 
1835a1d355fSStephan Aßmus typedef EntryRef AttributeRef;
1845a1d355fSStephan Aßmus 
1855a1d355fSStephan Aßmus // NodeAttributeChangedEventMap
1865a1d355fSStephan Aßmus struct VolumeManager::NodeAttributeChangedEventMap
1875a1d355fSStephan Aßmus 	: HashMap<AttributeRef, AttributeChangedEvent*> {
1885a1d355fSStephan Aßmus };
1895a1d355fSStephan Aßmus 
1905a1d355fSStephan Aßmus 
1915a1d355fSStephan Aßmus // #pragma mark -
1925a1d355fSStephan Aßmus 
1935a1d355fSStephan Aßmus // constructor
VolumeManager()1945a1d355fSStephan Aßmus VolumeManager::VolumeManager()
1955a1d355fSStephan Aßmus 	: fLock("volume manager"),
1965a1d355fSStephan Aßmus 	  fVolumes(NULL),
1975a1d355fSStephan Aßmus 	  fRootVolume(NULL),
1985a1d355fSStephan Aßmus 	  fClientVolumes(NULL),
1995a1d355fSStephan Aßmus 	  fNodeMonitor(NULL),
2005a1d355fSStephan Aßmus 	  fNodeMonitoringProcessor(-1),
2015a1d355fSStephan Aßmus 	  fNodeMonitoringEvents(),
2025a1d355fSStephan Aßmus 	  fRecentNodeMonitoringEvents(),
2035a1d355fSStephan Aßmus 	  fEntryCreatedEvents(NULL),
2045a1d355fSStephan Aßmus 	  fEntryRemovedEvents(NULL),
2055a1d355fSStephan Aßmus 	  fEntryMovedEvents(NULL),
2065a1d355fSStephan Aßmus 	  fNodeStatChangedEvents(NULL),
2075a1d355fSStephan Aßmus 	  fNodeAttributeChangedEvents(NULL),
2085a1d355fSStephan Aßmus 	  fRevision(0),
2095a1d355fSStephan Aßmus 	  fTerminating(false)
2105a1d355fSStephan Aßmus {
2115a1d355fSStephan Aßmus }
2125a1d355fSStephan Aßmus 
2135a1d355fSStephan Aßmus // destructor
~VolumeManager()2145a1d355fSStephan Aßmus VolumeManager::~VolumeManager()
2155a1d355fSStephan Aßmus {
2165a1d355fSStephan Aßmus 	// terminate the node monitor and the node monitoring processor
2175a1d355fSStephan Aßmus 	fTerminating = true;
2185a1d355fSStephan Aßmus 	if (fNodeMonitor && fNodeMonitor->Lock())
2195a1d355fSStephan Aßmus 		fNodeMonitor->Quit();
2205a1d355fSStephan Aßmus 	fNodeMonitoringEvents.Close(true);
2215a1d355fSStephan Aßmus 	if (fNodeMonitoringProcessor >= 0) {
2225a1d355fSStephan Aßmus 		int32 result;
2235a1d355fSStephan Aßmus 		wait_for_thread(fNodeMonitoringProcessor, &result);
2245a1d355fSStephan Aßmus 	}
2255a1d355fSStephan Aßmus 
2265a1d355fSStephan Aßmus 	// delete all events
2275a1d355fSStephan Aßmus 	// entry created events
2285a1d355fSStephan Aßmus 	for (EntryCreatedEventMap::Iterator it = fEntryCreatedEvents->GetIterator();
2295a1d355fSStephan Aßmus 		 it.HasNext();) {
23088e38c17SIngo Weinhold 		it.Next().value->ReleaseReference();
2315a1d355fSStephan Aßmus 	}
2325a1d355fSStephan Aßmus 	delete fEntryCreatedEvents;
2335a1d355fSStephan Aßmus 
2345a1d355fSStephan Aßmus 	// entry removed events
2355a1d355fSStephan Aßmus 	for (EntryRemovedEventMap::Iterator it = fEntryRemovedEvents->GetIterator();
2365a1d355fSStephan Aßmus 		 it.HasNext();) {
23788e38c17SIngo Weinhold 		it.Next().value->ReleaseReference();
2385a1d355fSStephan Aßmus 	}
2395a1d355fSStephan Aßmus 	delete fEntryRemovedEvents;
2405a1d355fSStephan Aßmus 
2415a1d355fSStephan Aßmus 	// entry moved events
2425a1d355fSStephan Aßmus 	for (EntryMovedEventMap::Iterator it = fEntryMovedEvents->GetIterator();
2435a1d355fSStephan Aßmus 		 it.HasNext();) {
24488e38c17SIngo Weinhold 		it.Next().value->ReleaseReference();
2455a1d355fSStephan Aßmus 	}
2465a1d355fSStephan Aßmus 	delete fEntryMovedEvents;
2475a1d355fSStephan Aßmus 
2485a1d355fSStephan Aßmus 	// stat changed events
2495a1d355fSStephan Aßmus 	for (NodeStatChangedEventMap::Iterator it
2505a1d355fSStephan Aßmus 			= fNodeStatChangedEvents->GetIterator();
2515a1d355fSStephan Aßmus 		 it.HasNext();) {
25288e38c17SIngo Weinhold 		it.Next().value->ReleaseReference();
2535a1d355fSStephan Aßmus 	}
2545a1d355fSStephan Aßmus 	delete fNodeStatChangedEvents;
2555a1d355fSStephan Aßmus 
2565a1d355fSStephan Aßmus 	// attribute changed events
2575a1d355fSStephan Aßmus 	for (NodeAttributeChangedEventMap::Iterator it
2585a1d355fSStephan Aßmus 			= fNodeAttributeChangedEvents->GetIterator();
2595a1d355fSStephan Aßmus 		 it.HasNext();) {
26088e38c17SIngo Weinhold 		it.Next().value->ReleaseReference();
2615a1d355fSStephan Aßmus 	}
2625a1d355fSStephan Aßmus 	delete fNodeAttributeChangedEvents;
2635a1d355fSStephan Aßmus 
2645a1d355fSStephan Aßmus 	delete fClientVolumes;
2655a1d355fSStephan Aßmus 
2665a1d355fSStephan Aßmus 	// delete the volumes
2675a1d355fSStephan Aßmus 	for (VolumeMap::Iterator it = fVolumes->GetIterator(); it.HasNext();) {
2685a1d355fSStephan Aßmus 		Volume* volume = it.Next().value;
2695a1d355fSStephan Aßmus 		delete volume;
2705a1d355fSStephan Aßmus 	}
2715a1d355fSStephan Aßmus 	delete fVolumes;
2725a1d355fSStephan Aßmus }
2735a1d355fSStephan Aßmus 
2745a1d355fSStephan Aßmus // Init
2755a1d355fSStephan Aßmus status_t
Init()2765a1d355fSStephan Aßmus VolumeManager::Init()
2775a1d355fSStephan Aßmus {
2785a1d355fSStephan Aßmus 	// check node monitoring message queue
2795a1d355fSStephan Aßmus 	status_t error = fNodeMonitoringEvents.InitCheck();
2805a1d355fSStephan Aßmus 	if (error != B_OK)
2815a1d355fSStephan Aßmus 		return error;
2825a1d355fSStephan Aßmus 
2835a1d355fSStephan Aßmus 	// entry created event map
2845a1d355fSStephan Aßmus 	fEntryCreatedEvents = new(std::nothrow) EntryCreatedEventMap;
2855a1d355fSStephan Aßmus 	if (!fEntryCreatedEvents)
2865a1d355fSStephan Aßmus 		return B_NO_MEMORY;
2875a1d355fSStephan Aßmus 
2885a1d355fSStephan Aßmus 	// entry removed event map
2895a1d355fSStephan Aßmus 	fEntryRemovedEvents = new(std::nothrow) EntryRemovedEventMap;
2905a1d355fSStephan Aßmus 	if (!fEntryRemovedEvents)
2915a1d355fSStephan Aßmus 		return B_NO_MEMORY;
2925a1d355fSStephan Aßmus 
2935a1d355fSStephan Aßmus 	// entry moved event map
2945a1d355fSStephan Aßmus 	fEntryMovedEvents = new(std::nothrow) EntryMovedEventMap;
2955a1d355fSStephan Aßmus 	if (!fEntryMovedEvents)
2965a1d355fSStephan Aßmus 		return B_NO_MEMORY;
2975a1d355fSStephan Aßmus 
2985a1d355fSStephan Aßmus 	// node stat changed event map
2995a1d355fSStephan Aßmus 	fNodeStatChangedEvents = new(std::nothrow) NodeStatChangedEventMap;
3005a1d355fSStephan Aßmus 	if (!fNodeStatChangedEvents)
3015a1d355fSStephan Aßmus 		return B_NO_MEMORY;
3025a1d355fSStephan Aßmus 
3035a1d355fSStephan Aßmus 	// node attribute changed event map
3045a1d355fSStephan Aßmus 	fNodeAttributeChangedEvents = new(std::nothrow) NodeAttributeChangedEventMap;
3055a1d355fSStephan Aßmus 	if (!fNodeAttributeChangedEvents)
3065a1d355fSStephan Aßmus 		return B_NO_MEMORY;
3075a1d355fSStephan Aßmus 
3085a1d355fSStephan Aßmus 	// create the node monitor
3095a1d355fSStephan Aßmus 	fNodeMonitor = new(std::nothrow) NodeMonitor(this);
3105a1d355fSStephan Aßmus 	if (!fNodeMonitor)
3115a1d355fSStephan Aßmus 		return B_NO_MEMORY;
3125a1d355fSStephan Aßmus 
3135a1d355fSStephan Aßmus 	// create the volume map
3145a1d355fSStephan Aßmus 	fVolumes = new(std::nothrow) VolumeMap;
3155a1d355fSStephan Aßmus 	if (!fVolumes)
3165a1d355fSStephan Aßmus 		return B_NO_MEMORY;
3175a1d355fSStephan Aßmus 	if (fVolumes->InitCheck() != B_OK)
3185a1d355fSStephan Aßmus 		return fVolumes->InitCheck();
3195a1d355fSStephan Aßmus 
3205a1d355fSStephan Aßmus 	// create the client volume map
3215a1d355fSStephan Aßmus 	fClientVolumes = new(std::nothrow) ClientVolumeMap;
3225a1d355fSStephan Aßmus 	if (!fClientVolumes)
3235a1d355fSStephan Aßmus 		return B_NO_MEMORY;
3245a1d355fSStephan Aßmus 	if (fClientVolumes->InitCheck() != B_OK)
3255a1d355fSStephan Aßmus 		return fClientVolumes->InitCheck();
3265a1d355fSStephan Aßmus 
3275a1d355fSStephan Aßmus 	// start the node monitor
3285a1d355fSStephan Aßmus 	thread_id monitorThread = fNodeMonitor->Run();
3295a1d355fSStephan Aßmus 	if (monitorThread < 0) {
3305a1d355fSStephan Aßmus 		delete fNodeMonitor;
3315a1d355fSStephan Aßmus 		fNodeMonitor = NULL;
3325a1d355fSStephan Aßmus 		return monitorThread;
3335a1d355fSStephan Aßmus 	}
3345a1d355fSStephan Aßmus 
3355a1d355fSStephan Aßmus 	// create all volumes
3365a1d355fSStephan Aßmus 	int32 cookie = 0;
3375a1d355fSStephan Aßmus 	dev_t volumeID;
3385a1d355fSStephan Aßmus 	while ((volumeID = next_dev(&cookie)) >= 0)
3395a1d355fSStephan Aßmus 		_AddVolume(volumeID);
3405a1d355fSStephan Aßmus 
3415a1d355fSStephan Aßmus 	// get the root volume
3425a1d355fSStephan Aßmus 	volumeID = dev_for_path("/");
3435a1d355fSStephan Aßmus 	if (volumeID < 0)
3445a1d355fSStephan Aßmus 		return volumeID;
3455a1d355fSStephan Aßmus 	fRootVolume = GetVolume(volumeID, true);
3465a1d355fSStephan Aßmus 	if (!fRootVolume)
3475a1d355fSStephan Aßmus 		return B_ERROR;
3485a1d355fSStephan Aßmus 
3495a1d355fSStephan Aßmus 	// spawn the node monitoring message processor
3505a1d355fSStephan Aßmus 	fNodeMonitoringProcessor = spawn_thread(&_NodeMonitoringProcessorEntry,
3515a1d355fSStephan Aßmus 		"node monitoring processor", B_NORMAL_PRIORITY, this);
3525a1d355fSStephan Aßmus 	if (fNodeMonitoringProcessor < 0)
3535a1d355fSStephan Aßmus 		return fNodeMonitoringProcessor;
3545a1d355fSStephan Aßmus 	resume_thread(fNodeMonitoringProcessor);
3555a1d355fSStephan Aßmus 
3565a1d355fSStephan Aßmus 	return B_OK;
3575a1d355fSStephan Aßmus }
3585a1d355fSStephan Aßmus 
3595a1d355fSStephan Aßmus // GetRootVolume
3605a1d355fSStephan Aßmus Volume*
GetRootVolume() const3615a1d355fSStephan Aßmus VolumeManager::GetRootVolume() const
3625a1d355fSStephan Aßmus {
3635a1d355fSStephan Aßmus 	return fRootVolume;
3645a1d355fSStephan Aßmus }
3655a1d355fSStephan Aßmus 
3665a1d355fSStephan Aßmus // AddClientVolume
3675a1d355fSStephan Aßmus status_t
AddClientVolume(ClientVolume * clientVolume)3685a1d355fSStephan Aßmus VolumeManager::AddClientVolume(ClientVolume* clientVolume)
3695a1d355fSStephan Aßmus {
3705a1d355fSStephan Aßmus 	if (!clientVolume)
3715a1d355fSStephan Aßmus 		return B_BAD_VALUE;
3725a1d355fSStephan Aßmus 
3735a1d355fSStephan Aßmus 	return fClientVolumes->Put(clientVolume->GetID(), clientVolume);
3745a1d355fSStephan Aßmus }
3755a1d355fSStephan Aßmus 
3765a1d355fSStephan Aßmus // RemoveClientVolume
3775a1d355fSStephan Aßmus void
RemoveClientVolume(ClientVolume * clientVolume)3785a1d355fSStephan Aßmus VolumeManager::RemoveClientVolume(ClientVolume* clientVolume)
3795a1d355fSStephan Aßmus {
3805a1d355fSStephan Aßmus 	if (!clientVolume)
3815a1d355fSStephan Aßmus 		return;
3825a1d355fSStephan Aßmus 
3835a1d355fSStephan Aßmus 	fClientVolumes->Remove(clientVolume->GetID());
3845a1d355fSStephan Aßmus }
3855a1d355fSStephan Aßmus 
3865a1d355fSStephan Aßmus // CreateDefault
3875a1d355fSStephan Aßmus status_t
CreateDefault()3885a1d355fSStephan Aßmus VolumeManager::CreateDefault()
3895a1d355fSStephan Aßmus {
3905a1d355fSStephan Aßmus 	if (sManager)
3915a1d355fSStephan Aßmus 		return B_OK;
3925a1d355fSStephan Aßmus 
3935a1d355fSStephan Aßmus 	VolumeManager* manager = new(std::nothrow) VolumeManager;
3945a1d355fSStephan Aßmus 	if (!manager)
3955a1d355fSStephan Aßmus 		return B_NO_MEMORY;
3965a1d355fSStephan Aßmus 
3975a1d355fSStephan Aßmus 	status_t error = manager->Init();
3985a1d355fSStephan Aßmus 	if (error != B_OK) {
3995a1d355fSStephan Aßmus 		delete manager;
4005a1d355fSStephan Aßmus 		return error;
4015a1d355fSStephan Aßmus 	}
4025a1d355fSStephan Aßmus 
4035a1d355fSStephan Aßmus 	sManager = manager;
4045a1d355fSStephan Aßmus 	return B_OK;
4055a1d355fSStephan Aßmus }
4065a1d355fSStephan Aßmus 
4075a1d355fSStephan Aßmus // DeleteDefault
4085a1d355fSStephan Aßmus void
DeleteDefault()4095a1d355fSStephan Aßmus VolumeManager::DeleteDefault()
4105a1d355fSStephan Aßmus {
4115a1d355fSStephan Aßmus 	if (sManager) {
4125a1d355fSStephan Aßmus 		delete sManager;
4135a1d355fSStephan Aßmus 		sManager = NULL;
4145a1d355fSStephan Aßmus 	}
4155a1d355fSStephan Aßmus }
4165a1d355fSStephan Aßmus 
4175a1d355fSStephan Aßmus // GetDefault
4185a1d355fSStephan Aßmus VolumeManager*
GetDefault()4195a1d355fSStephan Aßmus VolumeManager::GetDefault()
4205a1d355fSStephan Aßmus {
4215a1d355fSStephan Aßmus 	return sManager;
4225a1d355fSStephan Aßmus }
4235a1d355fSStephan Aßmus 
4245a1d355fSStephan Aßmus // Lock
4255a1d355fSStephan Aßmus bool
Lock()4265a1d355fSStephan Aßmus VolumeManager::Lock()
4275a1d355fSStephan Aßmus {
4285a1d355fSStephan Aßmus 	bool alreadyLocked = fLock.IsLocked();
4295a1d355fSStephan Aßmus 
4305a1d355fSStephan Aßmus 	bool success = fLock.Lock();
4315a1d355fSStephan Aßmus 
4325a1d355fSStephan Aßmus 	// If locking was successful and we didn't have a lock before, we increment
4335a1d355fSStephan Aßmus 	// the revision.
4345a1d355fSStephan Aßmus 	if (success && !alreadyLocked)
4355a1d355fSStephan Aßmus 		fRevision++;
4365a1d355fSStephan Aßmus 
4375a1d355fSStephan Aßmus 	return success;
4385a1d355fSStephan Aßmus }
4395a1d355fSStephan Aßmus 
4405a1d355fSStephan Aßmus // Unlock
4415a1d355fSStephan Aßmus void
Unlock()4425a1d355fSStephan Aßmus VolumeManager::Unlock()
4435a1d355fSStephan Aßmus {
4445a1d355fSStephan Aßmus 	return fLock.Unlock();
4455a1d355fSStephan Aßmus }
4465a1d355fSStephan Aßmus 
4475a1d355fSStephan Aßmus // GetRevision
4485a1d355fSStephan Aßmus int64
GetRevision() const4495a1d355fSStephan Aßmus VolumeManager::GetRevision() const
4505a1d355fSStephan Aßmus {
4515a1d355fSStephan Aßmus 	return fRevision;
4525a1d355fSStephan Aßmus }
4535a1d355fSStephan Aßmus 
4545a1d355fSStephan Aßmus // GetVolume
4555a1d355fSStephan Aßmus Volume*
GetVolume(dev_t volumeID,bool add)4565a1d355fSStephan Aßmus VolumeManager::GetVolume(dev_t volumeID, bool add)
4575a1d355fSStephan Aßmus {
4585a1d355fSStephan Aßmus 	Volume* volume = fVolumes->Get(volumeID);
4595a1d355fSStephan Aßmus 	if (!volume && add)
4605a1d355fSStephan Aßmus 		_AddVolume(volumeID, &volume);
4615a1d355fSStephan Aßmus 
4625a1d355fSStephan Aßmus 	return volume;
4635a1d355fSStephan Aßmus }
4645a1d355fSStephan Aßmus 
4655a1d355fSStephan Aßmus 
4665a1d355fSStephan Aßmus // #pragma mark -
4675a1d355fSStephan Aßmus 
4685a1d355fSStephan Aßmus // AddNode
4695a1d355fSStephan Aßmus status_t
AddNode(Node * node)4705a1d355fSStephan Aßmus VolumeManager::AddNode(Node* node)
4715a1d355fSStephan Aßmus {
4725a1d355fSStephan Aßmus 	if (!node || !node->GetVolume())
4735a1d355fSStephan Aßmus 		return B_BAD_VALUE;
4745a1d355fSStephan Aßmus 
4755a1d355fSStephan Aßmus 	status_t error = node->GetVolume()->AddNode(node);
4765a1d355fSStephan Aßmus 
4775a1d355fSStephan Aßmus 	// start watching the node
4785a1d355fSStephan Aßmus 	if (error == B_OK)
4795a1d355fSStephan Aßmus 		fNodeMonitor->StartWatching(node->GetNodeRef());
4805a1d355fSStephan Aßmus 
4815a1d355fSStephan Aßmus 	return error;
4825a1d355fSStephan Aßmus }
4835a1d355fSStephan Aßmus 
4845a1d355fSStephan Aßmus // RemoveNode
4855a1d355fSStephan Aßmus void
RemoveNode(Node * node)4865a1d355fSStephan Aßmus VolumeManager::RemoveNode(Node* node)
4875a1d355fSStephan Aßmus {
4885a1d355fSStephan Aßmus 	if (!node)
4895a1d355fSStephan Aßmus 		return;
4905a1d355fSStephan Aßmus 
4915a1d355fSStephan Aßmus 	// if the node is a directory, we remove all its entries first
4925a1d355fSStephan Aßmus 	if (Directory* directory = dynamic_cast<Directory*>(node)) {
4935a1d355fSStephan Aßmus 		while (Entry* entry = directory->GetFirstEntry()) {
4945a1d355fSStephan Aßmus 			RemoveEntry(entry);
4955a1d355fSStephan Aßmus 			delete entry;
4965a1d355fSStephan Aßmus 		}
4975a1d355fSStephan Aßmus 	}
4985a1d355fSStephan Aßmus 
4995a1d355fSStephan Aßmus 	// remove all referring entries
5005a1d355fSStephan Aßmus 	while (Entry* entry = node->GetFirstReferringEntry())
5015a1d355fSStephan Aßmus 		RemoveEntry(entry);
5025a1d355fSStephan Aßmus 
5035a1d355fSStephan Aßmus 	// remove the node from the volume
5045a1d355fSStephan Aßmus 	if (node->GetVolume())
5055a1d355fSStephan Aßmus 		node->GetVolume()->RemoveNode(node);
5065a1d355fSStephan Aßmus 
5075a1d355fSStephan Aßmus 	// stop watching the node
5085a1d355fSStephan Aßmus 	fNodeMonitor->StopWatching(node->GetNodeRef());
5095a1d355fSStephan Aßmus }
5105a1d355fSStephan Aßmus 
5115a1d355fSStephan Aßmus // GetNode
5125a1d355fSStephan Aßmus Node*
GetNode(dev_t volumeID,ino_t nodeID)5135a1d355fSStephan Aßmus VolumeManager::GetNode(dev_t volumeID, ino_t nodeID)
5145a1d355fSStephan Aßmus {
5155a1d355fSStephan Aßmus 	if (Volume* volume = GetVolume(volumeID))
5165a1d355fSStephan Aßmus 		return volume->GetNode(nodeID);
5175a1d355fSStephan Aßmus 	return NULL;
5185a1d355fSStephan Aßmus }
5195a1d355fSStephan Aßmus 
5205a1d355fSStephan Aßmus // LoadNode
5215a1d355fSStephan Aßmus status_t
LoadNode(const struct stat & st,Node ** _node)5225a1d355fSStephan Aßmus VolumeManager::LoadNode(const struct stat& st, Node** _node)
5235a1d355fSStephan Aßmus {
5245a1d355fSStephan Aßmus 	Node* node = GetNode(st.st_dev, st.st_ino);
5255a1d355fSStephan Aßmus 	if (!node) {
5265a1d355fSStephan Aßmus 		// node not known yet: create it
5275a1d355fSStephan Aßmus 
5285a1d355fSStephan Aßmus 		// get the volume
5295a1d355fSStephan Aßmus 		Volume* volume = GetVolume(st.st_dev, true);
5305a1d355fSStephan Aßmus 		if (!volume)
5315a1d355fSStephan Aßmus 			return B_BAD_VALUE;
5325a1d355fSStephan Aßmus 
5335a1d355fSStephan Aßmus 		// create the node
5345a1d355fSStephan Aßmus 		if (S_ISDIR(st.st_mode))
5355a1d355fSStephan Aßmus 			node = new(std::nothrow) Directory(volume, st);
5365a1d355fSStephan Aßmus 		else
5375a1d355fSStephan Aßmus 			node = new(std::nothrow) Node(volume, st);
5385a1d355fSStephan Aßmus 		if (!node)
5395a1d355fSStephan Aßmus 			return B_NO_MEMORY;
5405a1d355fSStephan Aßmus 
5415a1d355fSStephan Aßmus 		// add it
5425a1d355fSStephan Aßmus 		status_t error = AddNode(node);
5435a1d355fSStephan Aßmus 		if (error != B_OK) {
5445a1d355fSStephan Aßmus 			delete node;
5455a1d355fSStephan Aßmus 			return error;
5465a1d355fSStephan Aßmus 		}
5475a1d355fSStephan Aßmus 	}
5485a1d355fSStephan Aßmus 
5495a1d355fSStephan Aßmus 	if (_node)
5505a1d355fSStephan Aßmus 		*_node = node;
5515a1d355fSStephan Aßmus 	return B_OK;
5525a1d355fSStephan Aßmus }
5535a1d355fSStephan Aßmus 
5545a1d355fSStephan Aßmus 
5555a1d355fSStephan Aßmus // #pragma mark -
5565a1d355fSStephan Aßmus 
5575a1d355fSStephan Aßmus // GetDirectory
5585a1d355fSStephan Aßmus Directory*
GetDirectory(dev_t volumeID,ino_t nodeID)5595a1d355fSStephan Aßmus VolumeManager::GetDirectory(dev_t volumeID, ino_t nodeID)
5605a1d355fSStephan Aßmus {
5615a1d355fSStephan Aßmus 	return dynamic_cast<Directory*>(GetNode(volumeID, nodeID));
5625a1d355fSStephan Aßmus }
5635a1d355fSStephan Aßmus 
5645a1d355fSStephan Aßmus // GetRootDirectory
5655a1d355fSStephan Aßmus Directory*
GetRootDirectory() const5665a1d355fSStephan Aßmus VolumeManager::GetRootDirectory() const
5675a1d355fSStephan Aßmus {
5685a1d355fSStephan Aßmus 	return (fRootVolume ? fRootVolume->GetRootDirectory() : NULL);
5695a1d355fSStephan Aßmus }
5705a1d355fSStephan Aßmus 
5715a1d355fSStephan Aßmus // GetParentDirectory
5725a1d355fSStephan Aßmus Directory*
GetParentDirectory(Directory * directory)5735a1d355fSStephan Aßmus VolumeManager::GetParentDirectory(Directory* directory)
5745a1d355fSStephan Aßmus {
5755a1d355fSStephan Aßmus 	if (!directory)
5765a1d355fSStephan Aßmus 		return NULL;
5775a1d355fSStephan Aßmus 
5785a1d355fSStephan Aßmus 	// get ".." entry
5795a1d355fSStephan Aßmus 	Entry* parentEntry;
5805a1d355fSStephan Aßmus 	if (LoadEntry(directory->GetVolumeID(), directory->GetID(), "..", true,
5815a1d355fSStephan Aßmus 			&parentEntry) != B_OK) {
5825a1d355fSStephan Aßmus 		return NULL;
5835a1d355fSStephan Aßmus 	}
5845a1d355fSStephan Aßmus 
5855a1d355fSStephan Aßmus 	return dynamic_cast<Directory*>(parentEntry->GetNode());
5865a1d355fSStephan Aßmus }
5875a1d355fSStephan Aßmus 
5885a1d355fSStephan Aßmus // LoadDirectory
5895a1d355fSStephan Aßmus status_t
LoadDirectory(dev_t volumeID,ino_t directoryID,Directory ** _directory)5905a1d355fSStephan Aßmus VolumeManager::LoadDirectory(dev_t volumeID, ino_t directoryID,
5915a1d355fSStephan Aßmus 	Directory** _directory)
5925a1d355fSStephan Aßmus {
5935a1d355fSStephan Aßmus 	// try to get the node
5945a1d355fSStephan Aßmus 	Node* node = GetNode(volumeID, directoryID);
5955a1d355fSStephan Aßmus 	bool newNode = false;
5965a1d355fSStephan Aßmus 	if (!node) {
5975a1d355fSStephan Aßmus 		// directory not yet loaded: stat it
5985a1d355fSStephan Aßmus 		NoAllocEntryRef entryRef(volumeID, directoryID, ".");
5995a1d355fSStephan Aßmus 		struct stat st;
6005a1d355fSStephan Aßmus 		BEntry bEntry;
6015a1d355fSStephan Aßmus 		status_t error = FDManager::SetEntry(&bEntry, &entryRef);
6025a1d355fSStephan Aßmus 		if (error == B_OK)
6035a1d355fSStephan Aßmus 			error = bEntry.GetStat(&st);
6045a1d355fSStephan Aßmus 		if (error != B_OK)
6055a1d355fSStephan Aßmus 			return error;
6065a1d355fSStephan Aßmus 
6075a1d355fSStephan Aßmus 		// load the node
6085a1d355fSStephan Aßmus 		error = LoadNode(st, &node);
6095a1d355fSStephan Aßmus 		if (error != B_OK)
6105a1d355fSStephan Aßmus 			return error;
6115a1d355fSStephan Aßmus 
6125a1d355fSStephan Aßmus 		newNode = true;
6135a1d355fSStephan Aßmus 	}
6145a1d355fSStephan Aßmus 
6155a1d355fSStephan Aßmus 	// check, if the node is a directory
6165a1d355fSStephan Aßmus 	Directory* directory = dynamic_cast<Directory*>(node);
6175a1d355fSStephan Aßmus 	if (!directory)
6185a1d355fSStephan Aßmus 		return B_NOT_A_DIRECTORY;
6195a1d355fSStephan Aßmus 
6205a1d355fSStephan Aßmus 	if (newNode)
6215a1d355fSStephan Aßmus 		CompletePathToRoot(directory);
6225a1d355fSStephan Aßmus 
6235a1d355fSStephan Aßmus 	if (_directory)
6245a1d355fSStephan Aßmus 		*_directory = directory;
6255a1d355fSStephan Aßmus 	return B_OK;
6265a1d355fSStephan Aßmus }
6275a1d355fSStephan Aßmus 
6285a1d355fSStephan Aßmus 
6295a1d355fSStephan Aßmus // #pragma mark -
6305a1d355fSStephan Aßmus 
6315a1d355fSStephan Aßmus // AddEntry
6325a1d355fSStephan Aßmus status_t
AddEntry(Entry * entry)6335a1d355fSStephan Aßmus VolumeManager::AddEntry(Entry* entry)
6345a1d355fSStephan Aßmus {
6355a1d355fSStephan Aßmus 	if (!entry || !entry->GetVolume() || !entry->GetDirectory()
6365a1d355fSStephan Aßmus 		|| ! entry->GetNode()) {
6375a1d355fSStephan Aßmus 		return B_BAD_VALUE;
6385a1d355fSStephan Aßmus 	}
6395a1d355fSStephan Aßmus 
6405a1d355fSStephan Aßmus 	// add the entry to the volume
6415a1d355fSStephan Aßmus 	status_t error = entry->GetVolume()->AddEntry(entry);
6425a1d355fSStephan Aßmus 	if (error != B_OK)
6435a1d355fSStephan Aßmus 		return error;
6445a1d355fSStephan Aßmus 
6455a1d355fSStephan Aßmus 	// add the entry to its directory and node
6465a1d355fSStephan Aßmus 	entry->GetDirectory()->AddEntry(entry);
6475a1d355fSStephan Aßmus 	entry->GetNode()->AddReferringEntry(entry);
6485a1d355fSStephan Aßmus 
6495a1d355fSStephan Aßmus //PRINT(("VolumeManager::AddEntry(): %ld, %lld, `%s', dir: %p, "
6505a1d355fSStephan Aßmus //"entry count: %ld\n", entry->GetVolumeID(), entry->GetDirectoryID(),
6515a1d355fSStephan Aßmus //entry->GetName(), entry->GetDirectory(),
6525a1d355fSStephan Aßmus //entry->GetDirectory()->CountEntries()));
6535a1d355fSStephan Aßmus 
6545a1d355fSStephan Aßmus 	return B_OK;
6555a1d355fSStephan Aßmus }
6565a1d355fSStephan Aßmus 
6575a1d355fSStephan Aßmus // RemoveEntry
6585a1d355fSStephan Aßmus void
RemoveEntry(Entry * entry)6595a1d355fSStephan Aßmus VolumeManager::RemoveEntry(Entry* entry)
6605a1d355fSStephan Aßmus {
6615a1d355fSStephan Aßmus 	if (entry) {
6625a1d355fSStephan Aßmus 		// remove the entry from the volume
6635a1d355fSStephan Aßmus 		if (entry->GetVolume())
6645a1d355fSStephan Aßmus 			entry->GetVolume()->RemoveEntry(entry);
6655a1d355fSStephan Aßmus 
6665a1d355fSStephan Aßmus 		// remove the entry from the directory and its node
6675a1d355fSStephan Aßmus 		entry->GetDirectory()->RemoveEntry(entry);
6685a1d355fSStephan Aßmus 		entry->GetNode()->RemoveReferringEntry(entry);
6695a1d355fSStephan Aßmus 
6705a1d355fSStephan Aßmus //PRINT(("VolumeManager::RemoveEntry(): %ld, %lld, `%s', dir: %p, "
6715a1d355fSStephan Aßmus //"entry count: %ld\n", entry->GetVolumeID(), entry->GetDirectoryID(),
6725a1d355fSStephan Aßmus //entry->GetName(), entry->GetDirectory(),
6735a1d355fSStephan Aßmus //entry->GetDirectory()->CountEntries()));
6745a1d355fSStephan Aßmus 	}
6755a1d355fSStephan Aßmus }
6765a1d355fSStephan Aßmus 
6775a1d355fSStephan Aßmus // DeleteEntry
6785a1d355fSStephan Aßmus void
DeleteEntry(Entry * entry,bool keepNode)6795a1d355fSStephan Aßmus VolumeManager::DeleteEntry(Entry* entry, bool keepNode)
6805a1d355fSStephan Aßmus {
6815a1d355fSStephan Aßmus 	if (!entry)
6825a1d355fSStephan Aßmus 		return;
6835a1d355fSStephan Aßmus 
6845a1d355fSStephan Aßmus 	Node* node = entry->GetNode();
6855a1d355fSStephan Aßmus 
6865a1d355fSStephan Aßmus 	// remove the entry
6875a1d355fSStephan Aßmus 	RemoveEntry(entry);
6885a1d355fSStephan Aßmus 	delete entry;
6895a1d355fSStephan Aßmus 
6905a1d355fSStephan Aßmus 	// remove the node, if it doesn't have any more actual referring entries
6915a1d355fSStephan Aßmus 	if (!keepNode && !node->GetActualReferringEntry()) {
6925a1d355fSStephan Aßmus 		RemoveNode(node);
6935a1d355fSStephan Aßmus 		if (node != node->GetVolume()->GetRootDirectory())
6945a1d355fSStephan Aßmus 			delete node;
6955a1d355fSStephan Aßmus 	}
6965a1d355fSStephan Aßmus }
6975a1d355fSStephan Aßmus 
6985a1d355fSStephan Aßmus // GetEntry
6995a1d355fSStephan Aßmus Entry*
GetEntry(dev_t volumeID,ino_t directoryID,const char * name)7005a1d355fSStephan Aßmus VolumeManager::GetEntry(dev_t volumeID, ino_t directoryID, const char* name)
7015a1d355fSStephan Aßmus {
7025a1d355fSStephan Aßmus 	if (Volume* volume = GetVolume(volumeID))
7035a1d355fSStephan Aßmus 		return volume->GetEntry(directoryID, name);
7045a1d355fSStephan Aßmus 	return NULL;
7055a1d355fSStephan Aßmus }
7065a1d355fSStephan Aßmus 
7075a1d355fSStephan Aßmus // GetEntry
7085a1d355fSStephan Aßmus Entry*
GetEntry(const entry_ref & ref)7095a1d355fSStephan Aßmus VolumeManager::GetEntry(const entry_ref& ref)
7105a1d355fSStephan Aßmus {
7115a1d355fSStephan Aßmus 	return GetEntry(ref.device, ref.directory, ref.name);
7125a1d355fSStephan Aßmus }
7135a1d355fSStephan Aßmus 
7145a1d355fSStephan Aßmus // LoadEntry
7155a1d355fSStephan Aßmus status_t
LoadEntry(dev_t volumeID,ino_t directoryID,const char * name,bool loadDir,Entry ** _entry)7165a1d355fSStephan Aßmus VolumeManager::LoadEntry(dev_t volumeID, ino_t directoryID, const char* name,
7175a1d355fSStephan Aßmus 	bool loadDir, Entry** _entry)
7185a1d355fSStephan Aßmus {
7195a1d355fSStephan Aßmus 	Entry* entry = GetEntry(volumeID, directoryID, name);
7205a1d355fSStephan Aßmus 	if (!entry) {
7215a1d355fSStephan Aßmus 		// entry not known yet: create it
722*ebb21bd1SMurai Takashi 		PRINT("VolumeManager::LoadEntry(%" B_PRIdDEV ", "
723*ebb21bd1SMurai Takashi 			"%" B_PRIdINO ", `%s')\n", volumeID, directoryID, name);
7245a1d355fSStephan Aßmus 
7255a1d355fSStephan Aßmus 		// get the volume
7265a1d355fSStephan Aßmus 		Volume* volume = GetVolume(volumeID, true);
7275a1d355fSStephan Aßmus 		if (!volume)
7285a1d355fSStephan Aßmus 			return B_BAD_VALUE;
7295a1d355fSStephan Aßmus 
7305a1d355fSStephan Aßmus 		// get the directory
7315a1d355fSStephan Aßmus 		status_t error = B_OK;
7325a1d355fSStephan Aßmus 		Directory* directory = GetDirectory(volumeID, directoryID);
7335a1d355fSStephan Aßmus 		if (!directory) {
7345a1d355fSStephan Aßmus 			if (!loadDir)
7355a1d355fSStephan Aßmus 				return B_ENTRY_NOT_FOUND;
7365a1d355fSStephan Aßmus 
7375a1d355fSStephan Aßmus //PRINT(("  loading directory...\n"));
7385a1d355fSStephan Aßmus 			// load the directory
7395a1d355fSStephan Aßmus 			error = LoadDirectory(volumeID, directoryID, &directory);
7405a1d355fSStephan Aßmus 			if (error != B_OK)
7415a1d355fSStephan Aßmus 				return error;
7425a1d355fSStephan Aßmus 		}
7435a1d355fSStephan Aßmus 
7445a1d355fSStephan Aßmus //PRINT(("  opening BNode...\n"));
7455a1d355fSStephan Aßmus 		// stat the entry
7465a1d355fSStephan Aßmus 		NoAllocEntryRef entryRef(volumeID, directoryID, name);
7475a1d355fSStephan Aßmus 		struct stat st;
7485a1d355fSStephan Aßmus 		BNode bNode;
7495a1d355fSStephan Aßmus 		error = bNode.SetTo(&entryRef);
7505a1d355fSStephan Aßmus //PRINT(("  stat()ing BNode...\n"));
7515a1d355fSStephan Aßmus 		if (error == B_OK)
7525a1d355fSStephan Aßmus 			error = bNode.GetStat(&st);
7535a1d355fSStephan Aßmus 		if (error != B_OK)
7545a1d355fSStephan Aßmus 			return error;
7555a1d355fSStephan Aßmus 
7565a1d355fSStephan Aßmus //PRINT(("  loading node...\n"));
7575a1d355fSStephan Aßmus 		// load the node
7585a1d355fSStephan Aßmus 		Node* node;
7595a1d355fSStephan Aßmus 		error = LoadNode(st, &node);
7605a1d355fSStephan Aßmus 		if (error != B_OK)
7615a1d355fSStephan Aßmus 			return error;
7625a1d355fSStephan Aßmus 
7635a1d355fSStephan Aßmus //PRINT(("  creating and adding entry...\n"));
7645a1d355fSStephan Aßmus 		// create the entry
7655a1d355fSStephan Aßmus 		entry = new(std::nothrow) Entry(volume, directory, name, node);
7665a1d355fSStephan Aßmus 		if (!entry)
7675a1d355fSStephan Aßmus 			return B_NO_MEMORY;
7685a1d355fSStephan Aßmus 
7695a1d355fSStephan Aßmus 		// add it
7705a1d355fSStephan Aßmus 		error = AddEntry(entry);
7715a1d355fSStephan Aßmus 		if (error != B_OK) {
7725a1d355fSStephan Aßmus 			delete entry;
7735a1d355fSStephan Aßmus 			return error;
7745a1d355fSStephan Aßmus 		}
7755a1d355fSStephan Aßmus //PRINT(("  adding entry done\n"));
7765a1d355fSStephan Aßmus 	}
7775a1d355fSStephan Aßmus 
7785a1d355fSStephan Aßmus 	if (_entry)
7795a1d355fSStephan Aßmus 		*_entry = entry;
7805a1d355fSStephan Aßmus 	return B_OK;
7815a1d355fSStephan Aßmus }
7825a1d355fSStephan Aßmus 
7835a1d355fSStephan Aßmus 
7845a1d355fSStephan Aßmus // #pragma mark -
7855a1d355fSStephan Aßmus 
7865a1d355fSStephan Aßmus // OpenQuery
7875a1d355fSStephan Aßmus status_t
OpenQuery(QueryDomain * queryDomain,const char * queryString,uint32 flags,port_id remotePort,int32 remoteToken,QueryHandle ** handle)7885a1d355fSStephan Aßmus VolumeManager::OpenQuery(QueryDomain* queryDomain, const char* queryString,
7895a1d355fSStephan Aßmus 	uint32 flags, port_id remotePort, int32 remoteToken, QueryHandle** handle)
7905a1d355fSStephan Aßmus {
7915a1d355fSStephan Aßmus 	if (!queryDomain || !queryString || !handle)
7925a1d355fSStephan Aßmus 		return B_BAD_VALUE;
7935a1d355fSStephan Aßmus 	bool liveQuery = (flags & B_LIVE_QUERY);
794*ebb21bd1SMurai Takashi 	PRINT("VolumeManager::OpenQuery(%p, \"%s\", 0x%" B_PRIx32 ", "
795*ebb21bd1SMurai Takashi 		"%" B_PRId32 ", %" B_PRId32 ")\n",
7963c1afd35SPawel Dziepak 		queryDomain, queryString, flags, remotePort, remoteToken);
7975a1d355fSStephan Aßmus 
7985a1d355fSStephan Aßmus 	// allocate the handle
7995a1d355fSStephan Aßmus 	QueryHandle* queryHandle = new(std::nothrow) QueryHandle(remotePort,
8005a1d355fSStephan Aßmus 		remoteToken);
801cee04e80SArtur Wyszynski 	if (!queryHandle)
8025a1d355fSStephan Aßmus 		return B_NO_MEMORY;
8035a1d355fSStephan Aßmus 	ObjectDeleter<QueryHandle> handleDeleter(queryHandle);
8045a1d355fSStephan Aßmus 
8055a1d355fSStephan Aßmus 	// allocate a query handler, if this is a live query
8065a1d355fSStephan Aßmus 	QueryHandler* queryHandler = NULL;
8075a1d355fSStephan Aßmus 	if (liveQuery) {
8085a1d355fSStephan Aßmus 		queryHandler = new(std::nothrow) QueryHandler(this, queryDomain,
8095a1d355fSStephan Aßmus 			queryHandle);
8105a1d355fSStephan Aßmus 		if (!queryHandler)
8115a1d355fSStephan Aßmus 			return B_NO_MEMORY;
8125a1d355fSStephan Aßmus 
8135a1d355fSStephan Aßmus 		fNodeMonitor->Lock();
8145a1d355fSStephan Aßmus 		fNodeMonitor->AddHandler(queryHandler);
8155a1d355fSStephan Aßmus 		fNodeMonitor->Unlock();
8165a1d355fSStephan Aßmus 		queryHandle->SetQueryListener(queryHandler);
8175a1d355fSStephan Aßmus 	}
8185a1d355fSStephan Aßmus 
8195a1d355fSStephan Aßmus 	// iterate through the volumes and create a query for each one
8205a1d355fSStephan Aßmus 	// supporting queries
8215a1d355fSStephan Aßmus 	for (VolumeMap::Iterator it = fVolumes->GetIterator(); it.HasNext();) {
8225a1d355fSStephan Aßmus 		Volume* volume = it.Next().value;
8235a1d355fSStephan Aßmus 		if (!volume->KnowsQuery())
8245a1d355fSStephan Aßmus 			continue;
8255a1d355fSStephan Aßmus 
8265a1d355fSStephan Aßmus 		// The volume should either be contained by the client volume or
8275a1d355fSStephan Aßmus 		// the other way around. Otherwise they are located in different
8285a1d355fSStephan Aßmus 		// branches of the FS tree and don't have common nodes.
8295a1d355fSStephan Aßmus 		if (!queryDomain->QueryDomainIntersectsWith(volume))
8305a1d355fSStephan Aßmus 			continue;
831*ebb21bd1SMurai Takashi 		PRINT("VolumeManager::OpenQuery(): adding Query for volume "
832*ebb21bd1SMurai Takashi 			"%" B_PRIdDEV "\n", volume->GetID());
8335a1d355fSStephan Aßmus 
8345a1d355fSStephan Aßmus 		// create the query for this volume
8355a1d355fSStephan Aßmus 		BVolume bVolume(volume->GetID());
8365a1d355fSStephan Aßmus 		Query* query = new(std::nothrow) Query;
8375a1d355fSStephan Aßmus 		if (!query)
8385a1d355fSStephan Aßmus 			return B_NO_MEMORY;
8395a1d355fSStephan Aßmus 
8405a1d355fSStephan Aßmus 		// init the query
8415a1d355fSStephan Aßmus 		ObjectDeleter<Query> queryDeleter(query);
8425a1d355fSStephan Aßmus 		status_t error = query->SetVolume(&bVolume);
8435a1d355fSStephan Aßmus 		if (error != B_OK)
8445a1d355fSStephan Aßmus 			return error;
8455a1d355fSStephan Aßmus 		error = query->SetPredicate(queryString);
8465a1d355fSStephan Aßmus 		if (error != B_OK)
8475a1d355fSStephan Aßmus 			return error;
8485a1d355fSStephan Aßmus 		if (liveQuery) {
8495a1d355fSStephan Aßmus 			error = query->SetTarget(queryHandler);
8505a1d355fSStephan Aßmus 			if (error != B_OK)
8515a1d355fSStephan Aßmus 				return error;
8525a1d355fSStephan Aßmus 		}
8535a1d355fSStephan Aßmus 
8545a1d355fSStephan Aßmus 		// fetch
8555a1d355fSStephan Aßmus 		error = query->Fetch();
8565a1d355fSStephan Aßmus 		if (error != B_OK)
8575a1d355fSStephan Aßmus 			return error;
8585a1d355fSStephan Aßmus 
8595a1d355fSStephan Aßmus 		queryHandle->AddQuery(query);
8605a1d355fSStephan Aßmus 		queryDeleter.Detach();
8615a1d355fSStephan Aßmus 	}
8625a1d355fSStephan Aßmus 
8635a1d355fSStephan Aßmus 	*handle = queryHandle;
8645a1d355fSStephan Aßmus 	handleDeleter.Detach();
8655a1d355fSStephan Aßmus 	return B_OK;
8665a1d355fSStephan Aßmus }
8675a1d355fSStephan Aßmus 
8685a1d355fSStephan Aßmus // CompletePathToRoot
8695a1d355fSStephan Aßmus status_t
CompletePathToRoot(Directory * directory)8705a1d355fSStephan Aßmus VolumeManager::CompletePathToRoot(Directory* directory)
8715a1d355fSStephan Aßmus {
8725a1d355fSStephan Aßmus 	if (!directory)
8735a1d355fSStephan Aßmus 		return B_BAD_VALUE;
8745a1d355fSStephan Aßmus 
8755a1d355fSStephan Aßmus 	while (directory != GetRootDirectory()) {
8765a1d355fSStephan Aßmus 		// if the dir has a valid entry referring to it, we've nothing to do
8775a1d355fSStephan Aßmus 		if (directory->GetActualReferringEntry())
8785a1d355fSStephan Aßmus 			return B_OK;
8795a1d355fSStephan Aßmus 
8805a1d355fSStephan Aßmus 		// get a proper entry_ref
8815a1d355fSStephan Aßmus 		BEntry bEntry;
8825a1d355fSStephan Aßmus 		entry_ref entryRef(directory->GetVolumeID(), directory->GetID(), ".");
8835a1d355fSStephan Aßmus 		status_t error = FDManager::SetEntry(&bEntry, &entryRef);
8845a1d355fSStephan Aßmus 		if (error == B_OK)
8855a1d355fSStephan Aßmus 			error = bEntry.GetRef(&entryRef);
8865a1d355fSStephan Aßmus 		if (error != B_OK)
8875a1d355fSStephan Aßmus 			return error;
8885a1d355fSStephan Aßmus 
8895a1d355fSStephan Aßmus 		// if the entry is already loaded, we're done
8905a1d355fSStephan Aßmus 		if (GetEntry(entryRef))
8915a1d355fSStephan Aßmus 			return B_OK;
8925a1d355fSStephan Aßmus 
8935a1d355fSStephan Aßmus 		// the entry is not yet known -- load it
8945a1d355fSStephan Aßmus 		Entry* entry;
8955a1d355fSStephan Aßmus 		error = LoadEntry(entryRef.device, entryRef.directory, entryRef.name,
8965a1d355fSStephan Aßmus 			true, &entry);
8975a1d355fSStephan Aßmus 		if (error != B_OK)
8985a1d355fSStephan Aßmus 			return error;
8995a1d355fSStephan Aßmus 
9005a1d355fSStephan Aßmus 		// get the entry's parent dir and enter the next round
9015a1d355fSStephan Aßmus 		directory = entry->GetDirectory();
9025a1d355fSStephan Aßmus 	}
9035a1d355fSStephan Aßmus 
9045a1d355fSStephan Aßmus 	return B_OK;
9055a1d355fSStephan Aßmus }
9065a1d355fSStephan Aßmus 
9075a1d355fSStephan Aßmus // GetPath
9085a1d355fSStephan Aßmus status_t
GetPath(Entry * entry,Path * path)9095a1d355fSStephan Aßmus VolumeManager::GetPath(Entry* entry, Path* path)
9105a1d355fSStephan Aßmus {
9115a1d355fSStephan Aßmus 	// get directory path
9125a1d355fSStephan Aßmus 	status_t error = GetPath(entry->GetDirectory(), path);
9135a1d355fSStephan Aßmus 	if (error != B_OK)
9145a1d355fSStephan Aßmus 		return error;
9155a1d355fSStephan Aßmus 
9165a1d355fSStephan Aßmus 	// append the entry name
9175a1d355fSStephan Aßmus 	return path->Append(entry->GetName());
9185a1d355fSStephan Aßmus }
9195a1d355fSStephan Aßmus 
9205a1d355fSStephan Aßmus // GetPath
9215a1d355fSStephan Aßmus status_t
GetPath(Node * node,Path * path)9225a1d355fSStephan Aßmus VolumeManager::GetPath(Node* node, Path* path)
9235a1d355fSStephan Aßmus {
9245a1d355fSStephan Aßmus 	if (node == GetRootDirectory())
9255a1d355fSStephan Aßmus 		return path->SetTo("/");
9265a1d355fSStephan Aßmus 
9275a1d355fSStephan Aßmus 	// get an entry referring to the node
9285a1d355fSStephan Aßmus 	Entry* entry = node->GetActualReferringEntry();
9295a1d355fSStephan Aßmus 	if (!entry) {
9305a1d355fSStephan Aßmus 		// if the node is a directory, we complete the path to the root and
9315a1d355fSStephan Aßmus 		// try again
9325a1d355fSStephan Aßmus 		if (Directory* directory = dynamic_cast<Directory*>(node)) {
9335a1d355fSStephan Aßmus 			CompletePathToRoot(directory);
9345a1d355fSStephan Aßmus 			entry = node->GetActualReferringEntry();
9355a1d355fSStephan Aßmus 		}
9365a1d355fSStephan Aßmus 
9375a1d355fSStephan Aßmus 		if (!entry)
9385a1d355fSStephan Aßmus 			return B_ERROR;
9395a1d355fSStephan Aßmus 	}
9405a1d355fSStephan Aßmus 
9415a1d355fSStephan Aßmus 	return GetPath(entry, path);
9425a1d355fSStephan Aßmus }
9435a1d355fSStephan Aßmus 
9445a1d355fSStephan Aßmus // DirectoryContains
9455a1d355fSStephan Aßmus bool
DirectoryContains(Directory * directory,Entry * entry)9465a1d355fSStephan Aßmus VolumeManager::DirectoryContains(Directory* directory, Entry* entry)
9475a1d355fSStephan Aßmus {
9485a1d355fSStephan Aßmus 	if (!directory || !entry)
9495a1d355fSStephan Aßmus 		return false;
9505a1d355fSStephan Aßmus 
9515a1d355fSStephan Aßmus 	return DirectoryContains(directory, entry->GetDirectory(), true);
9525a1d355fSStephan Aßmus }
9535a1d355fSStephan Aßmus 
9545a1d355fSStephan Aßmus // DirectoryContains
9555a1d355fSStephan Aßmus bool
DirectoryContains(Directory * directory,Directory * descendant,bool reflexive)9565a1d355fSStephan Aßmus VolumeManager::DirectoryContains(Directory* directory, Directory* descendant,
9575a1d355fSStephan Aßmus 	bool reflexive)
9585a1d355fSStephan Aßmus {
9595a1d355fSStephan Aßmus 	if (!directory || !descendant)
9605a1d355fSStephan Aßmus 		return false;
9615a1d355fSStephan Aßmus 
9625a1d355fSStephan Aßmus 	// a directory contains itself, just as defined by the caller
9635a1d355fSStephan Aßmus 	if (directory == descendant)
9645a1d355fSStephan Aßmus 		return reflexive;
9655a1d355fSStephan Aßmus 
9665a1d355fSStephan Aßmus 	// if the directory is the root directory, it contains everything
9675a1d355fSStephan Aßmus 	Directory* rootDir = GetRootDirectory();
9685a1d355fSStephan Aßmus 	if (directory == rootDir)
9695a1d355fSStephan Aßmus 		return true;
9705a1d355fSStephan Aßmus 
9715a1d355fSStephan Aßmus 	// recursively get the descendant's parent dir until reaching the root dir
9725a1d355fSStephan Aßmus 	// or the given dir
9735a1d355fSStephan Aßmus 	while (descendant != rootDir) {
9745a1d355fSStephan Aßmus 		descendant = GetParentDirectory(descendant);
9755a1d355fSStephan Aßmus 		if (!descendant)
9765a1d355fSStephan Aßmus 			return false;
9775a1d355fSStephan Aßmus 
9785a1d355fSStephan Aßmus 		if (descendant == directory)
9795a1d355fSStephan Aßmus 			return true;
9805a1d355fSStephan Aßmus 	}
9815a1d355fSStephan Aßmus 
9825a1d355fSStephan Aßmus 	return false;
9835a1d355fSStephan Aßmus }
9845a1d355fSStephan Aßmus 
9855a1d355fSStephan Aßmus // DirectoryContains
9865a1d355fSStephan Aßmus bool
DirectoryContains(Directory * directory,Node * descendant,bool reflexive)9875a1d355fSStephan Aßmus VolumeManager::DirectoryContains(Directory* directory, Node* descendant,
9885a1d355fSStephan Aßmus 	bool reflexive)
9895a1d355fSStephan Aßmus {
9905a1d355fSStephan Aßmus 	if (!directory || !descendant)
9915a1d355fSStephan Aßmus 		return false;
9925a1d355fSStephan Aßmus 
9935a1d355fSStephan Aßmus 	// if the node is a directory, let the other version do the job
9945a1d355fSStephan Aßmus 	if (Directory* dir = dynamic_cast<Directory*>(descendant))
9955a1d355fSStephan Aßmus 		return DirectoryContains(directory, dir, reflexive);
9965a1d355fSStephan Aßmus 
9975a1d355fSStephan Aßmus 	// iterate through the referring entries and check, if the directory
9985a1d355fSStephan Aßmus 	// contains any of them
9995a1d355fSStephan Aßmus 	for (Entry* entry = descendant->GetFirstReferringEntry();
10005a1d355fSStephan Aßmus 		 entry;
10015a1d355fSStephan Aßmus 		 entry = descendant->GetNextReferringEntry(entry)) {
10025a1d355fSStephan Aßmus 		if (DirectoryContains(directory, entry))
10035a1d355fSStephan Aßmus 			return true;
10045a1d355fSStephan Aßmus 	}
10055a1d355fSStephan Aßmus 
10065a1d355fSStephan Aßmus 	return false;
10075a1d355fSStephan Aßmus }
10085a1d355fSStephan Aßmus 
10095a1d355fSStephan Aßmus 
10105a1d355fSStephan Aßmus // #pragma mark -
10115a1d355fSStephan Aßmus 
10125a1d355fSStephan Aßmus // ProcessNodeMonitoringEvent
10135a1d355fSStephan Aßmus void
ProcessNodeMonitoringEvent(NodeMonitoringEvent * event)10145a1d355fSStephan Aßmus VolumeManager::ProcessNodeMonitoringEvent(NodeMonitoringEvent* event)
10155a1d355fSStephan Aßmus {
10165a1d355fSStephan Aßmus 	if (fNodeMonitoringEvents.Push(event) != B_OK)
10175a1d355fSStephan Aßmus 		delete event;
10185a1d355fSStephan Aßmus }
10195a1d355fSStephan Aßmus 
10205a1d355fSStephan Aßmus // _AddVolume
10215a1d355fSStephan Aßmus status_t
_AddVolume(dev_t volumeID,Volume ** _volume)10225a1d355fSStephan Aßmus VolumeManager::_AddVolume(dev_t volumeID, Volume** _volume)
10235a1d355fSStephan Aßmus {
10245a1d355fSStephan Aßmus 	if (GetVolume(volumeID))
10255a1d355fSStephan Aßmus 		return B_OK;
10265a1d355fSStephan Aßmus 
10275a1d355fSStephan Aßmus 	// create the volume
10285a1d355fSStephan Aßmus 	Volume* volume = new(std::nothrow) Volume(volumeID);
10295a1d355fSStephan Aßmus 	if (!volume)
10305a1d355fSStephan Aßmus 		RETURN_ERROR(B_NO_MEMORY);
10315a1d355fSStephan Aßmus 	ObjectDeleter<Volume> volumeDeleter(volume);
10325a1d355fSStephan Aßmus 	status_t error = volume->Init();
10335a1d355fSStephan Aßmus 	if (error != B_OK)
10345a1d355fSStephan Aßmus 		RETURN_ERROR(error);
10355a1d355fSStephan Aßmus 
10365a1d355fSStephan Aßmus 	// add it
10375a1d355fSStephan Aßmus 	error = fVolumes->Put(volumeID, volume);
10385a1d355fSStephan Aßmus 	if (error != B_OK)
10395a1d355fSStephan Aßmus 		RETURN_ERROR(error);
10405a1d355fSStephan Aßmus 
10415a1d355fSStephan Aßmus 	// add the root node
10425a1d355fSStephan Aßmus 	error = AddNode(volume->GetRootDirectory());
10435a1d355fSStephan Aßmus 	if (error != B_OK) {
10445a1d355fSStephan Aßmus 		fVolumes->Remove(volumeID);
10455a1d355fSStephan Aßmus 		RETURN_ERROR(error);
10465a1d355fSStephan Aßmus 	}
10475a1d355fSStephan Aßmus 
10485a1d355fSStephan Aßmus 	// complete the root dir path
10495a1d355fSStephan Aßmus 	CompletePathToRoot(volume->GetRootDirectory());
10505a1d355fSStephan Aßmus 
10515a1d355fSStephan Aßmus 	volumeDeleter.Detach();
10525a1d355fSStephan Aßmus 	if (_volume)
10535a1d355fSStephan Aßmus 		*_volume = volume;
10545a1d355fSStephan Aßmus 	return B_OK;
10555a1d355fSStephan Aßmus }
10565a1d355fSStephan Aßmus 
10575a1d355fSStephan Aßmus // _EntryCreated
10585a1d355fSStephan Aßmus void
_EntryCreated(EntryCreatedEvent * event)10595a1d355fSStephan Aßmus VolumeManager::_EntryCreated(EntryCreatedEvent* event)
10605a1d355fSStephan Aßmus {
10615a1d355fSStephan Aßmus 	// get the directory
10625a1d355fSStephan Aßmus 	Directory* directory = GetDirectory(event->volumeID, event->directoryID);
10635a1d355fSStephan Aßmus 	if (!directory)
10645a1d355fSStephan Aßmus 		return;
10655a1d355fSStephan Aßmus 
10665a1d355fSStephan Aßmus 	// check, if there is an earlier similar event
10675a1d355fSStephan Aßmus 	bool notify = true;
10685a1d355fSStephan Aßmus 	NoAllocEntryRef ref(event->volumeID, event->directoryID,
10695a1d355fSStephan Aßmus 		event->name.GetString());
10705a1d355fSStephan Aßmus 	EntryCreatedEvent* oldEvent = fEntryCreatedEvents->Get(ref);
10715a1d355fSStephan Aßmus 
10725a1d355fSStephan Aßmus 	// remove the old event
10735a1d355fSStephan Aßmus 	if (oldEvent) {
10745a1d355fSStephan Aßmus 		fEntryCreatedEvents->Remove(ref);
10755a1d355fSStephan Aßmus 		fRecentNodeMonitoringEvents.Remove(oldEvent);
10765a1d355fSStephan Aßmus 		notify = !_IsRecentEvent(oldEvent);
107788e38c17SIngo Weinhold 		oldEvent->ReleaseReference();
10785a1d355fSStephan Aßmus 	}
10795a1d355fSStephan Aßmus 
10805a1d355fSStephan Aßmus 	// add the new event
10815a1d355fSStephan Aßmus 	if (fEntryCreatedEvents->Put(ref, event) == B_OK) {
10825a1d355fSStephan Aßmus 		fRecentNodeMonitoringEvents.Insert(event);
108388e38c17SIngo Weinhold 		event->AcquireReference();
10845a1d355fSStephan Aßmus 	}
10855a1d355fSStephan Aßmus 
10865a1d355fSStephan Aßmus 	// if the directory is complete or at least has iterators attached to it,
10875a1d355fSStephan Aßmus 	// we load the entry
10885a1d355fSStephan Aßmus 	if (directory->IsComplete() || directory->HasDirIterators()) {
10895a1d355fSStephan Aßmus 		Entry* entry;
10905a1d355fSStephan Aßmus 		LoadEntry(ref.device, ref.directory, ref.name, false, &entry);
10915a1d355fSStephan Aßmus 	}
10925a1d355fSStephan Aßmus 
10935a1d355fSStephan Aßmus 	// send notifications
10945a1d355fSStephan Aßmus 	if (notify) {
10955a1d355fSStephan Aßmus 		for (ClientVolumeMap::Iterator it = fClientVolumes->GetIterator();
10965a1d355fSStephan Aßmus 			 it.HasNext();) {
10975a1d355fSStephan Aßmus 			ClientVolume* clientVolume = it.Next().value;
10985a1d355fSStephan Aßmus 			if (DirectoryContains(clientVolume->GetRootDirectory(), directory,
10995a1d355fSStephan Aßmus 				true)) {
11005a1d355fSStephan Aßmus 				clientVolume->ProcessNodeMonitoringEvent(event);
11015a1d355fSStephan Aßmus 			}
11025a1d355fSStephan Aßmus 		}
11035a1d355fSStephan Aßmus 	}
11045a1d355fSStephan Aßmus }
11055a1d355fSStephan Aßmus 
11065a1d355fSStephan Aßmus // _EntryRemoved
11075a1d355fSStephan Aßmus void
_EntryRemoved(EntryRemovedEvent * event,bool keepNode)11085a1d355fSStephan Aßmus VolumeManager::_EntryRemoved(EntryRemovedEvent* event, bool keepNode)
11095a1d355fSStephan Aßmus {
11105a1d355fSStephan Aßmus 	// get node and directory
11115a1d355fSStephan Aßmus 	Node* node = GetNode(event->nodeVolumeID, event->nodeID);
11125a1d355fSStephan Aßmus 	Directory* directory = GetDirectory(event->volumeID, event->directoryID);
11135a1d355fSStephan Aßmus 	if (!directory)
11145a1d355fSStephan Aßmus 		return;
11155a1d355fSStephan Aßmus 
11165a1d355fSStephan Aßmus 	// find the entry
11175a1d355fSStephan Aßmus 	Entry* entry = NULL;
11185a1d355fSStephan Aßmus 	if (node) {
11195a1d355fSStephan Aßmus 		if (event->name.GetLength() == 0) {
11205a1d355fSStephan Aßmus 			for (entry = node->GetFirstReferringEntry();
11215a1d355fSStephan Aßmus 				 entry;
11225a1d355fSStephan Aßmus 				 entry = node->GetNextReferringEntry(entry)) {
11235a1d355fSStephan Aßmus 				if (!entry->Exists()) {
11245a1d355fSStephan Aßmus 					event->name.SetTo(entry->GetName());
11255a1d355fSStephan Aßmus 					break;
11265a1d355fSStephan Aßmus 				}
11275a1d355fSStephan Aßmus 			}
11285a1d355fSStephan Aßmus 		} else {
11295a1d355fSStephan Aßmus 			entry = GetEntry(directory->GetVolumeID(), directory->GetID(),
11305a1d355fSStephan Aßmus 				event->name.GetString());
11315a1d355fSStephan Aßmus 		}
11325a1d355fSStephan Aßmus 	}
11335a1d355fSStephan Aßmus 
11345a1d355fSStephan Aßmus 	// check, if there is an earlier similar event
11355a1d355fSStephan Aßmus 	bool notify = true;
11365a1d355fSStephan Aßmus 	NoAllocEntryRef ref(event->volumeID, event->directoryID,
11375a1d355fSStephan Aßmus 		event->name.GetString());
11385a1d355fSStephan Aßmus 	EntryRemovedEvent* oldEvent = fEntryRemovedEvents->Get(ref);
11395a1d355fSStephan Aßmus 		// TODO: Under BeOS R5 the entry name is not encoded in the
11405a1d355fSStephan Aßmus 		// "entry removed" node monitoring message. If we have seen the entry
11415a1d355fSStephan Aßmus 		// before, we can get the entry nevertheless (see above). Usually we
11425a1d355fSStephan Aßmus 		// get 2 "entry removed" events: One for watching the directory and one
11435a1d355fSStephan Aßmus 		// for watching the node. After the first one has been processed, we've
11445a1d355fSStephan Aßmus 		// forgotten everything about the entry and we won't be able to find out
11455a1d355fSStephan Aßmus 		// the entry's name for the second one. Hence we will never find the
11465a1d355fSStephan Aßmus 		// previous event in the fEntryRemovedEvents map. We should probably
11475a1d355fSStephan Aßmus 		// fall back to using a NodeRef as key under BeOS R5.
11485a1d355fSStephan Aßmus 
11495a1d355fSStephan Aßmus 	// remove the old event
11505a1d355fSStephan Aßmus 	if (oldEvent) {
11515a1d355fSStephan Aßmus 		fEntryRemovedEvents->Remove(ref);
11525a1d355fSStephan Aßmus 		fRecentNodeMonitoringEvents.Remove(oldEvent);
11535a1d355fSStephan Aßmus 		notify = !_IsRecentEvent(oldEvent);
115488e38c17SIngo Weinhold 		oldEvent->ReleaseReference();
11555a1d355fSStephan Aßmus 	}
11565a1d355fSStephan Aßmus 
11575a1d355fSStephan Aßmus 	// add the new event
11585a1d355fSStephan Aßmus 	if (fEntryRemovedEvents->Put(ref, event) == B_OK) {
11595a1d355fSStephan Aßmus 		fRecentNodeMonitoringEvents.Insert(event);
116088e38c17SIngo Weinhold 		event->AcquireReference();
11615a1d355fSStephan Aßmus 	}
11625a1d355fSStephan Aßmus 
11635a1d355fSStephan Aßmus 	// remove the entry
11645a1d355fSStephan Aßmus 	if (entry) {
11655a1d355fSStephan Aßmus 		RemoveEntry(entry);
11665a1d355fSStephan Aßmus 		delete entry;
11675a1d355fSStephan Aßmus 	}
11685a1d355fSStephan Aßmus 
11695a1d355fSStephan Aßmus 	// remove the node, if it doesn't have any more actual referring entries
11705a1d355fSStephan Aßmus 	if (node && !keepNode && !node->GetActualReferringEntry()) {
11715a1d355fSStephan Aßmus 		RemoveNode(node);
11725a1d355fSStephan Aßmus 		if (node != node->GetVolume()->GetRootDirectory())
11735a1d355fSStephan Aßmus 			delete node;
11745a1d355fSStephan Aßmus 	}
11755a1d355fSStephan Aßmus 
11765a1d355fSStephan Aßmus 	// send notifications
11775a1d355fSStephan Aßmus 	if (notify) {
11785a1d355fSStephan Aßmus 		NodeRef nodeRef(event->nodeVolumeID, event->nodeID);
11795a1d355fSStephan Aßmus 		for (ClientVolumeMap::Iterator it = fClientVolumes->GetIterator();
11805a1d355fSStephan Aßmus 			 it.HasNext();) {
11815a1d355fSStephan Aßmus 			// We send a notification, if the client volume contains the entry,
11825a1d355fSStephan Aßmus 			// but also, if the removed entry refers to the client volume's
11835a1d355fSStephan Aßmus 			// root. The client connection has a special handling for this
11845a1d355fSStephan Aßmus 			// case.
11855a1d355fSStephan Aßmus 			ClientVolume* clientVolume = it.Next().value;
11865a1d355fSStephan Aßmus 			Directory* rootDir = clientVolume->GetRootDirectory();
11875a1d355fSStephan Aßmus 			if (DirectoryContains(rootDir, directory, true)
11885a1d355fSStephan Aßmus 				|| clientVolume->GetRootNodeRef() == nodeRef) {
11895a1d355fSStephan Aßmus 				clientVolume->ProcessNodeMonitoringEvent(event);
11905a1d355fSStephan Aßmus 			}
11915a1d355fSStephan Aßmus 		}
11925a1d355fSStephan Aßmus 	}
11935a1d355fSStephan Aßmus }
11945a1d355fSStephan Aßmus 
11955a1d355fSStephan Aßmus // _EntryMoved
11965a1d355fSStephan Aßmus void
_EntryMoved(EntryMovedEvent * event)11975a1d355fSStephan Aßmus VolumeManager::_EntryMoved(EntryMovedEvent* event)
11985a1d355fSStephan Aßmus {
11995a1d355fSStephan Aßmus 	_CheckVolumeRootMoved(event);
12005a1d355fSStephan Aßmus 
12015a1d355fSStephan Aßmus 	Directory* fromDirectory
12025a1d355fSStephan Aßmus 		= GetDirectory(event->volumeID, event->fromDirectoryID);
12035a1d355fSStephan Aßmus 	Directory* toDirectory
12045a1d355fSStephan Aßmus 		= GetDirectory(event->volumeID, event->toDirectoryID);
12055a1d355fSStephan Aßmus 	Node* node = GetNode(event->nodeVolumeID, event->nodeID);
12065a1d355fSStephan Aßmus 
12075a1d355fSStephan Aßmus 	// we should at least have one of the directories
12085a1d355fSStephan Aßmus 	if (!fromDirectory && !toDirectory)
12095a1d355fSStephan Aßmus 		return;
12105a1d355fSStephan Aßmus 
12115a1d355fSStephan Aßmus 	// find the old entry
12125a1d355fSStephan Aßmus 	Entry* oldEntry = NULL;
12135a1d355fSStephan Aßmus 	if (node) {
12145a1d355fSStephan Aßmus 		if (event->fromName.GetLength() == 0) {
12155a1d355fSStephan Aßmus 			for (oldEntry = node->GetFirstReferringEntry();
12165a1d355fSStephan Aßmus 				 oldEntry;
12175a1d355fSStephan Aßmus 				 oldEntry = node->GetNextReferringEntry(oldEntry)) {
12185a1d355fSStephan Aßmus 				if (!oldEntry->Exists()) {
12195a1d355fSStephan Aßmus 					event->fromName.SetTo(oldEntry->GetName());
12205a1d355fSStephan Aßmus 					break;
12215a1d355fSStephan Aßmus 				}
12225a1d355fSStephan Aßmus 			}
12235a1d355fSStephan Aßmus 		} else {
12245a1d355fSStephan Aßmus 			oldEntry = GetEntry(event->volumeID, event->fromDirectoryID,
12255a1d355fSStephan Aßmus 				event->fromName.GetString());
12265a1d355fSStephan Aßmus 		}
12275a1d355fSStephan Aßmus 	}
12285a1d355fSStephan Aßmus 
12295a1d355fSStephan Aßmus 	// check, if there is an earlier similar event
12305a1d355fSStephan Aßmus 	bool notify = true;
12315a1d355fSStephan Aßmus 	if (event->fromName.GetLength() > 0) {
12325a1d355fSStephan Aßmus 		EntryMovedEventKey key(event->volumeID, event->fromDirectoryID,
12335a1d355fSStephan Aßmus 			event->fromName.GetString(), event->toDirectoryID,
12345a1d355fSStephan Aßmus 			event->toName.GetString());
12355a1d355fSStephan Aßmus 		EntryMovedEvent* oldEvent = fEntryMovedEvents->Get(key);
12365a1d355fSStephan Aßmus 
12375a1d355fSStephan Aßmus 		// remove the old event
12385a1d355fSStephan Aßmus 		if (oldEvent) {
12395a1d355fSStephan Aßmus 			fEntryMovedEvents->Remove(key);
12405a1d355fSStephan Aßmus 			fRecentNodeMonitoringEvents.Remove(oldEvent);
12415a1d355fSStephan Aßmus 			notify = !_IsRecentEvent(oldEvent);
124288e38c17SIngo Weinhold 			oldEvent->ReleaseReference();
12435a1d355fSStephan Aßmus 		}
12445a1d355fSStephan Aßmus 
12455a1d355fSStephan Aßmus 		// add the new event
12465a1d355fSStephan Aßmus 		if (fEntryMovedEvents->Put(key, event) == B_OK) {
12475a1d355fSStephan Aßmus 			fRecentNodeMonitoringEvents.Insert(event);
124888e38c17SIngo Weinhold 			event->AcquireReference();
12495a1d355fSStephan Aßmus 		}
12505a1d355fSStephan Aßmus 	}
12515a1d355fSStephan Aßmus 
12525a1d355fSStephan Aßmus 	// remove the old entry
12535a1d355fSStephan Aßmus 	if (oldEntry) {
12545a1d355fSStephan Aßmus 		RemoveEntry(oldEntry);
12555a1d355fSStephan Aßmus 		delete oldEntry;
12565a1d355fSStephan Aßmus 	}
12575a1d355fSStephan Aßmus 
12585a1d355fSStephan Aßmus 	// If the to directory is complete or at least has iterators attached to it,
12595a1d355fSStephan Aßmus 	// we load the new entry. We also load it, if the node is the root of a
12605a1d355fSStephan Aßmus 	// volume.
12615a1d355fSStephan Aßmus 	if (toDirectory
12625a1d355fSStephan Aßmus 		&& (toDirectory->IsComplete() || toDirectory->HasDirIterators()
12635a1d355fSStephan Aßmus 			|| (node && node == node->GetVolume()->GetRootDirectory()))) {
12645a1d355fSStephan Aßmus 		Entry* newEntry;
12655a1d355fSStephan Aßmus 		LoadEntry(event->volumeID, event->toDirectoryID,
12665a1d355fSStephan Aßmus 			event->toName.GetString(), false, &newEntry);
12675a1d355fSStephan Aßmus 	}
12685a1d355fSStephan Aßmus 
12695a1d355fSStephan Aßmus 	// remove the node, if it doesn't have any more actual referring entries
12705a1d355fSStephan Aßmus 	if (node && !node->GetActualReferringEntry()) {
12715a1d355fSStephan Aßmus 		RemoveNode(node);
12725a1d355fSStephan Aßmus 		if (node != node->GetVolume()->GetRootDirectory())
12735a1d355fSStephan Aßmus 			delete node;
12745a1d355fSStephan Aßmus 	}
12755a1d355fSStephan Aßmus 
12765a1d355fSStephan Aßmus 	// send notifications
12775a1d355fSStephan Aßmus 	if (notify) {
12785a1d355fSStephan Aßmus 		for (ClientVolumeMap::Iterator it = fClientVolumes->GetIterator();
12795a1d355fSStephan Aßmus 			 it.HasNext();) {
12805a1d355fSStephan Aßmus 			ClientVolume* clientVolume = it.Next().value;
12815a1d355fSStephan Aßmus 
12825a1d355fSStephan Aßmus 			// check, if it contains the from/to directories
12835a1d355fSStephan Aßmus 			Directory* rootDir = clientVolume->GetRootDirectory();
12845a1d355fSStephan Aßmus 			bool containsFrom = DirectoryContains(rootDir, fromDirectory, true);
12855a1d355fSStephan Aßmus 			bool containsTo = DirectoryContains(rootDir, toDirectory, true);
12865a1d355fSStephan Aßmus 
12875a1d355fSStephan Aßmus 			if (containsFrom) {
12885a1d355fSStephan Aßmus 				if (containsTo) {
12895a1d355fSStephan Aßmus 					// contains source and target dir
12905a1d355fSStephan Aßmus 					clientVolume->ProcessNodeMonitoringEvent(event);
12915a1d355fSStephan Aßmus 				} else {
12925a1d355fSStephan Aßmus 					// contains only the source dir: generate an "entry removed"
12935a1d355fSStephan Aßmus 					// event
12945a1d355fSStephan Aßmus 					EntryRemovedEvent *removedEvent
12955a1d355fSStephan Aßmus 						= new(std::nothrow) EntryRemovedEvent;
12965a1d355fSStephan Aßmus 					if (!removedEvent)
12975a1d355fSStephan Aßmus 						continue;
12985a1d355fSStephan Aßmus 					removedEvent->opcode = B_ENTRY_REMOVED;
12995a1d355fSStephan Aßmus 					removedEvent->time = event->time;
13005a1d355fSStephan Aßmus 					removedEvent->volumeID = event->volumeID;
13015a1d355fSStephan Aßmus 					removedEvent->directoryID = event->fromDirectoryID;
13025a1d355fSStephan Aßmus 					removedEvent->nodeVolumeID = event->nodeVolumeID;
13035a1d355fSStephan Aßmus 					removedEvent->nodeID = event->nodeID;
13045a1d355fSStephan Aßmus 					if (event->fromName.GetLength() > 0)
13055a1d355fSStephan Aßmus 						removedEvent->name = event->fromName;
13065a1d355fSStephan Aßmus 					clientVolume->ProcessNodeMonitoringEvent(removedEvent);
130788e38c17SIngo Weinhold 					removedEvent->ReleaseReference();
13085a1d355fSStephan Aßmus 				}
13095a1d355fSStephan Aßmus 			} else if (containsTo) {
13105a1d355fSStephan Aßmus 				// contains only the target directory: generate an
13115a1d355fSStephan Aßmus 				// "entry created" event
13125a1d355fSStephan Aßmus 				EntryCreatedEvent *createdEvent
13135a1d355fSStephan Aßmus 					= new(std::nothrow) EntryCreatedEvent;
13145a1d355fSStephan Aßmus 				if (!createdEvent)
13155a1d355fSStephan Aßmus 					continue;
13165a1d355fSStephan Aßmus 				createdEvent->opcode = B_ENTRY_CREATED;
13175a1d355fSStephan Aßmus 				createdEvent->time = event->time;
13185a1d355fSStephan Aßmus 				createdEvent->volumeID = event->volumeID;
13195a1d355fSStephan Aßmus 				createdEvent->directoryID = event->toDirectoryID;
13205a1d355fSStephan Aßmus 				createdEvent->name = event->toName;
13215a1d355fSStephan Aßmus 				clientVolume->ProcessNodeMonitoringEvent(createdEvent);
132288e38c17SIngo Weinhold 				createdEvent->ReleaseReference();
13235a1d355fSStephan Aßmus 			}
13245a1d355fSStephan Aßmus 		}
13255a1d355fSStephan Aßmus 	}
13265a1d355fSStephan Aßmus }
13275a1d355fSStephan Aßmus 
13285a1d355fSStephan Aßmus // _NodeStatChanged
13295a1d355fSStephan Aßmus void
_NodeStatChanged(StatChangedEvent * event)13305a1d355fSStephan Aßmus VolumeManager::_NodeStatChanged(StatChangedEvent* event)
13315a1d355fSStephan Aßmus {
13325a1d355fSStephan Aßmus 	// get the node
13335a1d355fSStephan Aßmus 	Node* node = GetNode(event->volumeID, event->nodeID);
13345a1d355fSStephan Aßmus 	if (!node)
13355a1d355fSStephan Aßmus 		return;
13365a1d355fSStephan Aßmus 
13375a1d355fSStephan Aßmus 	// check, if there is an earlier similar event
13385a1d355fSStephan Aßmus 	bool notify = true;
13395a1d355fSStephan Aßmus 	NodeRef ref(event->volumeID, event->nodeID);
13405a1d355fSStephan Aßmus 	StatChangedEvent* oldEvent = fNodeStatChangedEvents->Get(ref);
13415a1d355fSStephan Aßmus 
13425a1d355fSStephan Aßmus 	// remove the old event
13435a1d355fSStephan Aßmus 	if (oldEvent) {
13445a1d355fSStephan Aßmus 		fNodeStatChangedEvents->Remove(ref);
13455a1d355fSStephan Aßmus 		fRecentNodeMonitoringEvents.Remove(oldEvent);
13465a1d355fSStephan Aßmus 		notify = !_IsRecentEvent(oldEvent);
134788e38c17SIngo Weinhold 		oldEvent->ReleaseReference();
13485a1d355fSStephan Aßmus 	}
13495a1d355fSStephan Aßmus 
13505a1d355fSStephan Aßmus 	// add the new event
13515a1d355fSStephan Aßmus 	if (fNodeStatChangedEvents->Put(ref, event) == B_OK) {
13525a1d355fSStephan Aßmus 		fRecentNodeMonitoringEvents.Insert(event);
135388e38c17SIngo Weinhold 		event->AcquireReference();
13545a1d355fSStephan Aßmus 	}
13555a1d355fSStephan Aßmus 
13565a1d355fSStephan Aßmus 	if (notify) {
13575a1d355fSStephan Aßmus 		// update the cached node stat
13585a1d355fSStephan Aßmus 		node->UpdateStat();
13595a1d355fSStephan Aßmus 
13605a1d355fSStephan Aßmus 		// send notifications
13615a1d355fSStephan Aßmus 		for (ClientVolumeMap::Iterator it = fClientVolumes->GetIterator();
13625a1d355fSStephan Aßmus 			 it.HasNext();) {
13635a1d355fSStephan Aßmus 			ClientVolume* clientVolume = it.Next().value;
13645a1d355fSStephan Aßmus 			if (DirectoryContains(clientVolume->GetRootDirectory(), node, true))
13655a1d355fSStephan Aßmus 				clientVolume->ProcessNodeMonitoringEvent(event);
13665a1d355fSStephan Aßmus 		}
13675a1d355fSStephan Aßmus 	}
13685a1d355fSStephan Aßmus }
13695a1d355fSStephan Aßmus 
13705a1d355fSStephan Aßmus // _NodeAttributeChanged
13715a1d355fSStephan Aßmus void
_NodeAttributeChanged(AttributeChangedEvent * event)13725a1d355fSStephan Aßmus VolumeManager::_NodeAttributeChanged(AttributeChangedEvent* event)
13735a1d355fSStephan Aßmus {
13745a1d355fSStephan Aßmus 	// get the node
13755a1d355fSStephan Aßmus 	Node* node = GetNode(event->volumeID, event->nodeID);
13765a1d355fSStephan Aßmus 	if (!node)
13775a1d355fSStephan Aßmus 		return;
13785a1d355fSStephan Aßmus 
13795a1d355fSStephan Aßmus 	// check, if there is an earlier similar event
13805a1d355fSStephan Aßmus 	bool notify = true;
13815a1d355fSStephan Aßmus 	AttributeRef ref(event->volumeID, event->nodeID,
13825a1d355fSStephan Aßmus 		event->attribute.GetString());
13835a1d355fSStephan Aßmus 	AttributeChangedEvent* oldEvent = fNodeAttributeChangedEvents->Get(ref);
13845a1d355fSStephan Aßmus 
13855a1d355fSStephan Aßmus 	// remove the old event
13865a1d355fSStephan Aßmus 	if (oldEvent) {
13875a1d355fSStephan Aßmus 		fNodeAttributeChangedEvents->Remove(ref);
13885a1d355fSStephan Aßmus 		fRecentNodeMonitoringEvents.Remove(oldEvent);
13895a1d355fSStephan Aßmus 		notify = !_IsRecentEvent(oldEvent);
139088e38c17SIngo Weinhold 		oldEvent->ReleaseReference();
13915a1d355fSStephan Aßmus 	}
13925a1d355fSStephan Aßmus 
13935a1d355fSStephan Aßmus 	// add the new event
13945a1d355fSStephan Aßmus 	if (fNodeAttributeChangedEvents->Put(ref, event) == B_OK) {
13955a1d355fSStephan Aßmus 		fRecentNodeMonitoringEvents.Insert(event);
139688e38c17SIngo Weinhold 		event->AcquireReference();
13975a1d355fSStephan Aßmus 	}
13985a1d355fSStephan Aßmus 
13995a1d355fSStephan Aßmus 	// send notifications
14005a1d355fSStephan Aßmus 	if (notify) {
14015a1d355fSStephan Aßmus 		for (ClientVolumeMap::Iterator it = fClientVolumes->GetIterator();
14025a1d355fSStephan Aßmus 			 it.HasNext();) {
14035a1d355fSStephan Aßmus 			ClientVolume* clientVolume = it.Next().value;
14045a1d355fSStephan Aßmus 			if (DirectoryContains(clientVolume->GetRootDirectory(), node, true))
14055a1d355fSStephan Aßmus 				clientVolume->ProcessNodeMonitoringEvent(event);
14065a1d355fSStephan Aßmus 		}
14075a1d355fSStephan Aßmus 	}
14085a1d355fSStephan Aßmus }
14095a1d355fSStephan Aßmus 
14105a1d355fSStephan Aßmus // _VolumeMounted
14115a1d355fSStephan Aßmus void
_VolumeMounted(VolumeMountedEvent * event)14125a1d355fSStephan Aßmus VolumeManager::_VolumeMounted(VolumeMountedEvent* event)
14135a1d355fSStephan Aßmus {
14145a1d355fSStephan Aßmus 	entry_ref rootRef;
14155a1d355fSStephan Aßmus 	bool rootRefInitialized = false;
14165a1d355fSStephan Aßmus 
14175a1d355fSStephan Aßmus 	// remove the entry referring to the covered directory
14185a1d355fSStephan Aßmus 	Directory* coveredDirectory = GetDirectory(event->volumeID,
14195a1d355fSStephan Aßmus 		event->directoryID);
14205a1d355fSStephan Aßmus 	if (coveredDirectory) {
14215a1d355fSStephan Aßmus 		if (Entry* entry = coveredDirectory->GetActualReferringEntry()) {
14225a1d355fSStephan Aßmus 			// get an entry for later
14235a1d355fSStephan Aßmus 			rootRef = entry->GetEntryRef();
14245a1d355fSStephan Aßmus 			rootRefInitialized = true;
14255a1d355fSStephan Aßmus 
14265a1d355fSStephan Aßmus 			// send the "entry removed" event
14275a1d355fSStephan Aßmus 			EntryRemovedEvent* event;
14285a1d355fSStephan Aßmus 			if (_GenerateEntryRemovedEvent(entry, system_time(),
14295a1d355fSStephan Aßmus 					&event) == B_OK) {
14305a1d355fSStephan Aßmus 				_EntryRemoved(event, true);
143188e38c17SIngo Weinhold 				event->ReleaseReference();
14325a1d355fSStephan Aßmus 			} else {
14335a1d355fSStephan Aßmus 				RemoveEntry(entry);
14345a1d355fSStephan Aßmus 				delete entry;
14355a1d355fSStephan Aßmus 			}
14365a1d355fSStephan Aßmus 		}
14375a1d355fSStephan Aßmus 	}
14385a1d355fSStephan Aßmus 
14395a1d355fSStephan Aßmus 	// add the volume
14405a1d355fSStephan Aßmus 	_AddVolume(event->newVolumeID);
14415a1d355fSStephan Aßmus 
14425a1d355fSStephan Aßmus 	// generate an "entry created" event for the root dir entry
14435a1d355fSStephan Aßmus 	if (rootRefInitialized)
14445a1d355fSStephan Aßmus 		_GenerateEntryCreatedEvent(rootRef, event->time);
14455a1d355fSStephan Aßmus }
14465a1d355fSStephan Aßmus 
14475a1d355fSStephan Aßmus // _VolumeUnmounted
14485a1d355fSStephan Aßmus void
_VolumeUnmounted(VolumeUnmountedEvent * event)14495a1d355fSStephan Aßmus VolumeManager::_VolumeUnmounted(VolumeUnmountedEvent* event)
14505a1d355fSStephan Aßmus {
14515a1d355fSStephan Aßmus 	// get the volume
14525a1d355fSStephan Aßmus 	Volume* volume = GetVolume(event->volumeID);
14535a1d355fSStephan Aßmus 	if (!volume)
14545a1d355fSStephan Aßmus 		return;
14555a1d355fSStephan Aßmus 
14565a1d355fSStephan Aßmus 	entry_ref rootRef;
14575a1d355fSStephan Aßmus 	bool rootRefInitialized = false;
14585a1d355fSStephan Aßmus 
14595a1d355fSStephan Aßmus 	// remove all actual entries referring to the root directory (should only
14605a1d355fSStephan Aßmus 	// be one)
14615a1d355fSStephan Aßmus 	if (Directory* rootDir = volume->GetRootDirectory()) {
14625a1d355fSStephan Aßmus 		// get an entry ref for the root dir
14635a1d355fSStephan Aßmus 		if (Entry* entry = rootDir->GetActualReferringEntry()) {
14645a1d355fSStephan Aßmus 			rootRef = entry->GetEntryRef();
14655a1d355fSStephan Aßmus 			rootRefInitialized = true;
14665a1d355fSStephan Aßmus 		}
14675a1d355fSStephan Aßmus 
14685a1d355fSStephan Aßmus 		Entry* entry = rootDir->GetFirstReferringEntry();
14695a1d355fSStephan Aßmus 		while (entry) {
14705a1d355fSStephan Aßmus 			Entry* nextEntry = rootDir->GetNextReferringEntry(entry);
14715a1d355fSStephan Aßmus 
14725a1d355fSStephan Aßmus 			if (entry->IsActualEntry()) {
14735a1d355fSStephan Aßmus 				EntryRemovedEvent* removedEvent;
14745a1d355fSStephan Aßmus 				if (_GenerateEntryRemovedEvent(entry, event->time,
14755a1d355fSStephan Aßmus 						&removedEvent) == B_OK) {
14765a1d355fSStephan Aßmus 					_EntryRemoved(removedEvent, true);
147788e38c17SIngo Weinhold 					removedEvent->ReleaseReference();
14785a1d355fSStephan Aßmus 				} else {
14795a1d355fSStephan Aßmus 					RemoveEntry(entry);
14805a1d355fSStephan Aßmus 					delete entry;
14815a1d355fSStephan Aßmus 				}
14825a1d355fSStephan Aßmus 			}
14835a1d355fSStephan Aßmus 
14845a1d355fSStephan Aßmus 			entry = nextEntry;
14855a1d355fSStephan Aßmus 		}
14865a1d355fSStephan Aßmus 	}
14875a1d355fSStephan Aßmus 
14885a1d355fSStephan Aßmus 	// remove all entries of the volume
14895a1d355fSStephan Aßmus 	while (Entry* entry = volume->GetFirstEntry()) {
14905a1d355fSStephan Aßmus 		bool remove = true;
14915a1d355fSStephan Aßmus 		if (entry->IsActualEntry()) {
14925a1d355fSStephan Aßmus 			if (_GenerateEntryRemovedEvent(entry, event->time) != B_OK)
14935a1d355fSStephan Aßmus 				remove = false;
14945a1d355fSStephan Aßmus 		}
14955a1d355fSStephan Aßmus 
14965a1d355fSStephan Aßmus 		if (remove) {
14975a1d355fSStephan Aßmus 			RemoveEntry(entry);
14985a1d355fSStephan Aßmus 			delete entry;
14995a1d355fSStephan Aßmus 		}
15005a1d355fSStephan Aßmus 	}
15015a1d355fSStephan Aßmus 
15025a1d355fSStephan Aßmus 	// remove all nodes
15035a1d355fSStephan Aßmus 	while (Node* node = volume->GetFirstNode()) {
15045a1d355fSStephan Aßmus 		RemoveNode(node);
15055a1d355fSStephan Aßmus 		if (node != volume->GetRootDirectory())
15065a1d355fSStephan Aßmus 			delete node;
15075a1d355fSStephan Aßmus 	}
15085a1d355fSStephan Aßmus 
15095a1d355fSStephan Aßmus 	// remove the volume
15105a1d355fSStephan Aßmus 	fVolumes->Remove(volume->GetID());
15115a1d355fSStephan Aßmus 	delete volume;
15125a1d355fSStephan Aßmus 
15135a1d355fSStephan Aßmus 	// generate an "entry created" event for the covered node
15145a1d355fSStephan Aßmus 	if (rootRefInitialized)
15155a1d355fSStephan Aßmus 		_GenerateEntryCreatedEvent(rootRef, event->time);
15165a1d355fSStephan Aßmus }
15175a1d355fSStephan Aßmus 
15185a1d355fSStephan Aßmus // _QueryEntryCreated
15195a1d355fSStephan Aßmus void
_QueryEntryCreated(EntryCreatedEvent * event)15205a1d355fSStephan Aßmus VolumeManager::_QueryEntryCreated(EntryCreatedEvent* event)
15215a1d355fSStephan Aßmus {
15225a1d355fSStephan Aßmus 	// get the query handler
15235a1d355fSStephan Aßmus 	QueryHandler* queryHandler
15245a1d355fSStephan Aßmus 		= dynamic_cast<QueryHandler*>(event->queryHandler);
15255a1d355fSStephan Aßmus 	if (!queryHandler)
15265a1d355fSStephan Aßmus 		return;
15275a1d355fSStephan Aßmus 
15285a1d355fSStephan Aßmus 	// load the entry (just to make sure that it really exists)
15295a1d355fSStephan Aßmus 	Entry* entry = NULL;
15305a1d355fSStephan Aßmus 	status_t error = LoadEntry(event->volumeID, event->directoryID,
15315a1d355fSStephan Aßmus 		event->name.GetString(), true, &entry);
15325a1d355fSStephan Aßmus 	if (error != B_OK)
15335a1d355fSStephan Aßmus 		return;
15345a1d355fSStephan Aßmus 
15355a1d355fSStephan Aßmus 	// get remote port and token
15365a1d355fSStephan Aßmus 	if (!queryHandler->LockLooper())
15375a1d355fSStephan Aßmus 		return;
15385a1d355fSStephan Aßmus 
15395a1d355fSStephan Aßmus 	QueryHandle* queryHandle = queryHandler->GetQueryHandle();
15405a1d355fSStephan Aßmus 	event->remotePort = queryHandle->GetRemotePort();
15415a1d355fSStephan Aßmus 	event->remoteToken = queryHandle->GetRemoteToken();
15425a1d355fSStephan Aßmus 	queryHandler->UnlockLooper();
15435a1d355fSStephan Aßmus 
15445a1d355fSStephan Aßmus 	// send a notification to the client volume
15455a1d355fSStephan Aßmus 	queryHandler->GetQueryDomain()->ProcessQueryEvent(event);
15465a1d355fSStephan Aßmus }
15475a1d355fSStephan Aßmus 
15485a1d355fSStephan Aßmus // _QueryEntryRemoved
15495a1d355fSStephan Aßmus void
_QueryEntryRemoved(EntryRemovedEvent * event)15505a1d355fSStephan Aßmus VolumeManager::_QueryEntryRemoved(EntryRemovedEvent* event)
15515a1d355fSStephan Aßmus {
15525a1d355fSStephan Aßmus 	// get the query handler
15535a1d355fSStephan Aßmus 	QueryHandler* queryHandler
15545a1d355fSStephan Aßmus 		= dynamic_cast<QueryHandler*>(event->queryHandler);
15555a1d355fSStephan Aßmus 	if (!queryHandler)
15565a1d355fSStephan Aßmus 		return;
15575a1d355fSStephan Aßmus 
15585a1d355fSStephan Aßmus 	// load the directory (just to make sure that it really exists)
15595a1d355fSStephan Aßmus 	Directory* directory = NULL;
15605a1d355fSStephan Aßmus 	status_t error = LoadDirectory(event->volumeID, event->directoryID,
15615a1d355fSStephan Aßmus 		&directory);
15625a1d355fSStephan Aßmus 	if (error != B_OK)
15635a1d355fSStephan Aßmus 		return;
15645a1d355fSStephan Aßmus 
15655a1d355fSStephan Aßmus 	// get remote port and token
15665a1d355fSStephan Aßmus 	if (!queryHandler->LockLooper())
15675a1d355fSStephan Aßmus 		return;
15685a1d355fSStephan Aßmus 	QueryHandle* queryHandle = queryHandler->GetQueryHandle();
15695a1d355fSStephan Aßmus 	event->remotePort = queryHandle->GetRemotePort();
15705a1d355fSStephan Aßmus 	event->remoteToken = queryHandle->GetRemoteToken();
15715a1d355fSStephan Aßmus 	queryHandler->UnlockLooper();
15725a1d355fSStephan Aßmus 
15735a1d355fSStephan Aßmus 	// send a notification to the client volume
15745a1d355fSStephan Aßmus 	queryHandler->GetQueryDomain()->ProcessQueryEvent(event);
15755a1d355fSStephan Aßmus }
15765a1d355fSStephan Aßmus 
15775a1d355fSStephan Aßmus // _QueryEntryMoved
15785a1d355fSStephan Aßmus void
_QueryEntryMoved(EntryMovedEvent * event)15795a1d355fSStephan Aßmus VolumeManager::_QueryEntryMoved(EntryMovedEvent* event)
15805a1d355fSStephan Aßmus {
15815a1d355fSStephan Aßmus 	// we simply split the event into a `removed' and a `created' event
15825a1d355fSStephan Aßmus 
15835a1d355fSStephan Aßmus 	// allocate the events
15845a1d355fSStephan Aßmus 	EntryRemovedEvent* removedEvent = new(std::nothrow) EntryRemovedEvent;
15855a1d355fSStephan Aßmus 	EntryCreatedEvent* createdEvent = new(std::nothrow) EntryCreatedEvent;
15865a1d355fSStephan Aßmus 	if (!removedEvent || !createdEvent) {
15875a1d355fSStephan Aßmus 		delete removedEvent;
15885a1d355fSStephan Aßmus 		delete createdEvent;
15895a1d355fSStephan Aßmus 		return;
15905a1d355fSStephan Aßmus 	}
15915a1d355fSStephan Aßmus 
15925a1d355fSStephan Aßmus 	// init the removed event
15935a1d355fSStephan Aßmus 	removedEvent->opcode = B_ENTRY_REMOVED;
15945a1d355fSStephan Aßmus 	removedEvent->time = event->time;
15955a1d355fSStephan Aßmus 	removedEvent->queryHandler = event->queryHandler;
159688e38c17SIngo Weinhold 	removedEvent->queryHandler->AcquireReference();
15975a1d355fSStephan Aßmus 	removedEvent->volumeID = event->volumeID;
15985a1d355fSStephan Aßmus 	removedEvent->directoryID = event->fromDirectoryID;
15995a1d355fSStephan Aßmus 	removedEvent->nodeVolumeID = event->volumeID;
16005a1d355fSStephan Aßmus 	removedEvent->nodeID = event->nodeID;
16015a1d355fSStephan Aßmus 	removedEvent->name = event->fromName;
16025a1d355fSStephan Aßmus 
16035a1d355fSStephan Aßmus 	// init the created event
16045a1d355fSStephan Aßmus 	createdEvent->opcode = B_ENTRY_CREATED;
16055a1d355fSStephan Aßmus 	createdEvent->time = event->time;
16065a1d355fSStephan Aßmus 	createdEvent->queryHandler = event->queryHandler;
160788e38c17SIngo Weinhold 	createdEvent->queryHandler->AcquireReference();
16085a1d355fSStephan Aßmus 	createdEvent->volumeID = event->volumeID;
16095a1d355fSStephan Aßmus 	createdEvent->directoryID = event->toDirectoryID;
16105a1d355fSStephan Aßmus 	createdEvent->nodeID = event->nodeID;
16115a1d355fSStephan Aßmus 	createdEvent->name = event->toName;
16125a1d355fSStephan Aßmus 
16135a1d355fSStephan Aßmus 	// send them
16145a1d355fSStephan Aßmus 	_QueryEntryRemoved(removedEvent);
161588e38c17SIngo Weinhold 	removedEvent->ReleaseReference();
16165a1d355fSStephan Aßmus 	_QueryEntryCreated(createdEvent);
161788e38c17SIngo Weinhold 	createdEvent->ReleaseReference();
16185a1d355fSStephan Aßmus }
16195a1d355fSStephan Aßmus 
16205a1d355fSStephan Aßmus // _IsRecentEvent
16215a1d355fSStephan Aßmus bool
_IsRecentEvent(NodeMonitoringEvent * event) const16225a1d355fSStephan Aßmus VolumeManager::_IsRecentEvent(NodeMonitoringEvent* event) const
16235a1d355fSStephan Aßmus {
16245a1d355fSStephan Aßmus 	return (event && system_time() < event->time + kRecentEventLifeTime);
16255a1d355fSStephan Aßmus }
16265a1d355fSStephan Aßmus 
16275a1d355fSStephan Aßmus // _GenerateEntryCreatedEvent
16285a1d355fSStephan Aßmus status_t
_GenerateEntryCreatedEvent(const entry_ref & ref,bigtime_t time,EntryCreatedEvent ** _event)16295a1d355fSStephan Aßmus VolumeManager::_GenerateEntryCreatedEvent(const entry_ref& ref, bigtime_t time,
16305a1d355fSStephan Aßmus 	EntryCreatedEvent** _event)
16315a1d355fSStephan Aßmus {
16325a1d355fSStephan Aßmus 	// load the entry
16335a1d355fSStephan Aßmus 	Entry* entry;
16345a1d355fSStephan Aßmus 	status_t error = LoadEntry(ref.device, ref.directory, ref.name, true,
16355a1d355fSStephan Aßmus 		&entry);
16365a1d355fSStephan Aßmus 	if (error != B_OK)
16375a1d355fSStephan Aßmus 		return error;
16385a1d355fSStephan Aßmus 
16395a1d355fSStephan Aßmus 	// create the event
16405a1d355fSStephan Aßmus 	EntryCreatedEvent* event = new(std::nothrow) EntryCreatedEvent;
16415a1d355fSStephan Aßmus 	if (!event)
16425a1d355fSStephan Aßmus 		return B_NO_MEMORY;
16435a1d355fSStephan Aßmus 
16445a1d355fSStephan Aßmus 	// fill in the fields
16455a1d355fSStephan Aßmus 	event->opcode = B_ENTRY_CREATED;
16465a1d355fSStephan Aßmus 	event->time = time;
16475a1d355fSStephan Aßmus 	event->volumeID = entry->GetVolumeID();
16485a1d355fSStephan Aßmus 	event->directoryID = entry->GetDirectoryID();
16495a1d355fSStephan Aßmus 	event->nodeID = entry->GetNode()->GetID();
16505a1d355fSStephan Aßmus 	event->name.SetTo(entry->GetName());
16515a1d355fSStephan Aßmus 
16525a1d355fSStephan Aßmus 	if (_event) {
16535a1d355fSStephan Aßmus 		*_event = event;
16545a1d355fSStephan Aßmus 	} else {
16555a1d355fSStephan Aßmus 		_EntryCreated(event);
165688e38c17SIngo Weinhold 		event->ReleaseReference();
16575a1d355fSStephan Aßmus 	}
16585a1d355fSStephan Aßmus 
16595a1d355fSStephan Aßmus 	return B_OK;
16605a1d355fSStephan Aßmus }
16615a1d355fSStephan Aßmus 
16625a1d355fSStephan Aßmus // _GenerateEntryRemovedEvent
16635a1d355fSStephan Aßmus status_t
_GenerateEntryRemovedEvent(Entry * entry,bigtime_t time,EntryRemovedEvent ** _event)16645a1d355fSStephan Aßmus VolumeManager::_GenerateEntryRemovedEvent(Entry* entry, bigtime_t time,
16655a1d355fSStephan Aßmus 	EntryRemovedEvent** _event)
16665a1d355fSStephan Aßmus {
16675a1d355fSStephan Aßmus 	if (!entry)
16685a1d355fSStephan Aßmus 		return B_BAD_VALUE;
16695a1d355fSStephan Aßmus 
16705a1d355fSStephan Aßmus 	// create the event
16715a1d355fSStephan Aßmus 	EntryRemovedEvent* event = new(std::nothrow) EntryRemovedEvent;
16725a1d355fSStephan Aßmus 	if (!event)
16735a1d355fSStephan Aßmus 		return B_NO_MEMORY;
16745a1d355fSStephan Aßmus 
16755a1d355fSStephan Aßmus 	// fill in the fields
16765a1d355fSStephan Aßmus 	event->opcode = B_ENTRY_REMOVED;
16775a1d355fSStephan Aßmus 	event->time = time;
16785a1d355fSStephan Aßmus 	event->volumeID = entry->GetVolumeID();
16795a1d355fSStephan Aßmus 	event->directoryID = entry->GetDirectoryID();
16805a1d355fSStephan Aßmus 	event->nodeVolumeID = entry->GetNode()->GetVolumeID();
16815a1d355fSStephan Aßmus 	event->nodeID = entry->GetNode()->GetID();
16825a1d355fSStephan Aßmus 	event->name.SetTo(entry->GetName());
16835a1d355fSStephan Aßmus 
16845a1d355fSStephan Aßmus 	if (_event) {
16855a1d355fSStephan Aßmus 		*_event = event;
16865a1d355fSStephan Aßmus 	} else {
16875a1d355fSStephan Aßmus 		_EntryRemoved(event, false);
168888e38c17SIngo Weinhold 		event->ReleaseReference();
16895a1d355fSStephan Aßmus 	}
16905a1d355fSStephan Aßmus 
16915a1d355fSStephan Aßmus 	return B_OK;
16925a1d355fSStephan Aßmus }
16935a1d355fSStephan Aßmus 
16945a1d355fSStephan Aßmus // _CheckVolumeRootMoved
16955a1d355fSStephan Aßmus void
_CheckVolumeRootMoved(EntryMovedEvent * event)16965a1d355fSStephan Aßmus VolumeManager::_CheckVolumeRootMoved(EntryMovedEvent* event)
16975a1d355fSStephan Aßmus {
16985a1d355fSStephan Aßmus 	// If a volume root is moved, the sent node monitoring message does
16995a1d355fSStephan Aßmus 	// unforunately contain the node_ref of the covered node, not that of the
17005a1d355fSStephan Aßmus 	// volume root -- a BeOS R5 VFS bug. Since we have the entry_ref of the
17015a1d355fSStephan Aßmus 	// new entry, we can stat the node.
17025a1d355fSStephan Aßmus 
17035a1d355fSStephan Aßmus 	// check whether the node is the root of a volume
17045a1d355fSStephan Aßmus 	NoAllocEntryRef ref(event->volumeID, event->toDirectoryID,
17055a1d355fSStephan Aßmus 		event->toName.GetString());
17065a1d355fSStephan Aßmus 	BEntry entry;
17075a1d355fSStephan Aßmus 	struct stat st;
17085a1d355fSStephan Aßmus 	if (FDManager::SetEntry(&entry, &ref) == B_OK
17095a1d355fSStephan Aßmus 		&& entry.GetStat(&st) == B_OK) {
17105a1d355fSStephan Aßmus 		event->nodeVolumeID = st.st_dev;
17115a1d355fSStephan Aßmus 		event->nodeID = st.st_ino;
17125a1d355fSStephan Aßmus 		if (Volume* volume = GetVolume(st.st_dev)) {
17135a1d355fSStephan Aßmus 			if (volume->GetRootID() == st.st_ino) {
1714*ebb21bd1SMurai Takashi 				PRINT("Mount point for volume %" B_PRIdDEV " renamed\n",
17153c1afd35SPawel Dziepak 					volume->GetID());
17165a1d355fSStephan Aßmus 			}
17175a1d355fSStephan Aßmus 		}
17185a1d355fSStephan Aßmus 	}
17195a1d355fSStephan Aßmus }
17205a1d355fSStephan Aßmus 
17215a1d355fSStephan Aßmus // _NodeMonitoringProcessorEntry
17225a1d355fSStephan Aßmus int32
_NodeMonitoringProcessorEntry(void * data)17235a1d355fSStephan Aßmus VolumeManager::_NodeMonitoringProcessorEntry(void* data)
17245a1d355fSStephan Aßmus {
17255a1d355fSStephan Aßmus 	return ((VolumeManager*)data)->_NodeMonitoringProcessor();
17265a1d355fSStephan Aßmus }
17275a1d355fSStephan Aßmus 
17285a1d355fSStephan Aßmus // _NodeMonitoryProcessor
17295a1d355fSStephan Aßmus int32
_NodeMonitoringProcessor()17305a1d355fSStephan Aßmus VolumeManager::_NodeMonitoringProcessor()
17315a1d355fSStephan Aßmus {
17325a1d355fSStephan Aßmus 	do {
17335a1d355fSStephan Aßmus 		NodeMonitoringEvent* event = NULL;
17345a1d355fSStephan Aßmus 		status_t error = fNodeMonitoringEvents.Pop(&event);
17355a1d355fSStephan Aßmus 
17365a1d355fSStephan Aßmus 		VolumeManagerLocker managerLocker;
17375a1d355fSStephan Aßmus 
17385a1d355fSStephan Aßmus 		while (error == B_OK) {
17395a1d355fSStephan Aßmus 			if (event->queryHandler) {
17405a1d355fSStephan Aßmus 				switch (event->opcode) {
17415a1d355fSStephan Aßmus 					case B_ENTRY_CREATED:
17425a1d355fSStephan Aßmus 						_QueryEntryCreated(
17435a1d355fSStephan Aßmus 							dynamic_cast<EntryCreatedEvent*>(event));
17445a1d355fSStephan Aßmus 						break;
17455a1d355fSStephan Aßmus 					case B_ENTRY_REMOVED:
17465a1d355fSStephan Aßmus 						_QueryEntryRemoved(
17475a1d355fSStephan Aßmus 							dynamic_cast<EntryRemovedEvent*>(event));
17485a1d355fSStephan Aßmus 						break;
17495a1d355fSStephan Aßmus 					case B_ENTRY_MOVED:
17505a1d355fSStephan Aßmus 						_QueryEntryMoved(dynamic_cast<EntryMovedEvent*>(event));
17515a1d355fSStephan Aßmus 						break;
17525a1d355fSStephan Aßmus 				}
17535a1d355fSStephan Aßmus 			} else {
17545a1d355fSStephan Aßmus 				switch (event->opcode) {
17555a1d355fSStephan Aßmus 					case B_ENTRY_CREATED:
17565a1d355fSStephan Aßmus 						_EntryCreated(dynamic_cast<EntryCreatedEvent*>(event));
17575a1d355fSStephan Aßmus 						break;
17585a1d355fSStephan Aßmus 					case B_ENTRY_REMOVED:
17595a1d355fSStephan Aßmus 						_EntryRemoved(dynamic_cast<EntryRemovedEvent*>(event),
17605a1d355fSStephan Aßmus 							false);
17615a1d355fSStephan Aßmus 						break;
17625a1d355fSStephan Aßmus 					case B_ENTRY_MOVED:
17635a1d355fSStephan Aßmus 						_EntryMoved(dynamic_cast<EntryMovedEvent*>(event));
17645a1d355fSStephan Aßmus 						break;
17655a1d355fSStephan Aßmus 					case B_STAT_CHANGED:
17665a1d355fSStephan Aßmus 						_NodeStatChanged(
17675a1d355fSStephan Aßmus 							dynamic_cast<StatChangedEvent*>(event));
17685a1d355fSStephan Aßmus 						break;
17695a1d355fSStephan Aßmus 					case B_ATTR_CHANGED:
17705a1d355fSStephan Aßmus 						_NodeAttributeChanged(
17715a1d355fSStephan Aßmus 							dynamic_cast<AttributeChangedEvent*>(event));
17725a1d355fSStephan Aßmus 						break;
17735a1d355fSStephan Aßmus 					case B_DEVICE_MOUNTED:
17745a1d355fSStephan Aßmus 						_VolumeMounted(dynamic_cast<VolumeMountedEvent*>(event));
17755a1d355fSStephan Aßmus 						break;
17765a1d355fSStephan Aßmus 					case B_DEVICE_UNMOUNTED:
17775a1d355fSStephan Aßmus 						_VolumeUnmounted(
17785a1d355fSStephan Aßmus 							dynamic_cast<VolumeUnmountedEvent*>(event));
17795a1d355fSStephan Aßmus 						break;
17805a1d355fSStephan Aßmus 				}
17815a1d355fSStephan Aßmus 			}
178288e38c17SIngo Weinhold 			event->ReleaseReference();
17835a1d355fSStephan Aßmus 
17845a1d355fSStephan Aßmus 			// If there is another event available, get it as long as we
17855a1d355fSStephan Aßmus 			// have the VolumeManager lock.
17865a1d355fSStephan Aßmus 			error = fNodeMonitoringEvents.Pop(&event, 0);
17875a1d355fSStephan Aßmus 		}
17885a1d355fSStephan Aßmus 	} while (!fTerminating);
17895a1d355fSStephan Aßmus 
17905a1d355fSStephan Aßmus 	return 0;
17915a1d355fSStephan Aßmus }
17925a1d355fSStephan Aßmus 
17935a1d355fSStephan Aßmus 
17945a1d355fSStephan Aßmus // sManager
17955a1d355fSStephan Aßmus VolumeManager* VolumeManager::sManager = NULL;
1796