private void outputEntry(TraceEntry te) {
    ThreadData td = te.getThread();
    if (td == null) return;

    // System.err.println("TRACE: " + te);

    BdynCallback cb = bdyn_factory.getCallback(te.getEntryLocation());
    if (cb == null) return;

    if (cb.getCallbackType() == CallbackType.CONSTRUCTOR) {
      OutputTask ot = td.getCurrentTransaction();
      if (ot == null) return;
      if (ot.isMainTask() && !BdynFactory.getOptions().useMainTask()) return;
      int i0 = te.getObject1();
      if (i0 != 0) {
        // System.err.println("ASSOC TASK " + i0 + " " + te.getObject2() + " " +
        // ot.getTaskRoot().getDisplayName());
        OutputTask ot1 = object_tasks.get(i0);
        if (ot1 == null) object_tasks.put(i0, ot);
        else if (ot1 != dummy_task && ot1 != ot) object_tasks.put(i0, dummy_task);
      }
      return;
    }

    td.beginTask(te);
    end_time = Math.max(end_time, te.getTime());
  }
 OutputEntry createOutputEntry(TraceEntry te) {
   BdynCallback cb = bdyn_factory.getCallback(te.getEntryLocation());
   OutputEntry oe = new OutputEntry(te.getTime(), 0, this, current_transaction, cb);
   if (te.getUseCount() > 1) oe.setUse(te.getUseCount(), te.getFractionUsed());
   output_set.add(oe);
   if (trace_writer != null)
     trace_writer.println(
         "START " + cb.getId() + " " + nest_level + " " + te.getTime() + " " + oe.hashCode());
   return oe;
 }
 OutputEntry(long startt, long endt, ThreadData td, OutputTask ot, BdynCallback tt) {
   start_time = startt;
   finish_time = (endt == 0 ? MAX_TIME : endt);
   entry_thread = td;
   entry_transaction = ot;
   entry_task = tt;
   num_traces = 1;
   trace_fraction = 1;
   can_delete = (tt.getCallbackType() == CallbackType.KEY);
 }
 @Override
 public String toString() {
   StringBuffer buf = new StringBuffer();
   if (entry_transaction != null && getEntryTransaction() != entry_task) {
     buf.append(getEntryTransaction().toString());
     buf.append("::");
   }
   if (entry_task != null) {
     buf.append(entry_task.toString());
   }
   buf.append("@");
   buf.append(start_time);
   if (finish_time != 0 && finish_time != MAX_TIME) {
     buf.append("-");
     buf.append(finish_time);
   }
   return buf.toString();
 }
 boolean isMainTask() {
   if (task_root == null) return true;
   if (task_root.getCallbackType() == CallbackType.MAIN) return true;
   return false;
 }
    void beginTask(TraceEntry te) {
      BdynCallback cb = bdyn_factory.getCallback(te.getEntryLocation());
      if (cb == null) return;

      if (trace_writer != null)
        trace_writer.println(
            "PROCESS " + te.getEntryLocation() + " " + te.isExit() + " " + te.getTime());

      if (current_transaction == null) {
        OutputTask ot = null;
        if (te.isExit()) return;
        int i0 = te.getObject1();
        int i1 = te.getObject2();
        if (i0 != 0) {
          ot = object_tasks.get(i0);
          if (ot == dummy_task) ot = null;
        }
        if (ot == null) {
          if (i1 != 0) {
            ot = object_tasks.get(i1);
            if (ot == dummy_task) ot = null;
          }
        }
        if (ot == null) {
          ot = new OutputTask(++task_counter, cb);
        }
        current_transaction = ot;
        nest_level = 0;
      }
      if (!te.isExit()) {
        OutputEntry oe = null;
        if (nest_level == 0) {
          oe = createOutputEntry(te);
        } else if (cb.getCallbackType() == CallbackType.KEY
            && BdynFactory.getOptions().useKeyCallback()) {
          for (int i = output_stack.size() - 1; i >= 0; --i) {
            OutputEntry poe = output_stack.get(i);
            if (poe != null) {
              poe.finishAt(te.getTime());
              if (trace_writer != null)
                trace_writer.println(
                    "FINISHINT "
                        + poe.getEntryTask().getId()
                        + " "
                        + nest_level
                        + " "
                        + poe.getTotalTime(0)
                        + " "
                        + poe.hashCode());
              break;
            }
          }
          oe = createOutputEntry(te);
        } else {
          if (trace_writer != null) trace_writer.println("IGNORE " + cb.getId() + " " + nest_level);
          // System.err.println("TRACE: Ignore " + cb.getDisplayName() + " " + nest_level);
        }
        output_stack.push(oe);
        active_threads.add(this);
        ++nest_level;
      } else {
        if (nest_level <= 0) {
          return;
        }
        --nest_level;
        OutputEntry oe = output_stack.pop();
        if (oe != null) {
          // TODO: max_delta doesn't take into account calls that haven't ended yet
          max_delta = Math.max(max_delta, te.getTime() - oe.getStartTime());
          oe.finishAt(te.getTime());
          if (trace_writer != null)
            trace_writer.println(
                "FINISH "
                    + oe.getEntryTask().getId()
                    + " "
                    + nest_level
                    + " "
                    + oe.getTotalTime(0)
                    + " "
                    + oe.hashCode());
          if (!oe.isRelevant()) {
            output_set.remove(oe);
            if (trace_writer != null)
              trace_writer.println("REMOVE KEY " + oe.getEntryTask().getId() + " " + nest_level);
            // System.err.println("REMOVE KEY " + oe.getEntryTask().getDisplayName());
            oe = null;
            for (int i = output_stack.size() - 1; i >= 0; --i) {
              OutputEntry poe = output_stack.get(i);
              if (poe != null) {
                poe.finishAt(0);
                if (trace_writer != null)
                  trace_writer.println(
                      "NO END "
                          + poe.getEntryTask().getId()
                          + " "
                          + nest_level
                          + " "
                          + poe.hashCode());
                break;
              }
            }
          }
        }

        if (last_entry != null
            && oe != null
            && last_entry.getEntryTask() == oe.getEntryTask()
            && (te.getTime() - last_entry.getStartTime()) < MERGE_TIME) {
          last_entry.mergeWith(oe);
          output_set.remove(oe);
          if (trace_writer != null)
            trace_writer.println("MERGE KEY " + oe.getEntryTask().getId() + " " + nest_level);
          // System.err.println("REMOVE " + oe.getEntryTask().getDisplayName());
        }

        if (oe != null) last_entry = oe;

        if (nest_level == 0) endTask();
        else if (oe != null) {
          for (int i = output_stack.size() - 1; i >= 0; --i) {
            OutputEntry poe = output_stack.get(i);
            if (poe != null) {
              if (!poe.isSignificant()) {
                output_set.remove(poe);
              }
              if (trace_writer != null)
                trace_writer.println(
                    "NEST KEY "
                        + poe.getEntryTask().getId()
                        + " "
                        + nest_level
                        + " "
                        + poe.isSignificant());
              oe = new OutputEntry(te.getTime(), 0, this, current_transaction, poe.getEntryTask());
              oe.setDeletable();
              output_set.add(oe);
              output_stack.set(i, oe);
              break;
            }
          }
        }
      }
    }