1/* DBKFreeNodesPage.m 2 * 3 * Copyright (C) 2005-2010 Free Software Foundation, Inc. 4 * 5 * Author: Enrico Sersale <enrico@imago.ro> 6 * Date: June 2005 7 * 8 * This file is part of the GNUstep GWorkspace application 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA. 23 */ 24 25#include "DBKFreeNodesPage.h" 26#include "DBKBTree.h" 27#include "DBKBTreeNode.h" 28#include "DBKFixLenRecordsFile.h" 29 30@implementation DBKFreeNodesPage 31 32- (void)dealloc 33{ 34 RELEASE (pageData); 35 RELEASE (file); 36 37 [super dealloc]; 38} 39 40- (id)initInTree:(DBKBTree *)atree 41 withFile:(DBKFixLenRecordsFile *)afile 42 atOffset:(unsigned long)ofst 43 length:(unsigned)len 44{ 45 self = [super init]; 46 47 if (self) { 48 pageData = [[NSMutableData alloc] initWithCapacity: 1]; 49 50 tree = atree; 51 ASSIGN (file, afile); 52 53 firstOffset = ofst; 54 currOffset = ofst; 55 dlength = len; 56 57 llen = sizeof(unsigned long); 58 headlen = llen * 4; 59 60 [self gotoLastValidPage]; 61 } 62 63 return self; 64} 65 66- (void)gotoLastValidPage 67{ 68 CREATE_AUTORELEASE_POOL (pool); 69 NSData *data; 70 unsigned long count; 71 72 currOffset = firstOffset; 73 nextOffset = firstOffset; 74 data = nil; 75 76 while (nextOffset != 0) { 77 data = [self dataOfPageAtOffset: nextOffset]; 78 [self getOffsetsFromData: data]; 79 } 80 81 if ((nodesCount == 0) && (currOffset != firstOffset)) { 82 while (nodesCount == 0) { 83 data = [self dataOfPageAtOffset: prevOffset]; 84 [self getOffsetsFromData: data]; 85 86 if (currOffset == firstOffset) { 87 break; 88 } 89 } 90 } 91 92 [pageData setLength: 0]; 93 [pageData appendData: data]; 94 95 count = (nodesCount > 0) ? (nodesCount - 1) : nodesCount; 96 lastNodeRange = NSMakeRange(headlen + (count * llen), llen); 97 98 RELEASE (pool); 99} 100 101- (NSData *)dataOfPageAtOffset:(unsigned long)offset 102{ 103 return [file dataOfLength: dlength 104 atOffset: [NSNumber numberWithUnsignedLong: offset]]; 105} 106 107- (void)getOffsetsFromData:(NSData *)data 108{ 109 [data getBytes: &currOffset range: NSMakeRange(0, llen)]; 110 [data getBytes: &prevOffset range: NSMakeRange(llen, llen)]; 111 [data getBytes: &nextOffset range: NSMakeRange(llen * 2, llen)]; 112 [data getBytes: &nodesCount range: NSMakeRange(llen * 3, llen)]; 113} 114 115- (void)writeCurrentPage 116{ 117 CREATE_AUTORELEASE_POOL (pool); 118 NSData *data = [pageData copy]; 119 120 [file writeData: data 121 atOffset: [NSNumber numberWithUnsignedLong: currOffset]]; 122 123 RELEASE (data); 124 RELEASE (pool); 125} 126 127- (void)addFreeOffset:(unsigned long)offset 128{ 129 CREATE_AUTORELEASE_POOL (arp); 130 unsigned long nodeofs; 131 132 [pageData getBytes: &nodeofs range: lastNodeRange]; 133 134 if (nodeofs != 0) { 135 lastNodeRange.location += llen; 136 } 137 138 if (lastNodeRange.location == dlength) { 139 NSData *data; 140 141 if (nextOffset == 0) { 142 nextOffset = [tree offsetForFreeNodesPage]; 143 [pageData replaceBytesInRange: NSMakeRange(llen * 2, llen) 144 withBytes: &nextOffset]; 145 } 146 147 [self writeCurrentPage]; 148 149 data = [self dataOfPageAtOffset: nextOffset]; 150 [self getOffsetsFromData: data]; 151 152 [pageData setLength: 0]; 153 [pageData appendData: data]; 154 155 lastNodeRange.location = headlen; 156 } 157 158 [pageData replaceBytesInRange: lastNodeRange withBytes: &offset]; 159 nodesCount++; 160 [pageData replaceBytesInRange: NSMakeRange(llen * 3, llen) 161 withBytes: &nodesCount]; 162 163 RELEASE (arp); 164} 165 166- (unsigned long)getFreeOffset 167{ 168 unsigned long offset = 0; 169 170 if (nodesCount > 0) { 171 CREATE_AUTORELEASE_POOL (arp); 172 173 [pageData getBytes: &offset range: lastNodeRange]; 174 [pageData resetBytesInRange: lastNodeRange]; 175 176 nodesCount--; 177 [pageData replaceBytesInRange: NSMakeRange(llen * 3, llen) 178 withBytes: &nodesCount]; 179 180 lastNodeRange.location -= llen; 181 182 if (nodesCount == 0) { 183 if (currOffset != firstOffset) { 184 NSData *data; 185 unsigned long count; 186 187 [self writeCurrentPage]; 188 189 data = [self dataOfPageAtOffset: prevOffset]; 190 [self getOffsetsFromData: data]; 191 192 count = (nodesCount > 0) ? (nodesCount - 1) : nodesCount; 193 lastNodeRange = NSMakeRange(headlen + (count * llen), llen); 194 195 [pageData setLength: 0]; 196 [pageData appendData: data]; 197 198 } else { 199 lastNodeRange.location = headlen; 200 } 201 } 202 203 RELEASE (arp); 204 } 205 206 return offset; 207} 208 209- (unsigned long)currentPageOffset 210{ 211 return currOffset; 212} 213 214- (unsigned long)previousPageOffset 215{ 216 return prevOffset; 217} 218 219- (unsigned long)nextPageOffset 220{ 221 return nextOffset; 222} 223 224@end 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253