private void read (ControlMessage first) throws SocketException, IOException,
            UnsupportedOperationException {
        
        String filename = first.ParseEControl();
        

        if (filename == null) {
            /* This means that the client is requesting a node 
             * list. That is the task for ClusterMgr
             */
            log.fine("Node list request received");
            ClusterMgr c = ClusterMgr.getInstance();
            String clustrInfo = c.prepareJoinMessagePayload();
            ControlMessage nodeListMsg = new ControlMessage('j',
                    sock.getInetAddress(), 0, clustrInfo);
            log.fine("Sending the node list to client");
            oOut.writeObject(nodeListMsg);
            oOut.flush();

        } else {
            
            log.log(Level.FINE, "Received a read request for file {0}",
                filename);
            /*
             * First get the list of nodes that have chunks of this file
             */

            NetMgr netmgr = new NetMgr (sock.getLocalPort());
            ControlMessage probe = new ControlMessage ('e', 
                    NetMgr.getBroadcastAddr(), filename);
            log.log(Level.FINE, "Querying for the chunk list of file {0}", 
                    filename);
            netmgr.send(probe, ConfigMgr.getCoOrdPort());
            netmgr.setTimeout(1000);
            HashMap<Integer, LinkedList<InetAddress>> chunkMap = 
                    new HashMap<>();
            
            while (true) {
            
                log.fine("Waiting for chunk reply");
                ControlMessage reply = null;
                try {
                    reply = (ControlMessage) netmgr.receive();
                } catch (SocketTimeoutException e) {
                    /* This means no more replies are coming.
                     * We must have gotten all of them.
                     */
                    log.fine("Tired of waiting for chunk replies");
                    break;
                }
                
                
                if (reply.getMessageSubtype() != 'k') {
                    continue;
                }
                
                String data = reply.parseKControl();
                String[] chunkIds = data.split(":");
                InetAddress addr = reply.getSourceIp();
                
                for (String id:chunkIds) {
                    /* Prepare a map in which chunkId is key and InetAddress
                     * list is value.
                     */
                    if (id.equals("")) {
                        continue;
                    }
                    Integer i = Integer.parseInt(id);
                    if (chunkMap.containsKey(i)) {
                        LinkedList<InetAddress> foo = chunkMap.get(i);
                        foo.add(addr);
                        chunkMap.put(i, foo);
                    } else {
                        LinkedList<InetAddress> foo = new LinkedList<>();
                        foo.add(addr);
                        chunkMap.put(i, foo);
                    }
                }
                
            }
            
            /* We are here means chunk map is prepared. Now prepare the list 
             * message to be sent.
             */
            String payload = prepareChunkNodeList (chunkMap);
            ControlMessage list = new ControlMessage ('l', 
                    sock.getInetAddress(), payload);
            oOut.writeObject(list);
            oOut.flush();

        }
    }