/** * Get a {@link ManagedLock} that manages a {@link ReentrantLock}. * * @return a managed lock */ public static @NotNull ManagedLock newManagedLock() { return manage(new ReentrantLock()); }
/** * Convenience method that simply calls * {@link #weakManagedLockFactory(Function, Supplier)} with the * {@link #lockFactory() default lock factory}. * * @param <T> the type of the thing used to look up locks * @param <D> the type used to map lock instances, should be a good map key * @param stripeFunction to convert Ts to Ds. * @see #weakManagedLockFactory(Function, Supplier) */ public static @NotNull <T, D> com.atlassian.util.concurrent.Function<T, ManagedLock> weakManagedLockFactory( final @NotNull Function<T, D> stripeFunction) { return weakManagedLockFactory(stripeFunction, lockFactory()); }
final Function<D, ManagedLock> lockFactory = fromSupplier(managedLockFactory(lockFactory())); return createManager(stripeFunction, weakMemoizer(lockFactory));
/** * A convenience method for calling * {@link #weakReadWriteManagedLockFactory(Function, Supplier)} that uses * default {@link ReentrantReadWriteLock locks} * * @param <T> the type of the thing used to look up locks * @param <D> the type used to map lock instances, should be a good map key * @param stripeFunction * @return a new {@link Function} that provides {@link ManagedLock.ReadWrite} * instances that stores created instances with weak references. */ public static @NotNull <T, D> com.atlassian.util.concurrent.Function<T, ManagedLock.ReadWrite> weakReadWriteManagedLockFactory( final Function<T, D> stripeFunction) { return weakReadWriteManagedLockFactory(stripeFunction, readWriteLockFactory()); }
/** * Convenience method that calls * {@link ManagedLocks#weakManagedLockFactory(Function)} using the * {@link Functions#identity() identity function} for striping, essentially * meaning that unique input will have its own lock. * * @param <T> the type of the thing used to look up locks * @see #weakManagedLockFactory(Function, Supplier) */ public static @NotNull <T> com.atlassian.util.concurrent.Function<T, ManagedLock> weakManagedLockFactory() { return weakManagedLockFactory(Functions.<T> identity()); }
/** * A convenience method for calling * {@link #weakReadWriteManagedLockFactory(Function)} that uses the * {@link Functions#identity() identity function} for striping, essentially * meaning that unique input will have its own lock. * * @param <T> the type of the thing used to look up locks * @return a new {@link Function} that provides the appropriate * {@link ReadWrite} for the argument {@link ManagedLock.ReadWrite} instances * that stores created instances with weak references. */ public static @NotNull <T> com.atlassian.util.concurrent.Function<T, ManagedLock.ReadWrite> weakReadWriteManagedLockFactory() { return weakReadWriteManagedLockFactory(Functions.<T> identity()); }
/** * Create a {@link Function} for resolving {@link ManagedLock managed locks} . * The particular lock is resolved using a striping {@link Function} that is * used look up a lock instance. This allows for a finite set of locks to be * used even if the set of T is essentially unbounded. The locks are stored * using weak references so infrequently accessed locks should not use excess * memory. * * @param <T> the type of the thing used to look up locks * @param <D> the type used to map lock instances, should be a good map key * @param stripeFunction to convert the input to the thing used to look up the * individual locks * @param lockFactory the factory for creating the individual locks * @return a new {@link Function} that provides {@link ManagedLock} instances * that stores created instances with weak references. */ public static @NotNull <T, D> com.atlassian.util.concurrent.Function<T, ManagedLock> weakManagedLockFactory( final @NotNull Function<T, D> stripeFunction, final @NotNull Supplier<Lock> lockFactory) { final Function<D, ManagedLock> lockFunction = fromSupplier(managedLockFactory(lockFactory)); return managedFactory(weakMemoizer(lockFunction), stripeFunction); }
/** * Create a {@link Function} for resolving {@link ManagedLock.ReadWrite * managed read-write locks}. The particular lock is resolved using a striping * {@link Function} that is used look up a lock instance. This allows for a * finite set of locks to be used even if the set of T is essentially * unbounded. The locks are stored using weak references so infrequently * accessed locks should not use excess memory. * * @param <T> the type of the thing used to look up locks * @param <D> the type used to map lock instances, should be a good map key * @param stripeFunction to convert the input to the thing used to look up the * individual locks * @param lockFactory the factory for creating the individual locks * @return a new {@link Function} that provides {@link ManagedLock.ReadWrite} * instances that stores created instances with weak references. */ public static @NotNull <T, D> com.atlassian.util.concurrent.Function<T, ManagedLock.ReadWrite> weakReadWriteManagedLockFactory( final @NotNull Function<T, D> stripeFunction, final @NotNull Supplier<ReadWriteLock> lockFactory) { notNull("stripeFunction", stripeFunction); final Function<D, ReadWrite> readWriteManagedLockFactory = fromSupplier(managedReadWriteLockFactory(lockFactory)); final WeakMemoizer<D, ManagedLock.ReadWrite> locks = weakMemoizer(readWriteManagedLockFactory); return new Function<T, ManagedLock.ReadWrite>() { public ManagedLock.ReadWrite get(final T input) { return locks.get(stripeFunction.get(input)); }; }; }
/** * Gets all locks for ids and then after having acquired them executes the action. */ private void acquireLocksAndExecute(final Iterable<Long> ids, final WorkflowAction lockType, final Runnable action) { if (Iterables.isEmpty(ids)) { action.run(); } else { final Set<Long> sortedIds = Sets.newTreeSet(ids); ManagedLocks.manage(getLock(Iterables.getFirst(sortedIds, null), lockType)).withLock(new Runnable() { @Override public void run() { acquireLocksAndExecute(Iterables.skip(sortedIds, 1), lockType, action); } }); } }
@Override public void deleteScheme(final Long id) { if (id == null) { return; } ManagedLocks.manage(getLock(id, DELETE_SCHEME)).withLock(new Runnable() { @Override public void run() { final AssignableWorkflowScheme scheme = getWorkflowSchemeObj(id); doDeleteScheme(scheme); } }); }
@Override public void updateScheme(final Scheme scheme) throws DataAccessException { ManagedLocks.manage(getLock(scheme.getId(), UPDATE_SCHEME)).withLock(new Runnable() { @Override public void run() { final AssignableWorkflowScheme schemeObj = toWorkflowScheme(getScheme(scheme.getId())); checkMigration(schemeObj); doUpdateScheme(scheme); } }); }
@Override public AssignableWorkflowScheme updateWorkflowScheme(@Nonnull final AssignableWorkflowScheme workflowScheme) { notNull("scheme", workflowScheme); notNull("scheme.id", workflowScheme.getId()); final Lock lock = getLock(workflowScheme.getId(), UPDATE_WORKFLOW_SCHEME); return ManagedLocks.manage(lock).withLock(new com.atlassian.util.concurrent.Supplier<AssignableWorkflowScheme>() { @Override public AssignableWorkflowScheme get() { checkMigration(workflowScheme); Scheme scheme = getSchemeObject(workflowScheme.getId()); // Delete all existing entitites. Collection<SchemeEntity> entities = scheme.getEntities(); for (SchemeEntity entity : entities) { deleteEntity(entity.getId()); } scheme = new Scheme(workflowScheme.getId(), getSchemeEntityName(), workflowScheme.getName(), workflowScheme.getDescription(), Collections.<SchemeEntity>emptyList()); doUpdateScheme(scheme); createSchemeEntities(workflowScheme); return getWorkflowSchemeObj(workflowScheme.getId()); } }); }
@Override public DraftWorkflowScheme updateDraftWorkflowScheme(final ApplicationUser user, @Nonnull final DraftWorkflowScheme scheme) { notNull("scheme", scheme); notNull("scheme.id", scheme.getId()); // We lock the parent scheme in case of drafts final Lock lock = getLock(scheme.getParentScheme().getId(), UPDATE_DRAFT_WORKFLOW_SCHEME); return ManagedLocks.manage(lock).withLock(new com.atlassian.util.concurrent.Supplier<DraftWorkflowScheme>() { @Override public DraftWorkflowScheme get() { WorkflowSchemeMigrationTaskAccessor taskAccessor = getTaskAccessor(); if (taskAccessor.getActiveByProjects(scheme, true) != null) { throw new SchemeIsBeingMigratedException(); } DraftWorkflowSchemeStore.DraftState savedState = draftWorkflowSchemeStore.get(scheme.getId()); notNull(format("scheme with id %d does not exist.", scheme.getId()), savedState); DraftWorkflowSchemeStore.DraftState.Builder builder = savedState.builder(); builder.setMappings(scheme.getMappings()); builder.setLastModifiedUser(user == null ? null : user.getKey()); return toWorkflowScheme(draftWorkflowSchemeStore.update(builder.build())); } }); }
return ManagedLocks.manage(lock).withLock(new com.atlassian.util.concurrent.Supplier<Boolean>()