code: synchronized void jobCompleted(JobInProgress job) {
      QueueSchedulingInfo qsi = 
        queueInfoMap.get(job.getProfile().getQueueName());
      // qsi shouldn't be null
      // update numJobsByUser
      LOG.debug("JOb to be removed for user " + job.getProfile().getUser());
      Integer i = qsi.numJobsByUser.get(job.getProfile().getUser());
      i--;
      if (0 == i.intValue()) {
        qsi.numJobsByUser.remove(job.getProfile().getUser());
        // remove job footprint from our TSIs
        qsi.mapTSI.numSlotsOccupiedByUser.remove(job.getProfile().getUser());
        qsi.reduceTSI.numSlotsOccupiedByUser.remove(job.getProfile().getUser());
        LOG.debug("No more jobs for user, number of users = " + qsi.numJobsByUser.size());
      }
      else {
        qsi.numJobsByUser.put(job.getProfile().getUser(), i);
        LOG.debug("User still has " + i + " jobs, number of users = "
                  + qsi.numJobsByUser.size());
      }
    }
docs: called when a job completes