-
Notifications
You must be signed in to change notification settings - Fork 1
/
Inode.java
217 lines (204 loc) · 6.7 KB
/
Inode.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
* @file Inode.java
* @brief Inode contains all the pertinent information for each file on disk.
* A flag system is used to indicate what 'mode' the Inode is in, and
* direct/indirect block pointers are used to direct rawread/rawwrite commands
* to the correct diskBlock.
* @author Chris Grass
* @date December 14, 2012
*/
public class Inode {
public final static int iNodeSize = 32; // fixed to 32 bytes
public final static int directSize = 11; // # direct pointers
public int length; // file size in bytes
public short count; // # file-table entries pointing to this
public short flag; // how is this file (inode) being used?
public short direct[] = new short[directSize]; // direct pointers
public short indirect; // an indirect pointer
private short nextIndirectPointer; //count of indirect pointers
Inode () { // a default constructor (new file)
length = 0; // number of bytes in file
count = 0; // number of threads pointing to file
flag = 1; //Flag Modes:
for ( int i = 0; i < directSize; i++ ) //-1 = ready for deletion
direct[i] = -1; //0 = not in use
indirect = -1; //1 = in use
//2 = thread currently reading
//3 = thread currently writing
}
/**
* Overloaded Constructor
* @param iNumber represents iNumber of inode being read from disk .
* @pre .
* @post .
* retrieves inode(iNumber) from disk and loads to memory. saves Inode data
*/
Inode ( short iNumber ) {
int blkNumber = iNumber / 16 + 1; //determines block# on disk
byte[] data = new byte[Disk.blockSize];
SysLib.rawread( blkNumber, data ); //read block corresponding to iNumber
int offset = ( iNumber % 16 ) * iNodeSize;
length = SysLib.bytes2int( data, offset );
offset += 4;
count = SysLib.bytes2short( data, offset );
offset += 2;
flag = SysLib.bytes2short( data, offset );
offset += 2;
for ( int i = 0; i < directSize; i++ ) {
direct[i] = SysLib.bytes2short( data, offset );
offset += 2;
}
indirect = SysLib.bytes2short( data, offset );
if(length/512-11 > 0)
nextIndirectPointer = (short) (length/512-11);
else
nextIndirectPointer = 0;
}
/**
* toDisk
* @param iNumber represents iNumber to be written to disk .
* @pre .
* @post .
* writes an iNode to disk
*/
public void toDisk(short iNumber){
int blkNumber = iNumber / 16 + 1; //determines block# on disk
int offset = ( iNumber % 16 ) * iNodeSize;
//byte[] iNodeData = new byte[iNodeSize]; //allocate block for data
byte[] originalData = new byte[Disk.blockSize];
SysLib.rawread( blkNumber, originalData ); //read original block
SysLib.int2bytes(length, originalData, offset); //write length
offset +=4;
SysLib.short2bytes(count, originalData, offset); //write count
offset +=2;
SysLib.short2bytes(flag, originalData, offset); //write flag
offset +=2;
for ( int i = 0; i < directSize; i++ ) { //write direct pointers
SysLib.short2bytes( direct[i],originalData, offset );
offset +=2;
}
SysLib.short2bytes(indirect, originalData, offset); //write indirect pointer
SysLib.rawwrite(blkNumber, originalData); //write data to disk
}
/**
* findIndexBlock
* @param .
* @pre .
* @post .
* @return indirect block number
*/
int findIndexBlock(){
return indirect;
}
/**
* registerIndexBlock
* @param short indexBlockNumber .
* @pre .
* @post .
* sets indirect block number to param
*/
boolean registerIndexBlock( short indexBlockNumber ){
indirect = indexBlockNumber;
nextIndirectPointer = 0;
return true;
}
/**
* findTargetBlock
* @param int offset .
* @pre .
* @post .
* @return int pointer to targetBlock
* in this context, offset will be byte index location in file.
* TargetBlock = offset/512. If TargetBlock > 11, we must look in indirect
* block for byte info.
*/
int findTargetBlock( int offset ){
int targetBlock = offset/512;
if (targetBlock<11){
if (direct[targetBlock] < 0)
return -1;
else
return direct[targetBlock];
}
else //look in indirect
if(indirect == -1)
return -1;
else
return scanIndirect(offset);
}
/**
* registerTargetBlock
* @param int numBytes, short targetBlockNumber .
* @pre .
* @post .
* @return returns 0 on success, -1 on failure
*
*/
int registerTargetBlock( int numBytes, short targetBlockNumber){
//if beyond maxFileSize or beyond totalBlocks
if (targetBlockNumber > 1000 || numBytes > 512*11 + 512 * 256)
return -1;
for (int i =0; i<11;i++){
if (direct[i] < 0){
direct[i]=targetBlockNumber;
return 0;
}
}
//if beyond direct blocks, write to indirect block
writeIndirect(targetBlockNumber);
return 0;
}
/**
* unregisterIndexBlock
* @param .
* @pre .
* @post .
* @return byte array of block info stored in indirect.
*/
byte[] unregisterIndexBlock(){
byte[] indirectArray = new byte[512];
SysLib.rawread(indirect,indirectArray);
for (int i = 0; i < 512; i++){
indirectArray[i] = 0;
}
nextIndirectPointer = 0;
return indirectArray;
}
/**
* scanIndirect
* @param int offset .
* @pre .
* @post .
* @return Block information related to direct pointer
* inside indirect pointer
* Finds block information by scanning through index block
* for appropriate offset. Offset/blockSize*shortSize = location. Read in
* that location data and return int representing blockNum.
*/
private int scanIndirect(int offset){
int targetBlock = -1;
byte directLoc = (byte) ((offset/512-11)*2); //determine loc in indirectArray
//if out of current range
if(offset>=length)
return -1;
byte[] indirectArray = new byte[512];
SysLib.rawread(indirect, indirectArray); //read inderectArray
targetBlock = indirectArray[directLoc+1]; //find directBlock data
return targetBlock;
}
/**
* writeIndirect
* @param short targetBlockNum .
* @pre .
* @post .
* Writes block information by writing to next free block. Increment
* nextIndirectPointer variable.
*/
private void writeIndirect(short targetBlockNum){
byte[] indirectArray = new byte[512];
SysLib.rawread(indirect, indirectArray); //read inderectArray
SysLib.short2bytes(targetBlockNum, indirectArray, (int) nextIndirectPointer*2);
SysLib.rawwrite(indirect, indirectArray);
nextIndirectPointer++;
}
}