/**
   * Remove the given bundle from the list. Returns true if the bundle was successfully removed,
   * false otherwise.
   *
   * @param free whether to free the bundle. This freeing will remove Bundle from storage including
   *     its payload
   */
  public boolean erase(Bundle bundle, boolean free) {
    if (bundle == null) {
      return false;
    }
    lock_.lock();

    // "Now we need to take the bundle lock in order to search through
    // its mappings" [DTN2]
    bundle.get_lock().lock();

    try {
      int pos = list_.indexOf(bundle);
      if (pos == -1) return false;

      Bundle b = del_bundle(pos, free);
      assert (b == bundle);

      return true;

    } catch (BundleListLockNotHoldByCurrentThread e) {
      Log.e(TAG, e.getMessage());
      return false;
    } finally {
      bundle.get_lock().unlock();
      lock_.unlock();
    }
  }
  /**
   * "Helper routine to add a bundle at the indicated position." [DTN2]
   *
   * @throws BundleLockNotHeldByCurrentThread
   * @throws InterruptedException
   */
  private void add_bundle(final Bundle b, final int pos)
      throws BundleListLockNotHoldByCurrentThread, BundleLockNotHeldByCurrentThread,
          InterruptedException {
    if (!lock_.isHeldByCurrentThread()) throw new BundleListLockNotHoldByCurrentThread();
    if (!b.get_lock().isHeldByCurrentThread()) throw new BundleLockNotHeldByCurrentThread();

    if (b.is_queued_on(this)) {
      Log.e(
          TAG,
          String.format(
              "ERROR in add bundle: " + "bundle id %d already on list [%s]", b.bundleid(), name_));

      return;
    }

    list_.add(pos, b);

    b.mappings().add(this);

    Log.d(
        TAG,
        String.format(
            "bundle id %d is added to list [%s] , the size become",
            b.bundleid(), name_, list_.size()));
  }
  /** Add a new bundle to the front of the list. */
  public boolean push_front(Bundle bundle) {

    lock_.lock();
    bundle.get_lock().lock();
    try {
      add_bundle(bundle, 0);
      return true;
    } catch (BundleLockNotHeldByCurrentThread e) {
      Log.e(TAG, e.getMessage());
    } catch (InterruptedException e) {
      Log.e(TAG, e.getMessage());
    } catch (BundleListLockNotHoldByCurrentThread e) {
      Log.e(TAG, e.getMessage());
    } finally {
      bundle.get_lock().unlock();
      lock_.unlock();
    }
    return true;
  }
 /** Insert the given bundle sorted by the given sort method. */
 public boolean insert_sorted(Bundle bundle, Comparator<Bundle> sort_comparator) {
   lock_.lock();
   bundle.get_lock().lock();
   try {
     add_bundle(bundle, list_.size());
     Collections.sort(this.list_, sort_comparator);
     return true;
   } catch (BundleLockNotHeldByCurrentThread e) {
     Log.e(TAG, e.getMessage());
     return false;
   } catch (InterruptedException e) {
     Log.e(TAG, e.getMessage());
     return false;
   } catch (BundleListLockNotHoldByCurrentThread e) {
     Log.e(TAG, e.getMessage());
     return false;
   } finally {
     bundle.get_lock().unlock();
     lock_.unlock();
   }
 }
  /**
   * Helper routine to remove a bundle from the indicated position. This is called by other public
   * functions such as pop_front This is the function will actually post the bundle free event to
   * the Bundle daemon
   *
   * @param pos Position to delete a flag indicate whether to free the bundle as well
   * @param free whether to free the bundle. This freeing will remove Bundle from storage including
   *     its payload
   * @throws BundleListLockNotHoldByCurrentThread
   * @returns the bundle that, before this call, was at the position
   */
  private Bundle del_bundle(final int pos, boolean free)
      throws BundleListLockNotHoldByCurrentThread {

    Bundle b = list_.get(pos);
    assert (lock_.isHeldByCurrentThread());

    if (!lock_.isHeldByCurrentThread()) throw new BundleListLockNotHoldByCurrentThread();

    b.get_lock().lock();

    try {

      Log.d(
          TAG,
          String.format("bundle id %d del_bundle: deleting mapping [%s]", b.bundleid(), name_));

      if (!b.mappings().contains(this)) {
        Log.e(
            TAG,
            String.format(
                "ERROR in del bundle: " + "bundle id %d has no mapping for list [%s]",
                b.bundleid(), name_));
      } else {
        b.mappings().remove(this);
      }

      // "remove the bundle from the list" [DTN2]
      list_.remove(b);

      if (free) BundleDaemon.getInstance().post(new BundleFreeEvent(b));

      return b;
    } catch (BundleLockNotHeldByCurrentThread e) {
      Log.e(TAG, e.getMessage());
      return null;

    } finally {
      b.get_lock().unlock();
    }
  }