/**
   * Sets the "frozen" state of this job.
   *
   * <p>This is an internal operation to be used only by the <code>{@link CmsScheduleManager}</code>
   * .
   *
   * <p>
   *
   * @param frozen the "frozen" state to set
   */
  protected synchronized void setFrozen(boolean frozen) {

    if (frozen && !m_frozen) {
      // "freeze" the job configuration
      m_parameters = Collections.unmodifiableSortedMap(m_parameters);
      m_context.freeze();
      m_frozen = true;
    } else if (!frozen && m_frozen) {
      // "unfreeze" the job configuration
      m_parameters = new TreeMap<String, String>(m_parameters);
      m_frozen = false;
    }
  }
 public MethodSignature(Configuration configuration, Method method) throws BindingException {
   this.returnType = method.getReturnType();
   this.returnsVoid = void.class.equals(this.returnType);
   this.returnsMany =
       (configuration.getObjectFactory().isCollection(this.returnType)
           || this.returnType.isArray());
   this.mapKey = getMapKey(method);
   this.returnsMap = (this.mapKey != null);
   this.hasNamedParameters = hasNamedParams(method);
   this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
   this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
   this.params = Collections.unmodifiableSortedMap(getParams(method, this.hasNamedParameters));
 }
Example #3
0
 public SortedMap<Instant, Double> getAbscisse(StringBounder stringBounder) {
   final SortedMap<Instant, Double> pos = new TreeMap<Instant, Double>();
   final double caseWidth = getCaseWidth(stringBounder);
   final Instant end = project.getEnd();
   double x = 0;
   for (Instant cur = project.getStart();
       cur.compareTo(end) <= 0;
       cur = cur.next(project.getDayClose())) {
     pos.put(cur, x);
     x += caseWidth;
   }
   return Collections.unmodifiableSortedMap(pos);
 }
  /**
   * @param fromKey Biggest build number to be in the returned set.
   * @param toKey Smallest build number-1 to be in the returned set (-1 because this is exclusive)
   */
  public SortedMap<Integer, R> subMap(Integer fromKey, Integer toKey) {
    // TODO: if this method can produce a lazy map, that'd be wonderful
    // because due to the lack of floor/ceil/higher/lower kind of methods
    // to look up keys in SortedMap, various places of Jenkins rely on
    // subMap+firstKey/lastKey combo.

    R start = search(fromKey, DESC);
    if (start == null) return EMPTY_SORTED_MAP;

    R end = search(toKey, ASC);
    if (end == null) return EMPTY_SORTED_MAP;

    for (R i = start; i != end; ) {
      i = search(getNumberOf(i) - 1, DESC);
      assert i != null;
    }

    return Collections.unmodifiableSortedMap(
        new BuildReferenceMapAdapter<R>(this, index.byNumber.subMap(fromKey, toKey)));
  }
Example #5
0
 /**
  * Caches. Fails silently.
  *
  * @param event matching this event only, case sensitive
  * @param since since this time, 0 for all
  * @return non-null, Map of times to (possibly empty) info strings, sorted, earliest first,
  *     unmodifiable
  */
 public synchronized SortedMap<Long, String> getEvents(String event, long since) {
   SortedMap<Long, String> rv = _cache.get(event);
   if (rv != null) {
     Long cacheTime = _cacheTime.get(event);
     if (cacheTime != null) {
       if (since >= cacheTime.longValue()) return rv.tailMap(Long.valueOf(since));
     }
   }
   rv = new TreeMap<Long, String>();
   BufferedReader br = null;
   try {
     br = new BufferedReader(new InputStreamReader(new FileInputStream(_file), "UTF-8"));
     String line = null;
     while ((line = br.readLine()) != null) {
       try {
         String[] s = line.split(" ", 3);
         if (!s[1].equals(event)) continue;
         long time = Long.parseLong(s[0]);
         if (time <= since) continue;
         Long ltime = Long.valueOf(time);
         String info = s.length > 2 ? s[2] : "";
         rv.put(ltime, info);
       } catch (IndexOutOfBoundsException ioobe) {
       } catch (NumberFormatException nfe) {
       }
     }
     rv = Collections.unmodifiableSortedMap(rv);
     _cache.put(event, rv);
     _cacheTime.put(event, Long.valueOf(since));
   } catch (IOException ioe) {
   } finally {
     if (br != null)
       try {
         br.close();
       } catch (IOException ioe) {
       }
   }
   return rv;
 }
 /**
  * Returns a grouped and sorted map of all registered metrics which match then given {@link
  * MetricPredicate}.
  *
  * @param predicate a predicate which metrics have to match to be in the results
  * @return all registered metrics which match {@code predicate}, sorted by name
  */
 public SortedMap<String, SortedMap<MetricName, Metric>> getGroupedMetrics(
     MetricPredicate predicate) {
   final SortedMap<String, SortedMap<MetricName, Metric>> groups =
       new TreeMap<String, SortedMap<MetricName, Metric>>();
   for (Map.Entry<MetricName, Metric> entry : metrics.entrySet()) {
     final String qualifiedTypeName = entry.getKey().getGroup() + "." + entry.getKey().getType();
     if (predicate.matches(entry.getKey(), entry.getValue())) {
       final String scopedName;
       if (entry.getKey().hasScope()) {
         scopedName = qualifiedTypeName + "." + entry.getKey().getScope();
       } else {
         scopedName = qualifiedTypeName;
       }
       SortedMap<MetricName, Metric> group = groups.get(scopedName);
       if (group == null) {
         group = new TreeMap<MetricName, Metric>();
         groups.put(scopedName, group);
       }
       group.put(entry.getKey(), entry.getValue());
     }
   }
   return Collections.unmodifiableSortedMap(groups);
 }
 /**
  * インスタンスを生成する。
  *
  * @param name 識別子
  * @param command コマンド行
  * @param profileName プロファイル名
  * @param variables 環境変数一覧
  * @throws IllegalArgumentException 引数に{@code null}が指定された場合
  */
 public ScriptWorkDescription(
     String name, String command, String profileName, Map<String, String> variables) {
   if (name == null) {
     throw new IllegalArgumentException("name must not be null"); // $NON-NLS-1$
   }
   if (command == null) {
     throw new IllegalArgumentException("command must not be null"); // $NON-NLS-1$
   }
   if (profileName == null) {
     throw new IllegalArgumentException("profileName must not be null"); // $NON-NLS-1$
   }
   if (variables == null) {
     throw new IllegalArgumentException("variables must not be null"); // $NON-NLS-1$
   }
   if (isValidName(name) == false) {
     throw new IllegalArgumentException(
         MessageFormat.format("{0}はスクリプトの名前として正しくありません ({0})", name, command));
   }
   this.name = name;
   this.command = command;
   this.profileName = profileName;
   this.variables = Collections.unmodifiableSortedMap(new TreeMap<String, String>(variables));
 }
