time_to_wait-=System.currentTimeMillis() - start_time;
time_to_wait=timeout - (System.currentTimeMillis() - start_time);
    public void down(Event evt) {        Message msg;        PingHeader hdr;        long time_to_wait, start_time;        Vector gossip_rsps=null;        switch(evt.getType()) {        case Event.FIND_INITIAL_MBRS:   // sent by GMS layer, pass up a GET_MBRS_OK event            initial_members.removeAllElements();            if(client != null) {                gossip_rsps=client.getMembers(group_addr);                if(gossip_rsps != null && gossip_rsps.size() > 0) {                    // Set a temporary membership in the UDP layer, so that the following multicast                    // will be sent to all of them                    Event view_event=new Event(Event.TMP_VIEW, makeView(gossip_rsps));                    passDown(view_event); // needed e.g. by failure detector or UDP                }                else {                    passUp(new Event(Event.FIND_INITIAL_MBRS_OK, null));                    return;                }                if(gossip_rsps != null && gossip_rsps.size() > 0) {                    for(int i=0; i < gossip_rsps.size(); i++) {                        Address dest=(Address)gossip_rsps.elementAt(i);                        msg=new Message(dest, null, null);  // mcast msg                        msg.putHeader(getName(), new PingHeader(PingHeader.GET_MBRS_REQ, null));                        passDown(new Event(Event.MSG, msg));                    }                }                Util.sleep(500);            }            else {                if(initial_hosts != null && initial_hosts.size() > 0) {                    IpAddress h;                    List hlist;                    msg=new Message(null, null, null);                    msg.putHeader(getName(), new PingHeader(PingHeader.GET_MBRS_REQ, null));                    synchronized(members) {                        int numMembers=members.size();                        int numMemberInitialHosts=0;                        Address coord=numMembers > 0 ? (Address)members.firstElement() : local_addr;                        for(Enumeration en=initial_hosts.elements(); en.hasMoreElements();) {                            hlist=(List)en.nextElement();                            boolean isMember=false;                            for(Enumeration hen=hlist.elements(); hen.hasMoreElements() && !isMember && numMemberInitialHosts < numMembers;) {                                h=(IpAddress)hen.nextElement();                                if(members_set.contains(h)) {                                    //update the initial_members list for this already connected member                                    initial_members.add(new PingRsp(h, coord));                                    isMember=true;                                    numMemberInitialHosts++;                                    if(log.isDebugEnabled())                                        log.debug("[FIND_INITIAL_MBRS] " + h + " is already a member");                                }                            }                            for(Enumeration hen=hlist.elements(); hen.hasMoreElements() && !isMember;) {                                h=(IpAddress)hen.nextElement();                                msg.setDest(h);                                if(log.isTraceEnabled())                                    log.trace("[FIND_INITIAL_MBRS] sending PING request to " + msg.getDest());                                passDown(new Event(Event.MSG, msg.copy()));                            }                        }                    }                }                else {                    // 1. Mcast GET_MBRS_REQ message                    if(log.isTraceEnabled()) log.trace("FIND_INITIAL_MBRS");                    hdr=new PingHeader(PingHeader.GET_MBRS_REQ, null);                    msg=new Message(null, null, null);  // mcast msg                    msg.putHeader(getName(), hdr);                    passDown(new Event(Event.MSG, msg));                }            }            // 2. Wait 'timeout' ms or until 'num_initial_members' have been retrieved            synchronized(initial_members) {                start_time=System.currentTimeMillis();                time_to_wait=timeout;                while(initial_members.size() < num_initial_members && time_to_wait > 0) {                    if(log.isTraceEnabled()) // +++ remove                        log.trace("waiting for initial members: time_to_wait=" + time_to_wait +                                  ", got " + initial_members.size() + " rsps");                    try {                        initial_members.wait(time_to_wait);                    }                    catch(Exception e) {                    }                    time_to_wait-=System.currentTimeMillis() - start_time;                }            }            // 3. Send response            if(log.isDebugEnabled())                log.debug("initial mbrs are " + initial_members);            passUp(new Event(Event.FIND_INITIAL_MBRS_OK, initial_members));            break;        case Event.TMP_VIEW:        case Event.VIEW_CHANGE:            Vector tmp;            if((tmp=((View)evt.getArg()).getMembers()) != null) {                synchronized(members) {                    members.clear();                    members.addAll(tmp);                    members_set.clear();                    members_set.addAll(tmp);                }            }            passDown(evt);            break;        case Event.BECOME_SERVER: // called after client has joined and is fully working group member            passDown(evt);            is_server=true;            // System.out.println("## down(BECOME_SERVER): is_server=" + is_server);            break;        case Event.CONNECT:            group_addr=(String)evt.getArg();            passDown(evt);            if(client != null)                client.register(group_addr, local_addr);            break;        case Event.DISCONNECT:            if(client != null)                client.stop();            passDown(evt);            break;        default:            passDown(evt);          // Pass on to the layer below us            break;        }    }