<commit_before>package org.jgroups.protocols;

import org.jgroups.Address;
import org.jgroups.Event;
import org.jgroups.PhysicalAddress;
import org.jgroups.View;
import org.jgroups.annotations.ManagedAttribute;
import org.jgroups.annotations.ManagedOperation;
import org.jgroups.annotations.Property;
import org.jgroups.util.Responses;
import org.jgroups.util.TimeScheduler;
import org.jgroups.util.UUID;
import org.jgroups.util.Util;

import java.io.*;
import java.util.*;
import java.util.concurrent.Future;


/**
 * Simple discovery protocol which uses a file on shared storage such as an SMB share, NFS mount or S3. The local
 * address information, e.g. UUID and physical addresses mappings are written to the file and the content is read and
 * added to our transport's UUID-PhysicalAddress cache.<p/>
 * The design is at doc/design/FILE_PING.txt
 * @author <NAME>
 */
public class FILE_PING extends Discovery {
    protected static final String SUFFIX=".list";

    /* -----------------------------------------    Properties     -------------------------------------------------- */


    @Property(description="The absolute path of the shared file")
    protected String location=File.separator + "tmp" + File.separator + "jgroups";

    @Property(description="If true, on a view change, the new coordinator removes files from old coordinators")
    protected boolean remove_old_coords_on_view_change=false;

    @Property(description="If true, on a view change, the new coordinator removes all files except its own")
    protected boolean remove_all_files_on_view_change=false;

    @Property(description="The max number of times my own information should be written to the DB after a view change")
    protected int info_writer_max_writes_after_view=2;

    @Property(description="Interval (in ms) at which the info writer should kick in")
    protected long info_writer_sleep_time=10000;


    @ManagedAttribute(description="Number of writes to the file system or cloud store")
    protected int writes;

    @ManagedAttribute(description="Number of reads from the file system or cloud store")
    protected int reads;


    /* --------------------------------------------- Fields ------------------------------------------------------ */
    protected File                        root_dir=null;
    protected static final FilenameFilter filter=(dir, name1) -> name1.endsWith(SUFFIX);
    protected Future<?>                   info_writer;

    public boolean isDynamic() {return true;}

    @ManagedAttribute(description="Whether the InfoWriter task is running")
    public synchronized boolean isInfoWriterRunning() {return info_writer != null && !info_writer.isDone();}

    @ManagedOperation(description="Causes the member to write its own information into the DB, replacing an existing entry")
    public void writeInfo() {if(is_coord) writeAll();}

    public void init() throws Exception {
        super.init();
        createRootDir();
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                remove(cluster_name, local_addr);
            }
        });
    }


    public void resetStats() {
        super.resetStats();
        reads=writes=0;
    }

    public Object down(Event evt) {
        switch(evt.getType()) {
            case Event.VIEW_CHANGE:
                View old_view=view;
                boolean previous_coord=is_coord;
                Object retval=super.down(evt);
                View new_view=(View)evt.getArg();
                handleView(new_view, old_view, previous_coord != is_coord);
                return retval;
            case Event.DISCONNECT:
                remove(cluster_name, local_addr);
                break;
        }
        return super.down(evt);
    }

    public void findMembers(final List<Address> members, final boolean initial_discovery, Responses responses) {
        try {
            readAll(members, cluster_name, responses);
            if(responses.isEmpty()) {
                PhysicalAddress physical_addr=(PhysicalAddress)down(new Event(Event.GET_PHYSICAL_ADDRESS,local_addr));
                PingData coord_data=new PingData(local_addr, true, UUID.get(local_addr), physical_addr).coord(is_coord);
                write(Collections.singletonList(coord_data), cluster_name);
                return;
            }

            PhysicalAddress phys_addr=(PhysicalAddress)down_prot.down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr));
            PingData data=responses.findResponseFrom(local_addr);
            // the logical addr *and* IP address:port have to match
            if(data != null && data.getPhysicalAddr().equals(phys_addr)) {
                if(data.isCoord() && initial_discovery)
                    responses.clear();
                else
                    ; // use case #1 if we have predefined files: most members join but are not coord
            }
            else {
                sendDiscoveryResponse(local_addr, phys_addr, UUID.get(local_addr), null, false);
            }
        }
        finally {
            responses.done();
        }
    }



    /** Only add the discovery response if the logical address is not present or the physical addrs are different */
    protected boolean addDiscoveryResponseToCaches(Address mbr, String logical_name, PhysicalAddress physical_addr) {
        PhysicalAddress phys_addr=(PhysicalAddress)down_prot.down(new Event(Event.GET_PHYSICAL_ADDRESS, mbr));
        boolean added=!Objects.equals(phys_addr, physical_addr);
        super.addDiscoveryResponseToCaches(mbr, logical_name, physical_addr);
        if(added && is_coord)
            writeAll();
        return added;
    }

    protected static String addressToFilename(Address mbr) {
        String logical_name=UUID.get(mbr);
        return (addressAsString(mbr) + (logical_name != null? "." + logical_name + SUFFIX : SUFFIX))
          .replaceAll("[\0<>:\"/\\|?*]", "-");
    }
<commit_msg>Moved regexp created in addressToFilename() to static field<commit_after>package org.jgroups.protocols;

