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

com.xeiam.xchange.coinsetter.service.polling.CoinsetterClientSessionService Maven / Gradle / Ivy

package com.xeiam.xchange.coinsetter.service.polling;

import static com.xeiam.xchange.coinsetter.CoinsetterExchange.ACCOUNT_UUID_KEY;
import static com.xeiam.xchange.coinsetter.CoinsetterExchange.SESSION_HEARTBEAT_INTERVAL_KEY;
import static com.xeiam.xchange.coinsetter.CoinsetterExchange.SESSION_HEARTBEAT_MAX_FAILURE_TIMES_KEY;
import static com.xeiam.xchange.coinsetter.CoinsetterExchange.SESSION_IP_ADDRESS_KEY;
import static com.xeiam.xchange.coinsetter.CoinsetterExchange.SESSION_KEY;
import static com.xeiam.xchange.coinsetter.CoinsetterExchange.SESSION_LOCK_KEY;

import java.io.IOException;
import java.util.concurrent.locks.ReadWriteLock;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.xeiam.xchange.Exchange;
import com.xeiam.xchange.coinsetter.CoinsetterException;
import com.xeiam.xchange.coinsetter.dto.CoinsetterResponse;
import com.xeiam.xchange.coinsetter.dto.account.CoinsetterAccount;
import com.xeiam.xchange.coinsetter.dto.account.CoinsetterAccountList;
import com.xeiam.xchange.coinsetter.dto.clientsession.response.CoinsetterClientSession;

/**
 * Client session manager.
 */
public class CoinsetterClientSessionService extends CoinsetterClientSessionServiceRaw {

  private final Logger log = LoggerFactory.getLogger(CoinsetterClientSessionService.class);

  private final CoinsetterAccountServiceRaw accountServiceRaw;
  private final ReadWriteLock lock;
  private final long heartbeatInterval;
  private final int heartbeatMaxFailureTimes;

  private volatile HeartbeatThread heartbeatThread;

  /**
   * Constructor
   *
   * @param exchange
   */
  public CoinsetterClientSessionService(Exchange exchange) {

    super(exchange);

    accountServiceRaw = new CoinsetterAccountServiceRaw(exchange);
    lock = (ReadWriteLock) exchange.getExchangeSpecification().getExchangeSpecificParametersItem(SESSION_LOCK_KEY);
    heartbeatInterval = (Long) exchange.getExchangeSpecification().getExchangeSpecificParametersItem(SESSION_HEARTBEAT_INTERVAL_KEY);
    heartbeatMaxFailureTimes = (Integer) exchange.getExchangeSpecification()
        .getExchangeSpecificParametersItem(SESSION_HEARTBEAT_MAX_FAILURE_TIMES_KEY);
  }

  public CoinsetterClientSession getSession() throws IOException {

    CoinsetterClientSession session = readSession();

    if (session == null) {
      writeSession();

      // Read again, as we should have.
      session = readSession();
    }

    return session;
  }

  public void logout() throws IOException {
    if (heartbeatThread != null) {
      heartbeatThread.interrupt();
    }

    logout(readSession().getUuid());
  }

  private CoinsetterClientSession readSession() {

    final CoinsetterClientSession session;
    try {
      lock.readLock().lock();
      session = (CoinsetterClientSession) exchange.getExchangeSpecification().getExchangeSpecificParametersItem(SESSION_KEY);
    } finally {
      lock.readLock().unlock();
    }
    return session;
  }

  private void writeSession() throws IOException {

    try {
      lock.writeLock().lock();
      // Got the write lock, now no one else can got read lock or write lock.

      // Check if it is updated by someone else, before we got the write lock.
      if ((CoinsetterClientSession) exchange.getExchangeSpecification().getExchangeSpecificParametersItem(SESSION_KEY) == null) {
        // It is still null, retrieve one from server.

        final CoinsetterClientSession session = login();
        exchange.getExchangeSpecification().setExchangeSpecificParametersItem(SESSION_KEY, session);

        final String heatbeatThreadName = String.format("Coinsetter-heatbeat-%s(%s)-%s", session.getUsername(), session.getCustomerUuid(),
            session.getUuid());
        heartbeatThread = new HeartbeatThread(heatbeatThreadName, session, heartbeatInterval, heartbeatMaxFailureTimes);
        heartbeatThread.start();

        if (exchange.getExchangeSpecification().getExchangeSpecificParametersItem(ACCOUNT_UUID_KEY) == null) {
          CoinsetterAccountList accountList = accountServiceRaw.list(session.getUuid());
          CoinsetterAccount account = accountList.getAccountList()[0];
          exchange.getExchangeSpecification().setExchangeSpecificParametersItem(ACCOUNT_UUID_KEY, account.getAccountUuid());
        }
      }
    } finally {
      lock.writeLock().unlock();
    }
  }

  private CoinsetterClientSession login() throws IOException {

    String ipAddress = (String) exchange.getExchangeSpecification().getExchangeSpecificParametersItem(SESSION_IP_ADDRESS_KEY);
    CoinsetterClientSession session = login(exchange.getExchangeSpecification().getUserName(), exchange.getExchangeSpecification().getPassword(),
        ipAddress);
    return session;
  }

  private class HeartbeatThread extends Thread {

    private final CoinsetterClientSession session;
    private final long heatbeatInterval;
    private final int heartbeatMaxFailureTimes;

    public HeartbeatThread(String name, CoinsetterClientSession session, long heartbeatInterval, int heartbeatMaxFailureTimes) {

      super(name);
      this.session = session;
      this.heatbeatInterval = heartbeatInterval;
      this.heartbeatMaxFailureTimes = heartbeatMaxFailureTimes;
    }

    @Override
    public void run() {

      CoinsetterResponse heatbeatResponse = null;
      int tryTimes = 0;
      do {
        try {
          Thread.sleep(heatbeatInterval);
          heatbeatResponse = heartbeat(session.getUuid());
          log.trace("heatbeat: {}", heatbeatResponse);
          tryTimes = 0;
        } catch (CoinsetterException e) {
          heatbeatResponse = null;
        } catch (IOException e) {
          log.warn(e.getMessage(), e);
          tryTimes++;
        } catch (InterruptedException e) {
          log.debug("Interrupted: {}", e.getMessage());
          this.interrupt();
        }
      } while (!this.isInterrupted() && tryTimes < heartbeatMaxFailureTimes && heatbeatResponse != null
          && "SUCCESS".equals(heatbeatResponse.getRequestStatus()));

      // Session logged out or session is invalid
      log.debug("Session logged out or session is invalid.");
      try {
        lock.writeLock().lock();
        exchange.getExchangeSpecification().setExchangeSpecificParametersItem(SESSION_KEY, null);
      } finally {
        lock.writeLock().unlock();
      }
    }

  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy