001package org.eclipse.aether.named.hazelcast;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import com.hazelcast.core.HazelcastInstance;
023import com.hazelcast.cp.ISemaphore;
024import org.eclipse.aether.named.support.AdaptedSemaphoreNamedLock;
025import org.eclipse.aether.named.support.AdaptedSemaphoreNamedLock.AdaptedSemaphore;
026import org.eclipse.aether.named.support.NamedLockFactorySupport;
027import org.eclipse.aether.named.support.NamedLockSupport;
028
029import java.util.concurrent.ConcurrentHashMap;
030import java.util.concurrent.TimeUnit;
031import java.util.function.BiFunction;
032
033/**
034 * Factory of {@link AdaptedSemaphoreNamedLock} instances using adapted Hazelcast {@link ISemaphore}. This class may
035 * use {@link HazelcastInstance} backed by Hazelcast Server or Hazelcast Client.
036 */
037public class HazelcastSemaphoreNamedLockFactory
038    extends NamedLockFactorySupport
039{
040    protected static final String NAME_PREFIX = "maven:resolver:";
041
042    private final HazelcastInstance hazelcastInstance;
043
044    private final BiFunction<HazelcastInstance, String, ISemaphore> semaphoreFunction;
045
046    private final boolean destroySemaphore;
047
048    private final boolean manageHazelcast;
049
050    private final ConcurrentHashMap<String, ISemaphore> semaphores;
051
052    public HazelcastSemaphoreNamedLockFactory(
053        final HazelcastInstance hazelcastInstance,
054        final BiFunction<HazelcastInstance, String, ISemaphore> semaphoreFunction,
055        final boolean destroySemaphore,
056        final boolean manageHazelcast
057    )
058    {
059        this.hazelcastInstance = hazelcastInstance;
060        this.semaphoreFunction = semaphoreFunction;
061        this.destroySemaphore = destroySemaphore;
062        this.manageHazelcast = manageHazelcast;
063        this.semaphores = new ConcurrentHashMap<>();
064    }
065
066    @Override
067    protected NamedLockSupport createLock( final String name )
068    {
069        ISemaphore semaphore = semaphores.computeIfAbsent(
070                name, k -> semaphoreFunction.apply( hazelcastInstance, k )
071        );
072        return new AdaptedSemaphoreNamedLock( name, this, new HazelcastSemaphore( semaphore ) );
073    }
074
075    @Override
076    public void shutdown()
077    {
078        if ( manageHazelcast )
079        {
080            hazelcastInstance.shutdown();
081        }
082    }
083
084    @Override
085    protected void destroyLock( final NamedLockSupport lock )
086    {
087        ISemaphore semaphore = semaphores.remove( lock.name() );
088        if ( destroySemaphore )
089        {
090            semaphore.destroy();
091        }
092    }
093
094    private static final class HazelcastSemaphore implements AdaptedSemaphore
095    {
096        private final ISemaphore semaphore;
097
098        private HazelcastSemaphore( final ISemaphore semaphore )
099        {
100            semaphore.init( Integer.MAX_VALUE );
101            this.semaphore = semaphore;
102        }
103
104        @Override
105        public boolean tryAcquire( final int perms, final long time, final TimeUnit unit )
106            throws InterruptedException
107        {
108            return semaphore.tryAcquire( perms, time, unit );
109        }
110
111        @Override
112        public void release( final int perms )
113        {
114            semaphore.release( perms );
115        }
116    }
117}