import org.jgroups.Address;
import org.jgroups.Event;
import org.jgroups.PhysicalAddress;
import org.jgroups.View;
import org.jgroups.annotations.ManagedAttribute;
import org.jgroups.annotations.ManagedOperation;
import org.jgroups.annotations.Property;
import org.jgroups.util.Responses;
import org.jgroups.util.TimeScheduler;
import org.jgroups.util.UUID;
import org.jgroups.util.Util;

import java.io.*;
import java.util.*;
import java.util.concurrent.Future;
import java.util.regex.Pattern;


/**
 * Simple discovery protocol which uses a file on shared storage such as an SMB share, NFS mount or S3. The local
 * address information, e.g. UUID and physical addresses mappings are written to the file and the content is read and
 * added to our transport's UUID-PhysicalAddress cache.<p/>
 * The design is at doc/design/FILE_PING.txt
 * @author <NAME>
 */
public class FILE_PING extends Discovery {
    protected static final String SUFFIX=".list";
    protected static final Pattern regexp=Pattern.compile("[\0<>:\"/\\|?*]");

    /* -----------------------------------------    Properties     -------------------------------------------------- */


    @Property(description="The absolute path of the shared file")
    protected String location=File.separator + "tmp" + File.separator + "jgroups";

    @Property(description="If true, on a view change, the new coordinator removes files from old coordinators")
    protected boolean remove_old_coords_on_view_change=false;

    @Property(description="If true, on a view change, the new coordinator removes all files except its own")
    protected boolean remove_all_files_on_view_change=false;

    @Property(description="The max number of times my own information should be written to the DB after a view change")
    protected int info_writer_max_writes_after_view=2;

    @Property(description="Interval (in ms) at which the info writer should kick in")
    protected long info_writer_sleep_time=10000;


    @ManagedAttribute(description="Number of writes to the file system or cloud store")
    protected int writes;

    @ManagedAttribute(description="Number of reads from the file system or cloud store")
    protected int reads;


    /* --------------------------------------------- Fields ------------------------------------------------------ */
    protected File                        root_dir=null;
    protected static final FilenameFilter filter=(dir, name1) -> name1.endsWith(SUFFIX);
    protected Future<?>                   info_writer;

    public boolean isDynamic() {return true;}

    @ManagedAttribute(description="Whether the InfoWriter task is running")
    public synchronized boolean isInfoWriterRunning() {return info_writer != null && !info_writer.isDone();}

    @ManagedOperation(description="Causes the member to write its own information into the DB, replacing an existing entry")
    public void writeInfo() {if(is_coord) writeAll();}

    public void init() throws Exception {
        super.init();
        createRootDir();
        Runtime.getRuntime().addShutdownHook(new Thread() {
            public void run() {
                remove(cluster_name, local_addr);
            }
        });
    }


    public void resetStats() {
        super.resetStats();
        reads=writes=0;
    }

    public Object down(Event evt) {
        switch(evt.getType()) {
            case Event.VIEW_CHANGE:
                View old_view=view;
                boolean previous_coord=is_coord;
                Object retval=super.down(evt);
                View new_view=(View)evt.getArg();
                handleView(new_view, old_view, previous_coord != is_coord);
                return retval;
            case Event.DISCONNECT:
                remove(cluster_name, local_addr);
                break;
        }
        return super.down(evt);
    }

    public void findMembers(final List<Address> members, final boolean initial_discovery, Responses responses) {
        try {
            readAll(members, cluster_name, responses);
            if(responses.isEmpty()) {
                PhysicalAddress physical_addr=(PhysicalAddress)down(new Event(Event.GET_PHYSICAL_ADDRESS,local_addr));
                PingData coord_data=new PingData(local_addr, true, UUID.get(local_addr), physical_addr).coord(is_coord);
                write(Collections.singletonList(coord_data), cluster_name);
                return;
            }

            PhysicalAddress phys_addr=(PhysicalAddress)down_prot.down(new Event(Event.GET_PHYSICAL_ADDRESS, local_addr));
            PingData data=responses.findResponseFrom(local_addr);
            // the logical addr *and* IP address:port have to match
            if(data != null && data.getPhysicalAddr().equals(phys_addr)) {
                if(data.isCoord() && initial_discovery)
                    responses.clear();
                else
                    ; // use case #1 if we have predefined files: most members join but are not coord
            }
            else {
                sendDiscoveryResponse(local_addr, phys_addr, UUID.get(local_addr), null, false);
            }
        }
        finally {
            responses.done();
        }
    }



    /** Only add the discovery response if the logical address is not present or the physical addrs are different */
    protected boolean addDiscoveryResponseToCaches(Address mbr, String logical_name, PhysicalAddress physical_addr) {
        PhysicalAddress phys_addr=(PhysicalAddress)down_prot.down(new Event(Event.GET_PHYSICAL_ADDRESS, mbr));
        boolean added=!Objects.equals(phys_addr, physical_addr);
        super.addDiscoveryResponseToCaches(mbr, logical_name, physical_addr);
        if(added && is_coord)
            writeAll();
        return added;
    }

    protected static String addressToFilename(Address mbr) {
        String logical_name=UUID.get(mbr);
        String name=(addressAsString(mbr) + (logical_name != null? "." + logical_name + SUFFIX : SUFFIX));
        return regexp.matcher(name).replaceAll("-");
    }

{'fraction_non_alphanumeric': 0.11991062562065541, 'fraction_numerical': 0.0019860973187686196, 'mean_word_length': 2.5670011806375443, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5701966', 'n_tokens_mistral': 3183, 'n_tokens_neox': 3061, 'n_words': 877}