Example #8
0
 /**
  * Provides column metadata map, keyed by attribute name. Table columns correspond to ActiveJDBC
  * model attributes.
  *
  * @return Provides column metadata map, keyed by attribute name.
  */
 public SortedMap<String, ColumnMeta> getColumnMetadata() {
   checkNotNull(columnMetadata, "Failed to found table: " + getTableName());
   return Collections.unmodifiableSortedMap(columnMetadata);
 }
Example #9
0
/**
 * An Entity is an abstract descriptor for an entity mapping concept. Entity can represent either a
 * descriptor of database table or a persistent object.
 *
 * @author Andrei Adamchik
 */
public abstract class Entity extends MapObject {
  public static final String PATH_SEPARATOR = ".";

  // ====================================================
  // Attributes
  // ====================================================
  protected CayenneMap attributes = new CayenneMap(this);
  //  read-through reference for public access
  protected SortedMap attributesMapRef = Collections.unmodifiableSortedMap(attributes);
  //  read-through reference for public access
  protected Collection attributesRef = Collections.unmodifiableCollection(attributes.values());

  // ====================================================
  // Relationships
  // ====================================================
  protected CayenneMap relationships = new CayenneMap(this);
  //  read-through reference for public access
  protected SortedMap relationshipsMapRef = Collections.unmodifiableSortedMap(relationships);
  //  read-through reference for public access
  protected Collection relationshipsRef =
      Collections.unmodifiableCollection(relationships.values());

  /** @return parent DataMap of this entity. */
  public DataMap getDataMap() {
    return (DataMap) getParent();
  }

  /** Sets parent DataMap of this entity. */
  public void setDataMap(DataMap dataMap) {
    this.setParent(dataMap);
  }

  /**
   * Returns a named query associated with this entity.
   *
   * @since 1.1 Return type is changed to Query from SelectQuery.
   * @deprecated Since 1.1 Queries are stored at the DataMap level.
   */
  public Query getQuery(String queryName) {
    return getDataMap().getQuery(getName() + ":" + queryName);
  }

  /**
   * Creates a named association of a SelectQuery with this entity. Throws IllegalArgumentException
   * if query root can not be resolved to this entity.
   *
   * @deprecated Since 1.1 Queries are stored at the DataMap level.
   */
  public void addQuery(String queryName, Query query) {
    query.setName(getName() + ":" + queryName);
    getDataMap().addQuery(query);
  }

  /**
   * Removes a named query from this Entity.
   *
   * @deprecated Since 1.1 Queries are stored at the DataMap level.
   */
  public void removeQuery(String queryName) {
    getDataMap().removeQuery(getName() + ":" + queryName);
  }

  /** @deprecated Since 1.1 Queries are stored at the DataMap level. */
  public void clearQueries() {
    // TODO: for backwards compatibility
    // we must scan all queries that start with this entity
    // name and only clean those.
    getDataMap().clearQueries();
  }

  /**
   * Helper method that checks that a Query belongs to this entity by validating query root object.
   *
   * @throws IllegalArgumentException if query does not belong to this entity.
   * @deprecated Unused since 1.1
   */
  protected abstract void validateQueryRoot(Query query) throws IllegalArgumentException;

  /**
   * Returns attribute with name <code>attrName</code>. Will return null if no attribute with this
   * name exists.
   */
  public Attribute getAttribute(String attrName) {
    return (Attribute) attributes.get(attrName);
  }

  /**
   * Adds new attribute to the entity. If attribute has no name, IllegalArgumentException is thrown.
   *
   * <p>Also sets <code>attr</code>'s entity to be this entity.
   */
  public void addAttribute(Attribute attr) {
    if (attr.getName() == null) {
      throw new IllegalArgumentException("Attempt to insert unnamed attribute.");
    }

    attributes.put(attr.getName(), attr);
  }

  /** Removes an attribute named <code>attrName</code>. */
  public void removeAttribute(String attrName) {
    attributes.remove(attrName);
  }

  public void clearAttributes() {
    attributes.clear();
  }

  /**
   * Returns relationship with name <code>relName</code>. Will return null if no relationship with
   * this name exists in the entity.
   */
  public Relationship getRelationship(String relName) {
    return (Relationship) relationships.get(relName);
  }

  /** Adds new relationship to the entity. */
  public void addRelationship(Relationship rel) {
    relationships.put(rel.getName(), rel);
  }

  /** Removes a relationship named <code>attrName</code>. */
  public void removeRelationship(String relName) {
    relationships.remove(relName);
  }

  public void clearRelationships() {
    relationships.clear();
  }

