Tuesday 2 August 2016

Implement pooling functionality for connection objects

My friend got this question in an interview. Interviewer given two interfaces like below.

public interface Connection {
  /**
   * Return some integer.
   * 
   * @return
   */
  int read();
  
  /**
   * Close the connection
   */
  void close();
}

public interface ConnectionFactory {
  /* Return a connection object */
  Connection getConnection();
}

Your implementation should support following.
1.   Assume some vendors have their own implementation of Connection and ConnectionFactory interfaces. You need to provide pool of connections functionality to vendor’s implementation.
2.   If pool is empty, on first request new connection object should be added to pool. If all the connection objects from pool are buzy, then you have to create new Connection object and add to pool.
3.   If any connection object is free in the pool, you can use.
4.   It should be thread-safe

To solve this problem, I want to use two collections, one to keep track of working connection objects and other to keep tracking of free connection objects.

private Set<Connection> workingPool = new HashSet<>();
private List<Connection> freePool = new ArrayList<>();

I provided a constructor to ConnectionPool class to initialize Vendor specific connection factory.

public class ConnectionPool {
  private ConnectionFactory factory;
  
  public ConnectionPool(ConnectionFactory factory) {
    this.factory = factory;
  }
}


One thing to be noted is, whenever connection is closed, specific object should come back to the freePool and wait for the next task. Let me implement this use case first.
private class ConnectionImpl implements Connection {
  private Connection conn;

  ConnectionImpl(Connection conn) {
    this.conn = conn;
  }

  @Override
  public int read() {
    return 0;

  }

  @Override
  public void close() {
    conn.close();
    synchronized (obj) {
      workingPool.remove(this);
      freePool.add(this);
    }
  }

}

ConnectionImpl(Connection conn)
Above constructor is used to initialize vendor specific Connection object.

As you observe close() method implementation, after closing the connection, I removed it from workingPool and add it to freePool.


Now let me implement getConnection() method, As per the requirement, if pool has any free connection objects, it should return, else it should create new connection object and it should be thread safe. I implemented getConnection method like below.
public Connection getConnection() {
  Connection conn = null;

  synchronized (obj) {

    if (freePool.isEmpty()) {
      conn = new ConnectionImpl(factory.getConnection());
      workingPool.add(conn);
      return conn;
    }

    conn = freePool.remove(0);
    workingPool.add(conn);
    return conn;

  }

}


Following is the complete working application.
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class ConnectionPool {
  private ConnectionFactory factory;
  private Set<Connection> workingPool = new HashSet<>();
  private List<Connection> freePool = new ArrayList<>();

  /* Dummy object to handle synchronization */
  private Object obj = new Object();

  public ConnectionPool(ConnectionFactory factory) {
    this.factory = factory;
  }

  public Connection getConnection() {
    Connection conn = null;

    synchronized (obj) {
      if (freePool.isEmpty()) {
        conn = new ConnectionImpl(factory.getConnection());
        workingPool.add(conn);
        return conn;
      }

      conn = freePool.remove(0);
      workingPool.add(conn);
      return conn;

    }

  }

  private class ConnectionImpl implements Connection {
    private Connection conn;

    ConnectionImpl(Connection conn) {
      this.conn = conn;
    }

    @Override
    public int read() {
      return 0;

    }

    @Override
    public void close() {
      conn.close();
      synchronized (obj) {
        workingPool.remove(this);
        freePool.add(this);
      }
    }

  }

}


This is my view of implementation, if you had any better suggestions, please comment your answer.

You may like



No comments:

Post a Comment