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