/** * Resolve a concrete address from this service. This service may represent multiple remote sessions, so this will * select one that is online. * * @return A concrete service address. */ public RPCServiceAddress resolve() { if (pattern.startsWith("tcp/")) { int pos = pattern.lastIndexOf('/'); if (pos > 0 && pos < pattern.length() - 1) { RPCServiceAddress ret = new RPCServiceAddress(pattern, pattern.substring(0, pos)); if (!ret.isMalformed()) { return ret; } } } else { if (addressGen != mirror.updates()) { addressGen = mirror.updates(); addressList = mirror.lookup(pattern); } if (addressList != null && addressList.length > 0) { addressIdx = ++addressIdx % addressList.length; Mirror.Entry entry = addressList[addressIdx]; return new RPCServiceAddress(entry.getName(), entry.getSpec()); } } return null; }
public Mirror.Entry[] lookup(RoutingContext context, String pattern) { IMirror mirror1 = (mirror != null ? mirror : context.getMirror()); Mirror.Entry[] arr = mirror1.lookup(pattern); if ((arr.length == 0) && firstTry) { synchronized(this) { try { int count = 0; while (arr.length == 0 && count < 100) { Thread.sleep(50); arr = mirror1.lookup(pattern); count++; } } catch (InterruptedException e) { } } } firstTry = false; return arr; }
@Override public String getTargetSpec(Integer distributor, RoutingContext context) { GenerationCache cache = generationCache; int currentGeneration = getMirror(context).updates(); // The below code might race with other threads during a generation change. That is OK, as the cache // is thread safe and will quickly converge to a stable state for the new generation. if (cache == null || currentGeneration != cache.generation()) { cache = new GenerationCache(currentGeneration); generationCache = cache; } if (distributor != null) { return cachingGetTargetSpec(distributor, context, cache); } // Wildcard lookup case. Must not be cached. return super.getTargetSpec(null, context); }
/** * Wait for a required slobrok state. * * @param slobrokState The state to wait for. * @return Whether or not the required state was reached. */ public boolean waitState(SlobrokState slobrokState) { for (int i = 0; i < 6000 && !Thread.currentThread().isInterrupted(); ++i) { boolean done = true; for (String pattern : slobrokState.getPatterns()) { Mirror.Entry[] res = net.getMirror().lookup(pattern); if (res.length != slobrokState.getCount(pattern)) { done = false; } } if (done) { return true; } try { Thread.sleep(10); } catch (InterruptedException e) { // ignore } } return false; }
/** * Updates and returns the cache entry for the given routing context. This method assumes that synchronization is * handled outside of it. * * @param ctx The routing context. * @return The updated cache entry. */ private CacheEntry update(RoutingContext ctx) { String key = getCacheKey(ctx); CacheEntry entry = cache.get(key); if (entry == null) { entry = new CacheEntry(); cache.put(key, entry); } int upd = ctx.getMirror().updates(); if (entry.generation != upd) { entry.generation = upd; entry.recipients.clear(); Mirror.Entry[] arr = ctx.getMirror().lookup(ctx.getHopPrefix() + "*" + ctx.getHopSuffix()); int pos = ctx.getMessageBus().getConnectionSpec().hashCode(); for (int i = 0; i < subsetSize && i < arr.length; ++i) { entry.recipients.add(Hop.parse(arr[((pos + i) & Integer.MAX_VALUE) % arr.length].getName())); } } return entry; }
/** * Updates and returns the cache entry for the given routing context. This method assumes that synchronization is * handled outside of it. * * @param ctx The routing context. * @return The updated cache entry. */ private CacheEntry update(RoutingContext ctx) { String key = getCacheKey(ctx); CacheEntry entry = cache.get(key); if (entry == null) { entry = new CacheEntry(); cache.put(key, entry); } int upd = ctx.getMirror().updates(); if (entry.generation != upd) { entry.generation = upd; entry.recipients.clear(); for (int i = 0; i < ctx.getNumRecipients(); ++i) { Mirror.Entry[] arr = ctx.getMirror().lookup(ctx.getRecipient(i).getHop(0).toString()); for (Mirror.Entry item : arr) { entry.recipients.add(Hop.parse(item.getName())); } } } return entry; }
/** * Updates and returns the cache entry for the given routing context. This method assumes that synchronization is * handled outside of it. * * @param ctx The routing context. * @return The updated cache entry. */ private CacheEntry update(RoutingContext ctx) { String key = getCacheKey(ctx); CacheEntry entry = cache.get(key); if (entry == null) { entry = new CacheEntry(); cache.put(key, entry); } int upd = ctx.getMirror().updates(); if (entry.generation != upd) { entry.generation = upd; entry.recipients.clear(); Mirror.Entry[] arr = ctx.getMirror().lookup(ctx.getHopPrefix() + "*" + ctx.getHopSuffix()); String self = localAddress != null ? localAddress : toAddress(ctx.getMessageBus().getConnectionSpec()); for (Mirror.Entry item : arr) { if (self.equals(toAddress(item.getSpec()))) { entry.recipients.add(Hop.parse(item.getName())); } } } return entry; }