def poll
    added = []
    deleted = []
    updated = []
    @ctimes.each do |d,prev_ctime|
      subdir = File.join @dir, d
      debug "polling maildir #{subdir}"
      raise FatalSourceError, "#{subdir} not a directory" unless File.directory? subdir
      ctime = File.ctime subdir
      next if prev_ctime >= ctime
      @ctimes[d] = ctime

      old_ids = benchmark(:maildir_read_index) { Index.instance.enum_for(:each_source_info, self.id, "#{d}/").to_a }
      new_ids = benchmark(:maildir_read_dir) {
        Dir.open(subdir).select {
          |f| !File.directory? f}.map {
            |x| File.join(d,File.basename(x)) }.sort }
      added += new_ids - old_ids
      deleted += old_ids - new_ids
      debug "#{old_ids.size} in index, #{new_ids.size} in filesystem"
    end

    ## find updated mails by checking if an id is in both added and
    ## deleted arrays, meaning that its flags changed or that it has
    ## been moved, these ids need to be removed from added and deleted
    add_to_delete = del_to_delete = []
    map = Hash.new { |hash, key| hash[key] = [] }
    deleted.each do |id_del|
        map[maildir_data(id_del)[0]].push id_del
    end
    added.each do |id_add|
        map[maildir_data(id_add)[0]].each do |id_del|
          updated.push [ id_del, id_add ]
          add_to_delete.push id_add
          del_to_delete.push id_del
        end
    end
    added -= add_to_delete
    deleted -= del_to_delete
    debug "#{added.size} added, #{deleted.size} deleted, #{updated.size} updated"
    total_size = added.size+deleted.size+updated.size

    added.each_with_index do |id,i|
      yield :add,
      :info => id,
      :labels => @labels + maildir_labels(id) + [:inbox],
      :progress => i.to_f/total_size
    end

    deleted.each_with_index do |id,i|
      yield :delete,
      :info => id,
      :progress => (i.to_f+added.size)/total_size
    end

    updated.each_with_index do |id,i|
      yield :update,
      :old_info => id[0],
      :new_info => id[1],
      :labels => @labels + maildir_labels(id[1]),
      :progress => (i.to_f+added.size+deleted.size)/total_size
    end
    nil
  end
def poll
    added = []
    deleted = []
    updated = []
    @ctimes.each do |d,prev_ctime|
      subdir = File.join @dir, d
      debug "polling maildir #{subdir}"
      raise FatalSourceError, "#{subdir} not a directory" unless File.directory? subdir
      ctime = File.ctime subdir
      next if prev_ctime >= ctime
      @ctimes[d] = ctime

      old_ids = benchmark(:maildir_read_index) { Index.instance.enum_for(:each_source_info, self.id, "#{d}/").to_a }
      new_ids = benchmark(:maildir_read_dir) {
        Dir.open(subdir).select {
          |f| !File.directory? f}.map {
            |x| File.join(d,File.basename(x)) }.sort }
      added += new_ids - old_ids
      deleted += old_ids - new_ids
      debug "#{old_ids.size} in index, #{new_ids.size} in filesystem"
    end

    ## find updated mails by checking if an id is in both added and
    ## deleted arrays, meaning that its flags changed or that it has
    ## been moved, these ids need to be removed from added and deleted
    add_to_delete = del_to_delete = []
    map = Hash.new { |hash, key| hash[key] = [] }
    deleted.each do |id_del|
        map[maildir_data(id_del)[0]].push id_del
    end
    added.each do |id_add|
        map[maildir_data(id_add)[0]].each do |id_del|
          updated.push [ id_del, id_add ]
          add_to_delete.push id_add
          del_to_delete.push id_del
        end
    end
    added -= add_to_delete
    deleted -= del_to_delete
    debug "#{added.size} added, #{deleted.size} deleted, #{updated.size} updated"
    total_size = added.size+deleted.size+updated.size

    added.each_with_index do |id,i|
      yield :add,
      :info => id,
      :labels => @labels + maildir_labels(id) + [:inbox],
      :progress => i.to_f/total_size
    end

    deleted.each_with_index do |id,i|
      yield :delete,
      :info => id,
      :progress => (i.to_f+added.size)/total_size
    end

    updated.each_with_index do |id,i|
      yield :update,
      :old_info => id[0],
      :new_info => id[1],
      :labels => @labels + maildir_labels(id[1]),
      :progress => (i.to_f+added.size+deleted.size)/total_size
    end
    nil
  end
XXX use less memory