1 64 65 package com.jcorporate.expresso.core.dbobj; 66 67 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap; 68 import com.jcorporate.expresso.core.dataobjects.DataFieldMetaData; 69 import com.jcorporate.expresso.core.dataobjects.jdbc.JDBCObjectMetaData; 70 import com.jcorporate.expresso.core.db.DBException; 71 import com.jcorporate.expresso.core.misc.ConfigManager; 72 import com.jcorporate.expresso.core.misc.ReusableLong; 73 74 import java.util.Enumeration ; 75 import java.util.Iterator ; 76 77 78 89 public class NextNumberImpl 90 extends NextNumber { 91 92 99 protected volatile ConcurrentReaderHashMap contextMap = new ConcurrentReaderHashMap(); 100 101 private Object mInitLock = new Object (); 102 103 106 public NextNumberImpl() { 107 for (Enumeration e = ConfigManager.getAllConfigKeys(); e.hasMoreElements();) { 108 String configKey = (String ) e.nextElement(); 109 contextMap.put(configKey, new ConcurrentReaderHashMap(40)); 110 } 111 } 112 113 121 public void initialize(String db, DBObject callingObject) 122 throws DBException { 123 callingObject.setDataContext(db); 124 125 Iterator i = callingObject.getMetaData().getAllFieldsMap().values().iterator(); 126 while (i.hasNext()) { 127 DBField dbf = (DBField) i.next(); 128 129 if (dbf.isAutoIncremented()) { 130 String fieldName = dbf.getName(); 131 registerField(db, callingObject, fieldName); 133 } 134 135 } 136 } 137 138 141 public void registerField(String db, DBObject callingDBOBject, 142 String fieldName) 143 throws DBException { 144 String hashKey = getKey(callingDBOBject, fieldName); 145 ConcurrentReaderHashMap nextNumMap = (ConcurrentReaderHashMap) contextMap.get(db); 146 147 if (nextNumMap == null) { 148 throw new DBException("Uninitialized nextnumber context map"); 149 } 150 if (!nextNumMap.containsKey(hashKey)) { 151 152 long l = getMax(db, callingDBOBject, fieldName); 154 long setValue = 0; 155 boolean didInit = false; 156 157 synchronized (nextNumMap) { 161 if (!nextNumMap.containsKey(hashKey)) { 163 nextNumMap.put(hashKey, new ReusableLong(l)); 164 setValue = ((ReusableLong) nextNumMap.get(hashKey)).longValue(); 166 didInit = true; 167 } 168 } 169 170 if (didInit && log.isDebugEnabled()) { 171 log.debug("initialized hash entry for key: " 172 + hashKey + " to value: " + l 173 + " and confirmed value: " + setValue); 174 } 175 176 } 177 } 178 179 191 private ReusableLong getNextNumberObject(String db, 192 DBObject callingDBObject, 193 String fieldName) 194 throws DBException { 195 String key = getKey(callingDBObject, fieldName); 196 ConcurrentReaderHashMap myDBMap = (ConcurrentReaderHashMap) contextMap.get(db); 197 ReusableLong rl = (ReusableLong) myDBMap.get(key); 198 199 if (rl == null) { 200 synchronized (mInitLock) { 205 if (myDBMap.get(key) == null) { 207 initialize(db, callingDBObject); 208 } 209 } 210 211 rl = (ReusableLong) myDBMap.get(key); 212 213 if (rl == null) { 214 DataFieldMetaData meta = callingDBObject.getFieldMetaData(fieldName); 217 if (!meta.isAutoIncremented() && log.isDebugEnabled()) { 218 log.debug("NextNumber.getNext() called for table.field, '" 219 + ((JDBCObjectMetaData) callingDBObject.getMetaData()).getTargetSQLTable( 220 callingDBObject.getDataContext()) 221 + "." + fieldName 222 + "', which is not auto-incrementing type. Setting up hash entry anyway."); 223 } 224 registerField(db, callingDBObject, fieldName); 225 rl = (ReusableLong) myDBMap.get(key); 226 } 227 228 if (rl == null) { 229 throw new DBException("Unable to locate nextnumber entry for key: " + key); 230 } 231 } 232 233 return rl; 234 } 235 236 244 protected void checkParams(String db, 245 DBObject callingObject, 246 String fieldName) 247 throws DBException { 248 249 if (db == null || db.length() == 0) { 250 throw new DBException("NextNumber parameter 'db' must not be null or zero length"); 251 } 252 if (callingObject == null) { 253 throw new DBException("NextNumber parameter 'callingDBOBject' must not be null"); 254 } 255 if (fieldName == null) { 256 throw new DBException("NextNumber parameter 'fieldName' must not be null"); 257 } 258 259 if (contextMap.get(db) == null) { 260 throw new DBException("NextNumber Unable to locate nextnumber map for context " + db); 261 } 262 263 } 264 265 268 public long getNext(String db, DBObject callingDBObject, String fieldName) 269 throws DBException { 270 271 if (CHECK_PARAMETERS) { 272 checkParams(db, 273 callingDBObject, 274 fieldName); 275 } 276 277 278 ReusableLong theNextNumberObject = getNextNumberObject(db, 279 callingDBObject, 280 fieldName); 281 282 283 long result; 284 285 synchronized (theNextNumberObject) { 289 result = theNextNumberObject.longValue(); 290 result++; 291 theNextNumberObject.setLong(result); 292 } 293 294 if (log.isDebugEnabled()) { 295 log.debug("getNext returns, for hash key: " 296 + getKey(callingDBObject, fieldName) + " the value: " + result); 297 } 298 299 300 return result; 301 } 302 303 309 public void reset(String db) { 310 ConcurrentReaderHashMap myDBMap = (ConcurrentReaderHashMap) contextMap.get(db); 311 312 if (myDBMap != null) { 313 synchronized (myDBMap) { 317 myDBMap.clear(); 318 } 319 } 320 } 321 322 329 public void reset(String db, DBObject callingObject) { 330 ConcurrentReaderHashMap myDBMap = (ConcurrentReaderHashMap) contextMap.get(db); 331 332 try { 333 if (myDBMap != null) { 334 Iterator i = callingObject.getMetaData().getAllFieldsMap().values().iterator(); 335 336 while (i.hasNext()) { 337 DBField dbf = (DBField) i.next(); 338 339 if (dbf.isAutoIncremented()) { 340 String fieldName = dbf.getName(); 341 String hashKey = getKey(callingObject, fieldName); 342 343 if (myDBMap.containsKey(hashKey)) { 344 345 synchronized (myDBMap) { 349 if (myDBMap.containsKey(hashKey)) { 351 myDBMap.remove(hashKey); 352 } 353 } 354 355 } 356 357 } 358 359 } 360 } 361 } catch (DBException dbe) { 362 log.error("Error clearing one dbobject for next number, clearing whole stack"); 363 364 if (myDBMap != null) { 365 synchronized (myDBMap) { 366 myDBMap.clear(); 367 } 368 } 369 } 370 } 371 } 372 | Popular Tags |