All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.zeebe.transport.impl.RemoteAddressListImpl Maven / Gradle / Ivy

There is a newer version: 0.16.4
Show newest version
/*
 * Copyright © 2017 camunda services GmbH ([email protected])
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.zeebe.transport.impl;

import io.zeebe.transport.RemoteAddress;
import io.zeebe.transport.RemoteAddressList;
import io.zeebe.transport.SocketAddress;
import java.util.Iterator;
import java.util.function.Consumer;

/** Threadsafe datastructure for indexing remote addresses and assigning streamIds. */
public class RemoteAddressListImpl implements RemoteAddressList {
  private volatile int size;
  private RemoteAddressImpl[] index = new RemoteAddressImpl[0];

  private Consumer onAddressAddedConsumer = r -> {};

  @Override
  public RemoteAddressImpl getByStreamId(int streamId) {
    if (streamId < size) {
      return index[streamId];
    }

    return null;
  }

  /**
   * Returns only active addresses
   *
   * @param inetSocketAddress
   * @return
   */
  @Override
  public RemoteAddressImpl getByAddress(SocketAddress inetSocketAddress) {
    return getByAddress(inetSocketAddress, RemoteAddressImpl.STATE_ACTIVE);
  }

  public RemoteAddressImpl getByAddress(SocketAddress inetSocketAddress, int stateMask) {
    final int currSize = size;

    for (int i = 0; i < currSize; i++) {
      final RemoteAddressImpl remoteAddress = index[i];

      if (remoteAddress != null) {
        if (remoteAddress.getAddress().equals(inetSocketAddress)
            && remoteAddress.isInAnyState(stateMask)) {
          return remoteAddress;
        }
      }
    }

    return null;
  }

  /**
   * Effect: This remote address/stream is never used again; no channel will every be managed for
   * this again; if the underlying socket address is registered again, a new remote address is
   * assigned (+ new stream id)
   */
  @Override
  public synchronized void retire(RemoteAddress remote) {
    getByStreamId(remote.getStreamId()).retire();
  }

  /**
   * This stream is deactivated until it is registered again; the stream id in this case will remain
   * stable
   *
   * @param remote
   */
  @Override
  public synchronized void deactivate(RemoteAddress remote) {
    getByStreamId(remote.getStreamId()).deactivate();
  }

  @Override
  public synchronized void deactivateAll() {
    for (int i = 0; i < size; i++) {
      index[i].deactivate();
    }
  }

  @Override
  public RemoteAddressImpl register(SocketAddress inetSocketAddress) {
    RemoteAddressImpl result = getByAddress(inetSocketAddress);

    if (result == null) {
      synchronized (this) {
        result =
            getByAddress(
                inetSocketAddress,
                RemoteAddressImpl.STATE_ACTIVE | RemoteAddressImpl.STATE_INACTIVE);

        if (result == null) {
          final int prevSize = size;
          final int newSize = prevSize + 1;

          final RemoteAddressImpl remoteAddress =
              new RemoteAddressImpl(prevSize, new SocketAddress(inetSocketAddress));

          final RemoteAddressImpl[] newAddresses = new RemoteAddressImpl[newSize];
          System.arraycopy(index, 0, newAddresses, 0, prevSize);
          newAddresses[remoteAddress.getStreamId()] = remoteAddress;

          this.index = newAddresses;
          this.size = newSize; // publish

          result = remoteAddress;
        } else {
          if (result.isInAnyState(RemoteAddressImpl.STATE_INACTIVE)) {
            result.activate();
          }
        }

        onAddressAddedConsumer.accept(result);
      }
    }

    return result;
  }

  public Iterator iterator() {
    iterator.reset();
    return iterator;
  }

  protected AddressIterator iterator = new AddressIterator();

  protected class AddressIterator implements Iterator {

    protected int curr = 0;
    protected int currentSize;

    public void reset() {
      curr = 0;
      currentSize = size;
    }

    @Override
    public boolean hasNext() {
      return curr < currentSize;
    }

    @Override
    public RemoteAddressImpl next() {
      final RemoteAddressImpl next = index[curr];
      curr++;
      return next;
    }
  };

  public void setOnAddressAddedConsumer(Consumer onAddressAddedConsumer) {
    this.onAddressAddedConsumer = onAddressAddedConsumer;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy