001: package org.apache.ojb.broker.util.sequence;
002:
003: /* Copyright 2002-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import org.apache.ojb.broker.PersistenceBroker;
019: import org.apache.ojb.broker.metadata.FieldDescriptor;
020:
021: import java.util.HashMap;
022: import java.util.Map;
023:
024: /**
025: * <p>
026: * Very fast in memory sequence manager implementation, only the first
027: * time an id was requested for a class, the manager query the database
028: * for the max id in requested column - all following request were
029: * performed in memory.
030: * </p>
031: * <b>Limitations:</b>
032: * <ul type="disc">
033: * <li>do not use in clustered environments</li>
034: * <li>do not use if other applications generate id's for objects</li>
035: * </ul>
036: *
037: *
038: *
039: * <p>
040: * Implementation configuration properties:
041: * </p>
042: *
043: * <table cellspacing="2" cellpadding="2" border="3" frame="box">
044: * <tr>
045: * <td><strong>Property Key</strong></td>
046: * <td><strong>Property Values</strong></td>
047: * </tr>
048: * <tr>
049: * <td>seq.start</td>
050: * <td>
051: * Set the start index of used sequences (e.g. set 100000, id generation starts with 100001).
052: * Default start index is <em>1</em>.
053: * </td>
054: * </tr>
055: * <tr>
056: * <td>autoNaming</td>
057: * <td>
058: * Default was 'true'. If set 'true' OJB try to build a
059: * sequence name automatic if none found in field-descriptor
060: * and set this generated name as <code>sequence-name</code>
061: * in field-descriptor. If set 'false' OJB throws an exception
062: * if none sequence name was found in field-descriptor.
063: * </td>
064: * </tr>
065: * <tr>
066: * <td>sequenceStart</td>
067: * <td>
068: * <em>Deprecated, use property 'seq.start'.</em> Set the start index
069: * of used sequences (e.g. set 100000, id generation starts with 100001).
070: * Default start index is <em>1</em>.
071: * </td>
072: * </tr>
073: * </table>
074: *
075: * <br/>
076: * <br/>
077: * <br/>
078: *
079: * @see org.apache.ojb.broker.util.sequence.SequenceManager
080: * @see org.apache.ojb.broker.util.sequence.SequenceManagerFactory
081: * @see org.apache.ojb.broker.util.sequence.SequenceManagerHelper
082: *
083: *
084: * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
085: * @version $Id: SequenceManagerInMemoryImpl.java,v 1.14.2.3 2005/12/21 22:28:41 tomdz Exp $
086: */
087: public class SequenceManagerInMemoryImpl extends
088: AbstractSequenceManager {
089: protected static Map sequencesDBMap = new HashMap();
090: private long sequenceStart;
091:
092: public SequenceManagerInMemoryImpl(PersistenceBroker broker) {
093: super (broker);
094: Long start = SequenceManagerHelper
095: .getSeqStart(getConfigurationProperties());
096: sequenceStart = start != null ? start.longValue() : 1;
097: }
098:
099: protected long getUniqueLong(FieldDescriptor field)
100: throws SequenceManagerException {
101: String seqName = calculateSequenceName(field);
102: // we have to be threadsafe
103: synchronized (SequenceManagerInMemoryImpl.class) {
104: // get id for given seq name
105: Long currentId = getSequence(seqName);
106: // check - first time we search for sequence name
107: if (currentId == null) {
108: long maxKey = SequenceManagerHelper.getMaxForExtent(
109: getBrokerForClass(), field);
110: maxKey = sequenceStart > maxKey ? sequenceStart
111: : maxKey;
112: currentId = new Long(maxKey);
113: }
114: currentId = new Long(currentId.longValue() + 1);
115: // put new id back to map
116: addSequence(seqName, currentId);
117: return currentId.intValue();
118: }
119: }
120:
121: /**
122: * Returns last used sequence value or <code>null</code> if no sequence
123: * was add for given sequence name.
124: *
125: * @param sequenceName Name of the sequence.
126: * @return Last used sequence value or <code>null</code>
127: */
128: private Long getSequence(String sequenceName) {
129: Long result = null;
130: // now lookup the sequence map for calling DB
131: Map mapForDB = (Map) sequencesDBMap.get(getBrokerForClass()
132: .serviceConnectionManager().getConnectionDescriptor()
133: .getJcdAlias());
134: if (mapForDB != null) {
135: result = (Long) mapForDB.get(sequenceName);
136: }
137: return result;
138: }
139:
140: /**
141: * Add new sequence value for sequence name.
142: * @param sequenceName Name of the sequence.
143: * @param seq The sequence value to add.
144: */
145: private void addSequence(String sequenceName, Long seq) {
146: // lookup the sequence map for calling DB
147: String jcdAlias = getBrokerForClass()
148: .serviceConnectionManager().getConnectionDescriptor()
149: .getJcdAlias();
150: Map mapForDB = (Map) sequencesDBMap.get(jcdAlias);
151: if (mapForDB == null) {
152: mapForDB = new HashMap();
153: }
154: mapForDB.put(sequenceName, seq);
155: sequencesDBMap.put(jcdAlias, mapForDB);
156: }
157:
158: /**
159: * Remove the sequence for given sequence name.
160: *
161: * @param sequenceName Name of the sequence to remove.
162: */
163: protected void removeSequence(String sequenceName) {
164: // lookup the sequence map for calling DB
165: Map mapForDB = (Map) sequencesDBMap.get(getBrokerForClass()
166: .serviceConnectionManager().getConnectionDescriptor()
167: .getJcdAlias());
168: if (mapForDB != null) {
169: synchronized (SequenceManagerInMemoryImpl.class) {
170: mapForDB.remove(sequenceName);
171: }
172: }
173: }
174: }
|