public boolean clean() { Iterator it = names(); while (it.hasNext()) { Name name; try { name = (Name) it.next(); } catch (ConcurrentModificationException e) { return false; } Object[] elements = findExactSets(name); for (int i = 0; i < elements.length; i++) { Element element = (Element) elements[i]; if (element.expired()) removeSet(name, element.getType(), element); } } return true; }
/** * Looks up Records in the Cache. This follows CNAMEs and handles negatively cached data. * * @param name The name to look up * @param type The type to look up * @param minCred The minimum acceptable credibility * @return A SetResponse object * @see SetResponse * @see Credibility */ public SetResponse lookupRecords(Name name, short type, byte minCred) { SetResponse cr = null; boolean verbose = Options.check("verbosecache"); Object o = lookup(name, type); if (verbose) logLookup(name, type, "Starting"); if (o == null || o == NXRRSET) { /* * The name exists, but the type was not found. Or, the * name does not exist and no parent does either. Punt. */ if (verbose) logLookup(name, type, "no information found"); return SetResponse.ofType(SetResponse.UNKNOWN); } Object[] objects; if (o instanceof Element) objects = new Object[] {o}; else objects = (Object[]) o; int nelements = 0; for (int i = 0; i < objects.length; i++) { Element element = (Element) objects[i]; if (element.expired()) { if (verbose) { logLookup(name, type, element.toString()); logLookup(name, type, "expired: ignoring"); } removeSet(name, type, element); objects[i] = null; } else if (element.credibility < minCred) { if (verbose) { logLookup(name, type, element.toString()); logLookup(name, type, "not credible: ignoring"); } objects[i] = null; } else { nelements++; } } if (nelements == 0) { /* We have data, but can't use it. Punt. */ if (verbose) logLookup(name, type, "no useful data found"); return SetResponse.ofType(SetResponse.UNKNOWN); } /* * We have something at the name. It could be the answer, * a CNAME, DNAME, or NS, or a negative cache entry. * * Ignore wildcards, since it's pretty unlikely that any will be * cached. The occasional extra query is easily balanced by the * reduced number of lookups. */ for (int i = 0; i < objects.length; i++) { if (objects[i] == null) continue; Element element = (Element) objects[i]; if (verbose) logLookup(name, type, element.toString()); RRset rrset = null; if (element instanceof PositiveElement) rrset = ((PositiveElement) element).rrset; /* Is this a negatively cached entry? */ if (rrset == null) { /* * If this is an NXDOMAIN entry, return NXDOMAIN. */ if (element.getType() == 0) { if (verbose) logLookup(name, type, "NXDOMAIN"); return SetResponse.ofType(SetResponse.NXDOMAIN); } /* * If we're not looking for type ANY, return NXRRSET. * Otherwise ignore this. */ if (type != Type.ANY) { if (verbose) logLookup(name, type, "NXRRSET"); return SetResponse.ofType(SetResponse.NXRRSET); } else { if (verbose) logLookup(name, type, "ANY query; " + "ignoring NXRRSET"); continue; } } short rtype = rrset.getType(); Name rname = rrset.getName(); if (name.equals(rname)) { if (type != Type.CNAME && type != Type.ANY && rtype == Type.CNAME) { if (verbose) logLookup(name, type, "cname"); return new SetResponse(SetResponse.CNAME, rrset); } else if (type != Type.NS && type != Type.ANY && rtype == Type.NS) { if (verbose) logLookup(name, type, "exact delegation"); return new SetResponse(SetResponse.DELEGATION, rrset); } else { if (verbose) logLookup(name, type, "exact match"); if (cr == null) cr = new SetResponse(SetResponse.SUCCESSFUL); cr.addRRset(rrset); } } else if (name.subdomain(rname)) { if (rtype == Type.DNAME) { if (verbose) logLookup(name, type, "dname"); return new SetResponse(SetResponse.DNAME, rrset); } else if (rtype == Type.NS) { if (verbose) logLookup(name, type, "parent delegation"); return new SetResponse(SetResponse.DELEGATION, rrset); } else { if (verbose) logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")"); } } else { if (verbose) logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")"); } } /* * As far as I can tell, the only legitimate time cr will be null is * if we queried for ANY and only saw negative responses, but not an * NXDOMAIN. Return UNKNOWN. */ if (cr == null && type == Type.ANY) return SetResponse.ofType(SetResponse.UNKNOWN); else if (cr == null) throw new IllegalStateException( "looking up (" + name + " " + Type.string(type) + "): " + "cr == null."); return cr; }