xref: /haiku/src/add-ons/kernel/file_systems/packagefs/package/CachedDataReader.h (revision 37fedaf8494b34aad811abcc49e79aa32943f880)
1 /*
2  * Copyright 2013, Ingo Weinhold, ingo_weinhold@gmx.de.
3  * Distributed under the terms of the MIT License.
4  */
5 #ifndef HEAP_CACHE_H
6 #define HEAP_CACHE_H
7 
8 
9 #include <package/hpkg/DataReader.h>
10 
11 #include <condition_variable.h>
12 #include <util/DoublyLinkedList.h>
13 #include <util/OpenHashTable.h>
14 #include <vm/vm_types.h>
15 
16 
17 using BPackageKit::BHPKG::BAbstractBufferedDataReader;
18 using BPackageKit::BHPKG::BDataReader;
19 
20 
21 class BDataIO;
22 
23 
24 class CachedDataReader : public BAbstractBufferedDataReader {
25 public:
26 								CachedDataReader();
27 	virtual						~CachedDataReader();
28 
29 			status_t			Init(BAbstractBufferedDataReader* reader,
30 									off_t size);
31 
32 	virtual	status_t			ReadData(off_t offset, void* buffer,
33 									size_t size);
34 	virtual	status_t			ReadDataToOutput(off_t offset, size_t size,
35 									BDataIO* output);
36 
37 private:
38 			class CacheLineLocker
39 				: public DoublyLinkedListLinkImpl<CacheLineLocker> {
40 			public:
41 				CacheLineLocker(CachedDataReader* reader, off_t cacheLineOffset)
42 					:
43 					fReader(reader),
44 					fOffset(cacheLineOffset)
45 				{
46 					fReader->_LockCacheLine(this);
47 				}
48 
49 				~CacheLineLocker()
50 				{
51 					fReader->_UnlockCacheLine(this);
52 				}
53 
54 				off_t Offset() const
55 				{
56 					return fOffset;
57 				}
58 
59 				CacheLineLocker*& HashNext()
60 				{
61 					return fHashNext;
62 				}
63 
64 				DoublyLinkedList<CacheLineLocker>& Queue()
65 				{
66 					return fQueue;
67 				}
68 
69 				void Wait(mutex& lock)
70 				{
71 					fWaitCondition.Init(this, "cached reader line locker");
72 					ConditionVariableEntry waitEntry;
73 					fWaitCondition.Add(&waitEntry);
74 					mutex_unlock(&lock);
75 					waitEntry.Wait();
76 					mutex_lock(&lock);
77 				}
78 
79 				void WakeUp()
80 				{
81 					fWaitCondition.NotifyOne();
82 				}
83 
84 			private:
85 				CachedDataReader*					fReader;
86 				off_t								fOffset;
87 				CacheLineLocker*					fHashNext;
88 				DoublyLinkedList<CacheLineLocker>	fQueue;
89 				ConditionVariable					fWaitCondition;
90 			};
91 
92 			friend class CacheLineLocker;
93 
94 			struct LockerHashDefinition {
95 				typedef off_t			KeyType;
96 				typedef	CacheLineLocker	ValueType;
97 
98 				size_t HashKey(off_t key) const
99 				{
100 					return size_t(key / kCacheLineSize);
101 				}
102 
103 				size_t Hash(const CacheLineLocker* value) const
104 				{
105 					return HashKey(value->Offset());
106 				}
107 
108 				bool Compare(off_t key, const CacheLineLocker* value) const
109 				{
110 					return value->Offset() == key;
111 				}
112 
113 				CacheLineLocker*& GetLink(CacheLineLocker* value) const
114 				{
115 					return value->HashNext();
116 				}
117 			};
118 
119 			typedef BOpenHashTable<LockerHashDefinition> LockerTable;
120 
121 			struct PagesDataOutput;
122 
123 private:
124 			status_t			_ReadCacheLine(off_t lineOffset,
125 									size_t lineSize, off_t requestOffset,
126 							 		size_t requestLength, BDataIO* output);
127 
128 			void				_DiscardPages(vm_page** pages, size_t firstPage,
129 									size_t pageCount);
130 			void				_CachePages(vm_page** pages, size_t firstPage,
131 									size_t pageCount);
132 			status_t			_WritePages(vm_page** pages,
133 									size_t pagesRelativeOffset,
134 									size_t requestLength, BDataIO* output);
135 			status_t			_ReadIntoPages(vm_page** pages,
136 									size_t firstPage, size_t pageCount);
137 
138 			void				_LockCacheLine(CacheLineLocker* lineLocker);
139 			void				_UnlockCacheLine(CacheLineLocker* lineLocker);
140 
141 private:
142 			static const size_t kCacheLineSize = 64 * 1024;
143 			static const size_t kPagesPerCacheLine
144 				= kCacheLineSize / B_PAGE_SIZE;
145 
146 private:
147 			mutex				fLock;
148 			BAbstractBufferedDataReader* fReader;
149 			VMCache*			fCache;
150 			LockerTable			fCacheLineLockers;
151 };
152 
153 
154 #endif	// HEAP_CACHE_H
155