Quadcap Embeddable Database

com/quadcap/sql/file/BlockPath.java

Go to the documentation of this file.
00001 package com.quadcap.sql.file; 00002 00003 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.IOException; 00042 00043 import com.quadcap.util.Debug; 00044 00045 /** 00046 * This class is used to locate a specified offset within a randomly 00047 * accessible <code>BlockAccess</code> object. The path has two 00048 * components, a logical component, <b>p</b> which specifies the offsets of the 00049 * block references needed to locate the block and position corresponding 00050 * to the selected byte, and a physical component <b>r</b> which contains 00051 * the block references of the blocks needed to locate the actual byte. 00052 * 00053 * @author Stan Bailes 00054 */ 00055 00056 class BlockPath { 00057 /** The actual bytes */ 00058 BlockAccess a; 00059 /** Depth of this path */ 00060 int depth; 00061 /** Byte offset info 'a' */ 00062 long pos; 00063 /** Logical path */ 00064 int[] p; 00065 /** Block refs */ 00066 long[] r; 00067 /** A temporary (logical) path */ 00068 int[] tp; 00069 00070 /** 00071 * Construct a new BlockPath to represent the specified byte in the 00072 * specified region. 00073 * 00074 * @param a the region into which the index is made 00075 * @param pos the byte offset in the region 00076 */ 00077 public BlockPath(BlockAccess a, long pos) throws IOException { 00078 this.a = a; 00079 this.pos = pos; 00080 00081 depth = a.depth; 00082 00083 p = new int[depth + 1]; 00084 r = new long[depth + 1]; 00085 tp = new int[depth + 1]; 00086 00087 getPath(pos, p); 00088 getRefs(); 00089 } 00090 00091 /** 00092 * Return the block which actually contains the data. This is the 00093 * final block in the path. 00094 * <p> 00095 * <B>NOTE</b>: This block needs to have its reference count decremented 00096 * when you're done with it!! 00097 */ 00098 public final Page getLeafBlock() throws IOException { 00099 return a.file.getPage(r[r.length-1]); 00100 } 00101 00102 /** 00103 * Return the byte offset within the leaf block where the designated 00104 * byte can be found. 00105 */ 00106 public final int getBufPos() { 00107 return p[p.length-1]; 00108 } 00109 00110 /** 00111 * Return the depth of this path 00112 */ 00113 public final int getDepth() { return depth; } 00114 00115 /** 00116 * Return the current position referred to by this path 00117 */ 00118 public final long getPos() { return pos; } 00119 00120 00121 /** 00122 * Return the current position referred to by this path 00123 */ 00124 public final void setPos(long newpos) throws IOException { 00125 if (newpos != pos) { 00126 getPath(newpos, tp); 00127 updatePath(tp); 00128 pos = newpos; 00129 } 00130 } 00131 00132 /** 00133 * Adjust this BlockPath to point to a new location, with a minimum 00134 * number of block accesses. 00135 * 00136 * @param cnt The offset from the current location 00137 */ 00138 public final void incr(long offset) throws IOException { 00139 setPos(pos + offset); 00140 } 00141 00142 /** 00143 * Build the (logical) path vector for a specified byte in the region. 00144 */ 00145 private final void getPath(long pos, int[] path) { 00146 //Debug.println("getPath(" + pos + ")"); 00147 int len = a.radices.length; 00148 for (int i = 0; i < len; i++) { 00149 path[i] = (int)(pos / a.radices[i]); 00150 pos %= a.radices[i]; 00151 //Debug.println(" " + i + ": " + path[i] + " (" + a.radices[i] + 00152 // ", pos = " + pos + ")"); 00153 } 00154 path[len] = (int)pos; 00155 //Debug.println(" * " + len + ": " + path[len]); 00156 } 00157 00158 /** 00159 * Find the actual block refs, given the logical path vector. 00160 */ 00161 private final void getRefs() throws IOException { 00162 r[0] = a.rootBlock; 00163 for (int i = 1; i < r.length; i++) { 00164 try { 00165 Page b = a.file.getPage(r[i-1]); 00166 try { 00167 r[i] = a.makeBlockRef(b, p[i-1], i==1); 00168 } finally { 00169 b.decrRefCount(); 00170 } 00171 } catch (IOException ex) { 00172 Debug.println("getRefs, i = " + i + 00173 ", r[" + i + "]=" + 00174 SubPageManager.toString(r[i-1])); 00175 Debug.println("this = " + this); 00176 throw ex; 00177 } catch (RuntimeException ex) { 00178 Debug.println("getRefs, i = " + i + 00179 ", r[" + i + "]=" + 00180 SubPageManager.toString(r[i-1])); 00181 Debug.println("this = " + this); 00182 throw ex; 00183 } 00184 } 00185 } 00186 00187 /** 00188 * Update the block refs, given a new logical path, attempting 00189 * to minimize the number of block accesses. 00190 */ 00191 private final void updatePath(int[] path) throws IOException { 00192 if (true) { 00193 this.p = path; 00194 getRefs(); 00195 } else { 00196 boolean update = false; 00197 for (int i = 1; i < r.length; i++) { 00198 update |= (p[i-1] != path[i-1]); 00199 p[i-1] = path[i-1]; 00200 if (update) { 00201 Page b = a.file.getPage(r[i-1]); 00202 try { 00203 r[i] = a.makeBlockRef(b, path[i-1], i==1); 00204 } finally { 00205 b.decrRefCount(); 00206 } 00207 } 00208 } 00209 p[r.length-1] = path[r.length-1]; 00210 } 00211 } 00212 00213 //#ifdef DEBUG 00214 /** 00215 * For debugging, return a displayable representation of this BlockPath. 00216 */ 00217 public String toString() { 00218 StringBuffer sb = new StringBuffer(); 00219 sb.append("Path[" + pos + "] p("); 00220 for (int i = 0; i < p.length; i++) { 00221 if (i > 0) sb.append(", "); 00222 sb.append("" + p[i]); 00223 } 00224 sb.append(") r("); 00225 for (int i = 0; i < r.length; i++) { 00226 if (i > 0) sb.append(", "); 00227 sb.append("" + SubPageManager.toString(r[i])); 00228 } 00229 sb.append(")"); 00230 return sb.toString(); 00231 } 00232 //#endif 00233 00234 }