  /** Returns a map of relationships sorted by name. */
  public SortedMap getRelationshipMap() {
    return relationshipsMapRef;
  }

  /**
   * Returns a relationship that has a specified entity as a target. If there is more than one
   * relationship for the same target, it is unpredictable which one will be returned.
   *
   * @since 1.1
   */
  public Relationship getAnyRelationship(Entity targetEntity) {
    Collection relationships = getRelationships();
    if (relationships.isEmpty()) {
      return null;
    }

    Iterator it = relationships.iterator();
    while (it.hasNext()) {
      Relationship r = (Relationship) it.next();
      if (r.getTargetEntity() == targetEntity) {
        return r;
      }
    }
    return null;
  }

  /** Returns a collection of Relationships that exist in this entity. */
  public Collection getRelationships() {
    return relationshipsRef;
  }

  /** Returns entity attributes as an unmodifiable map. Since 1.1 returns a SortedMap. */
  public SortedMap getAttributeMap() {
    return attributesMapRef;
  }

  /** Returns entity attributes. */
  public Collection getAttributes() {
    return attributesRef;
  }

  /**
   * Translates Expression rooted in this entity to an analogous expression rooted in related
   * entity.
   *
   * @since 1.1
   */
  public abstract Expression translateToRelatedEntity(
      Expression expression, String relationshipPath);

  /**
   * Convenience method returning the last component in the path iterator.
   *
   * @since 1.1
   * @see #resolvePathComponents(Expression)
   */
  public Object lastPathComponent(Expression pathExp) {
    Object last = null;
    Iterator it = resolvePathComponents(pathExp);
    while (it.hasNext()) {
      last = it.next();
    }

    return last;
  }

  /**
   * Processes expression <code>pathExp</code> and returns an Iterator of path components that
   * contains a sequence of Attributes and Relationships. Note that if path is invalid and can not
   * be resolved from this entity, this method will still return an Iterator, but an attempt to read
   * the first invalid path component will result in ExpressionException.
   */
  public abstract Iterator resolvePathComponents(Expression pathExp) throws ExpressionException;

  /**
   * Returns an Iterator over the path components that contains a sequence of Attributes and
   * Relationships. Note that if path is invalid and can not be resolved from this entity, this
   * method will still return an Iterator, but an attempt to read the first invalid path component
   * will result in ExpressionException.
   */
  public Iterator resolvePathComponents(String path) throws ExpressionException {
    return new PathIterator(path);
  }

  // An iterator resolving mapping components represented by the path string.
  // This entity is assumed to be the root of the path.
  final class PathIterator implements Iterator {

    private StringTokenizer toks;
    private Entity currentEnt;
    private String path;

    PathIterator(String path) {
      super();
      this.currentEnt = Entity.this;
      this.toks = new StringTokenizer(path, PATH_SEPARATOR);
      this.path = path;
    }

    public boolean hasNext() {
      return toks.hasMoreTokens();
    }

    public Object next() {
      String pathComp = toks.nextToken();

      // see if this is an attribute
      Attribute attr = currentEnt.getAttribute(pathComp);
      if (attr != null) {
        // do a sanity check...
        if (toks.hasMoreTokens()) {
          throw new ExpressionException(
              "Attribute must be the last component of the path: '" + pathComp + "'.", path, null);
        }

        return attr;
      }

      Relationship rel = currentEnt.getRelationship(pathComp);
      if (rel != null) {
        currentEnt = rel.getTargetEntity();
        return rel;
      }

      // build error message
      StringBuffer buf = new StringBuffer();
      buf.append("Can't resolve path component: [")
          .append(currentEnt.getName())
          .append('.')
          .append(pathComp)
          .append("].");
      throw new ExpressionException(buf.toString(), path, null);
    }

    public void remove() {
      throw new UnsupportedOperationException("'remove' operation is not supported.");
    }
  }

  final MappingNamespace getNonNullNamespace() {
    MappingNamespace parent = (MappingNamespace) getParent();
    if (parent == null) {
      throw new CayenneRuntimeException(
          "Entity '" + getName() + "' has no parent MappingNamespace (such as DataMap)");
    }

    return parent;
  }
}
/**
 * {@link SortedMap} that keeps build records by their build numbers, in the descending order (newer
 * ones first.)
 *
 * <p>The main thing about this class is that it encapsulates the lazy loading logic. That is, while
 * this class looks and feels like a normal {@link SortedMap} from outside, it actually doesn't have
 * every item in the map instantiated yet. As items in the map get requested, this class {@link
 * #retrieve(File) retrieves them} on demand, one by one.
 *
 * <p>The lookup is primarily done by using the build number as the key (hence the key type is
 * {@link Integer}), but this class also provides look up based on {@linkplain #getIdOf(Object) the
 * build ID}.
 *
 * <p>This class makes the following assumption about the on-disk layout of the data:
 *
 * <ul>
 *   <li>Every build is stored in a directory, named after its ID.
 *   <li>ID and build number are in the consistent order. That is, if there are two builds #M and
 *       #N, {@code M>N <=> M.id > N.id}.
 * </ul>
 *
 * <p>On certain platforms, there are symbolic links named after build numbers that link to the
 * build ID. If these are available, they are used as a hint to speed up the lookup. Otherwise we
 * rely on the assumption above and perform a binary search to locate the build. (notice that we'll
 * have to do linear search if we don't have the consistent ordering assumption, which robs the
 * whole point of doing lazy loading.)
 *
 * <p>Some of the {@link SortedMap} operations are weakly implemented. For example, {@link #size()}
 * may be inaccurate because we only count the number of directories that look like build records,
 * without checking if they are loadable. But these weaknesses aren't distinguishable from
 * concurrent modifications, where another thread deletes a build while one thread iterates them.
 *
 * <p>Some of the {@link SortedMap} operations are inefficiently implemented, by {@linkplain #all()
 * loading all the build records eagerly}. We hope to replace these implementations by more
 * efficient lazy-loading ones as we go.
 *
 * <p>Object lock of {@code this} is used to make sure mutation occurs sequentially. That is, ensure
 * that only one thread is actually calling {@link #retrieve(File)} and updating {@link
 * Index#byNumber} and {@link Index#byId}.
 *
 * @author Kohsuke Kawaguchi
 * @since 1.485
 */
public abstract class AbstractLazyLoadRunMap<R> extends AbstractMap<Integer, R>
    implements SortedMap<Integer, R> {
  /** Used in {@link #all()} to quickly determine if we've already loaded everything. */
  private boolean fullyLoaded;

  /**
   * Currently visible index. Updated atomically. Once set to this field, the index object may not
   * be modified.
   */
  private volatile Index index = new Index();

  /**
   * Pair of two maps into a single class, so that the changes can be made visible atomically, and
   * updates can happen concurrently to read.
   *
   * <p>The idiom is that you put yourself in a synchronized block, {@linkplain #copy() make a copy
   * of this}, update the copy, then set it to {@link #index}.
   */
  private class Index {
    /** Stores the mapping from build number to build, for builds that are already loaded. */
    private final TreeMap<Integer, BuildReference<R>> byNumber;

    /**
     * Stores the build ID to build number for builds that we already know.
     *
     * <p>If we have known load failure of the given ID, we record that in the map by using the null
     * value (not to be confused with a non-null {@link BuildReference} with null referent, which
     * just means the record was GCed.)
     */
    private final TreeMap<String, BuildReference<R>> byId;

    private Index() {
      byId = new TreeMap<String, BuildReference<R>>();
      byNumber = new TreeMap<Integer, BuildReference<R>>(COMPARATOR);
    }

    private Index(Index rhs) {
      byId = new TreeMap<String, BuildReference<R>>(rhs.byId);
      byNumber = new TreeMap<Integer, BuildReference<R>>(rhs.byNumber);
    }

    /** Returns the build record #M (<=n) */
    private Map.Entry<Integer, BuildReference<R>> ceilingEntry(int n) {
      // switch to this once we depend on JDK6
      //            return byNumber.ceilingEntry(n);

      Set<Entry<Integer, BuildReference<R>>> s = byNumber.tailMap(n).entrySet();
      if (s.isEmpty()) return null;
      else return s.iterator().next();
    }

    /** Returns the build record #M (>=n) */
    // >= and not <= because byNumber is in the descending order
    private Map.Entry<Integer, BuildReference<R>> floorEntry(int n) {
      // switch to this once we depend on JDK6
      //            return byNumber.floorEntry(n);

      SortedMap<Integer, BuildReference<R>> sub = byNumber.headMap(n);
      if (sub.isEmpty()) return null;
      Integer k = sub.lastKey();
      return new DefaultMapEntry(k, sub.get(k));
    }
  }

  /** Build IDs found as directories, in the ascending order. */
  // copy on write
  private volatile SortedList<String> idOnDisk =
      new SortedList<String>(Collections.<String>emptyList());

  /** Build number shortcuts found on disk, in the ascending order. */
  // copy on write
  private volatile SortedIntList numberOnDisk = new SortedIntList(0);

  /**
   * Base directory for data. In effect this is treated as a final field, but can't mark it final
   * because the compatibility requires that we make it settable in the first call after the
   * constructor.
   */
  private File dir;

  protected AbstractLazyLoadRunMap(File dir) {
    initBaseDir(dir);
  }

  @Restricted(NoExternalUse.class)
  protected void initBaseDir(File dir) {
    assert this.dir == null;
    this.dir = dir;
    if (dir != null) loadIdOnDisk();
  }

  private void loadIdOnDisk() {
    String[] buildDirs = dir.list(createDirectoryFilter());
    if (buildDirs == null) {
      // the job may have just been created
      buildDirs = EMPTY_STRING_ARRAY;
    }
    // wrap into ArrayList to enable mutation
    Arrays.sort(buildDirs);
    idOnDisk = new SortedList(new ArrayList<String>(Arrays.asList(buildDirs)));

    // TODO: should we check that shortcuts is a symlink?
    String[] shortcuts = dir.list();
    if (shortcuts == null) shortcuts = EMPTY_STRING_ARRAY;
    SortedIntList list = new SortedIntList(shortcuts.length / 2);
    for (String s : shortcuts) {
      try {
        list.add(Integer.parseInt(s));
      } catch (NumberFormatException e) {
        // this isn't a shortcut
      }
    }
    list.sort();
    numberOnDisk = list;
  }

  public Comparator<? super Integer> comparator() {
    return COMPARATOR;
  }

  /**
   * If we have non-zero R in memory, we can return false right away. If we have zero R in memory,
   * try loading one and see if we can find something.
   */
  @Override
  public boolean isEmpty() {
    return index.byId.isEmpty() && search(Integer.MAX_VALUE, DESC) == null;
  }

  @Override
  public Set<Entry<Integer, R>> entrySet() {
    return Collections.unmodifiableSet(new BuildReferenceMapAdapter<R>(this, all()).entrySet());
  }

  /** Returns a read-only view of records that has already been loaded. */
  public SortedMap<Integer, R> getLoadedBuilds() {
    return Collections.unmodifiableSortedMap(new BuildReferenceMapAdapter<R>(this, index.byNumber));
  }

  /**
   * @param fromKey Biggest build number to be in the returned set.
   * @param toKey Smallest build number-1 to be in the returned set (-1 because this is exclusive)
   */
  public SortedMap<Integer, R> subMap(Integer fromKey, Integer toKey) {
    // TODO: if this method can produce a lazy map, that'd be wonderful
    // because due to the lack of floor/ceil/higher/lower kind of methods
    // to look up keys in SortedMap, various places of Jenkins rely on
    // subMap+firstKey/lastKey combo.

    R start = search(fromKey, DESC);
    if (start == null) return EMPTY_SORTED_MAP;

    R end = search(toKey, ASC);
    if (end == null) return EMPTY_SORTED_MAP;

    for (R i = start; i != end; ) {
      i = search(getNumberOf(i) - 1, DESC);
      assert i != null;
    }

    return Collections.unmodifiableSortedMap(
        new BuildReferenceMapAdapter<R>(this, index.byNumber.subMap(fromKey, toKey)));
  }

  public SortedMap<Integer, R> headMap(Integer toKey) {
    return subMap(Integer.MAX_VALUE, toKey);
  }

  public SortedMap<Integer, R> tailMap(Integer fromKey) {
    return subMap(fromKey, Integer.MIN_VALUE);
  }

  public Integer firstKey() {
    R r = newestBuild();
    if (r == null) throw new NoSuchElementException();
    return getNumberOf(r);
  }

  public Integer lastKey() {
    R r = oldestBuild();
    if (r == null) throw new NoSuchElementException();
    return getNumberOf(r);
  }

  public R newestBuild() {
    return search(Integer.MAX_VALUE, DESC);
  }

  public R oldestBuild() {
    return search(Integer.MIN_VALUE, ASC);
  }

  @Override
  public R get(Object key) {
    if (key instanceof Integer) {
      int n = (Integer) key;
      return get(n);
    }
    return super.get(key);
  }

  public R get(int n) {
    return search(n, Direction.EXACT);
  }

  /**
   * Finds the build #M where M is nearby the given 'n'.
   *
   * <p>
   *
   * @param n the index to start the search from
   * @param d defines what we mean by "nearby" above. If EXACT, find #N or return null. If ASC,
   *     finds the closest #M that satisfies M>=N. If DESC, finds the closest #M that satisfies
   *     M<=N.
   */
  public R search(final int n, final Direction d) {
    Entry<Integer, BuildReference<R>> c = index.ceilingEntry(n);
    if (c != null && c.getKey() == n) {
      R r = c.getValue().get();
      if (r != null) return r; // found the exact #n
    }

    // at this point we know that we don't have #n loaded yet

    { // check numberOnDisk as a cache to see if we can find it there
      int npos = numberOnDisk.find(n);
      if (npos >= 0) { // found exact match
        R r = load(numberOnDisk.get(npos), null);
        if (r != null) return r;
      }

      switch (d) {
        case ASC:
        case DESC:
          // didn't find the exact match, but what's the nearest ascending value in the cache?
          int neighbor = (d == ASC ? HIGHER : LOWER).apply(npos);
          if (numberOnDisk.isInRange(neighbor)) {
            R r = getByNumber(numberOnDisk.get(neighbor));
            if (r != null) {
              // make sure that the cache is accurate by looking at the previous ID
              // and it actually satisfies the constraint
              int prev = (d == ASC ? LOWER : HIGHER).apply(idOnDisk.find(getIdOf(r)));
              if (idOnDisk.isInRange(prev)) {
                R pr = getById(idOnDisk.get(prev));
                // sign*sign is making sure that #pr and #r sandwiches #n.
                if (pr != null
                    && signOfCompare(getNumberOf(pr), n) * signOfCompare(n, getNumberOf(r)) > 0)
                  return r;
                else {
                  // cache is lying. there's something fishy.
                  // ignore the cache and do the slow search
                }
              } else {
                // r is the build with youngest ID
                return r;
              }
            } else {
              // cache says we should have a build but we didn't.
              // ignore the cache and do the slow search
            }
          }
          break;
        case EXACT:
          // fall through
      }

      // didn't find it in the cache, but don't give up yet
      // maybe the cache just doesn't exist.
      // so fall back to the slow search
    }

    // capture the snapshot and work off with it since it can be overwritten by other threads
    SortedList<String> idOnDisk = this.idOnDisk;
    boolean clonedIdOnDisk =
        false; // if we modify idOnDisk we need to write it back. this flag is set to true when we
               // overwrit idOnDisk local var

    // slow path: we have to find the build from idOnDisk by guessing ID of the build.
    // first, narrow down the candidate IDs to try by using two known number-to-ID mapping
    if (idOnDisk.isEmpty()) return null;

    Entry<Integer, BuildReference<R>> f = index.floorEntry(n);

    // if bound is null, use a sentinel value
    String cid = c == null ? "\u0000" : c.getValue().id;
    String fid = f == null ? "\uFFFF" : f.getValue().id;
    // at this point, #n must be in (cid,fid)

    // We know that the build we are looking for exists in [lo,hi)  --- it's "hi)" and not "hi]"
    // because we do +1.
    // we will narrow this down via binary search
    final int initialSize = idOnDisk.size();
    int lo = idOnDisk.higher(cid);
    int hi = idOnDisk.lower(fid) + 1;

    final int initialLo = lo, initialHi = hi;

    if (!(0 <= lo && lo <= hi && hi <= idOnDisk.size())) {
      // assertion error, but we are so far unable to get to the bottom of this bug.
      // but don't let this kill the loading the hard way
      String msg =
          String.format(
              "Assertion error: failing to load #%d %s: lo=%d,hi=%d,size=%d,size2=%d",
              n, d, lo, hi, idOnDisk.size(), initialSize);
      LOGGER.log(Level.WARNING, msg, new Exception());
      throw new ArrayIndexOutOfBoundsException(msg);
    }

    while (lo < hi) {
      final int pivot = (lo + hi) / 2;
      if (!(0 <= lo && lo <= pivot && pivot < hi && hi <= idOnDisk.size())) {
        // assertion error, but we are so far unable to get to the bottom of this bug.
        // but don't let this kill the loading the hard way
        String msg =
            String.format(
                "Assertion error: failing to load #%d %s: lo=%d,hi=%d,pivot=%d,size=%d (initial:lo=%d,hi=%d,size=%d)",
                n, d, lo, hi, pivot, idOnDisk.size(), initialLo, initialHi, initialSize);
        LOGGER.log(Level.WARNING, msg, new Exception());
        throw new ArrayIndexOutOfBoundsException(msg);
      }
      R r = load(idOnDisk.get(pivot), null);
      if (r == null) {
        // this ID isn't valid. get rid of that and retry pivot
        hi--;
        if (!clonedIdOnDisk) { // if we are making an edit, we need to own a copy
          idOnDisk = new SortedList<String>(idOnDisk);
          clonedIdOnDisk = true;
        }
        idOnDisk.remove(pivot);
        continue;
      }

      int found = getNumberOf(r);
      if (found == n) return r; // exact match

      if (found < n) lo = pivot + 1; // the pivot was too small. look in the upper half
      else hi = pivot; // the pivot was too big. look in the lower half
    }

    if (clonedIdOnDisk) this.idOnDisk = idOnDisk; // feedback the modified result atomically

    assert lo == hi;
    // didn't find the exact match
    // both lo and hi point to the insertion point on idOnDisk
    switch (d) {
      case ASC:
        if (hi == idOnDisk.size()) return null;
        return getById(idOnDisk.get(hi));
      case DESC:
        if (lo <= 0) return null;
        if (lo - 1 >= idOnDisk.size()) {
          // assertion error, but we are so far unable to get to the bottom of this bug.
          // but don't let this kill the loading the hard way
          LOGGER.log(
              Level.WARNING,
              String.format(
                  "Assertion error: failing to load #%d %s: lo=%d,hi=%d,size=%d (initial:lo=%d,hi=%d,size=%d)",
                  n, d, lo, hi, idOnDisk.size(), initialLo, initialHi, initialSize),
              new Exception());
          return null;
        }
        return getById(idOnDisk.get(lo - 1));
      case EXACT:
        return null;
      default:
        throw new AssertionError();
    }
  }

  /** sign of (a-b). */
  private static int signOfCompare(int a, int b) {
    if (a > b) return 1;
    if (a < b) return -1;
    return 0;
  }

  public R getById(String id) {
    Index snapshot = index;
    if (snapshot.byId.containsKey(id)) {
      BuildReference<R> ref = snapshot.byId.get(id);
      if (ref == null) return null; // known failure
      R v = unwrap(ref);
      if (v != null) return v; // already in memory
      // otherwise fall through to load
    }
    return load(id, null);
  }

  public R getByNumber(int n) {
    return search(n, Direction.EXACT);
  }

  public R put(R value) {
    return _put(value);
  }

  protected R _put(R value) {
    return put(getNumberOf(value), value);
  }

  @Override
  public synchronized R put(Integer key, R r) {
    String id = getIdOf(r);
    int n = getNumberOf(r);

    Index copy = copy();
    BuildReference<R> ref = createReference(r);
    BuildReference<R> old = copy.byId.put(id, ref);
    copy.byNumber.put(n, ref);
    index = copy;

    /*
       search relies on the fact that every object added via
       put() method be available in the xyzOnDisk index, so I'm adding them here
       however, this is awfully inefficient. I wonder if there's any better way to do this?
    */
    if (!idOnDisk.contains(id)) {
      ArrayList<String> a = new ArrayList<String>(idOnDisk);
      a.add(id);
      Collections.sort(a);
      idOnDisk = new SortedList<String>(a);
    }

    if (!numberOnDisk.contains(n)) {
      SortedIntList a = new SortedIntList(numberOnDisk);
      a.add(n);
      a.sort();
      numberOnDisk = a;
    }

    return unwrap(old);
  }

  private R unwrap(Reference<R> ref) {
    return ref != null ? ref.get() : null;
  }

  @Override
  public synchronized void putAll(Map<? extends Integer, ? extends R> rhs) {
    Index copy = copy();
    for (R r : rhs.values()) {
      String id = getIdOf(r);
      BuildReference<R> ref = createReference(r);
      copy.byId.put(id, ref);
      copy.byNumber.put(getNumberOf(r), ref);
    }
    index = copy;
  }

  /**
   * Loads all the build records to fully populate the map. Calling this method results in eager
   * loading everything, so the whole point of this class is to avoid this call as much as possible
   * for typical code path.
   *
   * @return fully populated map.
   */
  private TreeMap<Integer, BuildReference<R>> all() {
    if (!fullyLoaded) {
      synchronized (this) {
        if (!fullyLoaded) {
          Index copy = copy();
          for (String id : idOnDisk) {
            if (!copy.byId.containsKey(id)) load(id, copy);
          }
          index = copy;
          fullyLoaded = true;
        }
      }
    }
    return index.byNumber;
  }

  /** Creates a duplicate for the COW data structure in preparation for mutation. */
  private Index copy() {
    return new Index(index);
  }

  /**
   * Tries to load the record #N by using the shortcut.
   *
   * @return null if the data failed to load.
   */
  protected R load(int n, Index editInPlace) {
    R r = null;
    File shortcut = new File(dir, String.valueOf(n));
    if (shortcut.isDirectory()) {
      synchronized (this) {
        r = load(shortcut, editInPlace);

        // make sure what we actually loaded is #n,
        // because the shortcuts can lie.
        if (r != null && getNumberOf(r) != n) r = null;

        if (r == null) {
          // if failed to locate, record that fact
          SortedIntList update = new SortedIntList(numberOnDisk);
          update.removeValue(n);
          numberOnDisk = update;
        }
      }
    }
    return r;
  }

  protected R load(String id, Index editInPlace) {
    assert dir != null;
    R v = load(new File(dir, id), editInPlace);
    if (v == null && editInPlace != null) {
      // remember the failure.
      // if editInPlace==null, we can create a new copy for this, but not sure if it's worth doing,
      // given that we also update idOnDisk anyway.
      editInPlace.byId.put(id, null);
    }
    return v;
  }

  /**
   * @param editInPlace If non-null, update this data structure. Otherwise do a copy-on-write of
   *     {@link #index}
   */
  protected synchronized R load(File dataDir, Index editInPlace) {
    try {
      R r = retrieve(dataDir);
      if (r == null) return null;

      Index copy = editInPlace != null ? editInPlace : new Index(index);

      String id = getIdOf(r);
      BuildReference<R> ref = createReference(r);
      copy.byId.put(id, ref);
      copy.byNumber.put(getNumberOf(r), ref);

      if (editInPlace == null) index = copy;

      return r;
    } catch (IOException e) {
      LOGGER.log(Level.WARNING, "Failed to load " + dataDir, e);
    }
    return null;
  }

  /** Subtype to provide {@link Run#getNumber()} so that this class doesn't have to depend on it. */
  protected abstract int getNumberOf(R r);
  /** Subtype to provide {@link Run#getId()} so that this class doesn't have to depend on it. */
  protected abstract String getIdOf(R r);

  /** Allow subtype to capture a reference. */
  protected BuildReference<R> createReference(R r) {
    return new BuildReference<R>(getIdOf(r), r);
  }

  /**
   * Parses {@code R} instance from data in the specified directory.
   *
   * @return null if the parsing failed.
   * @throws IOException if the parsing failed. This is just like returning null except the caller
   *     will catch the exception and report it.
   */
  protected abstract R retrieve(File dir) throws IOException;

  public synchronized boolean removeValue(R run) {
    Index copy = copy();
    copy.byNumber.remove(getNumberOf(run));
    BuildReference<R> old = copy.byId.remove(getIdOf(run));
    this.index = copy;

    return unwrap(old) != null;
  }

  /** Replaces all the current loaded Rs with the given ones. */
  public synchronized void reset(TreeMap<Integer, R> builds) {
    Index index = new Index();
    for (R r : builds.values()) {
      String id = getIdOf(r);
      BuildReference<R> ref = createReference(r);
      index.byId.put(id, ref);
      index.byNumber.put(getNumberOf(r), ref);
    }

    this.index = index;
  }

  @Override
  public int hashCode() {
    return System.identityHashCode(this);
  }

  @Override
  public boolean equals(Object o) {
    return o == this;
  }

  /** Lists the actual data directory */
  protected abstract FilenameFilter createDirectoryFilter();

  private static final Comparator<Comparable> COMPARATOR =
      new Comparator<Comparable>() {
        public int compare(Comparable o1, Comparable o2) {
          return -o1.compareTo(o2);
        }
      };

  public enum Direction {
    ASC,
    DESC,
    EXACT
  }

  private static final String[] EMPTY_STRING_ARRAY = new String[0];

  private static final SortedMap EMPTY_SORTED_MAP =
      Collections.unmodifiableSortedMap(new TreeMap());

  static final Logger LOGGER = Logger.getLogger(AbstractLazyLoadRunMap.class.getName());
}
 public SortedMap<Integer, Integer> hitsByLine() {
   return Collections.unmodifiableSortedMap(hitsByLine);
 }
Example #12
0
    public MetaData build() {
      // TODO: We should move these datastructures to IndexNameExpressionResolver, this will give
      // the following benefits:
      // 1) The datastructures will only be rebuilded when needed. Now during serializing we rebuild
      // these datastructures
      //    while these datastructures aren't even used.
      // 2) The aliasAndIndexLookup can be updated instead of rebuilding it all the time.

      // build all concrete indices arrays:
      // TODO: I think we can remove these arrays. it isn't worth the effort, for operations on all
      // indices.
      // When doing an operation across all indices, most of the time is spent on actually going to
      // all shards and
      // do the required operations, the bottleneck isn't resolving expressions into concrete
      // indices.
      List<String> allIndicesLst = new ArrayList<>();
      for (ObjectCursor<IndexMetaData> cursor : indices.values()) {
        allIndicesLst.add(cursor.value.getIndex().getName());
      }
      String[] allIndices = allIndicesLst.toArray(new String[allIndicesLst.size()]);

      List<String> allOpenIndicesLst = new ArrayList<>();
      List<String> allClosedIndicesLst = new ArrayList<>();
      for (ObjectCursor<IndexMetaData> cursor : indices.values()) {
        IndexMetaData indexMetaData = cursor.value;
        if (indexMetaData.getState() == IndexMetaData.State.OPEN) {
          allOpenIndicesLst.add(indexMetaData.getIndex().getName());
        } else if (indexMetaData.getState() == IndexMetaData.State.CLOSE) {
          allClosedIndicesLst.add(indexMetaData.getIndex().getName());
        }
      }
      String[] allOpenIndices = allOpenIndicesLst.toArray(new String[allOpenIndicesLst.size()]);
      String[] allClosedIndices =
          allClosedIndicesLst.toArray(new String[allClosedIndicesLst.size()]);

      // build all indices map
      SortedMap<String, AliasOrIndex> aliasAndIndexLookup = new TreeMap<>();
      for (ObjectCursor<IndexMetaData> cursor : indices.values()) {
        IndexMetaData indexMetaData = cursor.value;
        aliasAndIndexLookup.put(
            indexMetaData.getIndex().getName(), new AliasOrIndex.Index(indexMetaData));

        for (ObjectObjectCursor<String, AliasMetaData> aliasCursor : indexMetaData.getAliases()) {
          AliasMetaData aliasMetaData = aliasCursor.value;
          AliasOrIndex aliasOrIndex = aliasAndIndexLookup.get(aliasMetaData.getAlias());
          if (aliasOrIndex == null) {
            aliasOrIndex = new AliasOrIndex.Alias(aliasMetaData, indexMetaData);
            aliasAndIndexLookup.put(aliasMetaData.getAlias(), aliasOrIndex);
          } else if (aliasOrIndex instanceof AliasOrIndex.Alias) {
            AliasOrIndex.Alias alias = (AliasOrIndex.Alias) aliasOrIndex;
            alias.addIndex(indexMetaData);
          } else if (aliasOrIndex instanceof AliasOrIndex.Index) {
            AliasOrIndex.Index index = (AliasOrIndex.Index) aliasOrIndex;
            throw new IllegalStateException(
                "index and alias names need to be unique, but alias ["
                    + aliasMetaData.getAlias()
                    + "] and index "
                    + index.getIndex().getIndex()
                    + " have the same name");
          } else {
            throw new IllegalStateException(
                "unexpected alias [" + aliasMetaData.getAlias() + "][" + aliasOrIndex + "]");
          }
        }
      }
      aliasAndIndexLookup = Collections.unmodifiableSortedMap(aliasAndIndexLookup);
      return new MetaData(
          clusterUUID,
          version,
          transientSettings,
          persistentSettings,
          indices.build(),
          templates.build(),
          customs.build(),
          allIndices,
          allOpenIndices,
          allClosedIndices,
          aliasAndIndexLookup);
    }
Example #13
0
 /** Returns an unmodifiable sorted map of entity attributes. */
 public SortedMap<String, ? extends Attribute> getAttributeMap() {
   // create a new instance ... earlier attempts to cache it in the entity caused
   // serialization issues (esp. with Hessian).
   return Collections.unmodifiableSortedMap(attributes);
 }
 public SortedMap<String, List<OwsParameterValue>> getCommonValues() {
   return Collections.unmodifiableSortedMap(commonValues);
 }
 public CyclicDependencyException(SortedMap<String, Plugin> cyclics) {
   super(format("Cyclic dependencies have been found amongst these plugins:\n%s", info(cyclics)));
   this.cyclics = Collections.unmodifiableSortedMap(cyclics);
 }
Example #16
0
 /**
  * Returns a {@code Map} equivalent to this period.
  *
  * <p>The map will connect the unit to the single field period. The sort order is from largest
  * unit to smallest unit.
  *
  * @return the map equivalent to this period, unmodifiable, not null
  */
 public SortedMap<PeriodUnit, PeriodField> toMap() {
   return Collections.unmodifiableSortedMap(unitFieldMap);
 }
Example #17
0
  /**
   * Parses the subtags after the -u-
   *
   * @param source
   * @return
   */
  public UExtension parse(String source) {
    // the subtags that are up to the first two letter are attributes
    String key = null;
    List<String> list = null;
    Set<String> validSubtypes = null;
    Matcher alphanum = ALPHANUM.matcher("");

    for (String subtag : SEP.split(source)) {
      if (!alphanum.reset(subtag).matches()) {
        throw new IllegalArgumentException(
            "Invalid subtag contents, must be [0-9 A-Z a-z]{2,8}: " + subtag);
      }
      subtag = subtag.toLowerCase(Locale.ENGLISH); // normalize
      if (subtag.length() == 2) { // key
        if (list != null) { // check size of previous list
          if (list.size() == 0 || !key.equals("vt") && list.size() > 1) {
            throw new IllegalArgumentException(
                "Illegal number of subtypes for: " + key + "\t" + list);
          }
        }
        key = subtag;
        if (validating) {
          validSubtypes = validKeyTypes.getAll(key);
          if (validSubtypes == null) {
            throw new IllegalArgumentException("Invalid key: " + key);
          }
        }
        list = keyTypes.get(key);
        if (list != null) {
          throw new IllegalArgumentException("Multiple keys with same value: " + subtag);
        }
        list = new ArrayList<String>();
        keyTypes.put(key, list);
      } else { // add subtype
        if (key == null) {
          if (validating) {
            throw new IllegalArgumentException("No attributes currently valid: " + subtag);
          }
          attributes.add(subtag);
          break;
        }
        if (validating) {
          if (key.equals("vt")) {
            if (!CODEPOINTS.matcher(subtag).matches()) {
              throw new IllegalArgumentException("Illegal subtypes: " + key + "-" + subtag);
            }
          } else if (!validSubtypes.contains(subtag)) {
            throw new IllegalArgumentException("Illegal subtypes: " + key + "-" + subtag);
          }
        }
        list.add(subtag);
      }
    }
    // protect
    attributes = Collections.unmodifiableSet(attributes);
    for (String key2 : keyTypes.keySet()) {
      list = keyTypes.get(key2);
      keyTypes.put(key2, Collections.unmodifiableList(list));
    }
    keyTypes = Collections.unmodifiableSortedMap(keyTypes);
    return this;
  }
 /** Returns a read-only view of records that has already been loaded. */
 public SortedMap<Integer, R> getLoadedBuilds() {
   return Collections.unmodifiableSortedMap(new BuildReferenceMapAdapter<R>(this, index.byNumber));
 }
 public SortedMap<Integer, Integer> coveredConditionsByLine() {
   return Collections.unmodifiableSortedMap(coveredConditionsByLine);
 }
Example #20
0
 /** Gets all the builds in a map. */
 public SortedMap<Integer, RunT> getBuildsAsMap() {
   return Collections.unmodifiableSortedMap(_getRuns());
 }