KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > core > storage > gammaStore > IndexLeafNode


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Core License version 1 published by ozone-db.org.
3
//
4
// Copyright (C) 2003-@year@, Leo Mekenkamp. All rights reserved.
5
//
6
// $Id: IndexLeafNode.java,v 1.3 2004/01/27 21:28:53 leomekenkamp Exp $
7

8 package org.ozoneDB.core.storage.gammaStore;
9
10 import java.io.IOException JavaDoc;
11 import java.io.ObjectInputStream JavaDoc;
12 import java.io.ObjectOutputStream JavaDoc;
13 import java.util.HashMap JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.logging.Level JavaDoc;
17 import org.ozoneDB.ObjectNotFoundException;
18 import org.ozoneDB.OzoneInternalException;
19
20 /**
21  * @author <a HREF="mailto:leoATmekenkampD0Tcom">Leo Mekenkamp (mind the anti sp@m)</a>
22  * @version $Id: IndexLeafNode.java,v 1.3 2004/01/27 21:28:53 leomekenkamp Exp $
23  */

24 final class IndexLeafNode extends IndexNode {
25
26     private static final long serialVersionUID = 0L;
27
28     private ContainerLocationLoc containerLocationLoc;
29     
30     IndexLeafNode(IndexManager indexManager) {
31         super(indexManager);
32         setMaxSize(indexManager.getMaxLeafNodeSize());
33         containerLocationLoc = new ContainerLocationLoc(getMaxSize(), 0);
34         setIndexManager(indexManager);
35     }
36     
37     private void rawPutContainerLocation(long objectId, ContainerLocation containerLocation) {
38 //if (objectId == 1690734402) log.severe("raw add " + objectId + " to indexLeafNode " + this);
39
long oldMinObjectId = MINOBJECTID;
40         if (size() > 0) {
41             oldMinObjectId = getMinObjectId();
42         }
43         int pos = getContainerLocationLoc().putKey(objectId);
44         getContainerLocationLoc().putContainerLocation(pos, containerLocation);
45
46         if (getParentNodeId() != LONGNULL && getMinObjectId() != oldMinObjectId) {
47             if (log.isLoggable(Level.FINE)) log.finest("informing parent " + getParentNodeId() + " our minimum changed to " + getMinObjectId());
48             IndexBranchNode p = getParentNode();
49             p.childMinObjectIdChanged(this, oldMinObjectId);
50             p.endInvoke();
51         }
52         setDirty();
53 //if (objectId == 1690734402) log.severe("raw just added " + objectId + " to indexLeafNode " + this);
54
}
55     
56     void putContainerLocation(long objectId, ContainerLocation containerLocation) {
57 //if (objectId == 1690734402) log.severe("about to add " + objectId + " to indexLeafNode " + this);
58
if (log.isLoggable(Level.FINE)) log.fine("put " + objectId + " in indexLeafNode " + getNodeId());
59         if (!isFull()) {
60             rawPutContainerLocation(objectId, containerLocation);
61         } else {
62             if (log.isLoggable(Level.FINEST)) log.finest("indexLeafNode " + getNodeId() + " is full; splitting up");
63             
64             // we are full but should store this object, so we are splitting
65
// this node into 2 nodes; putting it in the other node takes
66
// care of the case where the objectId is the newest created
67
// object id (the largest one of all)
68
split(objectId, containerLocation);
69         }
70         if (log.isLoggable(Level.FINER)) log.fine("ready putting " + objectId + " in indexLeafNode " + getNodeId());
71     }
72     
73     /**
74      * @throws ObjectNotFoundException when given id not found
75      */

76     ContainerLocation getContainerLocation(long objectId) {
77         int pos = getContainerLocationLoc().getKeyPos(objectId);
78         if (pos < 0) {
79             throw new ObjectNotFoundException("no such object id: " + objectId);
80         }
81         return getContainerLocationLoc().getContainerLocation(pos);
82     }
83     
84     boolean existsContainerLocation(long objectId) {
85         return getContainerLocationLoc().getKeyPos(objectId) >= 0;
86     }
87     
88     /**
89      * @throws ObjectNotFoundException when given id not found
90      */

91     ContainerLocation removeContainerLocation(long objectId) {
92
93 //if (objectId == 1690734402) log.severe("remove " + objectId + " from indexLeafNode " + this);
94
if (log.isLoggable(Level.FINE)) log.fine("remove " + objectId + " from indexLeafNode " + this);
95
96         int pos = getContainerLocationLoc().getKeyPos(objectId);
97         if (pos < 0) {
98             throw new ObjectNotFoundException("no such object id (" + objectId + ") found in indexLeafNode " + this);
99         }
100
101         // "Goodbye, cruel world; I'm leaving you today. Goodbye, goodbye, goodbye."
102
if (size() == 1) {
103             boolean hasSibling = false;
104             
105             if (getPrevNodeId() != LONGNULL) {
106                 IndexNode p = getPrevNode();
107                 p.setNextNodeId(getNextNodeId());
108                 p.endInvoke();
109                 hasSibling = true;
110             }
111             if (getNextNodeId() != LONGNULL) {
112                 IndexNode n = getNextNode();
113                 n.setPrevNodeId(getPrevNodeId());
114                 n.endInvoke();
115                 hasSibling = true;
116             } else if (hasSibling) {
117                 
118                 // have a prev, but no next, so this must be the newest
119
IndexLeafNode p = (IndexLeafNode) getPrevNode();
120                 getIndexManager().setNewestLeafNode(p);
121                 p.endInvoke();
122             }
123
124             // must ensure there is always one leaf node, if we have no siblings
125
// then we must be the last one, so we do not remove ourselves
126
if (hasSibling) {
127                 IndexBranchNode p = getParentNode();
128                 p.removeChildNode(this);
129                 p.endInvoke();
130
131                 // removes us from the index manager cache and deletes from
132
// storage
133
setIndexManager(null);
134             }
135         }
136         
137         long oldMinObjectId = getMinObjectId();
138         ContainerLocation result = getContainerLocationLoc().getContainerLocation(pos);
139         getContainerLocationLoc().removePos(pos);
140         
141         // if we have detached ourselves from our parent there is no need to
142
// inform our former parent that we have changed
143
if (getParentNodeId() != LONGNULL) {
144             long newMinObjectId = getMinObjectId();
145             if (oldMinObjectId != newMinObjectId) {
146                 IndexBranchNode p = getParentNode();
147                 p.childMinObjectIdChanged(this, oldMinObjectId);
148                 p.endInvoke();
149             }
150         }
151
152         setDirty();
153         
154         return result;
155     }
156     
157     protected int size() {
158         return getContainerLocationLoc().size();
159     }
160     
161     // private so it can be inlined
162
private ContainerLocationLoc getContainerLocationLoc() {
163         return containerLocationLoc;
164     }
165
166     /**
167      * Will enter in endless recursion if empty and next node is also empty;
168      * when a node becomes empty it will remove itself from the tree, so this is
169      * not a problem.
170      */

171     long getMaxObjectId() {
172         long result;
173         if (size() == 0) {
174             result = MINOBJECTID;
175         } else {
176             result = getContainerLocationLoc().getMaxKey();
177         }
178         return result;
179     }
180     
181     /**
182      */

183     long getMinObjectId() {
184         long result;
185         if (size() == 0) {
186             result = MINOBJECTID;
187         } else {
188             result = getContainerLocationLoc().getMinKey();
189         }
190         return result;
191     }
192
193     /**
194      * Splits this instance into two nodes; the specified id is used to find
195      * out which container locations should remain in this instance, and which
196      * should be put in the other one. Say we have a full node with object
197      * ids [10, 20, 30, 40, 50] and we are adding 35, then we would split into
198      * [10, 20, 30] and [40, 50].
199      */

200     private void split(long objectId, ContainerLocation containerLocation) {
201         if (log.isLoggable(Level.FINE)) log.fine("split around " + objectId + " for indexLeafNode " + this);
202     
203         // since we are about to create a new node, we wait a little if the
204
// serializer has too much still to do
205
getIndexManager().checkSerializerSize();
206         IndexLeafNode result = new IndexLeafNode(getIndexManager());
207         if (log.isLoggable(Level.FINE)) log.fine("split created " + result.getNodeId());
208         
209         // Must test if new node is not full, because the maximum size may
210
// change at runtime. If we don't, the new node may split itself also,
211
// and since the new node does not know its parent yet we will then have
212
// a problem...
213
while (!result.isFull(1) && size() > 1) {
214             int pos = getContainerLocationLoc().getMaxPos();
215             if (getContainerLocationLoc().getKey(pos) < objectId) {
216                 break;
217             }
218             ContainerLocation moveContainer = getContainerLocationLoc().getContainerLocation(pos);
219             long moveObjectId = getContainerLocationLoc().getKey(pos);
220             removeContainerLocation(moveObjectId);
221             result.putContainerLocation(moveObjectId, moveContainer);
222         }
223
224         if (objectId > getContainerLocationLoc().getMaxKey()) {
225             result.rawPutContainerLocation(objectId, containerLocation);
226         } else {
227             rawPutContainerLocation(objectId, containerLocation);
228         }
229
230         // make new node known to our peers
231
result.setPrevNode(this);
232         if (getNextNodeId() == LONGNULL) {
233             getIndexManager().setNewestLeafNode(result);
234         } else {
235             result.setNextNodeId(getNextNodeId());
236             IndexNode n = getNextNode();
237             n.setPrevNode(result);
238             n.endInvoke();
239         }
240         setNextNode(result);
241
242         // make new node known to our parent
243
IndexBranchNode p = getParentNode();
244         p.putChildNode(result);
245         p.endInvoke();
246     }
247     
248     public String JavaDoc toString() {
249         return super.toString() + " " + getContainerLocationLoc();
250     }
251     
252 }
253
Popular Tags