/** Returns locks that have been successfully acquired */ protected synchronized List<Tuple<String,Owner>> getLockInfo() { List<Tuple<String,Owner>> l=new ArrayList<>(); // table.forEach((key, value) -> value.keySet().forEach(owner -> l.add(new Tuple<>(key, owner)))); table.forEach((k,v) -> v.forEach((owner, cl) -> { if(cl.acquired && !cl.denied) l.add(new Tuple<>(k, owner)); })); return l; }
public List<Tuple<Address,Long>> getMembersWithCreditsLessThan(long min_credits) { List<Tuple<Address,Long>> retval=new LinkedList<>(); lock.lock(); try { flushAccumulatedCredits(); credits.entrySet().stream().filter(entry -> entry.getValue() <= min_credits) .forEach(entry -> retval.add(new Tuple<>(entry.getKey(), entry.getValue()))); return retval; } finally { lock.unlock(); } }
/** Adds received INFO to views hashmap */ protected void addInfo(Address sender, ViewId view_id, String logical_name, PhysicalAddress physical_addr) { if(logical_name != null && sender instanceof UUID) NameCache.add(sender, logical_name); if(physical_addr != null) down(new Event(Event.ADD_PHYSICAL_ADDRESS, new Tuple<>(sender, physical_addr))); synchronized(views) { ViewId existing=views.get(sender); if(existing == null || existing.compareTo(view_id) < 0) views.put(sender, view_id); } }
protected boolean addDiscoveryResponseToCaches(Address mbr, String logical_name, PhysicalAddress physical_addr) { if(mbr == null) return false; if(logical_name != null) NameCache.add(mbr, logical_name); if(physical_addr != null) return (Boolean)down(new Event(Event.ADD_PHYSICAL_ADDRESS, new Tuple<>(mbr, physical_addr))); return false; }
protected Tuple<InputStream,Object> createStreamToProvider(final Address provider, final StateHeader hdr) { Util.close(input_stream); input_stream=new BlockingInputStream(buffer_size); return new Tuple<>(input_stream, null); }
protected void removeFromAddressMappings(Address client_addr) { if(client_addr == null) return; Set<Tuple<String,Address>> suspects=null; // group/address pairs for(Map.Entry<String,ConcurrentMap<Address,Entry>> entry: address_mappings.entrySet()) { ConcurrentMap<Address,Entry> map=entry.getValue(); for(Map.Entry<Address,Entry> entry2: map.entrySet()) { Entry e=entry2.getValue(); if(client_addr.equals(e.client_addr)) { map.remove(entry2.getKey()); log.debug("connection to %s closed", client_addr); if(map.isEmpty()) address_mappings.remove(entry.getKey()); if(suspects == null) suspects=new HashSet<>(); suspects.add(new Tuple<>(entry.getKey(), entry2.getKey())); break; } } } if(emit_suspect_events && suspects != null && !suspects.isEmpty()) { for(Tuple<String,Address> suspect: suspects) { String group=suspect.getVal1(); Address addr=suspect.getVal2(); ConcurrentMap<Address,Entry> map=address_mappings.get(group); if(map == null) continue; GossipData data=new GossipData(GossipType.SUSPECT, group, addr); sendToAllMembersInGroup(map.entrySet(), data); } } }
/** Called by ping task; will result in all members of host getting suspected */ protected void suspect(InetAddress host) { List<Address> suspects; suspect_history.add(new Tuple<>(host, System.currentTimeMillis())); // we need wall clock time here synchronized(hosts) { List<Address> tmp=hosts.get(host); suspects=tmp != null? new ArrayList<>(tmp) : null; } if(suspects != null) { log.debug("%s: suspecting host %s; suspected members: %s", local_addr, host, Util.printListWithDelimiter(suspects, ",")); suspect(suspects); } }
protected void suspect(List<Address> suspects) { if(suspects == null || suspects.isEmpty()) return; num_suspect_events+=suspects.size(); final List<Address> eligible_mbrs=new ArrayList<>(); synchronized(this) { for(Address suspect: suspects) { suspect_history.add(new Tuple<>(suspect, System.currentTimeMillis())); suspected_mbrs.add(suspect); } eligible_mbrs.addAll(members); eligible_mbrs.removeAll(suspected_mbrs); has_suspected_mbrs=!suspected_mbrs.isEmpty(); } // Check if we're coord, then send up the stack if(local_addr != null && !eligible_mbrs.isEmpty() && local_addr.equals(eligible_mbrs.get(0))) { log.debug("%s: suspecting %s", local_addr, suspects); up_prot.up(new Event(Event.SUSPECT, suspects)); down_prot.down(new Event(Event.SUSPECT, suspects)); } }
protected void suspect(List<Address> suspects) { if(suspects == null || suspects.isEmpty()) return; num_suspect_events+=suspects.size(); final List<Address> eligible_mbrs; synchronized(this) { for(Address suspect: suspects) { suspect_history.add(new Tuple<>(suspect, System.currentTimeMillis())); // need wall clock time suspected_mbrs.add(suspect); } eligible_mbrs=new ArrayList<>(members); eligible_mbrs.removeAll(suspected_mbrs); has_suspected_mbrs=!suspected_mbrs.isEmpty(); } // Check if we're coord, then send up the stack if(local_addr != null && !eligible_mbrs.isEmpty() && local_addr.equals(eligible_mbrs.get(0))) { log.debug("%s: suspecting %s", local_addr, suspects); up_prot.up(new Event(Event.SUSPECT, suspects)); down_prot.down(new Event(Event.SUSPECT, suspects)); } }
public void readFrom(DataInput in) throws Exception { int size=in.readInt(); if(size > 0) { existing_locks=new ArrayList<>(size); for(int i=0; i < size; i++) { String lock_name=Bits.readString(in); Owner owner=new Owner(); owner.readFrom(in); existing_locks.add(new Tuple<>(lock_name, owner)); } } size=in.readInt(); if(size > 0) { pending_requests=new ArrayList<>(); for(int i=0; i < size; i++) { Request req=new Request(); req.readFrom(in); pending_requests.add(req); } } }
public void fetchSecretKeyFrom(Address target) throws Exception { try(SSLSocket sock=createSocketTo(target)) { DataInput in=new DataInputStream(sock.getInputStream()); OutputStream out=sock.getOutputStream(); // send the secret key request out.write(Type.SECRET_KEY_REQ.ordinal()); out.flush(); byte ordinal=in.readByte(); Type rsp=Type.values()[ordinal]; if(rsp != Type.SECRET_KEY_RSP) throw new IllegalStateException(String.format("expected response of %s but got type=%d", Type.SECRET_KEY_RSP, ordinal)); int version_len=in.readInt(); byte[] version=new byte[version_len]; in.readFully(version); int secret_key_len=in.readInt(); byte[] secret_key=new byte[secret_key_len]; in.readFully(secret_key); SecretKey sk=new SecretKeySpec(secret_key, secret_key_algorithm); Tuple<SecretKey,byte[]> tuple=new Tuple<>(sk, version); log.debug("%s: sending up secret key (version: %s)", local_addr, Util.byteArrayToHexString(version)); up_prot.up(new Event(Event.SET_SECRET_KEY, tuple)); } }
protected Tuple<InputStream,Object> createStreamToProvider(Address provider, StateHeader hdr) throws Exception { IpAddress address=hdr.bind_addr; Socket socket=null; try { socket=getSocketFactory().createSocket("jgroups.state_sock.sock"); socket.bind(new InetSocketAddress(bind_addr, 0)); socket.setReceiveBufferSize(buffer_size); Util.connect(socket, new InetSocketAddress(address.getIpAddress(), address.getPort()), 0); log.debug("%s: connected to state provider %s:%d", local_addr, address.getIpAddress(), address.getPort()); DataOutputStream out=new DataOutputStream(socket.getOutputStream()); Util.writeAddress(local_addr, out); return new Tuple<>(new BufferedInputStream(socket.getInputStream(), buffer_size), socket); } catch(Throwable t) { Util.close(socket); if(t instanceof Exception) throw (Exception)t; throw new Exception("failed creating socket", t); } }
public Counter getOrCreateCounter(String name, long initial_value) { if(local_addr == null) throw new IllegalArgumentException("the channel needs to be connected before creating or getting a counter"); Owner owner=getOwner(); GetOrCreateRequest req=new GetOrCreateRequest(owner, name, initial_value); Promise<long[]> promise=new Promise<>(); pending_requests.put(owner, new Tuple<>(req, promise)); sendRequest(coord, req); long[] result=new long[0]; try { result=promise.getResultWithTimeout(timeout); long value=result[0], version=result[1]; if(!coord.equals(local_addr)) counters.put(name, new VersionedValue(value, version)); return new CounterImpl(name); } catch(TimeoutException e) { throw new RuntimeException(e); } }
/** * Installs a new rule * @param name The name of the rule * @param interval Number of ms between executions of the rule * @param rule The rule */ public void installRule(String name, long interval, Rule rule) { rule.supervisor(this).log(log).init(); Future<?> future=timer.scheduleAtFixedRate(rule, interval, interval, TimeUnit.MILLISECONDS); Tuple<Rule,Future<?>> existing=rules.put(name != null? name : rule.name(), new Tuple<>(rule, future)); if(existing != null) existing.getVal2().cancel(true); }
protected Tuple<Collection<? extends Address>,Digest> readParticipantsAndDigest(byte[] buffer, int offset, int length) { if(buffer == null) return null; try { DataInput in=new ByteArrayDataInputStream(buffer, offset, length); Collection<Address> participants=Util.readAddresses(in, ArrayList::new); Digest digest=Util.readStreamable(Digest::new, in); return new Tuple<>(participants, digest); } catch(Exception ex) { log.error("%s: failed reading particpants and digest from message: %s", localAddress, ex); return null; } }
@Override public long addAndGet(long delta) { if(local_addr.equals(coord)) { VersionedValue val=getCounter(name); long retval=val.addAndGet(delta)[0]; if(backup_coords != null) updateBackups(name, val.value, val.version); return retval; } Owner owner=getOwner(); Request req=new AddAndGetRequest(owner, name, delta); Promise<long[]> promise=new Promise<>(); pending_requests.put(owner, new Tuple<>(req, promise)); sendRequest(coord, req); Object obj=null; try { obj=promise.getResultWithTimeout(timeout); if(obj instanceof Throwable) throw new IllegalStateException((Throwable)obj); long[] result=(long[])obj; long value=result[0], version=result[1]; if(!coord.equals(local_addr)) counters.put(name, new VersionedValue(value, version)); return value; } catch(TimeoutException e) { throw new RuntimeException(e); } }
protected void handleSecretKeyResponse(PublicKey dh_public_key, byte[] encrypted_secret_key, byte[] version, Address sender) throws Exception { Tuple<SecretKey,byte[]> tuple=null; log.debug("%s: received public key rsp %s.. from %s", local_addr, print16(dh_public_key), sender); synchronized(this) { key_agreement.doPhase(dh_public_key, true); // Diffie-Hellman secret session key, to decrypt secret key byte[] secret_session_key=key_agreement.generateSecret(); SecretKey hashed_session_key=hash(secret_session_key); Cipher encrypter=Cipher.getInstance(secret_key_algorithm); encrypter.init(Cipher.DECRYPT_MODE, hashed_session_key); byte[] secret_key=encrypter.doFinal(encrypted_secret_key); // <-- this is the shared group key SecretKey sk=new SecretKeySpec(secret_key, secret_key_algorithm); tuple=new Tuple<>(sk, version); dh_key=null; } log.debug("%s: sending up secret key (version: %s)", local_addr, Util.byteArrayToHexString(version)); up_prot.up(new Event(Event.SET_SECRET_KEY, tuple)); }
public Object up(Event evt) { switch(evt.type()) { case Event.GET_SECRET_KEY: return new Tuple<>(secret_key, sym_version); case Event.SET_SECRET_KEY: Tuple<SecretKey,byte[]> tuple=evt.arg(); try { setKeys(null, tuple.getVal1(), tuple.getVal2()); } catch(Exception ex) { log.error("failed setting secret key", ex); } return null; } return up_prot.up(evt); }
/** Returns the current view and digest. Try to find a matching digest twice (if not found on the first try) */ public Tuple<View,Digest> getViewAndDigest() { MutableDigest digest=new MutableDigest(view.getMembersRaw()).set(getDigest()); return digest.allSet() || digest.set(getDigest()).allSet()? new Tuple<>(view, digest) : null; }
public static Tuple<View,Digest> _readViewAndDigest(byte[] buffer, int offset, int length) throws Exception { if(buffer == null) return null; DataInput in=new ByteArrayDataInputStream(buffer, offset, length); View tmp_view=null; Digest digest=null; short flags=in.readShort(); if((flags & VIEW_PRESENT) == VIEW_PRESENT) { tmp_view=(flags & MERGE_VIEW) == MERGE_VIEW? new MergeView() : (flags & DELTA_VIEW) == DELTA_VIEW? new DeltaView() : new View(); tmp_view.readFrom(in); } if((flags & DIGEST_PRESENT) == DIGEST_PRESENT) { if((flags & READ_ADDRS) == READ_ADDRS) { digest=new Digest(); digest.readFrom(in); } else { digest=new Digest(tmp_view.getMembersRaw()); digest.readFrom(in,false); } } return new Tuple<>(tmp_view, digest); }