class IgniteLockProvider implements ExtensibleLockProvider {
    /** Default ShedLock cache name. */
    public static final String DEFAULT_SHEDLOCK_CACHE_NAME = "shedLock";

    /** ShedLock cache. */
    private final IgniteCache<String, LockValue> cache;

    /**
     * @param ignite
     *            Ignite instance.
     */
    public IgniteLockProvider(Ignite ignite) {
        this(ignite, DEFAULT_SHEDLOCK_CACHE_NAME);
    }

    /**
     * @param ignite
     *            Ignite instance.
     * @param shedLockCacheName
     *            ShedLock cache name to use instead of default.
     */
    public IgniteLockProvider(Ignite ignite, String shedLockCacheName) {
        this.cache = ignite.getOrCreateCache(shedLockCacheName);
    }

    /** {@inheritDoc} */
    @Override
    public Optional<SimpleLock> lock(LockConfiguration lockCfg) {
        Instant now = Instant.now();
        String key = lockCfg.getName();

        LockValue newVal = new LockValue(now, lockCfg.getLockAtMostUntil(), getHostname());
        LockValue oldVal = cache.get(key);

        if (oldVal == null) {
            if (cache.putIfAbsent(key, newVal)) return Optional.of(new IgniteLock(lockCfg, this));

            return Optional.empty();
        }

        if (!now.isBefore(oldVal.getLockUntil()) && cache.replace(key, oldVal, newVal))
            return Optional.of(new IgniteLock(lockCfg, this));

        return Optional.empty();
    }

    /**
     * If there is a lock with given name and hostname, try to use
     * {@link IgniteCache#replace} to set lockUntil to
     * {@link LockConfiguration#getLockAtMostUntil}.
     *
     * @param lockCfg
     *            Lock configuration.
     * @return New lock if succeed extended. Empty, otherwise.
     */
    private Optional<SimpleLock> extend(LockConfiguration lockCfg) {<FILL_FUNCTION_BODY>}

    /**
     * If there is a lock with given name and hostname, try to use
     * {@link IgniteCache#replace} to set lockUntil to {@code now}.
     *
     * @param lockCfg
     *            Lock configuration.
     */
    private void unlock(LockConfiguration lockCfg) {
        String key = lockCfg.getName();
        LockValue oldVal = cache.get(key);

        if (oldVal != null && oldVal.getLockedBy().equals(getHostname())) {
            LockValue newVal = oldVal.withLockUntil(lockCfg.getUnlockTime());

            cache.replace(key, oldVal, newVal);
        }
    }

    /** Ignite lock. */
    private static final class IgniteLock extends AbstractSimpleLock {
        /** Ignite lock provider. */
        private final IgniteLockProvider lockProvider;

        /**
         * @param lockCfg
         *            Lock configuration.
         * @param lockProvider
         *            Ignite lock provider.
         */
        private IgniteLock(LockConfiguration lockCfg, IgniteLockProvider lockProvider) {
            super(lockCfg);

            this.lockProvider = lockProvider;
        }

        /** {@inheritDoc} */
        @Override
        public void doUnlock() {
            lockProvider.unlock(lockConfiguration);
        }

        /** {@inheritDoc} */
        @Override
        public Optional<SimpleLock> doExtend(LockConfiguration newLockConfiguration) {
            return lockProvider.extend(newLockConfiguration);
        }
    }
}

        Instant now = Instant.now();

        String key = lockCfg.getName();
        LockValue oldVal = cache.get(key);

        if (oldVal == null
                || !oldVal.getLockedBy().equals(getHostname())
                || !oldVal.getLockUntil().isAfter(now)) return Optional.empty();

        LockValue newVal = oldVal.withLockUntil(lockCfg.getLockAtMostUntil());

        if (cache.replace(key, oldVal, newVal)) return Optional.of(new IgniteLock(lockCfg, this));

        return Optional.empty();
    
<no_super_class>