1 using System;
  2 using System.Collections;
  3 using cmsx.util;
  4 
  5 namespace cmsx.kernel
  6 {
  7     public const int blockSize = 4096;
  8     public const int numBitsInBitmapBlock = blockSize * 8;
  9     public const int numULongsInBitmapBlock = blockSize / 8;
 10     public const int numBlockNumbersInBlock = blockSize / 4;
 11     public const int invalidBlockNumber = 0;
 12     public const int maxCachedBlocks = 1024;
 13     public const int nameMax = 252;
 14 
 15     public class BlockKey
 16     {
 17         public nothrow BlockKey() : blockNumber(-1)fsNumber(-1)
 18         {
 19         }
 20         public nothrow BlockKey(int blockNumber_int fsNumber_) : blockNumber(blockNumber_)fsNumber(fsNumber_)
 21         {
 22         }
 23         public nothrow string ToString() const
 24         {
 25             string s;
 26             s.Append("block.").Append(ToString(fsNumber)).Append('.').Append(ToString(blockNumber));
 27             return s;
 28         }
 29         public int blockNumber;
 30         public int fsNumber;
 31     }
 32 
 33     public nothrow bool operator==(const BlockKey& leftconst BlockKey& right)
 34     {
 35         return left.blockNumber == right.blockNumber && left.fsNumber == right.fsNumber;
 36     }
 37 
 38     public class BlockKeyHash : UnaryFun<BlockKeyulong>
 39     {
 40         public inline nothrow ulong operator()(const BlockKey& key) const
 41         {
 42             return cast<ulong>(1099511628211 * key.fsNumber + key.blockNumber);
 43         }
 44     }
 45 
 46     public class Block
 47     {
 48         public enum Flags : byte
 49         {
 50             none = 0u
 51             locked = 1u << 0u
 52             valid = 1u << 1u
 53             dirty = 1u << 2u
 54             old = 1u << 3u
 55         }
 56         public nothrow string BlockFlagStr(Flags flags)
 57         {
 58             string s = "flags";
 59             if ((flags & Flags.locked) != Flags.none)
 60             {
 61                 s.Append(".locked");
 62             }
 63             if ((flags & Flags.valid) != Flags.none)
 64             {
 65                 s.Append(".valid");
 66             }
 67             if ((flags & Flags.dirty) != Flags.none)
 68             {
 69                 s.Append(".dirty");
 70             }
 71             if ((flags & Flags.old) != Flags.none)
 72             {
 73                 s.Append(".old");
 74             }
 75             return s;
 76         }
 77         public nothrow Block(const BlockKey& key_BlockManager* manager_BlockCache* cache_) : key(key_)manager(manager_)cache(cache_)flags(Flags.none)iterator()owner(null)
 78         {
 79         }
 80         public inline nothrow cmsx.kernel.Process* Owner() const
 81         {
 82             return owner;
 83         }
 84         public inline nothrow void SetOwner(cmsx.kernel.Process* owner_)
 85         {
 86             owner = owner_;
 87         }
 88         public inline nothrow void ResetOwner()
 89         {
 90             owner = null;
 91         }
 92         public virtual default ~Block();
 93         public nothrow string ToString() const
 94         {
 95             string s;
 96             s.Append(key.ToString());
 97             s.Append('.').Append(BlockFlagStr(flags));
 98             return s;
 99         }
100         public nothrow void Read(MemoryReader& reader)
101         {
102             for (int i = 0; i < blockSize; ++i;)
103             {
104                 data[i] = reader.ReadByte();
105             }
106         }
107         public nothrow void Write(MemoryWriter& writer)
108         {
109             for (int i = 0; i < blockSize; ++i;)
110             {
111                 writer.Write(data[i]);
112             }
113             ResetFlag(Flags.dirty);
114         }
115         public nothrow void Clear()
116         {
117             for (int i = 0; i < data.Length(); ++i;)
118             {
119                 data[i] = 0u;
120             }
121             SetFlag(Flags.dirty);
122         }
123         public inline nothrow bool GetFlag(Flags flag) const
124         {
125             return (flags & flag) != Flags.none;
126         }
127         public inline nothrow void SetFlag(Flags flag)
128         {
129             flags = cast<Flags>(flags | flag);
130             if (flag == Flags.dirty)
131             {
132                 cache->AddDirtyBlock(this);
133             }
134         }
135         public inline nothrow void ResetFlag(Flags flag)
136         {
137             flags = cast<Flags>(flags & ~flag);
138         }
139         public inline nothrow void ResetFlags()
140         {
141             flags = Flags.none;
142         }
143         public inline nothrow BlockKey& Key() const
144         {
145             return key;
146         }
147         public nothrow void SetKey(const BlockKey& key_)
148         {
149             key = key_;
150         }
151         public void AddWaitingProcess(cmsx.kernel.Process* process)
152         {
153             waitingProcesses.Add(process);
154         }
155         public nothrow List<cmsx.kernel.Process*> GetWaitingProcesses()
156         {
157             List<cmsx.kernel.Process*> processes;
158             Swap(processeswaitingProcesses);
159             return processes;
160         }
161         public nothrow LinkedList<Block*>.Iterator GetIterator() const
162         {
163             return iterator;
164         }
165         public nothrow void SetIterator(LinkedList<Block*>.Iterator iterator_)
166         {
167             iterator = iterator_;
168         }
169         public inline nothrow BlockManager* Manager()
170         {
171             return manager;
172         }
173         public byte[blockSize] data;
174         private BlockKey key;
175         private BlockManager* manager;
176         private BlockCache* cache;
177         private Flags flags;
178         private List<cmsx.kernel.Process*> waitingProcesses;
179         private LinkedList<Block*>.Iterator iterator;
180         private cmsx.kernel.Process* owner;
181     }
182 
183     public class SuperBlock : Block
184     {
185         public nothrow SuperBlock(BlockManager* manager_BlockCache* cache_) : base(BlockKey(00)manager_cache_)
186         {
187         }
188         public nothrow int GetFirstINodeBitmapBlockNumber() const
189         {
190             MemoryReader reader(&data[firstINodeBitmapBlockNumberOffset]4);
191             return reader.ReadInt();
192         }
193         public nothrow void SetFirstINodeBitmapBlockNumber(int firstINodeBitmapBlockNumber)
194         {
195             MemoryWriter writer(&data[firstINodeBitmapBlockNumberOffset]4);
196             writer.Write(firstINodeBitmapBlockNumber);
197             SetFlag(Block.Flags.dirty);
198         }
199         public nothrow int GetNumINodeBitmapBlocks() const
200         {
201             MemoryReader reader(&data[numINodeBitmapBlocksOffset]4);
202             return reader.ReadInt();
203         }
204         public nothrow void SetNumINodeBitmapBlocks(int numINodeBitmapBlocks)
205         {
206             MemoryWriter writer(&data[numINodeBitmapBlocksOffset]4);
207             writer.Write(numINodeBitmapBlocks);
208             SetFlag(Block.Flags.dirty);
209         }
210         public nothrow int GetFirstBlockBitmapBlockNumber() const
211         {
212             MemoryReader reader(&data[firstBlockBitmapBlockNumberOffset]4);
213             return reader.ReadInt();
214         }
215         public nothrow void SetFirstBlockBitmapBlockNumber(int firstBlockBitmapBlockNumber)
216         {
217             MemoryWriter writer(&data[firstBlockBitmapBlockNumberOffset]4);
218             writer.Write(firstBlockBitmapBlockNumber);
219             SetFlag(Block.Flags.dirty);
220         }
221         public nothrow int GetNumBlockBitmapBlocks() const
222         {
223             MemoryReader reader(&data[numBlockBitmapBlocksOffset]4);
224             return reader.ReadInt();
225         }
226         public nothrow void SetNumBlockBitmapBlocks(int numBlockBitmapBlocks)
227         {
228             MemoryWriter writer(&data[numBlockBitmapBlocksOffset]4);
229             writer.Write(numBlockBitmapBlocks);
230             SetFlag(Block.Flags.dirty);
231         }
232         public nothrow int GetFirstINodeBlockNumber() const
233         {
234             MemoryReader reader(&data[firstINodeBlockNumberOffset]4);
235             return reader.ReadInt();
236         }
237         public nothrow void SetFirstINodeBlockNumber(int firstINodeBlockNumber)
238         {
239             MemoryWriter writer(&data[firstINodeBlockNumberOffset]4);
240             writer.Write(firstINodeBlockNumber);
241             SetFlag(Block.Flags.dirty);
242         }
243         public nothrow int GetNumINodeBlocks() const
244         {
245             MemoryReader reader(&data[numINodeBlocksOffset]4);
246             return reader.ReadInt();
247         }
248         public nothrow void SetNumINodeBlocks(int numINodeBlocks)
249         {
250             MemoryWriter writer(&data[numINodeBlocksOffset]4);
251             writer.Write(numINodeBlocks);
252             SetFlag(Block.Flags.dirty);
253         }
254         public nothrow int GetFirstDataBlockNumber() const
255         {
256             MemoryReader reader(&data[firstDataBlockNumberOffset]4);
257             return reader.ReadInt();
258         }
259         public nothrow void SetFirstDataBlockNumber(int firstDataBlockNumber)
260         {
261             MemoryWriter writer(&data[firstDataBlockNumberOffset]4);
262             writer.Write(firstDataBlockNumber);
263             SetFlag(Block.Flags.dirty);
264         }
265         public nothrow int GetRootDirINodeNumber() const
266         {
267             MemoryReader reader(&data[rootDirINodeNumberOffset]4);
268             return reader.ReadInt();
269         }
270         public nothrow void SetRootDirINodeNumber(int rootDirINodeNumber)
271         {
272             MemoryWriter writer(&data[rootDirINodeNumberOffset]4);
273             writer.Write(rootDirINodeNumber);
274             SetFlag(Block.Flags.dirty);
275         }
276         public nothrow int GetLastBlockNumber() const
277         {
278             MemoryReader reader(&data[lastBlockNumberOffset]4);
279             return reader.ReadInt();
280         }
281         public nothrow void SetLastBlockNumber(int lastBlockNumber)
282         {
283             MemoryWriter writer(&data[lastBlockNumberOffset]4);
284             writer.Write(lastBlockNumber);
285             SetFlag(Block.Flags.dirty);
286         }
287         private const int firstINodeBitmapBlockNumberOffset = 4 * 0;
288         private const int numINodeBitmapBlocksOffset = 4 * 1;
289         private const int firstBlockBitmapBlockNumberOffset = 4 * 2;
290         private const int numBlockBitmapBlocksOffset = 4 * 3;
291         private const int firstINodeBlockNumberOffset = 4 * 4;
292         private const int numINodeBlocksOffset = 4 * 5;
293         private const int firstDataBlockNumberOffset = 4 * 6;
294         private const int rootDirINodeNumberOffset = 4 * 7;
295         private const int lastBlockNumberOffset = 4 * 8;
296     }
297 
298     public class BitmapBlock : Block
299     {
300         public nothrow BitmapBlock(BlockManager* manager_BlockCache* cache_) : base(BlockKey(00)manager_cache_)
301         {
302         }
303         public nothrow ulong GetBitChunk(int i) const
304         {
305             MemoryReader reader(&data[i * 8]8);
306             return reader.ReadULong();
307         }
308         public nothrow void SetBitChunk(int iulong chunk)
309         {
310             MemoryWriter writer(&data[i * 8]8);
311             writer.Write(chunk);
312             SetFlag(Flags.dirty);
313         }
314         public nothrow int GetFirstZeroBitIndex() const
315         {
316             long n = numULongsInBitmapBlock;
317             for (long i = 0; i < n; ++i;)
318             {
319                 ulong chunk = GetBitChunk(cast<int>(i));
320                 if (chunk != MaxValue<ulong>())
321                 {
322                     for (byte j = 0u; j < 64u; ++j;)
323                     {
324                         if ((chunk & (cast<ulong>(1u) << j)) == 0u)
325                         {
326                             return cast<int>(i) * 64 + j;
327                         }
328                     }
329                 }
330             }
331             return -1;
332         }
333         public nothrow bool GetBit(int index) const
334         {
335             int i = index / 64;
336             byte j = cast<byte>(index % 64);
337             ulong chunk = GetBitChunk(i);
338             return (chunk & (cast<ulong>(1u) << j)) != 0u;
339         }
340         public nothrow void SetBit(int index)
341         {
342             int i = index / 64;
343             byte j = cast<byte>(index % 64);
344             ulong chunk = GetBitChunk(i);
345             chunk = chunk | (cast<ulong>(1u) << j);
346             SetBitChunk(ichunk);
347             SetFlag(Flags.dirty);
348         }
349         public nothrow void ResetBit(int index)
350         {
351             int i = index / 64;
352             byte j = cast<byte>(index % 64);
353             ulong chunk = GetBitChunk(i);
354             chunk = chunk & ~(cast<ulong>(1u) << j);
355             SetBitChunk(ichunk);
356             SetFlag(Flags.dirty);
357         }
358     }
359 
360     public class BlockNumberBlock : Block
361     {
362         public nothrow BlockNumberBlock(BlockManager* manager_BlockCache* cache_) : base(BlockKey(00)manager_cache_)
363         {
364         }
365         public nothrow int GetBlockNumber(int index) const
366         {
367             #assert(index >= 0 && index < numBlockNumbersInBlock);
368             MemoryReader reader(&data[index * 4]4);
369             return reader.ReadInt();
370         }
371         public nothrow void SetBlockNumber(int indexint blockNumber)
372         {
373             #assert(index >= 0 && index < numBlockNumbersInBlock);
374             MemoryWriter writer(&data[index * 4]4);
375             writer.Write(blockNumber);
376             SetFlag(Block.Flags.dirty);
377         }
378     }
379 
380     public class FileBlock : Block
381     {
382         public nothrow FileBlock(BlockManager* manager_BlockCache* cache_) : base(BlockKey(00)manager_cache_)
383         {
384         }
385         public inline nothrow byte GetByte(long index) const
386         {
387             return data[index];
388         }
389         public inline nothrow void SetByte(long indexbyte x)
390         {
391             data[index] = x;
392         }
393     }
394 
395     public class DirectoryEntry
396     {
397         public nothrow DirectoryEntry(int inodeNumber_const string& name_) : inodeNumber(inodeNumber_)name(name_)
398         {
399             #assert(name.Length() < nameMax);
400         }
401         public void Read(MemoryReader& reader)
402         {
403             inodeNumber = reader.ReadInt();
404             name = reader.ReadString();
405         }
406         public void Write(MemoryWriter& writer)
407         {
408             writer.Write(inodeNumber);
409             writer.Write(name);
410         }
411         public int inodeNumber;
412         public string name;
413     }
414 
415     public const int directoryEntrySize = 4 + nameMax;
416     public const int numDirectoryEntriesInBlock = blockSize / directoryEntrySize;
417 
418     public class DirectorySlot
419     {
420         public nothrow DirectorySlot() : blockNumber(invalidBlockNumber)fsNumber(0)offset(-1)
421         {
422         }
423         public nothrow DirectorySlot(int blockNumber_int fsNumber_long offset_) : blockNumber(blockNumber_)fsNumber(fsNumber_)offset(offset_)
424         {
425         }
426         public int blockNumber;
427         public int fsNumber;
428         public long offset;
429     }
430 
431     public class DirectoryBlock : Block
432     {
433         public nothrow DirectoryBlock(BlockManager* manager_BlockCache* cache_) : base(BlockKey(00)manager_cache_)
434         {
435         }
436         public nothrow DirectoryEntry GetDirectoryEntry(int index) const
437         {
438             #assert(index >= 0 && index < numDirectoryEntriesInBlock);
439             DirectoryEntry entry;
440             MemoryReader reader(&data[index * directoryEntrySize]directoryEntrySize);
441             entry.Read(reader);
442             return entry;
443         }
444         public nothrow void SetDirectoryEntry(int indexconst DirectoryEntry& entry)
445         {
446             #assert(index >= 0 && index < numDirectoryEntriesInBlock);
447             MemoryWriter writer(&data[index * directoryEntrySize]directoryEntrySize);
448             entry.Write(writer);
449         }
450     }
451 
452     public const int inodeSize = 128;
453     public const int numINodesInBlock = blockSize / inodeSize;
454 
455     public class INodeBlock : Block
456     {
457         public nothrow INodeBlock(BlockManager* manager_BlockCache* cache_) : base(BlockKey(00)manager_cache_)
458         {
459         }
460         public nothrow INode GetINode(int index) const
461         {
462             #assert(index >= 0 && index < numINodesInBlock);
463             INode inode;
464             MemoryReader reader(&data[index * inodeSize]inodeSize);
465             inode.Read(reader);
466             return inode;
467         }
468         public nothrow void SetINode(int indexconst INode& inode) const
469         {
470             #assert(index >= 0 && index < numINodesInBlock);
471             MemoryWriter writer(&data[index * inodeSize]inodeSize);
472             inode.Write(writer);
473         }
474     }
475 
476     public class BlockPutter
477     {
478         public nothrow BlockPutter() : block(null)
479         {
480         }
481         public nothrow BlockPutter(Block* block_) : block(block_)
482         {
483         }
484         public nothrow void Reset(Block* block_)
485         {
486             if (block != block_)
487             {
488                 if (block != null)
489                 {
490                     block->Manager()->PutBlock(block);
491                 }
492                 block = block_;
493             }
494         }
495         public nothrow Block* Release()
496         {
497             Block* result = block;
498             block = null;
499             return result;
500         }
501         public ~BlockPutter()
502         {
503             if (block != null)
504             {
505                 block->Manager()->PutBlock(block);
506             }
507         }
508         private Block* block;
509     }
510 }