3030
3131import java .io .IOException ;
3232import java .util .*;
33+ import java .util .concurrent .ConcurrentHashMap ;
34+ import java .util .concurrent .ConcurrentSkipListSet ;
35+ import java .util .concurrent .locks .Lock ;
36+ import java .util .concurrent .locks .ReentrantLock ;
3337
3438import static com .google .common .base .Preconditions .checkArgument ;
3539import static java .util .Objects .requireNonNull ;
4145public class SinglePointIndexFactory
4246{
4347 private static final Logger logger = LogManager .getLogger (SinglePointIndexFactory .class );
44- private final Map <TableIndex , SinglePointIndex > singlePointIndexImpls = new HashMap <>();
45- private final Set <SinglePointIndex .Scheme > enabledSchemes = new TreeSet <>();
46- private final Map <Long , TableIndex > indexIdToTableIndex = new HashMap <>();
48+ private final Map <TableIndex , SinglePointIndex > singlePointIndexImpls = new ConcurrentHashMap <>();
49+ private final Set <SinglePointIndex .Scheme > enabledSchemes = new ConcurrentSkipListSet <>();
50+ private final Map <Long , TableIndex > indexIdToTableIndex = new ConcurrentHashMap <>();
51+ private final Lock lock = new ReentrantLock ();
4752 /**
4853 * The providers of the enabled single point index schemes.
4954 */
@@ -128,27 +133,36 @@ public boolean isSchemeEnabled(SinglePointIndex.Scheme scheme)
128133 * @return the single point index instance
129134 * @throws SinglePointIndexException
130135 */
131- public synchronized SinglePointIndex getSinglePointIndex (long tableId , long indexId ) throws SinglePointIndexException
136+ public SinglePointIndex getSinglePointIndex (long tableId , long indexId ) throws SinglePointIndexException
132137 {
133- TableIndex tableIndex = indexIdToTableIndex .get (indexId );
138+ TableIndex tableIndex = this . indexIdToTableIndex .get (indexId );
134139 if (tableIndex == null )
135140 {
141+ this .lock .lock ();
136142 try
137143 {
138- io . pixelsdb . pixels . common . metadata . domain . SinglePointIndex singlePointIndex =
139- MetadataService . Instance (). getSinglePointIndex (indexId );
140- if (singlePointIndex == null )
144+ // double check to avoid redundant tableIndex creation
145+ tableIndex = this . indexIdToTableIndex . get (indexId );
146+ if (tableIndex == null )
141147 {
142- throw new SinglePointIndexException ("single point index with id " + indexId + " does not exist" );
148+ io .pixelsdb .pixels .common .metadata .domain .SinglePointIndex spi =
149+ MetadataService .Instance ().getSinglePointIndex (indexId );
150+ if (spi == null )
151+ {
152+ throw new SinglePointIndexException ("single point index with id " + indexId + " does not exist" );
153+ }
154+ tableIndex = new TableIndex (tableId , indexId , spi .getIndexScheme (), spi .isUnique ());
155+ this .indexIdToTableIndex .put (indexId , tableIndex );
143156 }
144- tableIndex = new TableIndex (tableId , indexId , singlePointIndex .getIndexScheme (), singlePointIndex .isUnique ());
145- indexIdToTableIndex .put (indexId , tableIndex );
146157 } catch (MetadataException e )
147158 {
148159 throw new SinglePointIndexException ("failed to query single point index information from metadata" , e );
149160 }
161+ finally
162+ {
163+ this .lock .unlock ();
164+ }
150165 }
151- // 'synchronized' in Java is reentrant, it is fine to call the other getSinglePointIndex() from here.
152166 return getSinglePointIndex (tableIndex );
153167 }
154168
@@ -158,53 +172,68 @@ public synchronized SinglePointIndex getSinglePointIndex(long tableId, long inde
158172 * @return the single point index instance
159173 * @throws SinglePointIndexException
160174 */
161- public synchronized SinglePointIndex getSinglePointIndex (TableIndex tableIndex ) throws SinglePointIndexException
175+ public SinglePointIndex getSinglePointIndex (TableIndex tableIndex ) throws SinglePointIndexException
162176 {
163177 requireNonNull (tableIndex , "tableIndex is null" );
164178 checkArgument (this .enabledSchemes .contains (tableIndex .scheme ), "single point index scheme '" +
165179 tableIndex .scheme .toString () + "' is not enabled." );
166180
167- if (!indexIdToTableIndex .containsKey (tableIndex .indexId ))
168- {
169- indexIdToTableIndex .put (tableIndex .indexId , tableIndex );
170- }
181+ this .indexIdToTableIndex .putIfAbsent (tableIndex .indexId , tableIndex );
171182
172- if (singlePointIndexImpls .containsKey (tableIndex ))
183+ SinglePointIndex singlePointIndex = this .singlePointIndexImpls .get (tableIndex );
184+ if (singlePointIndex == null )
173185 {
174- return singlePointIndexImpls .get (tableIndex );
186+ this .lock .lock ();
187+ try
188+ {
189+ // double check to avoid redundant creation of singlePointIndex
190+ singlePointIndex = this .singlePointIndexImpls .get (tableIndex );
191+ if (singlePointIndex == null )
192+ {
193+ singlePointIndex = this .singlePointIndexProviders .get (tableIndex .getScheme ()).createInstance (
194+ tableIndex .tableId , tableIndex .indexId , tableIndex .scheme , tableIndex .isUnique ());
195+ this .singlePointIndexImpls .put (tableIndex , singlePointIndex );
196+ }
197+ }
198+ finally
199+ {
200+ this .lock .unlock ();
201+ }
175202 }
176-
177- SinglePointIndex singlePointIndex = this .singlePointIndexProviders .get (tableIndex .getScheme ())
178- .createInstance (tableIndex .tableId , tableIndex .indexId , tableIndex .scheme , tableIndex .isUnique ());
179- singlePointIndexImpls .put (tableIndex , singlePointIndex );
180-
181203 return singlePointIndex ;
182204 }
183205
184206 /**
185207 * Close all the opened single point index instances.
186208 * @throws IOException
187209 */
188- public synchronized void closeAll () throws SinglePointIndexException
210+ public void closeAll () throws SinglePointIndexException
189211 {
190- for (TableIndex tableIndex : singlePointIndexImpls .keySet ())
212+ this .lock .lock ();
213+ try
191214 {
192- try
215+ for ( TableIndex tableIndex : this . singlePointIndexImpls . keySet ())
193216 {
194- SinglePointIndex removing = singlePointIndexImpls .get (tableIndex );
195- if (removing != null )
217+ try
196218 {
197- removing .close ();
219+ SinglePointIndex removing = this .singlePointIndexImpls .get (tableIndex );
220+ if (removing != null )
221+ {
222+ removing .close ();
223+ }
224+ } catch (IOException e )
225+ {
226+ throw new SinglePointIndexException (
227+ "failed to close single point index with id " + tableIndex .indexId , e );
198228 }
199229 }
200- catch (IOException e )
201- {
202- throw new SinglePointIndexException (
203- "failed to close single point index with id " + tableIndex .indexId , e );
204- }
230+ this .singlePointIndexImpls .clear ();
231+ this .indexIdToTableIndex .clear ();
232+ }
233+ finally
234+ {
235+ this .lock .unlock ();
205236 }
206- singlePointIndexImpls .clear ();
207- indexIdToTableIndex .clear ();
208237 }
209238
210239 /**
@@ -214,61 +243,63 @@ public synchronized void closeAll() throws SinglePointIndexException
214243 * @param closeAndRemove remove the index storage after closing if true
215244 * @throws SinglePointIndexException
216245 */
217- public synchronized void closeIndex (long tableId , long indexId , boolean closeAndRemove ) throws SinglePointIndexException
246+ public void closeIndex (long tableId , long indexId , boolean closeAndRemove ) throws SinglePointIndexException
218247 {
219- TableIndex tableIndex = indexIdToTableIndex . remove ( indexId );
220- if ( tableIndex != null )
248+ this . lock . lock ( );
249+ try
221250 {
222- SinglePointIndex removed = singlePointIndexImpls . remove (tableIndex );
223- if (removed != null )
251+ TableIndex tableIndex = this . indexIdToTableIndex . remove (indexId );
252+ if (tableIndex != null )
224253 {
225- try
254+ SinglePointIndex removed = this .singlePointIndexImpls .remove (tableIndex );
255+ if (removed != null )
226256 {
227- if ( closeAndRemove )
257+ try
228258 {
229- removed .closeAndRemove ();
230- }
231- else
259+ if (closeAndRemove )
260+ {
261+ removed .closeAndRemove ();
262+ } else
263+ {
264+ removed .close ();
265+ }
266+ } catch (IOException e )
232267 {
233- removed .close ();
268+ throw new SinglePointIndexException (
269+ "failed to close single point index with id " + tableIndex .indexId , e );
234270 }
235- }
236- catch (IOException e )
271+ } else
237272 {
238- throw new SinglePointIndexException (
239- "failed to close single point index with id " + tableIndex .indexId , e );
273+ logger .warn ("index with id {} once opened but not found" , indexId );
240274 }
241- }
242- else
243- {
244- logger .warn ("index with id {} once opened but not found" , indexId );
245- }
246- }
247- else
248- {
249- TableIndex tableIndex1 = new TableIndex (tableId , indexId , null , false );
250- SinglePointIndex removed = singlePointIndexImpls .remove (tableIndex1 );
251- if (removed != null )
275+ } else
252276 {
253- try
277+ TableIndex tableIndex1 = new TableIndex (tableId , indexId , null , false );
278+ SinglePointIndex removed = this .singlePointIndexImpls .remove (tableIndex1 );
279+ if (removed != null )
254280 {
255- if ( closeAndRemove )
281+ try
256282 {
257- removed .closeAndRemove ();
258- }
259- else
283+ if (closeAndRemove )
284+ {
285+ removed .closeAndRemove ();
286+ } else
287+ {
288+ removed .close ();
289+ }
290+ } catch (IOException e )
260291 {
261- removed .close ();
292+ throw new SinglePointIndexException (
293+ "failed to close single point index with id " + tableIndex .indexId , e );
262294 }
295+ logger .warn ("index with id {} is found but not opened properly" , indexId );
263296 }
264- catch (IOException e )
265- {
266- throw new SinglePointIndexException (
267- "failed to close single point index with id " + tableIndex .indexId , e );
268- }
269- logger .warn ("index with id {} is found but not opened properly" , indexId );
270297 }
271298 }
299+ finally
300+ {
301+ this .lock .unlock ();
302+ }
272303 }
273304
274305 public static class TableIndex
0 commit comments