1 22 23 28 29 package org.xquark.mapper.metadata; 30 31 import java.sql.*; 32 import java.util.ArrayList ; 33 import java.util.Iterator ; 34 import java.util.List ; 35 36 import org.xquark.mapper.RepositoryException; 37 import org.xquark.mapper.dbms.*; 38 39 45 public class UOIDManager 46 { 47 private static final String RCSRevision = "$Revision: 1.1 $"; 48 private static final String RCSName = "$Name: $"; 49 50 public static final String SEQ_YES = "Y"; 51 52 private CollectionMetadata collection; 53 private String deleteStmt; 54 private String selectStmt; 55 56 private TableInfo freeDocOIDTable; 57 private Sequence docOIDSeq; 58 private long cid; 59 private byte cid_size; 60 private byte did_size; 61 private int did_shift; 62 private int cid_shift; 63 private long did_shift_mult; 64 private long nid_mask; 65 private long did_udid_mask; 66 private long did_uoid_mask; 67 private long max_node_oid; 68 private CollectionInfo collectionInfo; private ArrayList freeDIDs; 70 71 72 public UOIDManager(CollectionMetadata collection) 73 throws RepositoryException 74 { 75 this.collection = collection; 76 cid = (long)collection.getCollectionID(); 77 cid_size = collection.getRepository().getInfo().getColIDSize(); 78 did_size = collection.getInfo().getDocOIDSize(); 79 collectionInfo = collection.getInfo(); freeDocOIDTable = collection.getTableInfo(TableSpec.TYPE_FREE_DOC); 81 docOIDSeq = new Sequence(collection.getTableInfo(TableSpec.TYPE_DOC_SEQ), 82 collectionInfo.getDocOIDPreallocationSize() 83 ); 84 freeDIDs = new ArrayList (collectionInfo.getDocOIDPreallocationSize()); 85 init(); 86 } 87 88 89 private void init() 90 { 91 did_shift = RepositoryConstants.UOID_SIZE - (cid_size + did_size); 92 cid_shift = RepositoryConstants.UOID_SIZE - cid_size; 93 nid_mask = ~(Long.MAX_VALUE << did_shift); 94 did_shift_mult = 1L << did_shift; 95 max_node_oid = did_shift_mult - 1L; 96 did_udid_mask = (1L << did_size) - 1L; 97 initStatements(); 99 } 100 101 private void initStatements() 102 { 103 StringBuffer sql = new StringBuffer (); 104 sql.append("DELETE FROM "); 105 sql.append(freeDocOIDTable.getName()); 106 sql.append(" WHERE "); 107 sql.append(freeDocOIDTable.getColumns()[0].getName()); 108 sql.append("<="); 109 deleteStmt = sql.toString(); 110 111 selectStmt = collection.getMetadataConnection().getLockSelectStatement( 112 freeDocOIDTable, "ORDER BY FREE_DID"); 113 } 114 115 public synchronized long getNewDocOID() throws RepositoryException 116 { 117 Statement stmt = null; 118 ResultSet rs = null; 119 120 if (freeDIDs.size() == 0) { 122 AbstractConnection metaConn = collection.getMetadataConnection(); 123 synchronized(metaConn) { 125 try 127 { 128 metaConn.start(); 129 stmt = metaConn.getConnection().createStatement(); 130 stmt.setFetchSize(collectionInfo.getDocOIDPreallocationSize()); 131 rs = stmt.executeQuery(selectStmt); 132 while (rs.next() && (freeDIDs.size() < collectionInfo.getDocOIDPreallocationSize())) 135 { 136 freeDIDs.add(new Long (rs.getLong(1))); 137 } 138 rs.close(); 139 140 142 if (freeDIDs.size() > 0) 143 stmt.executeUpdate(deleteStmt + freeDIDs.get(freeDIDs.size() - 1)); 144 } 145 catch (SQLException e) 146 { 147 try 148 { 149 metaConn.rollback(); 150 } 151 catch (SQLException s) 152 { 153 } 155 freeDIDs.clear(); throw new RepositoryException(RepositoryException.DB_ERROR, 157 "JDBC error while recycling a document OIDs.", e); 158 } 159 finally 160 { 161 metaConn.commit(); try 163 { 164 if (stmt != null) 165 stmt.close(); 166 } 167 catch (SQLException e) 168 { 169 } 171 } 172 } 173 174 if (freeDIDs.size() == 0) { 177 long newOID = docOIDSeq.nextValue(metaConn); for (long i = newOID + collectionInfo.getDocOIDPreallocationSize() - 1; 179 i >= newOID; i--) 180 freeDIDs.add(new Long (i)); } 182 } 183 184 return ((Long )freeDIDs.remove(freeDIDs.size() - 1)).longValue(); 185 } 186 187 188 public synchronized void freeDocOIDs(List restoredDIDs) throws RepositoryException 189 { 190 PreparedStatement pStmt = null; 191 try 192 { 193 pStmt = collection.getMetadataConnection().getConnection().prepareStatement(freeDocOIDTable.getInsertStatement()); 194 Iterator it = restoredDIDs.iterator(); 195 while (it.hasNext()) 196 { 197 pStmt.setLong(1, ((Long )it.next()).longValue()); 198 pStmt.addBatch(); 199 } 200 pStmt.executeBatch(); 201 restoredDIDs.clear(); 202 } 203 catch (SQLException e) 204 { 205 throw new RepositoryException(RepositoryException.DB_ERROR, 206 "JDBC error while recycling document OIDs.", e); 207 } 208 finally 209 { 210 try 211 { 212 if (pStmt != null) 213 pStmt.close(); 214 } 215 catch (SQLException e) 216 { 217 } 219 } 220 } 221 222 223 private void clear() throws RepositoryException 224 { 225 if (freeDIDs.size() > 0) 226 freeDocOIDs(freeDIDs); 227 } 228 229 public void close() throws RepositoryException 230 { 231 clear(); 232 freeDIDs = null; 233 } 234 235 public long buildUOID(long docOID, long nodeOID) 236 { 237 return (cid << cid_shift) | (docOID << did_shift) | nodeOID; 239 } 240 241 public long buildUDID(long docOID) 242 { 243 return (cid << did_size) | docOID; 245 } 246 247 public short getCID(long uoid) 248 { 249 return (short)(uoid >>> cid_shift); 250 } 251 252 public long getUDID(long uoid) 253 { 254 return uoid >>> did_shift; 255 } 256 257 public long getDID(long udid) 258 { 259 return udid & did_udid_mask; 260 } 261 262 public long getNodeOID(long uoid) 263 { 264 return uoid & nid_mask; 265 } 266 267 public long getDocMinUOID(long docOID) 268 { 269 return buildUOID(docOID, 0); 270 } 271 272 public long getDocMaxUOID(long docOID) 273 { 274 return buildUOID(docOID, max_node_oid); 275 } 276 277 public long getDocMaxConstant() 278 { 279 return max_node_oid; 280 } 281 282 public long getDocMultiplier() 283 { 284 return did_shift_mult; 285 } 286 287 public long getBucketDivisor() 288 { 289 return did_shift_mult; 290 } 291 292 public int getDIDShift() 293 { 294 return did_shift; 295 } 296 } 297 | Popular Tags |