⛏️ index : haiku.git

/*
 * Copyright 2012 Haiku, Inc. All rights reserved.
 * Distributed under the terms of the MIT License.
 *
 * Authors:
 *		Paweł Dziepak, pdziepak@quarnos.org
 */
#ifndef DIRECTORYCACHE_H
#define DIRECTORYCACHE_H


#include <lock.h>
#include <SupportDefs.h>
#include <util/DoublyLinkedList.h>
#include <util/KernelReferenceable.h>
#include <util/SinglyLinkedList.h>

#include "Debug.h"


class Inode;

struct NameCacheEntry :
	public SinglyLinkedListLinkImpl<NameCacheEntry> {
			ino_t			fNode;
			const char*		fName;

							NameCacheEntry(const char* name, ino_t node);
							NameCacheEntry(const NameCacheEntry& entry);
							~NameCacheEntry();
};

struct DirectoryCacheSnapshot : public KernelReferenceable {
			SinglyLinkedList<NameCacheEntry>	fEntries;
	mutable	mutex			fLock;

							DirectoryCacheSnapshot();
							DirectoryCacheSnapshot(
								const DirectoryCacheSnapshot& snapshot);
							~DirectoryCacheSnapshot();
};

class DirectoryCache {
public:
							DirectoryCache(Inode* inode, bool attr = false);
							~DirectoryCache();

	inline	void			Lock();
	inline	void			Unlock();

			void			Reset();
			void			Trash();
	inline	bool			Valid();

			status_t		AddEntry(const char* name, ino_t node,
								bool created = false);
			void			RemoveEntry(const char* name);

	inline	status_t		GetSnapshot(DirectoryCacheSnapshot** snapshot);

	inline	SinglyLinkedList<NameCacheEntry>&	EntriesList();

			status_t		Revalidate();

	inline  status_t		ValidateChangeInfo(uint64 change);
	inline  void			SetChangeInfo(uint64 change);
	inline	uint64			ChangeInfo();

	inline	Inode*			GetInode();

			void			Dump(void (*xprintf)(const char*, ...) = dprintf);

	const	bigtime_t		fExpirationTime;

protected:
			void			NotifyChanges(DirectoryCacheSnapshot* oldSnapshot,
								DirectoryCacheSnapshot* newSnapshot);

private:
			void			_SetSnapshot(DirectoryCacheSnapshot* snapshot);
			status_t		_LoadSnapshot(bool trash);

			void			_DumpLocked(void (*xprintf)(const char*, ...)) const;

			SinglyLinkedList<NameCacheEntry>	fNameCache;

			DirectoryCacheSnapshot*	fDirectoryCache;

			Inode*			fInode;

			bool			fAttrDir;
			bool			fTrashed;
			mutex			fLock;

			uint64			fChange;
			bigtime_t		fExpireTime;
};


inline void
DirectoryCache::Lock()
{
	mutex_lock(&fLock);
}


inline void
DirectoryCache::Unlock()
{
	mutex_unlock(&fLock);
}


inline bool
DirectoryCache::Valid()
{
	return !fTrashed;
}


inline status_t
DirectoryCache::GetSnapshot(DirectoryCacheSnapshot** snapshot)
{
	ASSERT(snapshot != NULL);

	status_t result = B_OK;
	if (fDirectoryCache == NULL)
		result = _LoadSnapshot(false);
	*snapshot = fDirectoryCache;
	return result;
}


inline SinglyLinkedList<NameCacheEntry>&
DirectoryCache::EntriesList()
{
	return fNameCache;
}


inline status_t
DirectoryCache::ValidateChangeInfo(uint64 change)
{
	if (fTrashed || change != fChange) {
		Trash();
		fChange = change;
		fExpireTime = system_time() + fExpirationTime;
		fTrashed = false;

		return B_ERROR;
	}

	return B_OK;
}


inline void
DirectoryCache::SetChangeInfo(uint64 change)
{
	fExpireTime = system_time() + fExpirationTime;
	fChange = change;
}


inline uint64
DirectoryCache::ChangeInfo()
{
	return fChange;
}


inline Inode*
DirectoryCache::GetInode()
{
	return fInode;
}


#endif	// DIRECTORYCACHE_H