@@ -57,31 +57,28 @@ uint8_t *OrbisFSFile::getDataBlock(uint64_t num){
5757 retassure (_node->dataLnk [num].type == ORBIS_FS_CHAINLINK_TYPE_LINK, " bad dataLnk type 0x%02x" ,_node->dataLnk [num].type );
5858 return _parent->getBlock (_node->dataLnk [num].blk );
5959 }
60-
61- /*
62- Multistage lookup here
63- */
64- OrbisFSChainLink_t *fat = (OrbisFSChainLink_t*)_parent->getBlock (_node->dataLnk [0 ].blk );
65- if (_node->fatStages >= 3 ) {
66- retassure (_node->fatStages < 4 , " 4 level stage lookup not supported" );
67- /*
68- Stage 3 lookup
69- */
70- uint64_t stage3Idx = num / linkElemsPerPage;
71- retassure (stage3Idx < linkElemsPerPage, " Trying to access out of bounds block on stage 3 lookup" );
72- num %= linkElemsPerPage;
73- fat = &fat[stage3Idx];
74- retassure (fat->type == ORBIS_FS_CHAINLINK_TYPE_LINK, " bad dataLnk type 0x%02x in stage 3 lookup" ,fat->type );
75- fat = (OrbisFSChainLink_t*)_parent->getBlock (fat->blk );
76- }
7760
78- /*
79- Stage 2 lookup
80- */
81- retassure (num < linkElemsPerPage, " Trying to access out of bounds block on stage 3 lookup" );
82- fat = &fat[num];
83- retassure (fat->type == ORBIS_FS_CHAINLINK_TYPE_LINK, " bad fat type 0x%02x" ,fat->type );
84- return _parent->getBlock (fat->blk );
61+ OrbisFSChainLink_t *fat = NULL ;
62+ for (int i=_node->fatStages -1 ; i>=0 ; i--) {
63+ uint64_t elemsInThisStage = 1 ;
64+ for (int z=0 ; z<i; z++) elemsInThisStage *= linkElemsPerPage;
65+ uint32_t curIdx = (uint32_t )(num / elemsInThisStage);
66+ num %= elemsInThisStage;
67+
68+ if (!fat) {
69+ // this is the first level lookup
70+ retassure (curIdx < ARRAYOF (_node->dataLnk ), " 1 level lookup out of bounds" );
71+ retassure (_node->dataLnk [curIdx].type == ORBIS_FS_CHAINLINK_TYPE_LINK, " bad dataLnk type 0x%02x" ,_node->dataLnk [curIdx].type );
72+ fat = (OrbisFSChainLink_t*)_parent->getBlock (_node->dataLnk [curIdx].blk );
73+ }else {
74+ // this is further level lookup
75+ retassure (curIdx < linkElemsPerPage, " Trying to access out of bounds block on stage %d lookup" ,_node->fatStages -(i-1 ));
76+ fat = &fat[curIdx];
77+ retassure (fat->type == ORBIS_FS_CHAINLINK_TYPE_LINK, " bad fat type 0x%02x" ,fat->type );
78+ fat = (OrbisFSChainLink_t*)_parent->getBlock (fat->blk );
79+ }
80+ }
81+ return (uint8_t *)fat;
8582}
8683
8784uint8_t *OrbisFSFile::getDataForOffset (uint64_t offset){
@@ -105,14 +102,8 @@ std::vector<uint32_t> OrbisFSFile::getAllAllocatedBlocks(){
105102 ret.push_back (_node->dataLnk [i].blk );
106103 }
107104 }else if (_node->fatStages == 2 ){
108- retassure (_node->dataLnk [0 ].type == ORBIS_FS_CHAINLINK_TYPE_LINK, " bad dataLnk type 0x%02x" ,_node->dataLnk [0 ].type );
109- OrbisFSChainLink_t *fat = (OrbisFSChainLink_t*)_parent->getBlock (_node->dataLnk [0 ].blk );
110- ret.push_back (_node->dataLnk [0 ].blk );
111-
112- for (int i=0 ; i < linkElemsPerPage; i++) {
113- if (fat[i].type != ORBIS_FS_CHAINLINK_TYPE_LINK) break ;
114- ret.push_back (fat[i].blk );
115- }
105+ reterror (" TODO" );
106+
116107 }else if (_node->fatStages == 3 ){
117108
118109 reterror (" TODO" );
@@ -129,6 +120,105 @@ std::vector<uint32_t> OrbisFSFile::getAllAllocatedBlocks(){
129120 return ret;
130121}
131122
123+ void OrbisFSFile::popLastAllocatedBlock (){
124+ const uint32_t linkElemsPerPage = _blockSize/sizeof (OrbisFSChainLink_t);
125+ OrbisFSChainLink_t *tgt = NULL ;
126+ uint32_t curIdx = 0 ;
127+ int fatEndStage = 0 ;
128+ uint32_t usedResourceBlocks = 0 ;
129+
130+ for (int i=0 ; i<ARRAYOF (_node->resourceLnk ); i++) {
131+ if (_node->resourceLnk [i].type != ORBIS_FS_CHAINLINK_TYPE_LINK) break ;
132+ usedResourceBlocks++;
133+ }
134+
135+ if (!_node->fatStages ){
136+ reterror (" No stages available" );
137+ }else if (_node->fatStages == 1 ) {
138+ for (int i=ARRAYOF (_node->dataLnk )-1 ; i>=0 ; i--) {
139+ if (_node->dataLnk [i].type == ORBIS_FS_CHAINLINK_TYPE_LINK){
140+ tgt = &_node->dataLnk [i];
141+ if (i==0 ) _node->fatStages = 0 ;
142+ break ;
143+ }
144+ }
145+ }else {
146+ rePopBlock:
147+ retassure (_node->usedBlocks , " Why does this node not use any blocks??" );
148+ uint64_t num = _node->filesize / _blockSize;
149+ if ((_node->filesize & (_blockSize-1 )) == 0 ) num--; // num is actually blockIndex not blockNumber
150+
151+ OrbisFSChainLink_t *fat = NULL ;
152+ for (int i=_node->fatStages -1 ; i>=fatEndStage; i--) {
153+ uint64_t elemsInThisStage = 1 ;
154+ for (int z=0 ; z<i; z++) elemsInThisStage *= linkElemsPerPage;
155+ curIdx = (uint32_t )(num / elemsInThisStage);
156+ num %= elemsInThisStage;
157+
158+ if (!fat) {
159+ // this is the first level lookup
160+ retassure (curIdx < ARRAYOF (_node->dataLnk ), " 1 level lookup out of bounds" );
161+ tgt = &_node->dataLnk [curIdx];
162+ retassure (tgt->type == ORBIS_FS_CHAINLINK_TYPE_LINK, " bad dataLnk type 0x%02x" ,tgt->type );
163+ fat = (OrbisFSChainLink_t*)_parent->getBlock (tgt->blk );
164+ }else {
165+ // this is further level lookup
166+ retassure (curIdx < linkElemsPerPage, " Trying to access out of bounds block on stage %d lookup" ,_node->fatStages -(i-1 ));
167+ tgt = &fat[curIdx];
168+ retassure (tgt->type == ORBIS_FS_CHAINLINK_TYPE_LINK, " bad fat type 0x%02x" ,tgt->type );
169+ fat = (OrbisFSChainLink_t*)_parent->getBlock (tgt->blk );
170+ }
171+ }
172+ }
173+
174+ retassure (_node->fatStages < 4 , " 4 level stages currently not supported!" );
175+
176+ {
177+ uint32_t blk = tgt->blk ;
178+ memset (tgt, 0xFF , sizeof (*tgt));
179+ _parent->freeBlock (blk);
180+ _node->usedBlocks --;
181+ if (curIdx == 0 && (_node->fatStages -fatEndStage > 1 )) {
182+ fatEndStage++;
183+ goto rePopBlock;
184+ } else if (curIdx == 1 && (
185+ (_node->fatStages == 2 && _node->usedBlocks == 2 +usedResourceBlocks)
186+ || (_node->fatStages == 3 && _node->usedBlocks == linkElemsPerPage+2 +usedResourceBlocks)
187+ )){
188+ /*
189+ We are at fatStages>=2 but we can downgrage to fatStages>=1 here
190+ */
191+ retassure (_node->dataLnk [0 ].type == ORBIS_FS_CHAINLINK_TYPE_LINK, " unexpecte invalid dataLnk[0] when attepmting to downgrade fatStages 2 -> 1" );
192+ blk = _node->dataLnk [0 ].blk ;
193+ tgt = (OrbisFSChainLink_t*)_parent->getBlock (blk);
194+ retassure (tgt->type == ORBIS_FS_CHAINLINK_TYPE_LINK, " unexpecte invalid tgt when attepmting to downgrade fatStages 2 -> 1" );
195+ _node->dataLnk [0 ] = *tgt;
196+ _parent->freeBlock (blk);
197+ _node->usedBlocks --;
198+ _node->fatStages --;
199+ }
200+ }
201+ }
202+
203+ void OrbisFSFile::shrink (uint64_t subBytes){
204+ retassure (_node->filesize >= subBytes, " trying to shrink more bytes than available" );
205+ while (subBytes) {
206+ uint64_t lastBlockFill = _node->filesize & (_blockSize-1 );
207+ if (!lastBlockFill && _node->filesize >= _blockSize) lastBlockFill = _blockSize;
208+ if (subBytes >= lastBlockFill) {
209+ popLastAllocatedBlock ();
210+ }else {
211+ lastBlockFill = subBytes;
212+ }
213+ _node->filesize -= lastBlockFill;
214+ subBytes -= lastBlockFill;
215+ }
216+ }
217+
218+ void OrbisFSFile::grow (uint64_t addBytes){
219+ reterror (" TODO" );
220+ }
221+
132222#pragma mark OrbisFSFile public
133223#pragma mark IO operations
134224uint64_t OrbisFSFile::size (){
@@ -165,6 +255,14 @@ size_t OrbisFSFile::pwrite(const void *buf, size_t len, uint64_t offset){
165255 reterror (" TODO" );
166256}
167257
258+ void OrbisFSFile::resize (uint64_t size){
259+ if (size < _node->filesize ) {
260+ shrink (_node->filesize -size);
261+ }else if (size > _node->filesize ){
262+ grow (size-_node->filesize );
263+ }
264+ }
265+
168266#pragma mark resource IO
169267uint64_t OrbisFSFile::resource_size (){
170268 /*
0 commit comments