/**
   * Processes unlock request.
   *
   * @param nodeId Sender node ID.
   * @param req Unlock request.
   */
  @SuppressWarnings({"unchecked"})
  private void processUnlockRequest(UUID nodeId, GridDistributedUnlockRequest req) {
    assert nodeId != null;

    try {
      ClassLoader ldr = ctx.deploy().globalLoader();
      List<byte[]> keys = req.keyBytes();

      for (byte[] keyBytes : keys) {
        K key = (K) U.unmarshal(ctx.marshaller(), new ByteArrayInputStream(keyBytes), ldr);

        while (true) {
          boolean created = false;

          GridDistributedCacheEntry<K, V> entry = peekexx(key);

          if (entry == null) {
            entry = entryexx(key);

            created = true;
          }

          try {
            entry.doneRemote(
                req.version(), req.version(), req.committedVersions(), req.rolledbackVersions());

            // Note that we don't reorder completed versions here,
            // as there is no point to reorder relative to the version
            // we are about to remove.
            if (entry.removeLock(req.version())) {
              if (log.isDebugEnabled())
                log.debug("Removed lock [lockId=" + req.version() + ", key=" + key + ']');

              if (created && entry.markObsolete(req.version())) removeIfObsolete(entry.key());
            } else if (log.isDebugEnabled())
              log.debug(
                  "Received unlock request for unknown candidate "
                      + "(added to cancelled locks set): "
                      + req);

            break;
          } catch (GridCacheEntryRemovedException ignored) {
            if (log.isDebugEnabled())
              log.debug(
                  "Received remove lock request for removed entry (will retry) [entry="
                      + entry
                      + ", req="
                      + req
                      + ']');
          }
        }
      }
    } catch (GridException e) {
      U.error(log, "Failed to unmarshal unlock key (unlock will not be performed): " + req, e);
    }
  }