1 package org.apache.ojb.broker.util.sequence; 2 3 17 18 import java.util.HashMap ; 19 import java.util.Map ; 20 21 import org.apache.commons.lang.SystemUtils; 22 import org.apache.ojb.broker.Identity; 23 import org.apache.ojb.broker.OptimisticLockException; 24 import org.apache.ojb.broker.PersistenceBroker; 25 import org.apache.ojb.broker.PersistenceBrokerFactory; 26 import org.apache.ojb.broker.metadata.FieldDescriptor; 27 import org.apache.ojb.broker.util.ObjectModification; 28 import org.apache.ojb.broker.util.logging.Logger; 29 import org.apache.ojb.broker.util.logging.LoggerFactory; 30 31 116 public class SequenceManagerHighLowImpl extends AbstractSequenceManager 117 { 118 private static Logger log = LoggerFactory.getLogger(SequenceManagerHighLowImpl.class); 119 122 private static final String GLOBAL_SEQUENCE_NAME = "global - default sequence name"; 123 public static final String PROPERTY_GRAB_SIZE = "grabSize"; 124 public static final String PROPERTY_GLOBAL_SEQUENCE_ID = "globalSequenceId"; 125 public static final String PROPERTY_GLOBAL_SEQUENCE_START = "globalSequenceStart"; 126 127 protected static Map sequencesDBMap = new HashMap (); 128 129 protected boolean useGlobalSequenceIdentities; 130 protected int grabSize; 131 protected long sequenceStart; 132 protected int attempts; 133 134 public SequenceManagerHighLowImpl(PersistenceBroker broker) 135 { 136 super(broker); 137 Long start = SequenceManagerHelper.getSeqStart(getConfigurationProperties()); 138 sequenceStart = start != null ? start.longValue() : 1; 139 grabSize = Integer.parseInt(getConfigurationProperty(PROPERTY_GRAB_SIZE, "20")); 140 useGlobalSequenceIdentities = Boolean.getBoolean(getConfigurationProperty(PROPERTY_GLOBAL_SEQUENCE_ID, "false")); 141 long globalSequenceStart = Long.parseLong(getConfigurationProperty(PROPERTY_GLOBAL_SEQUENCE_START, "1")); 143 if(useGlobalSequenceIdentities && globalSequenceStart > sequenceStart) 144 { 145 sequenceStart = globalSequenceStart; 146 } 147 } 148 149 protected long getUniqueLong(FieldDescriptor field) throws SequenceManagerException 150 { 151 HighLowSequence seq; 152 String sequenceName = buildSequenceName(field); 153 synchronized (SequenceManagerHighLowImpl.class) 154 { 155 seq = getSequence(sequenceName); 157 158 if (seq == null) 159 { 160 seq = getSequence(getBrokerForClass(), field, sequenceName); 162 addSequence(sequenceName, seq); 163 } 164 165 long id = seq.getNextId(); 167 if (id == 0) 169 { 170 seq = getSequence(getBrokerForClass(), field, sequenceName); 171 addSequence(sequenceName, seq); 173 id = seq.getNextId(); 174 if (id == 0) 175 { 176 removeSequence(sequenceName); 178 throw new SequenceManagerException("Sequence generation failed: " + 179 SystemUtils.LINE_SEPARATOR + "Sequence: " + seq + 180 ". Unable to build new ID, id was always 0." + 181 SystemUtils.LINE_SEPARATOR + "Thread: " + Thread.currentThread() + 182 SystemUtils.LINE_SEPARATOR + "PB: " + getBrokerForClass()); 183 } 184 } 185 return id; 186 } 187 } 188 189 196 private HighLowSequence getSequence(String sequenceName) 197 { 198 HighLowSequence result = null; 199 Map mapForDB = (Map ) sequencesDBMap.get(getBrokerForClass() 201 .serviceConnectionManager().getConnectionDescriptor().getJcdAlias()); 202 if(mapForDB != null) 203 { 204 result = (HighLowSequence) mapForDB.get(sequenceName); 205 } 206 return result; 207 } 208 209 214 private void addSequence(String sequenceName, HighLowSequence seq) 215 { 216 String jcdAlias = getBrokerForClass() 218 .serviceConnectionManager().getConnectionDescriptor().getJcdAlias(); 219 Map mapForDB = (Map ) sequencesDBMap.get(jcdAlias); 220 if(mapForDB == null) 221 { 222 mapForDB = new HashMap (); 223 } 224 mapForDB.put(sequenceName, seq); 225 sequencesDBMap.put(jcdAlias, mapForDB); 226 } 227 228 233 protected void removeSequence(String sequenceName) 234 { 235 Map mapForDB = (Map ) sequencesDBMap.get(getBrokerForClass() 237 .serviceConnectionManager().getConnectionDescriptor().getJcdAlias()); 238 if(mapForDB != null) 239 { 240 synchronized(SequenceManagerHighLowImpl.class) 241 { 242 mapForDB.remove(sequenceName); 243 } 244 } 245 } 246 247 protected HighLowSequence getSequence(PersistenceBroker brokerForSequence, 248 FieldDescriptor field, 249 String sequenceName) throws SequenceManagerException 250 { 251 HighLowSequence newSequence = null; 252 PersistenceBroker internBroker = null; 253 try 254 { 255 264 internBroker = PersistenceBrokerFactory.createPersistenceBroker(brokerForSequence.getPBKey()); 265 internBroker.beginTransaction(); 266 267 newSequence = lookupStoreSequence(internBroker, field, sequenceName); 268 269 internBroker.commitTransaction(); 270 271 if (log.isDebugEnabled()) log.debug("new sequence was " + newSequence); 272 } 273 catch(Exception e) 274 { 275 log.error("Can't lookup new HighLowSequence for field " 276 + (field != null ? field.getAttributeName() : null) 277 + " using sequence name " + sequenceName, e); 278 if(internBroker != null && internBroker.isInTransaction()) internBroker.abortTransaction(); 279 throw new SequenceManagerException("Can't build new sequence", e); 280 } 281 finally 282 { 283 attempts = 0; 284 if (internBroker != null) internBroker.close(); 285 } 286 return newSequence; 287 } 288 289 protected HighLowSequence lookupStoreSequence(PersistenceBroker broker, FieldDescriptor field, String seqName) 290 { 291 HighLowSequence newSequence; 292 boolean needsInsert = false; 293 294 Identity oid = broker.serviceIdentity().buildIdentity(HighLowSequence.class, seqName); 295 newSequence = (HighLowSequence) broker.getObjectByIdentity(oid); 297 298 if (newSequence == null) 300 { 301 if (log.isDebugEnabled()) 302 { 303 log.debug("sequence for field " + field + " not found in db, store new HighLowSequence"); 304 } 305 308 long maxKey = getMaxKeyForSequence(getBrokerForClass(), field); 310 311 newSequence = newSequenceObject(seqName, field); 312 newSequence.setMaxKey(maxKey); 313 needsInsert = true; 314 } 315 if(newSequence.getMaxKey() < sequenceStart) 318 { 319 newSequence.setMaxKey(sequenceStart); 320 } 321 322 newSequence.setGrabSize(grabSize); 324 325 newSequence.grabNextKeySet(); 327 328 try 330 { 331 if(needsInsert) broker.store(newSequence, ObjectModification.INSERT); 332 else broker.store(newSequence, ObjectModification.UPDATE); 333 } 334 catch (OptimisticLockException e) 335 { 336 if(attempts < 5) 338 { 339 log.info("OptimisticLockException was thrown, will try again to store sequence. Sequence was "+newSequence); 340 attempts++; 341 newSequence = lookupStoreSequence(broker, field, seqName); 342 } 343 else throw e; 344 } 345 return newSequence; 346 } 347 348 protected HighLowSequence newSequenceObject(String sequenceName, 349 FieldDescriptor field) 350 { 351 HighLowSequence seq = new HighLowSequence(); 352 seq.setName(sequenceName); 353 seq.setGrabSize(grabSize); 354 return seq; 355 } 356 357 protected long getMaxKeyForSequence(PersistenceBroker broker, 358 FieldDescriptor field) 359 { 360 long maxKey; 361 if (useGlobalSequenceIdentities) 362 { 363 maxKey = sequenceStart; 364 } 365 else 366 { 367 370 maxKey = SequenceManagerHelper.getMaxForExtent(broker, field); 371 maxKey = sequenceStart > maxKey ? sequenceStart : maxKey; 373 } 374 return maxKey; 375 } 376 377 private String buildSequenceName(FieldDescriptor field) throws SequenceManagerException 378 { 379 String seqName; 380 if (useGlobalSequenceIdentities) 381 { 382 seqName = GLOBAL_SEQUENCE_NAME; 383 } 384 else 385 { 386 seqName = calculateSequenceName(field); 387 } 388 return seqName; 389 } 390 } 391 | Popular Tags |