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

org.jgroups.protocols.FILE_PING Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 35.0.0.Beta1
Show newest version
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.Property;
import org.jgroups.util.Responses;
import org.jgroups.util.UUID;
import org.jgroups.util.Util;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;


/**
 * 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.

* The design is at doc/design/FILE_PING.txt * @author Bela Ban */ 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"; @Deprecated @Property(description="Interval (in milliseconds) at which the own Address is written. 0 disables it.") protected long interval=60000; @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=new FilenameFilter() { public boolean accept(File dir, String name) {return name.endsWith(SUFFIX);} }; protected volatile View prev_view; public boolean isDynamic() {return true;} 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

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(Arrays.asList(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=phys_addr == null || !phys_addr.equals(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); } protected void createRootDir() { root_dir=new File(location); if(root_dir.exists()) { if(!root_dir.isDirectory()) throw new IllegalArgumentException("location " + root_dir.getPath() + " is not a directory"); } else root_dir.mkdirs(); if(!root_dir.exists()) throw new IllegalArgumentException("location " + root_dir.getPath() + " could not be accessed"); } // remove all files which are not from the current members protected void handleView(View new_view, View old_view, boolean coord_changed) { if(coord_changed) { if(is_coord) writeAll(); else remove(cluster_name, local_addr); } } protected void remove(String clustername, Address addr) { if(clustername == null || addr == null) return; File dir=new File(root_dir, clustername); if(!dir.exists()) return; log.debug("remove %s", clustername); String filename=addressToFilename(addr); File file=new File(dir, filename); deleteFile(file); } protected void readAll(List
members, String clustername, Responses responses) { File dir=new File(root_dir, clustername); if(!dir.exists()) dir.mkdir(); File[] files=dir.listFiles(filter); // finds all files ending with '.list' for(File file: files) { List list=null; // implementing a simple spin lock doing a few attempts to read the file // this is done since the file may be written in concurrency and may therefore not be readable for(int i=0; i < 3; i++) { if(file.exists()) { try { if((list=read(file)) != null) break; } catch(Exception e) { } } Util.sleep(50); } if(list == null) { log.warn("failed reading " + file.getAbsolutePath()); continue; } for(PingData data: list) { if(members == null || members.contains(data.getAddress())) responses.addResponse(data, true); if(local_addr != null && !local_addr.equals(data.getAddress())) addDiscoveryResponseToCaches(data.getAddress(), data.getLogicalName(), data.getPhysicalAddr()); } } } // Format: [name] [UUID] [address:port] [coord (T or F)]. See doc/design/CloudBasedDiscovery.txt for details protected List read(File file) throws Exception { return read(new FileInputStream(file)); } @Override protected List read(InputStream in) { try { return super.read(in); } finally { reads++; } } /** Write information about all of the member to file (only if I'm the coord) */ protected void writeAll() { Map cache_contents= (Map)down_prot.down(new Event(Event.GET_LOGICAL_PHYSICAL_MAPPINGS, false)); List list=new ArrayList<>(cache_contents.size()); for(Map.Entry entry: cache_contents.entrySet()) { Address addr=entry.getKey(); PhysicalAddress phys_addr=entry.getValue(); PingData data=new PingData(addr, true, UUID.get(addr), phys_addr).coord(addr.equals(local_addr)); list.add(data); } write(list, cluster_name); } protected void write(List list, String clustername) { File dir=new File(root_dir, clustername); if(!dir.exists()) dir.mkdir(); String filename=addressToFilename(local_addr); File destination=new File(dir, filename); try { write(list, new FileOutputStream(destination)); } catch(Exception ioe) { log.error("attempt to write data failed at " + clustername + " : " + destination.getName(), ioe); deleteFile(destination); } } protected void write(List list, OutputStream out) throws Exception { try { super.write(list, out); } finally { writes++; } } protected boolean deleteFile(File file) { boolean result = true; if(log.isTraceEnabled()) log.trace("Attempting to delete file : "+file.getAbsolutePath()); if(file != null && file.exists()) { try { result=file.delete(); log.trace("Deleted file result: "+file.getAbsolutePath() +" : "+result); } catch(Throwable e) { log.error("Failed to delete file: " + file.getAbsolutePath(), e); } } return result; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy