public Deferred<byte[]> getOrCreateIdAsync(final String name, 
      final String metric, final Map<String, String> tags) {
    // Look in the cache first.
    final byte[] id = getIdFromCache(name);
    if (id != null) {
      incrementCacheHits();
      return Deferred.fromResult(id);
    }
    // Not found in our cache, so look in HBase instead.

    /** Triggers the assignment if allowed through the filter */
    class AssignmentAllowedCB implements  Callback<Deferred<byte[]>, Boolean> {
      @Override
      public Deferred<byte[]> call(final Boolean allowed) throws Exception {
        if (!allowed) {
          rejected_assignments++;
          return Deferred.fromError(new FailedToAssignUniqueIdException(
              new String(kind), name, 0, "Blocked by UID filter."));
        }
        
        Deferred<byte[]> assignment = null;
        synchronized (pending_assignments) {
          assignment = pending_assignments.get(name);
          if (assignment == null) {
            // to prevent UID leaks that can be caused when multiple time
            // series for the same metric or tags arrive, we need to write a 
            // deferred to the pending map as quickly as possible. Then we can 
            // start the assignment process after we've stashed the deferred 
            // and released the lock
            assignment = new Deferred<byte[]>();
            pending_assignments.put(name, assignment);
          } else {
            LOG.info("Already waiting for UID assignment: " + name);
            return assignment;
          }
        }
        
        // start the assignment dance after stashing the deferred
        if (metric != null && LOG.isDebugEnabled()) {
          LOG.debug("Assigning UID for '" + name + "' of type '" + type + 
              "' for series '" + metric + ", " + tags + "'");
        }
        
        // start the assignment dance after stashing the deferred
        return new UniqueIdAllocator(name, assignment).tryAllocate();
      }
      @Override
      public String toString() {
        return "AssignmentAllowedCB";
      }
    }
    
    /** Triggers an assignment (possibly through the filter) if the exception 
     * returned was a NoSuchUniqueName. */
    class HandleNoSuchUniqueNameCB implements Callback<Object, Exception> {
      public Object call(final Exception e) {
        if (e instanceof NoSuchUniqueName) {
          if (tsdb != null && tsdb.getUidFilter() != null && 
              tsdb.getUidFilter().fillterUIDAssignments()) {
            return tsdb.getUidFilter()
                .allowUIDAssignment(type, name, metric, tags)
                .addCallbackDeferring(new AssignmentAllowedCB());
          } else {
            return Deferred.fromResult(true)
                .addCallbackDeferring(new AssignmentAllowedCB());
          }
        }
        return e;  // Other unexpected exception, let it bubble up.
      }
    }

    // Kick off the HBase lookup, and if we don't find it there either, start
    // the process to allocate a UID.
    return getIdAsync(name).addErrback(new HandleNoSuchUniqueNameCB());
  }
public Deferred < byte [ ] > getOrCreateIdAsync ( final String name , final String metric , final Map < String , String > tags ) { final byte [ ] id = getIdFromCache ( name ) ; if ( id != null ) { incrementCacheHits ( ) ; return Deferred . fromResult ( id ) ; } class AssignmentAllowedCB implements Callback < Deferred < byte [ ] > , Boolean > { @ Override public Deferred < byte [ ] > call ( final Boolean allowed ) throws Exception { if ( ! allowed ) { rejected_assignments ++ ; return Deferred . fromError ( new FailedToAssignUniqueIdException ( new String ( kind ) , name , 0 , "Blocked by UID filter." ) ) ; } Deferred < byte [ ] > assignment = null ; synchronized ( pending_assignments ) { assignment = pending_assignments . get ( name ) ; if ( assignment == null ) { assignment = new Deferred < byte [ ] > ( ) ; pending_assignments . put ( name , assignment ) ; } else { LOG . info ( "Already waiting for UID assignment: " + name ) ; return assignment ; } } if ( metric != null && LOG . isDebugEnabled ( ) ) { LOG . debug ( "Assigning UID for '" + name + "' of type '" + type + "' for series '" + metric + ", " + tags + "'" ) ; } return new UniqueIdAllocator ( name , assignment ) . tryAllocate ( ) ; } @ Override public String toString ( ) { return "AssignmentAllowedCB" ; } } class HandleNoSuchUniqueNameCB implements Callback < Object , Exception > { public Object call ( final Exception e ) { if ( e instanceof NoSuchUniqueName ) { if ( tsdb != null && tsdb . getUidFilter ( ) != null && tsdb . getUidFilter ( ) . fillterUIDAssignments ( ) ) { return tsdb . getUidFilter ( ) . allowUIDAssignment ( type , name , metric , tags ) . addCallbackDeferring ( new AssignmentAllowedCB ( ) ) ; } else { return Deferred . fromResult ( true ) . addCallbackDeferring ( new AssignmentAllowedCB ( ) ) ; } } return e ; } } return getIdAsync ( name ) . addErrback ( new HandleNoSuchUniqueNameCB ( ) ) ; }
Finds the ID associated with a given name or creates it.
<p>
The length of the byte array is fixed in advance by the implementation.

@param name The name to lookup in the table or to assign an ID to.
@param metric Name of the metric associated with the UID for filtering.
@param tags Tag set associated with the UID for filtering.
@throws HBaseException if there is a problem communicating with HBase.
@throws IllegalStateException if all possible IDs are already assigned.
@throws IllegalStateException if the ID found in HBase is encoded on the
wrong number of bytes.
@since 2.3