/** * @param key Key to lock. * @return Sync object that should be passed to {@link #unlock(Object, Object)} method. */ public <T> Object lock(T key) { assert key != null; boolean interrupted = false; Sync t = new Sync(); try { while (true) { Sync old = locks.putIfAbsent(key, t); if (old != null) { while (true) { try { old.await(); break; } catch (InterruptedException ignored) { interrupted = true; } } } else return t; } } finally { if (interrupted) Thread.currentThread().interrupt(); } }
/** * @param key Key to lock. * @return Sync object that should be passed to {@link #unlock(Object, Object)} method or {@code * null} if try lock failed. */ @Nullable public <T> Object tryLock(T key) { assert key != null; Sync t = new Sync(); Sync old = locks.putIfAbsent(key, t); return old != null ? null : t; }
/** * @param key Key to lock. * @return Sync object that should be passed to {@link #unlock(Object, Object)} method. * @throws InterruptedException If interrupted while acquiring lock. */ public <T> Object lockInterruptibly(T key) throws InterruptedException { assert key != null; Sync t = new Sync(); while (true) { Sync old = locks.putIfAbsent(key, t); if (old != null) old.await(); else return t; } }
/** * @param entries Entries. * @param resFut Result future. * @param activeKeys Active keys. * @param remaps Remaps count. */ private void load0( Collection<? extends Map.Entry<K, V>> entries, final GridFutureAdapter<Object> resFut, final Collection<K> activeKeys, final int remaps) { assert entries != null; if (remaps >= MAX_REMAP_CNT) { resFut.onDone(new GridException("Failed to finish operation (too many remaps): " + remaps)); return; } Map<GridNode, Collection<Map.Entry<K, V>>> mappings = new HashMap<>(); boolean initPda = ctx.deploy().enabled() && jobPda == null; for (Map.Entry<K, V> entry : entries) { GridNode node; try { K key = entry.getKey(); assert key != null; if (initPda) { jobPda = new DataLoaderPda(key, entry.getValue(), updater); initPda = false; } node = ctx.affinity().mapKeyToNode(cacheName, key); } catch (GridException e) { resFut.onDone(e); return; } if (node == null) { resFut.onDone( new GridTopologyException( "Failed to map key to node " + "(no nodes with cache found in topology) [infos=" + entries.size() + ", cacheName=" + cacheName + ']')); return; } Collection<Map.Entry<K, V>> col = mappings.get(node); if (col == null) mappings.put(node, col = new ArrayList<>()); col.add(entry); } for (final Map.Entry<GridNode, Collection<Map.Entry<K, V>>> e : mappings.entrySet()) { final UUID nodeId = e.getKey().id(); Buffer buf = bufMappings.get(nodeId); if (buf == null) { Buffer old = bufMappings.putIfAbsent(nodeId, buf = new Buffer(e.getKey())); if (old != null) buf = old; } final Collection<Map.Entry<K, V>> entriesForNode = e.getValue(); GridInClosure<GridFuture<?>> lsnr = new GridInClosure<GridFuture<?>>() { @Override public void apply(GridFuture<?> t) { try { t.get(); for (Map.Entry<K, V> e : entriesForNode) activeKeys.remove(e.getKey()); if (activeKeys.isEmpty()) resFut.onDone(); } catch (GridException e1) { if (log.isDebugEnabled()) log.debug("Future finished with error [nodeId=" + nodeId + ", err=" + e1 + ']'); if (cancelled) { resFut.onDone( new GridException( "Data loader has been cancelled: " + GridDataLoaderImpl.this, e1)); } else load0(entriesForNode, resFut, activeKeys, remaps + 1); } } }; GridFutureAdapter<?> f; try { f = buf.update(entriesForNode, lsnr); } catch (GridInterruptedException e1) { resFut.onDone(e1); return; } if (ctx.discovery().node(nodeId) == null) { if (bufMappings.remove(nodeId, buf)) buf.onNodeLeft(); if (f != null) f.onDone( new GridTopologyException( "Failed to wait for request completion " + "(node has left): " + nodeId)); } } }