Skip to main content
summaryrefslogtreecommitdiffstats
blob: 3cc7d8b54a737635d59cd7ecbeebe5094b3cbdc6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*******************************************************************************
 * Copyright (c) 2004, 2007 Boeing.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Boeing - initial API and implementation
 *******************************************************************************/
package org.eclipse.osee.framework.database.internal.core;

import java.util.HashMap;
import org.eclipse.osee.framework.core.exception.OseeDataStoreException;
import org.eclipse.osee.framework.database.IOseeDatabaseService;
import org.eclipse.osee.framework.database.core.IOseeSequence;
import org.eclipse.osee.framework.database.core.OseeConnection;

/**
 * @author Ryan D. Brooks
 */
public class OseeSequenceImpl implements IOseeSequence {
   private static final String QUERY_SEQUENCE = "SELECT last_sequence FROM osee_sequence WHERE sequence_name = ?";
   private static final String INSERT_SEQUENCE =
      "INSERT INTO osee_sequence (last_sequence, sequence_name) VALUES (?,?)";
   private static final String UPDATE_SEQUENCE =
      "UPDATE osee_sequence SET last_sequence = ? WHERE sequence_name = ? AND last_sequence = ?";

   private final static HashMap<String, SequenceRange> sequences = new HashMap<String, SequenceRange>(30);

   private final IOseeDatabaseService service;

   public OseeSequenceImpl(IOseeDatabaseService service) {
      this.service = service;
   }

   private IOseeDatabaseService getDatabase() {
      return service;
   }

   private SequenceRange getRange(String sequenceName) {
      SequenceRange range = sequences.get(sequenceName);
      if (range == null) {
         // do this to keep transaction id's sequential in the face of concurrent transaction by multiple users
         range = new SequenceRange(!sequenceName.equals(TRANSACTION_ID_SEQ));
         sequences.put(sequenceName, range);
      }
      return range;
   }

   @Override
   public synchronized void clear() throws OseeDataStoreException {
      sequences.clear();
   }

   @Override
   @SuppressWarnings("unchecked")
   public synchronized long getNextSequence(String sequenceName) throws OseeDataStoreException {
      SequenceRange range = getRange(sequenceName);
      if (range.lastAvailable == 0) {
         long lastValue = -1L;
         boolean gotSequence = false;
         OseeConnection connection = getDatabase().getConnection();
         try {
            while (!gotSequence) {
               long currentValue =
                  getDatabase().runPreparedQueryFetchObject(connection, lastValue, QUERY_SEQUENCE, sequenceName);
               if (currentValue == lastValue) {
                  internalInitializeSequence(sequenceName);
                  lastValue = 0;
               } else {
                  lastValue = currentValue;
               }
               gotSequence =
                  getDatabase().runPreparedUpdate(connection, UPDATE_SEQUENCE, lastValue + range.prefetchSize,
                     sequenceName, lastValue) == 1;
            }
            range.updateRange(lastValue);
         } finally {
            connection.close();
         }
      }
      range.currentValue++;
      if (range.currentValue == range.lastAvailable) {
         range.lastAvailable = 0;
      }
      return range.currentValue;
   }

   @SuppressWarnings("unchecked")
   private void internalInitializeSequence(String sequenceName) throws OseeDataStoreException {
      SequenceRange range = getRange(sequenceName);
      range.lastAvailable = 0;
      getDatabase().runPreparedUpdate(INSERT_SEQUENCE, 0, sequenceName);
   }

   @Override
   public int getNextSessionId() throws OseeDataStoreException {
      return (int) getNextSequence(TTE_SESSION_SEQ);
   }

   @Override
   public int getNextTransactionId() throws OseeDataStoreException {
      return (int) getNextSequence(TRANSACTION_ID_SEQ);
   }

   @Override
   public int getNextArtifactId() throws OseeDataStoreException {
      return (int) getNextSequence(ART_ID_SEQ);
   }

   @Override
   public int getNextOseeEnumTypeId() throws OseeDataStoreException {
      return (int) getNextSequence(ENUM_TYPE_ID_SEQ);
   }

   @Override
   public int getNextGammaId() throws OseeDataStoreException {
      return (int) getNextSequence(GAMMA_ID_SEQ);
   }

   @Override
   public int getNextArtifactTypeId() throws OseeDataStoreException {
      return (int) getNextSequence(ART_TYPE_ID_SEQ);
   }

   @Override
   public int getNextAttributeBaseTypeId() throws OseeDataStoreException {
      return (int) getNextSequence(ATTR_BASE_TYPE_ID_SEQ);
   }

   @Override
   public int getNextAttributeProviderTypeId() throws OseeDataStoreException {
      return (int) getNextSequence(ATTR_PROVIDER_TYPE_ID_SEQ);
   }

   @Override
   public int getNextAttributeId() throws OseeDataStoreException {
      return (int) getNextSequence(ATTR_ID_SEQ);
   }

   @Override
   public int getNextAttributeTypeId() throws OseeDataStoreException {
      return (int) getNextSequence(ATTR_TYPE_ID_SEQ);
   }

   @Override
   public int getNextFactoryId() throws OseeDataStoreException {
      return (int) getNextSequence(FACTORY_ID_SEQ);
   }

   @Override
   public int getNextBranchId() throws OseeDataStoreException {
      return (int) getNextSequence(BRANCH_ID_SEQ);
   }

   @Override
   public int getNextRelationTypeId() throws OseeDataStoreException {
      return (int) getNextSequence(REL_LINK_TYPE_ID_SEQ);
   }

   @Override
   public int getNextRelationId() throws OseeDataStoreException {
      return (int) getNextSequence(REL_LINK_ID_SEQ);
   }

   @Override
   public int getNextImportId() throws OseeDataStoreException {
      return (int) getNextSequence(IMPORT_ID_SEQ);
   }

   @Override
   public int getNextImportMappedIndexId() throws OseeDataStoreException {
      return (int) getNextSequence(IMPORT_MAPPED_INDEX_SEQ);
   }

   private static final class SequenceRange {
      private long currentValue;
      private long lastAvailable;
      private int prefetchSize;
      private final boolean aggressiveFetch;

      public SequenceRange(boolean aggressiveFetch) {
         super();
         this.prefetchSize = 1;
         this.aggressiveFetch = aggressiveFetch;
      }

      public void updateRange(long lastValue) {
         currentValue = lastValue;
         lastAvailable = lastValue + prefetchSize;

         if (aggressiveFetch) {
            prefetchSize *= 2; // next time grab twice as many
         }
      }
   }

}

Back to the top