text:
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>

#include <db/db.h>
#include <base/util.h>
#include <base/string_util.h>

#include <cmn/agent_cmn.h>
#include <init/agent_param.h>
#include <boost/functional/factory.hpp>
#include <cmn/agent_factory.h>
#include <oper/interface_common.h>
#include <oper/mirror_table.h>
#include <oper/global_vrouter.h>

#include <ksync/ksync_index.h>
#include <ksync/ksync_entry.h>
#include <ksync/ksync_object.h>
#include <ksync/ksync_netlink.h>
#include <ksync/ksync_sock.h>
#include <uve/agent_uve.h>
#include <vrouter/flow_stats/flow_stats_collector.h>
#include <uve/vn_uve_table.h>
#include <uve/vm_uve_table.h>
#include <uve/interface_uve_stats_table.h>
#include <uve/vrouter_uve_entry.h>
#include <algorithm>
#include <pkt/flow_proto.h>
#include <pkt/flow_mgmt.h>
#include <vrouter/ksync/ksync_init.h>
#include <vrouter/flow_stats/flow_stats_types.h>

bool flow_ageing_debug_ = false;
FlowStatsCollector::FlowStatsCollector(boost::asio::io_service &io, int intvl,
                                       uint32_t flow_cache_timeout,
                                       AgentUveBase *uve,
                                       uint32_t instance_id,
                                       FlowAgingTableKey *key,
                                       FlowStatsManager *aging_module,
                                       FlowStatsCollectorObject *obj) :
        StatsCollector(TaskScheduler::GetInstance()->GetTaskId
                       (kTaskFlowStatsCollector), instance_id,
                       io, kFlowStatsTimerInterval, "Flow stats collector"),
        agent_uve_(uve),
        task_id_(uve->agent()->task_scheduler()->GetTaskId
                 (kTaskFlowStatsCollector)),
        rand_gen_(boost::uuids::random_generator()),
        flow_iteration_key_(NULL),
        entries_to_visit_(0),
        flow_tcp_syn_age_time_(FlowTcpSynAgeTime),
        retry_delete_(true),
        request_queue_(agent_uve_->agent()->task_scheduler()->
                       GetTaskId(kTaskFlowStatsCollector),
                       instance_id,
                       boost::bind(&FlowStatsCollector::RequestHandler,
                                   this, _1)),
        flow_aging_key_(*key), instance_id_(instance_id),
        flow_stats_manager_(aging_module), parent_(obj), ageing_task_(NULL),
        current_time_(GetCurrentTime()), ageing_task_starts_(0) {
        if (flow_cache_timeout) {
            // Convert to usec
            flow_age_time_intvl_ = 1000000L * (uint64_t)flow_cache_timeout;
        } else {
            flow_age_time_intvl_ = FlowAgeTime;
        }
        deleted_ = false;
        request_queue_.set_name("Flow stats collector");
        request_queue_.set_measure_busy_time
            (agent_uve_->agent()->MeasureQueueDelay());
        request_queue_.SetEntryCallback
            (boost::bind(&FlowStatsCollector::RequestHandlerEntry, this));
        request_queue_.SetExitCallback
            (boost::bind(&FlowStatsCollector::RequestHandlerExit, this, _1));
        // Aging timer fires every kFlowStatsTimerInterval msec. Compute
        // number of timer fires needed to scan complete table
        timers_per_scan_ = TimersPerScan();
        InitDone();
}

FlowStatsCollector::~FlowStatsCollector() {
    flow_stats_manager_->FreeIndex(instance_id_);
}

boost::uuids::uuid FlowStatsCollector::rand_gen() {
    return rand_gen_();
}

uint64_t FlowStatsCollector::GetCurrentTime() {
    return UTCTimestampUsec();
}

void FlowStatsCollector::Shutdown() {
    assert(ageing_task_ == NULL);
    StatsCollector::Shutdown();
    request_queue_.Shutdown();
}

// We want to scan the flow table every 25% of configured ageing time.
// Compute number of timer fires needed to scan the flow-table once.
uint32_t FlowStatsCollector::TimersPerScan() {
    uint64_t scan_time_millisec;
    /* Use Age Time itself as scan-time for flows */

    // Convert aging-time configured in micro-sec to millisecond
    scan_time_millisec = flow_age_time_intvl_ / 1000;

    // Compute time in which we must scan the complete table to honor the
    // kFlowScanTime
    scan_time_millisec = (scan_time_millisec * kFlowScanTime) / 100;

    // Enforce min value on scan-time
    if (scan_time_millisec < kFlowStatsTimerInterval) {
        scan_time_millisec = kFlowStatsTimerInterval;
    }

    // Number of timer fires needed to scan table once
    return scan_time_millisec / kFlowStatsTimerInterval;
}

// Update entries_to_visit_ based on total flows
// Timer fires every kFlowScanTime. Its possible that we may not have visited
// all entries by the time next timer fires. So, keep accumulating the number
// of entries to visit into entries_to_visit_
//
// A lower-bound and an upper-bound are enforced on entries_to_visit_
void FlowStatsCollector::UpdateEntriesToVisit() {
    // Compute number of flows to visit per scan-time
    uint32_t count = flow_export_info_list_.size();
    uint32_t entries = count / timers_per_scan_;

    // Update number of entries to visit in flow.
    // The scan for previous timer may still be in progress. So, accmulate
    // number of entries to visit
    entries_to_visit_ += entries;

    // Cap number of entries to visit to 25% of table
    if (entries_to_visit_ > ((count * kFlowScanTime)/100))
        entries_to_visit_ = (count * kFlowScanTime)/100;

    // Apply lower-limit
    if (entries_to_visit_ < kMinFlowsPerTimer)
        entries_to_visit_ = kMinFlowsPerTimer;

    return;
}

bool FlowStatsCollector::ShouldBeAged(FlowExportInfo *info,
                                      const vr_flow_entry *k_flow,
                                      const vr_flow_stats &k_stats,
                                      uint64_t curr_time) {
    FlowEntry *flow = info->flow();
    //If both forward and reverse flow are marked
    //as TCP closed then immediately remote the flow
    if (k_flow != NULL) {
        uint64_t k_flow_bytes, bytes;
        k_flow_bytes = GetFlowStats(k_stats.flow_bytes_oflow,
                                    k_stats.flow_bytes);
        bytes = 0x0000ffffffffffffULL & info->bytes();
        /* Don't account for agent overflow bits while comparing change in
         * stats */
        if (bytes < k_flow_bytes) {
            return false;
        }
    }

    uint64_t diff_time = curr_time - info->last_modified_time();
    if (diff_time < flow_age_time_intvl()) {
        return false;
    }

    if (flow->is_flags_set(FlowEntry::BgpRouterService)) {
        return false;
    }

    return true;
}

uint64_t FlowStatsCollector::GetFlowStats(const uint16_t &oflow_data,
                                          const uint32_t &data) {
    uint64_t flow_stats = (uint64_t) oflow_data << (sizeof(uint32_t) * 8);
    flow_stats |= data;
    return flow_stats;
}

uint64_t FlowStatsCollector::GetUpdatedFlowBytes(const FlowExportInfo *stats,
                                                 uint64_t k_flow_bytes) {
    uint64_t oflow_bytes = 0xffff000000000000ULL & stats->bytes();
    uint64_t old_bytes = 0x0000ffffffffffffULL & stats->bytes();
    if (old_bytes > k_flow_bytes) {
        oflow_bytes += 0x0001000000000000ULL;
    }
    return (oflow_bytes |= k_flow_bytes);
}

uint64_t FlowStatsCollector::GetUpdatedFlowPackets(const FlowExportInfo *stats,
                                                   uint64_t k_flow_pkts) {
    uint64_t oflow_pkts = 0xffffff0000000000ULL & stats->packets();
    uint64_t old_pkts = 0x000000ffffffffffULL & stats->packets();
    if (old_pkts > k_flow_pkts) {
        oflow_pkts += 0x0000010000000000ULL;
    }
    return (oflow_pkts |= k_flow_pkts);
}

void FlowStatsCollector::UpdateFloatingIpStats(const FlowExportInfo *flow,
                                               uint64_t bytes, uint64_t pkts) {
    InterfaceUveTable::FipInfo fip_info;
    FlowEntry *fe = flow->flow();
    if (!fe) {
        return;
    }

    /* Ignore Non-Floating-IP flow */
    if (!fe->fip() || fe->fip_vmi().uuid_ == nil_uuid()) {
        return;
    }

    InterfaceUveStatsTable *table = static_cast<InterfaceUveStatsTable *>
        (agent_uve_->interface_uve_table());

    fip_info.bytes_ = bytes;
    fip_info.packets_ = pkts;
    fip_info.fip_ = fe->fip();
    fip_info.fip_vmi_ = fe->fip_vmi();
    fip_info.is_local_flow_ = fe->is_flags_set(FlowEntry::LocalFlow);
    fip_info.is_ingress_flow_ = fe->is_flags_set(FlowEntry::IngressDir);
    fip_info.is_reverse_flow_ = fe->is_flags_set(FlowEntry::ReverseFlow);
    fip_info.vn_ = fe->data().source_vn_match;

    fip_info.rev_fip_ = NULL;
    if (fe->fip() != ReverseFlowFip(flow)) {
        /* This is the case where Source and Destination VMs (part of
         * same compute node) ping to each other to their respective
         * Floating IPs. In this case for each flow we need to increment
         * stats for both the VMs */
        fip_info.rev_fip_ = ReverseFlowFipEntry(flow);
    }

    table->UpdateFloatingIpStats(fip_info);
}

InterfaceUveTable::FloatingIp *FlowStatsCollector::ReverseFlowFipEntry
    (const FlowExportInfo *flow) {
    uint32_t fip = ReverseFlowFip(flow);
    VmInterfaceKey vmi = ReverseFlowFipVmi(flow);
    Interface *intf = dynamic_cast<Interface *>
        (agent_uve_->agent()->interface_table()->FindActiveEntry(&vmi));

    if (intf) {
        InterfaceUveStatsTable *table = static_cast<InterfaceUveStatsTable *>
            (agent_uve_->interface_uve_table());
        const string &vn = flow->flow()->data().source_vn_match;
        return table->FipEntry(fip, vn, intf);
    }
    return NULL;
}

uint32_t FlowStatsCollector::ReverseFlowFip(const FlowExportInfo *info) {
    FlowEntry *rflow = info->reverse_flow();
    if (rflow) {
        return rflow->fip();
    }
    return 0;
}

VmInterfaceKey FlowStatsCollector::ReverseFlowFipVmi
    (const FlowExportInfo *info)
{
    FlowEntry *rflow = info->reverse_flow();
    if (rflow) {
        return rflow->fip_vmi();
    }
    return VmInterfaceKey(AgentKey::ADD_DEL_CHANGE, nil_uuid(), "");
}

void FlowStatsCollector::UpdateVmiTagBasedStats(FlowExportInfo *info,
                                                uint64_t bytes, uint64_t pkts) {
    FlowEntry *flow = info->flow();

    const Interface *itf = flow->intf_entry();
    if (!itf) {
        return;
    }
    if (itf->type() != Interface::VM_INTERFACE) {
        return;
    }
    const VmInterface *vmi = static_cast<const VmInterface *>(itf);
    const string &src_vn = flow->data().source_vn_match;
    const string &dst_vn = flow->data().dest_vn_match;

    /* Ignore flows for which source VN or destination VN are not known */
    if (!src_vn.length() || !dst_vn.length()) {
        return;
    }

    InterfaceUveStatsTable *itf_table = static_cast<InterfaceUveStatsTable *>
        (agent_uve_->interface_uve_table());
    EndpointStatsInfo ep;
    ep.vmi = vmi;
    ep.local_tagset = flow->local_tagset();
    ep.remote_tagset = flow->remote_tagset();
    ep.remote_prefix = flow->RemotePrefix();
    ep.policy = flow->fw_policy_name_uuid();
    ep.diff_bytes = bytes;
    ep.diff_pkts = pkts;
    FlowTable::GetFlowSandeshActionParams(flow->data().match_p.action_info,
                                          ep.action);
    if (flow->is_flags_set(FlowEntry::LocalFlow)) {
        /* When VM A talks to VM B which is in different compute nodes, the
         * following flows are created
         * (1) A-B, Ingress, Forward, pol1
         * (2) B-A, Egress, Reverse, pol1
         * (3) A-B, Egress, Forward, pol2
         * (4) B-A, Inress, Reverse, pol2
         * When both A and B are in single compute, we have only the following
         * flows (Flows marked as LocalFlow)
         * (1) A-B, Ingress, Forward, pol1
         * (2) B-A, Inress, Reverse, pol2
         * To simulate session stats similar to case where VMs are in different
         * computes, for local flows, we do the following.
         * (a) when "A-B, Ingress, Forward, pol1" flow is seen, we also
         *     update stats for "A-B, Egress, Forward, pol2". This is because
         *     diff stats for "A-B, Ingress, Forward, pol1" and
         *     "A-B, Egress, Forward, pol2" are same. Policy for implicit flow
         *     is picked from reverse flow
         * (b) when "B-A, Ingress, Reverse, pol2" flow is seen, we also
         *     update stats for "B-A, Egress, Reverse, pol1". This is because diff
         *     stats for "B-A, Ingress, Reverse, pol2" and
         *     "B-A, Egress, Reverse, pol1" is same. Policy for implicit flow is
         *     picked from reverse flow
         */
        ep.local_vn = src_vn;
        ep.remote_vn = dst_vn;
        ep.in_stats = true;
        bool egress_flow_is_client;
        if (flow->is_flags_set(FlowEntry::ReverseFlow)) {
            ep.client = false;
            egress_flow_is_client = true;
        } else {
            ep.client = true;
            egress_flow_is_client = false;
        }
        itf_table->UpdateVmiTagBasedStats(ep);

        /* Local flows will not have egress flows in the system. So we need to
         * explicitly build stats for egress flow using the data available from
         * ingress flow. Egress flow stats has to be updated on destination
         * VMI. We skip updation if we are unable to pick destination VMI from
         * reverse flow. */

        FlowEntry* rflow = info->reverse_flow();
        if (rflow) {
            const Interface *ritf = rflow->intf_entry();
            if (ritf && (ritf->type() == Interface::VM_INTERFACE)) {
                ep.local_tagset = flow->remote_tagset();
                ep.remote_tagset = flow->local_tagset();
                ep.local_vn = dst_vn;
                ep.remote_vn = src_vn;
                ep.policy = rflow->fw_policy_name_uuid();
                ep.client = egress_flow_is_client;
                ep.vmi = static_cast<const VmInterface *>(ritf);
                ep.in_stats = false;
                itf_table->UpdateVmiTagBasedStats(ep);
            }
        }
    } else {
        if (flow->is_flags_set(FlowEntry::IngressDir)) {
            ep.local_vn = src_vn;
            ep.remote_vn = dst_vn;
            ep.in_stats = true;
            if (flow->is_flags_set(FlowEntry::ReverseFlow)) {
                ep.client = false;
            } else {
                ep.client = true;
            }
        } else {
            ep.local_vn = dst_vn;
            ep.remote_vn = src_vn;
            ep.in_stats = false;
            if (flow->is_flags_set(FlowEntry::ReverseFlow)) {
                ep.client = true;
            } else {
                ep.client = false;
            }
        }
        itf_table->UpdateVmiTagBasedStats(ep);
    }
}

void FlowStatsCollector::UpdateInterVnStats(FlowExportInfo *info,
                                            uint64_t bytes, uint64_t pkts) {
    FlowEntry *flow = info->flow();
    string src_vn = flow->data().source_vn_match;
    string dst_vn = flow->data().dest_vn_match;
    VnUveTable *vn_table = static_cast<VnUveTable *>
        (agent_uve_->vn_uve_table());

    if (!src_vn.length())
        src_vn = FlowHandler::UnknownVn();
    if (!dst_vn.length())
        dst_vn = FlowHandler::UnknownVn();

    /* When packet is going from src_vn to dst_vn it should be interpreted
     * as ingress to vrouter and hence in-stats for src_vn w.r.t. dst_vn
     * should be incremented. Similarly when the packet is egressing vrouter
     * it should be considered as out-stats for dst_vn w.r.t. src_vn.
     * Here the direction "in" and "out" should be interpreted w.r.t vrouter
     */
    if (flow->is_flags_set(FlowEntry::LocalFlow)) {
        vn_table->UpdateInterVnStats(src_vn, dst_vn, bytes, pkts, false);
        vn_table->UpdateInterVnStats(dst_vn, src_vn, bytes, pkts, true);
    } else {
        if (flow->is_flags_set(FlowEntry::IngressDir)) {
            vn_table->UpdateInterVnStats(src_vn, dst_vn, bytes, pkts, false);
        } else {
            vn_table->UpdateInterVnStats(dst_vn, src_vn, bytes, pkts, true);
        }
    }
}

void FlowStatsCollector::UpdateFlowStats(FlowExportInfo *info,
                                         uint64_t teardown_time) {
    if (!info) {
        return;
    }
    FlowEntry *fe = info->flow();
    KSyncFlowMemory *ksync_obj = agent_uve_->agent()->ksync()->
                                         ksync_flow_memory();
    /* Fetch vrouter Flow entry using gen_id and flow_handle from FlowExportInfo
     * to account for the case where FlowEntry's flow_handle/gen_id has changed
     * during Delete processing by FlowStatsCollector */
    vr_flow_stats k_stats;
    const vr_flow_entry *k_flow = ksync_obj->GetKFlowStats(fe->key(),
                                                           info->flow_handle(),
                                                           info->gen_id(),
                                                           &k_stats);
    if (k_flow) {
        UpdateFlowStatsInternal(info, k_stats.flow_bytes,
                                k_stats.flow_bytes_oflow,
                                k_stats.flow_packets,
                                k_stats.flow_packets_oflow,
                                teardown_time, true);
        return;
    }
}

void FlowStatsCollector::FlowDeleteEnqueue(FlowExportInfo *info, uint64_t t) {
    flows_aged_++;
    FlowEntry *fe = info->flow();
    agent_uve_->agent()->pkt()->get_flow_proto()->DeleteFlowRequest(fe);
    info->set_delete_enqueue_time(t);
    FlowEntry *rflow = info->reverse_flow();
    if (rflow) {
        FlowExportInfo *rev_info = FindFlowExportInfo(rflow);
        if (rev_info) {
            rev_info->set_delete_enqueue_time(t);
        }
    }
}

void FlowStatsCollector::FlowEvictEnqueue(FlowExportInfo *info, uint64_t t,
                                          uint32_t flow_handle,
                                          uint16_t gen_id) {
    flows_evicted_++;
    FlowEntry *fe = info->flow();
    agent_uve_->agent()->pkt()->get_flow_proto()->EvictFlowRequest
        (fe, flow_handle, gen_id, (gen_id + 1));
    info->set_evict_enqueue_time(t);
}

void FlowStatsCollector::UpdateFlowStatsInternalLocked(FlowExportInfo *info,
                                                       uint32_t bytes,
                                                       uint16_t oflow_bytes,
                                                       uint32_t pkts,
                                                       uint16_t oflow_pkts,
                                                       uint64_t time,
                                                       bool teardown_time) {
    FlowEntry *flow = info->flow();
    FlowEntry *rflow = info->reverse_flow();
    FLOW_LOCK(flow, rflow, FlowEvent::FLOW_MESSAGE);
    UpdateFlowStatsInternal(info, bytes, oflow_bytes, pkts, oflow_pkts, time,
                            teardown_time);
}

void FlowStatsCollector::UpdateFlowStatsInternal(FlowExportInfo *info,
                                                 uint32_t bytes,
                                                 uint16_t oflow_bytes,
                                                 uint32_t pkts,
                                                 uint16_t oflow_pkts,
                                                 uint64_t time,
                                                 bool teardown_time) {
    uint64_t k_bytes, k_packets, total_bytes, total_packets;
    k_bytes = GetFlowStats(oflow_bytes, bytes);
    k_packets = GetFlowStats(oflow_pkts, pkts);

    total_bytes = GetUpdatedFlowBytes(info, k_bytes);
    total_packets = GetUpdatedFlowPackets(info, k_packets);
    uint64_t diff_bytes = total_bytes - info->bytes();
    uint64_t diff_pkts = total_packets - info->packets();
    info->set_bytes(total_bytes);
    info->set_packets(total_packets);
    if (teardown_time) {
        info->set_teardown_time(time);
    } else {
        info->set_last_modified_time(time);
    }

    /* In TSN mode, we don't export flows or statistics based on flows */
    if (agent_uve_->agent()->tsn_enabled()) {
        return;
    }
    //Update Inter-VN stats
    UpdateInterVnStats(info, diff_bytes, diff_pkts);
    //Update Endpoint stats
    UpdateVmiTagBasedStats(info, diff_bytes, diff_pkts);
    //Update Floating-IP stats
    UpdateFloatingIpStats(info, diff_bytes, diff_pkts);
}

// Check if flow needs to be evicted
bool FlowStatsCollector::EvictFlow(KSyncFlowMemory *ksync_obj,
                                   const vr_flow_entry *k_flow,
                                   uint16_t k_flow_flags,
                                   uint32_t flow_handle, uint16_t gen_id,
                                   FlowExportInfo *info, uint64_t curr_time) {
    FlowEntry *fe = info->flow();

    if ((fe->key().protocol != IPPROTO_TCP))
        return false;

    if (ksync_obj->IsEvictionMarked(k_flow, k_flow_flags) == false)
        return false;

    // Flow evict already enqueued? Re-Enqueue request after retry-time
    uint64_t evict_time = info->evict_enqueue_time();
    if (evict_time) {
        if ((curr_time - evict_time) > kFlowDeleteRetryTime) {
            FlowEvictEnqueue(info, curr_time, flow_handle, gen_id);
        }
    } else {
        FlowEvictEnqueue(info, curr_time, flow_handle, gen_id);
    }

    return true;
}

bool FlowStatsCollector::AgeFlow(KSyncFlowMemory *ksync_obj,
                                 const vr_flow_entry *k_flow,
                                 const vr_flow_stats &k_stats,
                                 const KFlowData& kinfo,
                                 FlowExportInfo *info, uint64_t curr_time) {
    FlowEntry *fe = info->flow();
    FlowEntry *rfe = info->reverse_flow();

    // if we come across deleted entry, retry flow deletion after some time
    // duplicate delete will be suppressed in flow_table
    uint64_t delete_time = info->delete_enqueue_time();
    if (delete_time) {
        if ((curr_time - delete_time) > kFlowDeleteRetryTime) {
            FlowDeleteEnqueue(info, curr_time);
        }
        return true;
    }

    // Delete short flows
    if ((flow_stats_manager_->delete_short_flow() == true) &&
        fe->is_flags_set(FlowEntry::ShortFlow)) {
        FlowDeleteEnqueue(info, curr_time);
        return true;
    }

    bool deleted = false;
    FlowExportInfo *rev_info = NULL;
    // Can the flow be aged?
    if (ShouldBeAged(info, k_flow, k_stats, curr_time)) {
        rev_info = FindFlowExportInfo(rfe);
        // ShouldBeAged looks at one flow only. So, check for both forward and
        // reverse flows
        if (rev_info) {
            const vr_flow_entry *k_flow_rev = NULL;
            vr_flow_stats k_rflow_stats;
            k_flow_rev = ksync_obj->GetKFlowStats(rfe->key(),
                                                  rev_info->flow_handle(),
                                                  rev_info->gen_id(),
                                                  &k_rflow_stats);
            if (ShouldBeAged(rev_info, k_flow_rev, k_rflow_stats, curr_time)) {
                deleted = true;
            }
        } else {
            deleted = true;
        }
    }

    if (deleted == true) {
        FlowDeleteEnqueue(info, curr_time);
    }

    // Update stats for flows not being deleted
    // Stats for deleted flow are updated when we get DELETE message
    if (deleted == false && k_flow) {
        uint64_t k_bytes, bytes;

        k_bytes = GetFlowStats(k_stats.flow_bytes_oflow,
                               k_stats.flow_bytes);
        bytes = 0x0000ffffffffffffULL & info->bytes();
        /* Don't account for agent overflow bits while comparing change in
         * stats */
        if (bytes != k_bytes) {
            UpdateFlowStatsInternalLocked(info,
                                          k_stats.flow_bytes,
                                          k_stats.flow_bytes_oflow,
                                          k_stats.flow_packets,
                                          k_stats.flow_packets_oflow,
                                          curr_time, false);
        }
    }
    return deleted;
}

// Check if a flow is to be aged or evicted. Returns number of flows visited
uint32_t FlowStatsCollector::ProcessFlow(FlowExportInfoList::iterator &it,
                                         KSyncFlowMemory *ksync_obj,
                                         FlowExportInfo *info,
                                         uint64_t curr_time) {
    uint32_t count = 1;
    FlowEntry *fe = info->flow();
    /* Use flow-handle and gen-id from FlowExportInfo instead of FlowEntry.
     * The stats that FlowExportInfo holds corresponds to a given
     * (FlowKey, gen-id and FlowHandle). Since gen-id/flow-handle for a flow
     * can change dynamically, we need to pick gen-id and flow-handle from
     * FlowExportInfo. Otherwise stats will go wrong. Whenever gen-id/
     * flow-handle changes, the stats will be reset as part of AddFlow API
     */
    uint32_t flow_handle = info->flow_handle();
    uint16_t gen_id = info->gen_id();

    /* If Flow handle is still not populated in FlowStatsCollector, pick the
     * value from FlowEntry
     */
    if (flow_handle == FlowEntry::kInvalidFlowHandle) {
        {
            FlowEntry *rflow = NULL;
            FLOW_LOCK(fe, rflow, FlowEvent::FLOW_MESSAGE);
            // since flow processing and stats collector can run in parallel
            // flow handle and gen id not being the key for flow entry can
            // change while processing, so flow handle and gen id should be
            // fetched by holding an lock.
            flow_handle = fe->flow_handle();
            gen_id = fe->gen_id();
            info->CopyFlowInfo(fe);
        }
    }
    const vr_flow_entry *k_flow = NULL;
    vr_flow_stats k_stats;
    KFlowData kinfo;

    /* Teardown time is set when Evicted flow stats update message is received.
     * For flows whose teardown time is set, we need not read stats from
     * vrouter
     */
    if (!info->teardown_time()) {
        k_flow = ksync_obj->GetKFlowStatsAndInfo(fe->key(), flow_handle,
                                                 gen_id, &k_stats, &kinfo);

        // Flow evicted?
        if (EvictFlow(ksync_obj, k_flow, kinfo.flags, flow_handle, gen_id,
                      info, curr_time) == true) {
            // If retry_delete_ enabled, dont change flow_export_info_list_
            if (retry_delete_ == true)
                return count;

            // We dont want to retry delete-events, remove flow from ageing list
            assert(info->is_linked());
            FlowExportInfoList::iterator flow_it =
                flow_export_info_list_.iterator_to(*info);
            flow_export_info_list_.erase(flow_it);

            return count;
        }
    }

    // Flow aged?
    if (AgeFlow(ksync_obj, k_flow, k_stats, kinfo, info, curr_time) == false)
        return count;

    // If retry_delete_ enabled, dont change flow_export_info_list_
    if (retry_delete_ == false)
        return count;

    // Flow aged, remove both forward and reverse flow
    assert(info->is_linked());
    FlowExportInfoList::iterator flow_it =
        flow_export_info_list_.iterator_to(*info);
    flow_export_info_list_.erase(flow_it);

    FlowEntry *rfe = info->reverse_flow();
    FlowExportInfo *rev_info = FindFlowExportInfo(rfe);
    if (rev_info) {
        if (rev_info->is_linked()) {
            FlowExportInfoList::iterator rev_flow_it =
                flow_export_info_list_.iterator_to(*rev_info);
            if (rev_flow_it == it) {
                it++;
            }
            flow_export_info_list_.erase(rev_flow_it);
        }
        count++;
    }
    return count;
}

uint32_t FlowStatsCollector::RunAgeing(uint32_t max_count) {
    FlowExportInfoList::iterator it;
    if (flow_iteration_key_ == NULL) {
        it = flow_export_info_list_.begin();
    } else {
        FlowEntryTree::iterator tree_it = flow_tree_.find(flow_iteration_key_);
        // Flow to iterate next is not found. Force stop this iteration.
        // We will continue from begining on next timer
        if (tree_it == flow_tree_.end()) {
            flow_iteration_key_ = NULL;
            return entries_to_visit_;
        }
        it = flow_export_info_list_.iterator_to(tree_it->second);
    }

    KSyncFlowMemory *ksync_obj = agent_uve_->agent()->ksync()->
        ksync_flow_memory();
    uint64_t curr_time = GetCurrentTime();
    uint32_t count = 0;
    while (count < max_count) {
        if (it == flow_export_info_list_.end()) {
            break;
        }

        FlowExportInfo *info = &(*it);
        it++;
        flows_visited_++;
        count += ProcessFlow(it, ksync_obj, info, curr_time);
    }

    // Update iterator for next pass
    if (it == flow_export_info_list_.end()) {
        flow_iteration_key_ = NULL;
    } else {
        flow_iteration_key_ = it->flow();
    }

    return count;
}

// Timer fired for ageing. Update the number of entries to visit and start the
// task if its already not ruuning
bool FlowStatsCollector::Run() {
    if (flow_tree_.size() == 0) {
        return true;
     }

    // Update number of entries to visit in flow.
    UpdateEntriesToVisit();

    // Start task to scan the entries
    if (ageing_task_ == NULL) {
        ageing_task_starts_++;

        if (flow_ageing_debug_) {
            LOG(DEBUG,
                UTCUsecToString(ClockMonotonicUsec())
                << " AgeingTasks Num " << ageing_task_starts_
                << " Request count " << request_queue_.Length()
                << " Tree size " << flow_tree_.size()
                << " List size " << flow_export_info_list_.size()
                << " flows visited " << flows_visited_
                << " flows aged " << flows_aged_
                << " flows evicted " << flows_evicted_);
        }
        flows_visited_ = 0;
        flows_aged_ = 0;
        flows_evicted_ = 0;
        ageing_task_ = new AgeingTask(this);
        agent_uve_->agent()->task_scheduler()->Enqueue(ageing_task_);
    }
    return true;
}

bool FlowStatsCollector::RunAgeingTask() {
    // Run ageing per task
    uint32_t count = RunAgeing(kFlowsPerTask);
    // Update number of entries visited
    if (count < entries_to_visit_)
        entries_to_visit_ -= count;
    else
        entries_to_visit_ = 0;
    // Done with task if we reach end of tree or count is exceeded
    if (flow_iteration_key_ == NULL || entries_to_visit_ == 0) {
        entries_to_visit_ = 0;
        ageing_task_ = NULL;
        return true;
    }

    // More entries to visit. Continue the task
    return false;
}

/////////////////////////////////////////////////////////////////////////////
// Utility methods to enqueue events into work-queue
/////////////////////////////////////////////////////////////////////////////
void FlowStatsCollector::AddEvent(const FlowEntryPtr &flow) {
    FlowExportInfo info(flow, GetCurrentTime());
    boost::shared_ptr<FlowExportReq>
        req(new FlowExportReq(FlowExportReq::ADD_FLOW, info));
    request_queue_.Enqueue(req);
}

void FlowStatsCollector::DeleteEvent(const FlowEntryPtr &flow,
                                     const RevFlowDepParams &params) {
    FlowExportInfo info(flow);
    boost::shared_ptr<FlowExportReq>
        req(new FlowExportReq(FlowExportReq::DELETE_FLOW, info,
                              GetCurrentTime(), params));
    request_queue_.Enqueue(req);
}

void FlowStatsCollector::UpdateStatsEvent(const FlowEntryPtr &flow,
                                          uint32_t bytes,
                                          uint32_t packets,
                                          uint32_t oflow_bytes,
                                          const boost::uuids::uuid &u) {
    FlowExportInfo info(flow);
    boost::shared_ptr<FlowExportReq>
        req(new FlowExportReq(FlowExportReq::UPDATE_FLOW_STATS, info, bytes,
                              packets, oflow_bytes, u));
    request_queue_.Enqueue(req);
}

bool FlowStatsCollector::RequestHandlerEntry() {
    current_time_ = GetCurrentTime();
    return true;
}

void FlowStatsCollector::RequestHandlerExit(bool done) {
}

bool FlowStatsCollector::RequestHandler(boost::shared_ptr<FlowExportReq> req) {
    const FlowExportInfo &info = req->info();
    FlowEntry *flow = info.flow();
    FlowEntry *rflow = info.reverse_flow();
    FLOW_LOCK(flow, rflow, FlowEvent::FLOW_MESSAGE);

    switch (req->event()) {
    case FlowExportReq::ADD_FLOW: {
        AddFlow(req->info());
        break;
    }

    case FlowExportReq::DELETE_FLOW: {
        FlowEntryTree::iterator it;
        // Get the FlowExportInfo for flow
        if (FindFlowExportInfo(flow, it) == false)
            break;

        /* We don't export flows in TSN mode */
        if (agent_uve_->agent()->tsn_enabled() == false) {
            FlowExportInfo *info = &it->second;
            /* While updating stats for evicted flows, we set the teardown_time
             * and export the flow. So delete handling for evicted flows need
             * not update stats and export flow */
            if (!info->teardown_time()) {
                UpdateFlowStats(info, req->time());
            }
        }
        /* Remove the entry from our tree */
        DeleteFlow(it);
        break;
    }

    case FlowExportReq::UPDATE_FLOW_STATS: {
        /* We don't export flows in TSN mode */
        if (agent_uve_->agent()->tsn_enabled() == false) {
            EvictedFlowStatsUpdate(flow, req->bytes(), req->packets(),
                                   req->oflow_bytes(), req->uuid());
        }
        break;
    }

    default:
         assert(0);
    }

    if (deleted_ && parent_->CanDelete()) {
        flow_stats_manager_->Free(flow_aging_key_);
    }

    return true;
}

FlowExportInfo *
FlowStatsCollector::FindFlowExportInfo(const FlowEntry *fe) {
    FlowEntryTree::iterator it = flow_tree_.find(fe);
    if (it == flow_tree_.end()) {
        return NULL;
    }

    return &it->second;
}

const FlowExportInfo *
FlowStatsCollector::FindFlowExportInfo(const FlowEntry *fe) const {
    FlowEntryTree::const_iterator it = flow_tree_.find(fe);
    if (it == flow_tree_.end()) {
        return NULL;
    }

    return &it->second;
}

bool FlowStatsCollector::FindFlowExportInfo(const FlowEntry *fe,
                                            FlowEntryTree::iterator &it) {
    it = flow_tree_.find(fe);
    if (it == flow_tree_.end()) {
        return false;
    }
    return true;
}

void FlowStatsCollector::NewFlow(FlowEntry *flow) {
    /* In TSN mode, we don't export flows or statistics based on flows */
    if (agent_uve_->agent()->tsn_enabled()) {
        return;
    }
    const FlowKey &key = flow->key();
    uint8_t proto = key.protocol;
    uint16_t sport = key.src_port;
    uint16_t dport = key.dst_port;

    // Update vrouter port bitmap
    VrouterUveEntry *vre = static_cast<VrouterUveEntry *>(
        agent_uve_->vrouter_uve_entry());
    vre->UpdateBitmap(proto, sport, dport);

    // Update source-vn port bitmap
    VnUveTable *vnte = static_cast<VnUveTable *>(agent_uve_->vn_uve_table());
    vnte->UpdateBitmap(flow->data().source_vn_match, proto, sport, dport);
    // Update dest-vn port bitmap
    vnte->UpdateBitmap(flow->data().dest_vn_match, proto, sport, dport);

    const VmInterface *port = dynamic_cast<const VmInterface *>
        (flow->intf_entry());
    if (port == NULL) {
        return;
    }
    const VmEntry *vm = port->vm();
    if (vm == NULL) {
        return;
    }

    // update vm and interface (all interfaces of vm) bitmap
    VmUveTable *vmt = static_cast<VmUveTable *>(agent_uve_->vm_uve_table());
    vmt->UpdateBitmap(vm, proto, sport, dport);
}

void FlowStatsCollector::AddFlow(FlowExportInfo info) {
    /* Before inserting update the gen_id and flow_handle in FlowExportInfo.
     * Locks for accessing fields of flow are taken in calling function.
     */
    FlowEntry* fe = info.flow();
    info.CopyFlowInfo(fe);
    std::pair<FlowEntryTree::iterator, bool> ret =
        flow_tree_.insert(make_pair(fe, info));
    if (ret.second == false) {
        FlowExportInfo &prev = ret.first->second;
        if (prev.uuid() != fe->uuid()) {
            /* Received ADD request for already added entry with a different
             * UUID. Because of state-compression of messages to
             * FlowStatsCollector in FlowMgmt, we have not received DELETE for
             * previous UUID. Send FlowExport to indicate delete for the flow.
             * This export need not be sent if teardown time is already set.
             * Teardown time would be set if EvictedFlowStats update request
             * comes before this duplicate add.
             */
            if (!prev.teardown_time()) {
                UpdateFlowStats(&prev, info.last_modified_time());
            }
            /* After sending Delete to collector (if required), reset the stats
             */
            prev.ResetStats();
        }
        prev.CopyFlowInfo(fe);
        prev.set_delete_enqueue_time(0);
        prev.set_evict_enqueue_time(0);
        prev.set_teardown_time(0);
    } else {
        NewFlow(info.flow());
    }
    if (ret.first->second.is_linked() == false) {
        flow_export_info_list_.push_back(ret.first->second);
    }
}

// The flow being deleted may be the first flow to visit in next ageing
// iteration. Update the flow to visit next in such case
void FlowStatsCollector::UpdateFlowIterationKey
(const FlowEntry *del_flow, FlowEntryTree::iterator &tree_it) {
    // Flow not found in tree is not a valid scenario. Lets be safe and
    // restart walk here
    if (tree_it == flow_tree_.end()) {
        flow_iteration_key_ = NULL;
    }

    if (flow_iteration_key_ == NULL) {
        return;
    }

    // The flow to visit next for ageing is being deleted. Update next flow to
    // visit
    FlowExportInfoList::iterator it =
        flow_export_info_list_.iterator_to(tree_it->second);
    ++it;

    // If this is end of list, start from begining again
    if (it == flow_export_info_list_.end())
        it = flow_export_info_list_.begin();

    if (it == flow_export_info_list_.end()) {
        flow_iteration_key_ = NULL;
    } else {
        flow_iteration_key_ = it->flow();
    }
}

void FlowStatsCollector::DeleteFlow(FlowEntryTree::iterator &it) {
    // Update flow_iteration_key_ if flow being deleted is flow to visit in
    // next ageing cycle
    // Nothing to do if flow being deleted is not the next-iteration key
    if (it->first == flow_iteration_key_) {
        UpdateFlowIterationKey(it->first, it);
    }

    if (it == flow_tree_.end())
        return;

    if (it->second.is_linked()) {
        FlowExportInfoList::iterator it1 =
            flow_export_info_list_.iterator_to(it->second);
        flow_export_info_list_.erase(it1);
    }

    flow_tree_.erase(it);
}

void FlowStatsCollector::EvictedFlowStatsUpdate(const FlowEntryPtr &flow,
                                                uint32_t bytes,
                                                uint32_t packets,
                                                uint32_t oflow_bytes,
                                                const boost::uuids::uuid &u) {
    FlowExportInfo *info = FindFlowExportInfo(flow.get());
    if (info) {
        /* Ignore stats update request for Evicted flow, if we don't have
         * FlowEntry corresponding to the Evicted Flow. The match is done using
         * UUID
         */
        if (info->uuid() != u) {
            return;
        }
        /* We are updating stats of evicted flow. Set teardown_time here.
         * When delete event is being handled we don't export flow if
         * teardown time is set */
        UpdateFlowStatsInternal(info, bytes, oflow_bytes & 0xFFFF,
                                packets, oflow_bytes & 0xFFFF0000,
                                GetCurrentTime(), true);
    }
}

/////////////////////////////////////////////////////////////////////////////
// Introspect routines
/////////////////////////////////////////////////////////////////////////////
static void KeyToSandeshFlowKey(const FlowKey &key,
                                SandeshFlowKey &skey) {
    skey.set_nh(key.nh);
    skey.set_sip(key.src_addr.to_string());
    skey.set_dip(key.dst_addr.to_string());
    skey.set_src_port(key.src_port);
    skey.set_dst_port(key.dst_port);
    skey.set_protocol(key.protocol);
}

static void FlowExportInfoToSandesh(const FlowExportInfo &value,
                                    SandeshFlowExportInfo &info) {
    SandeshFlowKey skey;
    FlowEntry *flow = value.flow();
    FlowEntry *rflow = value.reverse_flow();
    KeyToSandeshFlowKey(flow->key(), skey);
    info.set_key(skey);
    info.set_uuid(to_string(flow->uuid()));
    if (rflow) {
        info.set_rev_flow_uuid(to_string(rflow->uuid()));
    }
    info.set_source_vn(flow->data().source_vn_match);
    info.set_dest_vn(flow->data().dest_vn_match);
    info.set_sg_rule_uuid(flow->sg_rule_uuid());
    info.set_nw_ace_uuid(flow->nw_ace_uuid());
    info.set_teardown_time(value.teardown_time());
    info.set_last_modified_time(value.last_modified_time());
    info.set_bytes(value.bytes());
    info.set_packets(value.packets());
    info.set_flow_handle(flow->flow_handle());
    std::vector<ActionStr> action_str_l;
    SetActionStr(flow->data().match_p.action_info, action_str_l);
    info.set_action(action_str_l);
    info.set_vm_cfg_name(flow->data().vm_cfg_name);
    info.set_peer_vrouter(flow->peer_vrouter());
    info.set_tunnel_type(flow->tunnel_type().ToString());
    const VmInterfaceKey &vmi = flow->fip_vmi();
    string vmi_str = to_string(vmi.uuid_) + vmi.name_;
    info.set_fip_vmi(vmi_str);
    Ip4Address ip(flow->fip());
    info.set_fip(ip.to_string());
    info.set_delete_enqueued(value.delete_enqueue_time() ? true : false);
}

void FlowStatsRecordsReq::HandleRequest() const {
    FlowStatsCollector::FlowEntryTree::iterator it;
    vector<FlowStatsRecord> list;
    FlowStatsRecordsResp *resp = new FlowStatsRecordsResp();
    for (int i = 0; i < FlowStatsCollectorObject::kMaxCollectors; i++) {
        FlowStatsCollector *col = Agent::GetInstance()->
            flow_stats_manager()->default_flow_stats_collector_obj()->
            GetCollector(i);
        it = col->flow_tree_.begin();
        while (it != col->flow_tree_.end()) {
            const FlowExportInfo &value = it->second;
            ++it;

            SandeshFlowKey skey;
            KeyToSandeshFlowKey(value.flow()->key(), skey);

            SandeshFlowExportInfo info;
            FlowExportInfoToSandesh(value, info);

            FlowStatsRecord rec;
            rec.set_info(info);
            list.push_back(rec);
        }
    }
    resp->set_records_list(list);

    resp->set_context(context());
    resp->Response();
    return;
}

/////////////////////////////////////////////////////////////////////////////
// Flow Stats Ageing task
/////////////////////////////////////////////////////////////////////////////
FlowStatsCollector::AgeingTask::AgeingTask(FlowStatsCollector *fsc) :
    Task(fsc->task_id(), fsc->instance_id()), fsc_(fsc) {
}

FlowStatsCollector::AgeingTask::~AgeingTask() {
}

std::string FlowStatsCollector::AgeingTask::Description() const {
    return "Flow Stats Collector Ageing Task";
}

bool FlowStatsCollector::AgeingTask::Run() {
    return fsc_->RunAgeingTask();
}

/////////////////////////////////////////////////////////////////////////////
// FlowStatsCollectorObject methods
/////////////////////////////////////////////////////////////////////////////
FlowStatsCollectorObject::FlowStatsCollectorObject(Agent *agent,
                                                   FlowStatsCollectorReq *req,
                                                   FlowStatsManager *mgr) {
    FlowAgingTableKey *key = &(req->key);
    for (int i = 0; i < kMaxCollectors; i++) {
        uint32_t instance_id = mgr->AllocateIndex();
        collectors[i].reset(
            AgentObjectFactory::Create<FlowStatsCollector>(
                *(agent->event_manager()->io_service()),
                req->flow_stats_interval, req->flow_cache_timeout,
                agent->uve(), instance_id, key, mgr, this));
    }
}

FlowStatsCollector* FlowStatsCollectorObject::GetCollector(uint8_t idx) const {
    if (idx >= 0 && idx < kMaxCollectors) {
        return collectors[idx].get();
    }
    return NULL;
}

void FlowStatsCollectorObject::SetExpiryTime(int time) {
    for (int i = 0; i < kMaxCollectors; i++) {
        collectors[i]->set_expiry_time(time);
    }
}

int FlowStatsCollectorObject::GetExpiryTime() const {
    /* Same expiry time would be configured for all the collectors. Pick value
     * from any one of them */
    return collectors[0]->expiry_time();
}

void FlowStatsCollectorObject::MarkDelete() {
    for (int i = 0; i < kMaxCollectors; i++) {
        collectors[i]->set_deleted(true);
    }
}

void FlowStatsCollectorObject::ClearDelete() {
    for (int i = 0; i < kMaxCollectors; i++) {
        collectors[i]->set_deleted(false);
    }
}

bool FlowStatsCollectorObject::IsDeleted() const {
    for (int i = 0; i < kMaxCollectors; i++) {
        if (!collectors[i]->deleted()) {
            return false;
        }
    }
    return true;
}

void FlowStatsCollectorObject::SetFlowAgeTime(uint64_t value) {
    for (int i = 0; i < kMaxCollectors; i++) {
        collectors[i]->set_flow_age_time_intvl(value);
    }
}

uint64_t FlowStatsCollectorObject::GetFlowAgeTime() const {
    /* Same age time would be configured for all the collectors. Pick value
     * from any one of them */
    return collectors[0]->flow_age_time_intvl();
}

bool FlowStatsCollectorObject::CanDelete() const {
    for (int i = 0; i < kMaxCollectors; i++) {
        if (collectors[i]->flow_tree_.size() != 0 ||
            collectors[i]->request_queue_.IsQueueEmpty() == false) {
            return false;
        }
    }
    return true;
}

void FlowStatsCollectorObject::Shutdown() {
    for (int i = 0; i < kMaxCollectors; i++) {
        collectors[i]->Shutdown();
        collectors[i].reset();
    }
}

FlowStatsCollector* FlowStatsCollectorObject::FlowToCollector
    (const FlowEntry *flow) {
    uint8_t idx = 0;
    FlowTable *table = flow->flow_table();
    if (table) {
        idx = table->table_index() % kMaxCollectors;
    }
    return collectors[idx].get();
}

void FlowStatsCollectorObject::UpdateAgeTimeInSeconds(uint32_t age_time) {
    for (int i = 0; i < kMaxCollectors; i++) {
        collectors[i]->UpdateFlowAgeTimeInSecs(age_time);
    }
}

uint32_t FlowStatsCollectorObject::GetAgeTimeInSeconds() const {
    /* Same age time would be configured for all the collectors. Pick value
     * from any one of them */
    return collectors[0]->flow_age_time_intvl_in_secs();
}

size_t FlowStatsCollectorObject::Size() const {
    size_t size = 0;
    for (int i = 0; i < kMaxCollectors; i++) {
        size += collectors[i]->Size();
    }
    return size;
}


text:
/**
 *
 * @author grog (at) myrobotlab.org
 *
 * This file is part of MyRobotLab (http://myrobotlab.org).
 *
 * MyRobotLab is free software: you can redistribute it and/or modify
 * it under the terms of the Apache License 2.0 as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version (subject to the "Classpath" exception
 * as provided in the LICENSE.txt file that accompanied this code).
 *
 * MyRobotLab is distributed in the hope that it will be useful or fun,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Apache License 2.0 for more details.
 *
 * All libraries in thirdParty bundle are subject to their own license
 * requirements - please refer to http://myrobotlab.org/libraries for
 * details.
 *
 * Enjoy !
 *
 * */

package org.myrobotlab.swing.opencv;

import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.border.TitledBorder;

import org.myrobotlab.opencv.FilterWrapper;
import org.myrobotlab.opencv.OpenCVFilterSURF;
import org.myrobotlab.service.SwingGui;

public class OpenCVFilterSURFGui extends OpenCVFilterGui implements ActionListener {

  JTextField objectFilename = new JTextField("objectFilename", 200);

  public OpenCVFilterSURFGui(String boundFilterName, String boundServiceName, SwingGui myService) {
    super(boundFilterName, boundServiceName, myService);
    objectFilename.addActionListener(this);
    TitledBorder title;
    JPanel j = new JPanel(new GridBagLayout());
    title = BorderFactory.createTitledBorder("SURF Config");
    j.setBorder(title);
    j.add(new JLabel("Filename"));
    j.add(objectFilename);
    display.add(j, gc);
  }

  @Override
  public void actionPerformed(ActionEvent event) {
    // TODO Auto-generated method stub
    Object o = event.getSource();
    OpenCVFilterSURF sf = (OpenCVFilterSURF) boundFilter.filter;
    if (o == objectFilename) {
      String val = ((JTextField) o).getText();
      sf.loadObjectImageFilename(val);
    } else {
      log.warn("Inknown object invoked in surf filter ui");
    }
  }

  // FIXME - update components :)
  @Override
  public void getFilterState(final FilterWrapper filterWrapper) {
    boundFilter = filterWrapper;
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run() {
        // OpenCVFilterSURF af = (OpenCVFilterSURF) filterWrapper.filter;
        // TODO: doesn't do anything yet ? not implemented?
      }
    });

  }
}

redpajama_set_name: RedPajamaGithub


text:
using System.Diagnostics;
using System.Threading.Tasks;
using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;

namespace DeVi.ViewServices.Implementations
{
	internal class BackgroundTaskService : IBackgroundTaskService
	{
		public async Task<object> Execute( MetroWindow window, object args )
		{
			BackgroundTaskServiceArgs btsa = args as BackgroundTaskServiceArgs;
			Debug.Assert( btsa != null, "btsa != null" );

			var progressController = await window.ShowProgressAsync( btsa.Title, btsa.Message, true );
			var statistics = new ProgressStatistics( progressController );

			await Task.Run( () =>
			{
				btsa.Action( statistics );
			} );

			await progressController.CloseAsync();

			return statistics.Result;
		}
	}
}


text:
package com.crawler.autovit.data;

public class DataException extends Exception {

	private static final long serialVersionUID = 1L;

	public DataException(String message, Throwable cause) {
		super(message, cause);
	}

	public DataException(String message) {
		super(message);
	}

}


text:
from builtins import str
from builtins import object
import logging
from collections import defaultdict
from copy import deepcopy

from MySQLdb.cursors import DictCursor
from _mysql_exceptions import MySQLError
from bq_data_access.v1.feature_search.common import BackendException, InvalidFieldException, EmptyQueryException
from bq_data_access.v1.feature_search.common import FOUND_FEATURE_LIMIT
from bq_data_access.v1.mirna_data import MIRN_FEATURE_TYPE
from cohorts.metadata_helpers import get_sql_connection

class MIRNSearcher(object):
    feature_search_valid_fields = set(['mirna_name', 'platform', 'value_field'])
    field_search_valid_fields = set(['mirna_name'])

    searchable_fields = [
        {'name': 'mirna_name',
         'label': 'miRNA Name',
         'static': False},
        {'name': 'platform',
         'label': 'Platform',
         'static': True,
         'values': ['IlluminaGA', 'IlluminaHiSeq']},
        {'name': 'value_field',
         'label': 'Value',
         'static': True, 'values': ['RPM', 'normalized_count']}
    ]

    @classmethod
    def get_searchable_fields(cls):
        return deepcopy(cls.searchable_fields)

    @classmethod
    def get_datatype_identifier(cls):
        return MIRN_FEATURE_TYPE

    @classmethod
    def get_table_name(cls):
        return "feature_defs_mirna"

    def validate_field_search_input(self, keyword, field):
        if field not in self.field_search_valid_fields:
            raise InvalidFieldException("MIRN", keyword, field)

    def field_value_search(self, keyword, field):
        self.validate_field_search_input(keyword, field)

        query = 'SELECT DISTINCT {search_field} FROM {table_name} WHERE {search_field} LIKE %s LIMIT %s'.format(
            table_name=self.get_table_name(),
            search_field=field
        )
        # Format the keyword for MySQL string matching
        sql_keyword = '%' + keyword + '%'
        query_args = [sql_keyword, FOUND_FEATURE_LIMIT]

        try:
            db = get_sql_connection()
            cursor = db.cursor(DictCursor)
            cursor.execute(query, tuple(query_args))
            items = []

            for row in cursor.fetchall():
                items.append(row[field])

            return items

        except MySQLError as mse:
            raise BackendException('database error: ' + str(mse))

    def validate_feature_search_input(self, parameters):
        # Check that the input contains only allowed fields
        for field, keyword in parameters.items():
            if field not in self.feature_search_valid_fields:
                raise InvalidFieldException(", ".join([self.get_datatype_identifier(), field, keyword]))

        # At least one field has to have a non-empty keyword
        found_field = False
        for field, keyword in parameters.items():
            if len(keyword) > 0:
                found_field = True
                continue

        if not found_field:
            raise EmptyQueryException(self.get_datatype_identifier())

    def build_feature_label(self, row):
        # Example: 'MicroRNA | miRNA Name:hsa-mir-126, Platform:IlluminaGA, Value:RPM'
        label = "MicroRNA | miRNA Name:" + row['mirna_name'] + ", Platform:" + row['platform'] + ", Value:" + row['value_field']
        return label

    def search(self, parameters):
        self.validate_feature_search_input(parameters)

        query = 'SELECT mirna_name, platform, value_field, internal_feature_id ' \
                'FROM {table_name} ' \
                'WHERE mirna_name LIKE %s ' \
                'AND platform LIKE %s ' \
                'AND value_field LIKE %s ' \
                'LIMIT %s'.format(table_name=self.get_table_name()
        )
        logging.debug(query)
        # Fills in '' for fields that were not specified in the parameters
        input = defaultdict(lambda: '', parameters)

        # Format the keyword for MySQL string matching
        query_args = ['%' + input['mirna_name'] + '%',
                      '%' + input['platform'] + '%',
                      '%' + input['value_field'] + '%',
                      FOUND_FEATURE_LIMIT]

        try:
            db = get_sql_connection()
            cursor = db.cursor(DictCursor)
            cursor.execute(query, tuple(query_args))
            items = []

            for row in cursor.fetchall():
                items.append(row)

            # Generate human readable labels
            for item in items:
                item['feature_type'] = MIRN_FEATURE_TYPE
                item['label'] = self.build_feature_label(item)

            return items

        except MySQLError:
            raise BackendException('database error')


text:
class AddGeoEntityTypeToListingChangesMviews < ActiveRecord::Migration
  def change
    [:cites, :eu, :cms].each do |designation|
      listing_changes_mview = "#{designation}_listing_changes_mview"
      unless column_exists? listing_changes_mview, :geo_entity_type
        add_column listing_changes_mview, :geo_entity_type, :string
      end
    end
  end
end


text:
<?php
namespace App\Test\Fixture;

use Cake\TestSuite\Fixture\TestFixture;

/**
 * SenhasExpiradasFixture
 *
 */
class SenhasExpiradasFixture extends TestFixture
{

    /**
     * Fields
     *
     * @var array
     */
    // @codingStandardsIgnoreStart
    public $fields = [
        'titulo_id' => ['type' => 'biginteger', 'length' => 20, 'default' => null, 'null' => true, 'comment' => null, 'precision' => null, 'unsigned' => null, 'autoIncrement' => null],
        'titulo' => ['type' => 'string', 'length' => 200, 'default' => null, 'null' => true, 'comment' => null, 'precision' => null, 'fixed' => null],
        'conta_id' => ['type' => 'biginteger', 'length' => 20, 'default' => null, 'null' => true, 'comment' => null, 'precision' => null, 'unsigned' => null, 'autoIncrement' => null],
        'email' => ['type' => 'string', 'length' => 200, 'default' => null, 'null' => true, 'comment' => null, 'precision' => null, 'fixed' => null],
        'senha' => ['type' => 'string', 'length' => 20, 'default' => null, 'null' => true, 'comment' => null, 'precision' => null, 'fixed' => null],
    ];
    // @codingStandardsIgnoreEnd

    /**
     * Records
     *
     * @var array
     */
    public $records = [
        [
            'titulo_id' => '',
            'titulo' => 'Lorem ipsum dolor sit amet',
            'conta_id' => '',
            'email' => 'Lorem ipsum dolor sit amet',
            'senha' => 'Lorem ipsum dolor '
        ],
    ];
}


text:
from django.forms import ValidationError

class TemplateFormValidationError(ValidationError):
    def __init__(self, form, *args, **kwargs):
        self.form = form
        self.errors = form.errors
        super(TemplateFormValidationError, self).__init__(*args, **kwargs)


text:
/*
 * $RCSfile: LCColorConvertDescriptor.java,v $
 *
 * Copyright (c) 2005 Sun Microsystems, Inc. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * $Revision: 1.2 $
 * $Date: 2005/03/28 17:45:12 $
 * $State: Exp $
 */

package com.lightcrafts.jai.operator;

import javax.media.jai.EnumeratedParameter;
import javax.media.jai.JAI;
import javax.media.jai.OperationDescriptorImpl;
import javax.media.jai.ParameterBlockJAI;
import javax.media.jai.RenderableOp;
import javax.media.jai.RenderedOp;
import javax.media.jai.registry.RenderableRegistryMode;
import javax.media.jai.registry.RenderedRegistryMode;
import java.awt.*;
import java.awt.color.ICC_Profile;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.RenderableImage;

/**
 * An OperationDescriptor describing the "ColorConvert" operation.
 *
 *
 The "ColorConvert" operation performs a pixel-by-pixel color
 * conversion of the data in a rendered or renderable source image.
 *
 *
 The data are treated as having no alpha channel, i.e., all bands are
 * color bands.  The color space of the source image is specified by the
 * ColorSpace object of the source image ColorModel
 * which must not be null.  The color space of the destination
 * image is specified by the ColorSpace of the "colorModel"
 * parameter which must be a ColorModel.  If a
 * ColorModel is suggested via the RenderingHints
 * it is ignored.
 *
 *
 The calculation pathway is selected to optimize performance and
 * accuracy based on which ColorSpace subclasses are used to
 * represent the source and destination color spaces.  The subclass
 * categories are ICC_ColorSpace, ColorSpaceJAI,
 * and generic ColorSpace, i.e., one which is not an instance
 * of either the two aforementioned subclasses.  Note that in the Sun
 * Microsystems implementation, an ICC_ColorSpace instance
 * is what is returned by ColorSpace.getInstance().
 *
 *
 Integral data are assumed to occupy the full range of the respective
 * data type; floating point data are assumed to be normalized to the range
 * [0.0,1.0].
 *
 *
 By default, the destination image bounds, data type, and number of
 * bands are the same as those of the source image.
 *
 *

 *
Resource List

 *
Name	        Value

 *
GlobalName	  LCColorConvert

 *
LocalName	   LCColorConvert

 *
Vendor	      com.lightcrafts

 *
Description	 Convert the color space of an image.

 *
DocURL	      http://java.sun.com/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/operator/ColorConvertDescriptor.html

 *
Version	     1.0

 *
arg0Desc	    The destination ColorModel.

 *

 *
 *

 *
Parameter List

 *
Name	      Class Type
 *                        Default Value

 *
colorModel	 java.awt.image.ColorModel
 *                        NO_PARAMETER_DEFAULT
 *

 *
 * @see javax.media.jai.OperationDescriptor
 * @see java.awt.color.ColorSpace
 * @see java.awt.color.ICC_ColorSpace
 * @see java.awt.image.ColorModel
 * @see javax.media.jai.ColorSpaceJAI
 * @see javax.media.jai.IHSColorSpace
 */
public class LCColorConvertDescriptor extends OperationDescriptorImpl {

    public static final class RenderingIntent extends EnumeratedParameter {
        RenderingIntent(String name, int value) {
            super(name, value);
        }
    }

    public static final RenderingIntent DEFAULT = new RenderingIntent("DEFAULT", -1);
    public static final RenderingIntent PERCEPTUAL = new RenderingIntent("PERCEPTUAL", ICC_Profile.icPerceptual);
    public static final RenderingIntent SATURATION = new RenderingIntent("SATURATION", ICC_Profile.icSaturation);
    public static final RenderingIntent RELATIVE_COLORIMETRIC = new RenderingIntent("RELATIVE_COLORIMETRIC", ICC_Profile.icRelativeColorimetric);
    public static final RenderingIntent ABSOLUTE_COLORIMETRIC = new RenderingIntent("ABSOLUTE_COLORIMETRIC", ICC_Profile.icAbsoluteColorimetric);

    /**
     * The resource strings that provide the general documentation
     * and specify the parameter list for this operation.
     */
    private static final String[][] resources = {
        {"GlobalName",  "LCColorConvert"},
        {"LocalName",   "LCColorConvert"},
        {"Vendor",      "com.lightcrafts"},
        {"Description", LCJaiI18N.getString("LCColorConvertDescriptor0")},
        {"DocURL",      "none"},
        {"Version",     LCJaiI18N.getString("DescriptorVersion2")},
        {"arg0Desc",    LCJaiI18N.getString("LCColorConvertDescriptor1")}
    };

    /**
     * The parameter class list for this operation.
     */
    private static final Class[] paramClasses = {
        java.awt.image.ColorModel.class,
        RenderingIntent.class
    };

    /** The parameter name list for this operation. */
    private static final String[] paramNames = {
        "colorModel",
        "renderingIntent"
    };

    /** The parameter default value list for this operation. */
    private static final Object[] paramDefaults = {
        NO_PARAMETER_DEFAULT,
        DEFAULT
    };

    /** Constructor. */
    public LCColorConvertDescriptor() {
        super(resources, 1, paramClasses, paramNames, paramDefaults);
    }

    /** Returns true since renderable operation is supported. */
    public boolean isRenderableSupported() {
        return true;
    }

    /**
     * Convert the color space of an image.
     *
     *
Creates a ParameterBlockJAI from all
     * supplied arguments except hints and invokes
     * {@link javax.media.jai.JAI#create(String,java.awt.image.renderable.ParameterBlock,java.awt.RenderingHints)}.
     *
     * @see javax.media.jai.JAI
     * @see javax.media.jai.ParameterBlockJAI
     * @see javax.media.jai.RenderedOp
     *
     * @param source0 RenderedImage source 0.
     * @param colorModel The destination color space.
     * @param hints The RenderingHints to use.
     * May be null.
     * @return The RenderedOp destination.
     * @throws IllegalArgumentException if source0 is null.
     * @throws IllegalArgumentException if colorModel is null.
     */
    public static RenderedOp create(RenderedImage source0,
                                    ColorModel colorModel,
                                    RenderingIntent renderingIntent,
                                    RenderingHints hints)  {
        ParameterBlockJAI pb =
            new ParameterBlockJAI("LCColorConvert",
                                  RenderedRegistryMode.MODE_NAME);

        pb.setSource("source0", source0);

        pb.setParameter("colorModel", colorModel);
        pb.setParameter("renderingIntent", renderingIntent);

        return JAI.create("LCColorConvert", pb, hints);
    }

    /**
     * Convert the color space of an image.
     *
     *
Creates a ParameterBlockJAI from all
     * supplied arguments except hints and invokes
     * {@link JAI#createRenderable(String,java.awt.image.renderable.ParameterBlock,RenderingHints)}.
     *
     * @see JAI
     * @see ParameterBlockJAI
     * @see javax.media.jai.RenderableOp
     *
     * @param source0 RenderableImage source 0.
     * @param colorModel The destination color space.
     * @param hints The RenderingHints to use.
     * May be null.
     * @return The RenderableOp destination.
     * @throws IllegalArgumentException if source0 is null.
     * @throws IllegalArgumentException if colorModel is null.
     */
    public static RenderableOp createRenderable(RenderableImage source0,
                                                ColorModel colorModel,
                                                RenderingIntent renderingIntent,
                                                RenderingHints hints)  {
        ParameterBlockJAI pb =
            new ParameterBlockJAI("LCColorConvert",
                                  RenderableRegistryMode.MODE_NAME);

        pb.setSource("source0", source0);

        pb.setParameter("colorModel", colorModel);
        pb.setParameter("renderingIntent", renderingIntent);

        return JAI.createRenderable("LCColorConvert", pb, hints);
    }
}


text:
*Note:* This project uses old version of mediasoup and won't be updated any time soon.

# mediasoup-server
WebRTC SFU mediasoup implementation
* Optional RTSP server to play the streams.
* Optional ffmpeg recorder to media file or publish to RTMP media server.

* Mediasoup GitHub [https://github.com/ibc/mediasoup](https://github.com/ibc/mediasoup)
* Mediasoup Web site [https://mediasoup.org](https://mediasoup.org)

# Installation

# How to use library

## Install NPM modules

Python 2, make, g++ or clang are required for installing mediasoup.
```
$ npm install mediasoup-server
```

## Run WebRTC server

```javascript
const WebRtcServer = require('mediasoup-server').WebRtcServer;

const hostname = os.hostname();

const webRtcServer = new WebRtcServer();
webRtcServer
.listen({
	enableDebug: true,
	key: fs.readFileSync('keys/server.key'),
	cert: fs.readFileSync('keys/server.crt'),
	port: 3888,
	path: 'public',
})
.on('listen', () => {
	console.log('Mediasoup demo started');
})
.on('web-listen', (port) => {
	console.log(`Open https://${hostname}:${port} with browser`);
})
.on('new-connection', (connection) => {
	console.log(`New connection [${connection.id}]`);

	connection
	.on('error', (err) => {
		console.log(`Connection [${connection.id}] error: ${err}`);
	})
	.on('receive', (action, data) => {
		console.log(`Connection [${connection.id}] receive [${action}]`);
	})
	.on('send', (action, data) => {
		console.log(`Connection [${connection.id}] send [${action}]`);
	})
	.on('new-stream', (stream) => {
		console.log(`Connection [${connection.id}] peer [${stream.peer.id}] new stream [${stream.id}]`);
	})
	.on('ready', (peerConnection) => {
		console.log(`Connection [${connection.id}] peer [${peerConnection.peer.id}] ready`);
	})
	.on('close', (peerId) => {
		console.log(`Connection [${connection.id}] peer [${peerId}] closed`);
	})
	.on('disconnect', (err) => {
		console.log(`Connection [${connection.id}] signaling disconnected`);
		connection = null;
	});
});
```

## Run RTSP server

```javascript
const RtspServer = require('mediasoup-server').RtspServer;

const rtspServer = new RtspServer(webRtcServer);
rtspServer
.listen(5000)
.on('listen', (port) => {
	console.log(`RTSP server started rtsp://${hostname}:${port}`);
})
.on('new-source', (source) => {
	let rtspUrl = `rtsp://${hostname}:${rtspServer.port}/${source.id}.sdp`;
	source.on('enabled', () => {
		console.log(`RTSP source available: ${rtspUrl}`);
	});
});
```

## Record to disc

```javascript
const rtspServer = new RtspServer(webRtcServer);
rtspServer
.listen(5000)
.on('new-source', (source) => {
	source.on('enabled', () => {
		let rtspUrl = `rtsp://${hostname}:${rtspServer.port}/${source.id}.sdp`;
		let filepath = `${recordingsPath}/${source.id}.mp4`;
		let logpath = `${recordingsPath}/${source.id}.log`;

		console.log(`Recording [${source.id}]: ${filepath}`);
		let process = streamer.record(rtspUrl, filepath, logpath)
		.on('error', (err) => {
			console.error(`Streamer [${source.id}] error: ${err}`);
		})
		.on('exit', (code, signal) => {
			console.log(`Streamer [${source.id}] closed, log: ${logpath}`);
		});
	});
});
```

## Publish to RTMP server

```javascript
const rtspServer = new RtspServer(webRtcServer);
rtspServer
.listen(5000)
.on('new-source', (source) => {
	source.on('enabled', () => {
		let rtspUrl = `rtsp://${hostname}:${rtspServer.port}/${source.id}.sdp`;
		let rtmpUrl = `rtmp://${hostname}:1935/live/${source.id}`;
		let logpath = `${recordingsPath}/${source.id}.log`;

		console.log(`Publishing [${source.id}]: ${rtmpUrl}`);
		let process = streamer.publish(rtspUrl, rtmpUrl, logpath)
		.on('error', (err) => {
			console.error(`Streamer [${source.id}] error: ${err}`);
		})
		.on('exit', (code, signal) => {
			console.log(`Streamer [${source.id}] closed, log: ${logpath}`);
		});
	});
});
```

# How to use example

## Git clone
```
git clone https://github.com/tan-tan-kanarek/mediasoup-server.git
cd mediasoup-server/
```

## Install NPM modules

Python 2, make, g++ or clang are required for installing mediasoup.
```
$ npm install
```

## Run server example
```
$ node example
```
or
```
$ npm start
```

*access with borwser*

* Open [http://localhost:3888/](http://localhost:3888/).
* Set room name and click [Join] button

# TODO

## Server
* Execute ffmpeg remotely (send message to different server to execute ffmpeg)
* To support scalability and redundancy, hold list of rooms in all servers and redirect socket.io commands to the server that handles the room, SDPs should be generated on the server that holds the room.

## Client
* Rejoin room when socket.io reconnected.
* Accept new room created event.


text:
require "rails_helper"

RSpec.describe ApplicationController, type: :controller do
  controller do
    skip_authorization_check

    def index
      response.headers['Content-Length'] = -100
      render text: "test response"
    end
  end

  describe "Application wide tests" do
    it "it fails if content-length is negative" do
      expect {
        get :index
      }.to raise_error(CustomErrors::BadHeaderError)
    end
  end
end


text:
from ui.read import x as ui_read
from ui.read import spots as read_spots
from core.read import read as core_read
from core.analyse import analyse
from core.plasma import list as plist
from ui.write import write as ui_write

def optimise(view, edit):
    read_view = ui_read.all(view)
    spots = read_spots.spots(view)
    plasmas = core_read.plasmas(read_view.ptext)

    unused = analyse.unused(plasmas, spots)
    optimised = plist.remove_all(plasmas, unused)
    ui_write.plasmas(view, edit, plist.sort(optimised))


text:
package org.apache.storm.daemon.drpc;

import com.codahale.metrics.Meter;
import com.google.common.annotations.VisibleForTesting;

import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.apache.storm.Config;
import org.apache.storm.DaemonConfig;
import org.apache.storm.daemon.drpc.webapp.DRPCApplication;
import org.apache.storm.daemon.drpc.webapp.ReqContextFilter;
import org.apache.storm.generated.DistributedRPC;
import org.apache.storm.generated.DistributedRPCInvocations;
import org.apache.storm.metric.StormMetricsRegistry;
import org.apache.storm.security.auth.AuthUtils;
import org.apache.storm.security.auth.IHttpCredentialsPlugin;
import org.apache.storm.security.auth.ThriftConnectionType;
import org.apache.storm.security.auth.ThriftServer;
import org.apache.storm.ui.FilterConfiguration;
import org.apache.storm.ui.UIHelpers;
import org.apache.storm.utils.ObjectReader;
import org.apache.storm.utils.Utils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.servlet.ServletContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DRPCServer implements AutoCloseable {
    private static final Logger LOG = LoggerFactory.getLogger(DRPCServer.class);
    private static final Meter meterShutdownCalls = StormMetricsRegistry.registerMeter("drpc:num-shutdown-calls");

    //TODO in the future this might be better in a common webapp location

    /**
     * Add a request context filter to the Servlet Context Handler.
     * @param context The Servlet Context handler
     * @param configName Config name
     * @param conf Conf to be added in context filter
     */
    public static void addRequestContextFilter(ServletContextHandler context, String configName, Map<String, Object> conf) {
        IHttpCredentialsPlugin auth = AuthUtils.GetHttpCredentialsPlugin(conf, (String)conf.get(configName));
        ReqContextFilter filter = new ReqContextFilter(auth);
        context.addFilter(new FilterHolder(filter), "/*", FilterMapping.ALL);
    }

    private static ThriftServer mkHandlerServer(final DistributedRPC.Iface service, Integer port, Map<String, Object> conf) {
        ThriftServer ret = null;
        if (port != null && port >= 0) {
            ret = new ThriftServer(conf, new DistributedRPC.Processor<>(service),
                    ThriftConnectionType.DRPC);
        }
        return ret;
    }

    private static ThriftServer mkInvokeServer(final DistributedRPCInvocations.Iface service, int port, Map<String, Object> conf) {
        return new ThriftServer(conf, new DistributedRPCInvocations.Processor<>(service),
                ThriftConnectionType.DRPC_INVOCATIONS);
    }

    private static Server mkHttpServer(Map<String, Object> conf, DRPC drpc) {
        Integer drpcHttpPort = (Integer) conf.get(DaemonConfig.DRPC_HTTP_PORT);
        Server ret = null;
        if (drpcHttpPort != null && drpcHttpPort >= 0) {
            LOG.info("Starting RPC HTTP servers...");
            String filterClass = (String) (conf.get(DaemonConfig.DRPC_HTTP_FILTER));
            @SuppressWarnings("unchecked")
            Map<String, String> filterParams = (Map<String, String>) (conf.get(DaemonConfig.DRPC_HTTP_FILTER_PARAMS));
            FilterConfiguration filterConfiguration = new FilterConfiguration(filterClass, filterParams);
            final List<FilterConfiguration> filterConfigurations = Arrays.asList(filterConfiguration);
            final Integer httpsPort = ObjectReader.getInt(conf.get(DaemonConfig.DRPC_HTTPS_PORT), 0);
            final String httpsKsPath = (String) (conf.get(DaemonConfig.DRPC_HTTPS_KEYSTORE_PATH));
            final String httpsKsPassword = (String) (conf.get(DaemonConfig.DRPC_HTTPS_KEYSTORE_PASSWORD));
            final String httpsKsType = (String) (conf.get(DaemonConfig.DRPC_HTTPS_KEYSTORE_TYPE));
            final String httpsKeyPassword = (String) (conf.get(DaemonConfig.DRPC_HTTPS_KEY_PASSWORD));
            final String httpsTsPath = (String) (conf.get(DaemonConfig.DRPC_HTTPS_TRUSTSTORE_PATH));
            final String httpsTsPassword = (String) (conf.get(DaemonConfig.DRPC_HTTPS_TRUSTSTORE_PASSWORD));
            final String httpsTsType = (String) (conf.get(DaemonConfig.DRPC_HTTPS_TRUSTSTORE_TYPE));
            final Boolean httpsWantClientAuth = (Boolean) (conf.get(DaemonConfig.DRPC_HTTPS_WANT_CLIENT_AUTH));
            final Boolean httpsNeedClientAuth = (Boolean) (conf.get(DaemonConfig.DRPC_HTTPS_NEED_CLIENT_AUTH));

            //TODO a better way to do this would be great.
            DRPCApplication.setup(drpc);
            ret = UIHelpers.jettyCreateServer(drpcHttpPort, null, httpsPort);

            UIHelpers.configSsl(ret, httpsPort, httpsKsPath, httpsKsPassword, httpsKsType, httpsKeyPassword,
                    httpsTsPath, httpsTsPassword, httpsTsType, httpsNeedClientAuth, httpsWantClientAuth);

            ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
            context.setContextPath("/");
            ret.setHandler(context);

            ServletHolder jerseyServlet = context.addServlet(ServletContainer.class, "/*");
            jerseyServlet.setInitOrder(1);
            jerseyServlet.setInitParameter("javax.ws.rs.Application", DRPCApplication.class.getName());

            UIHelpers.configFilters(context, filterConfigurations);
            addRequestContextFilter(context, Config.DRPC_HTTP_CREDS_PLUGIN, conf);
        }
        return ret;
    }

    private final DRPC drpc;
    private final ThriftServer handlerServer;
    private final ThriftServer invokeServer;
    private final Server httpServer;
    private Thread handlerServerThread;
    private boolean closed = false;

    /**
     * Constructor.
     * @param conf Drpc conf for the servers
     */
    public DRPCServer(Map<String, Object> conf) {
        drpc = new DRPC(conf);
        DRPCThrift thrift = new DRPCThrift(drpc);
        handlerServer = mkHandlerServer(thrift, ObjectReader.getInt(conf.get(Config.DRPC_PORT), null), conf);
        invokeServer = mkInvokeServer(thrift, ObjectReader.getInt(conf.get(Config.DRPC_INVOCATIONS_PORT), 3773), conf);
        httpServer = mkHttpServer(conf, drpc);
    }

    @VisibleForTesting
    void start() throws Exception {
        LOG.info("Starting Distributed RPC servers...");
        new Thread(() -> invokeServer.serve()).start();

        if (httpServer != null) {
            httpServer.start();
        }

        if (handlerServer != null) {
            handlerServerThread = new Thread(handlerServer::serve);
            handlerServerThread.start();
        }
    }

    @VisibleForTesting
    void awaitTermination() throws InterruptedException {
        if (handlerServerThread != null) {
            handlerServerThread.join();
        } else {
            httpServer.join();
        }
    }

    @Override
    public synchronized void close() {
        if (!closed) {
            //This is kind of useless...
            meterShutdownCalls.mark();

            if (handlerServer != null) {
                handlerServer.stop();
            }

            if (invokeServer != null) {
                invokeServer.stop();
            }

            //TODO this is causing issues...
            //if (httpServer != null) {
            //    httpServer.destroy();
            //}

            drpc.close();
            closed = true;
        }
    }

    /**
     * @return The port the DRPC handler server is listening on.
     */
    public int getDrpcPort() {
        return handlerServer.getPort();
    }

    /**
     * @return The port the DRPC invoke server is listening on.
     */
    public int getDrpcInvokePort() {
        return invokeServer.getPort();
    }

    /**
     * @return The port the HTTP server is listening on. Not available until {@link #start() } has run.
     */
    public int getHttpServerPort() {
        assert httpServer.getConnectors().length == 1;

        return httpServer.getConnectors()[0].getLocalPort();
    }

    /**
     * Main method to start the server.
     */
    public static void main(String [] args) throws Exception {
        Utils.setupDefaultUncaughtExceptionHandler();
        Map<String, Object> conf = Utils.readStormConfig();
        try (DRPCServer server = new DRPCServer(conf)) {
            Utils.addShutdownHookWithForceKillIn1Sec(() -> server.close());
            StormMetricsRegistry.startMetricsReporters(conf);
            server.start();
            server.awaitTermination();
        }
    }
}


text:
.leaflet-control-messagebox {
	/* display: none; /* Initially hidden */
	opacity: 0;
	border: 2px solid #dd4958; /* navisens-orange */
	border-radius: 1px;
	background-color: white;
	padding: 3px 10px;
	margin-left: 30px;

	-webkit-transition: 0.5s;
    -moz-transition: 0.5s;
    -o-transition: 0.5s;
    transition: 0.5s;
}


text:
package edu.gslis.textrepresentation;

import java.util.ArrayList;
import java.util.List;

import edu.gslis.utils.Stopper;
import lemurproject.indri.DocumentVector;
import lemurproject.indri.ParsedDocument;
import lemurproject.indri.QueryEnvironment;

/**
 * Basic class for handling interactions with an indri index pertaining to an individual document
 *
 * @author Miles Efron
 *
 */
public class IndriDocument {

	private QueryEnvironment env;

	/**
	 * constructor for the case where we know the index
	 */
	public IndriDocument(QueryEnvironment env) {
		this.env = env;
	}

	/**
	 * gets the parsed text of the document.  this is all nice and clean... exactly as indri stores it.
	 * @param docID the indri-internal numeric ID of the document.  i.e. not its TREC-assigned DOCNO element
	 * @return character String containing the full text of the document
	 */
	public String getDocString(int docID)  {
		StringBuilder b = new StringBuilder();
		String[] toks = getDocToks(docID);
		for(String tok : toks) {
			if(tok.equals("[OOV]")) {
				continue;
			}
			b = b.append(" " + tok + " ");
		}
		String docText = b.toString();
		return docText.replaceAll("  ", " ");
	}

	public String[] getDocToks(int docID) {
		int[] inds = new int[1];
		inds[0] = docID;
		String[] stems = null;
		int[] positions = null;
		inds[0] = docID;
		try{
			DocumentVector[] dv = env.documentVectors(inds);
			stems = dv[0].stems;
			positions = dv[0].positions;
		} catch (Exception e) {
			e.printStackTrace();
		}
		String[] toks = new String[positions.length];

		for(int i=0; i<positions.length; i++) {
			toks[i] = stems[positions[i]];
		}
		return toks;
	}

	public FeatureVector getFeatureVector(int docID, Stopper stopper) {
		String[] toks = getDocToks(docID);
		FeatureVector features = new FeatureVector(stopper);
		for(String tok : toks) {
			if(tok.equals("[OOV]"))
				continue;
			if(stopper==null) {
				features.addTerm(tok, 1.0);
			} else if(!stopper.isStopWord(tok))
				features.addTerm(tok, 1.0);
		}
		return features;
	}

	/**
	 * gets the unparsed text of the document.  i.e. all formatting/tags/structure are present.  the document
	 * is exactly as it appears in the input file.
	 * @param docID the indri-internal numeric ID of the document.  i.e. not its TREC-assigned DOCNO element
	 * @return unparsed text of the document
	 */
	public String getUnparsedText(int docID) {
		String trecText = null;

		int[] id = {docID};
		try {
			ParsedDocument[] docArray = env.documents(id);
			trecText =  docArray[0].text;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return trecText;
	}

	/**
	 * gets the TREC-assigned docno element for the document with this indri docID, or null if docno element isn't present.
	 * @param docID indri-internal numeric ID of the document.  i.e. not its TREC-assigned DOCNO element
	 * @return trec DOCNO element, or null
	 */
	public String getDocno(int docID) {
		String docno = null;
		int[] docIDs = {docID};
		try {
		String[] docnos = env.documentMetadata(docIDs, "docno");
		docno = docnos[0];
		} catch (Exception e) {
			e.printStackTrace();
		}
		return docno;
	}

	/**
	 * gets the indri-assigned docID for the document with this TREC-assigned docno element.
	 * @param docno TREC-assigned docno of the document.
	 * @return indri-assigned docID, or -1
	 */
	public int getDocID(String docno) {
		String[] docnos = {docno};
		int[] docIDs = null;
		try {
			docIDs = env.documentIDsFromMetadata("docno", docnos);
		} catch (Exception e) {
			e.printStackTrace();		}
		if(docIDs==null || docIDs.length==0) {
			System.err.println("couldn't find the docId of doc " + docno);
			return 0;
		}
		return docIDs[0];
	}

	/**
	 *
	 * @param e the QueryEnvironment that contains the document
	 */
	public void setIndex(QueryEnvironment e) {
		env = e;
	}

	/**
	 * Returns an ordered list of terms for the specified document.
	 * @param docID
	 * @return
	 */
    public List<String> getTerms(int docID) {
        List<String> terms = new ArrayList<String>();
        int[] inds = new int[1];
        inds[0] = docID;
        String[] stems = null;
        int[] positions = null;
        inds[0] = docID;
        try{
            DocumentVector[] dv = env.documentVectors(inds);
            stems = dv[0].stems;
            positions = dv[0].positions;
        } catch (Exception e) {
            e.printStackTrace();
        }

        for(int i=0; i<positions.length; i++) {
            if(stems[positions[i]].equals("[OOV]"))
                continue;

            terms.add(stems[positions[i]]);
        }
        return terms;
    }

}


text:
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.j2objc.java8;

import junit.framework.TestCase;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;

interface UnaryOperator<T> {
  public T apply(T t);
}

interface UOToUO<T> {
  UnaryOperator<T> apply(UOToUO<T> x);
}

/**
 * Command-line tests for Lambda support.
 *
 * @author Seth Kirby
 */
public class LambdaTest extends TestCase {

  public LambdaTest() {}

  public void testBasicReflection() {
    assertEquals(false, ((Lambdas.One) (x) -> 1).equals((Lambdas.One) (x) -> 1));
    Lambdas.One f = x -> 1;
    Lambdas.One g = f;
    assertEquals(f, g);
    assertEquals(f.toString(), "" + g);
    String lambdaClassName = f.getClass().getName();
    assertEquals(true, lambdaClassName.contains("LambdaTest"));
    assertEquals(true, lambdaClassName.contains("ambda$"));
  }

  String outerCall() {
    return "Foo";
  }

  private String privateOuterCall() {
    return "Bar";
  }

  static class Foo {
    String outer() {
      return "Foo";
    }

    class Bar {
      String findMe() {
        return "Bar";
      }

      Lambdas.Zero fooS = () -> outer();
      Lambdas.Zero barS = () -> findMe();
    }

    Bar getBar() {
      return new Bar();
    }
  }

  public void testOuterMethodCalls() {
    assertEquals("Foo", Lambdas.get(() -> outerCall()).apply());
    assertEquals("Bar", Lambdas.get(() -> privateOuterCall()).apply());
    Foo foo = new Foo();
    assertEquals("Foo", Lambdas.get(() -> foo.outer()).apply());
    assertEquals("Bar", Lambdas.get(() -> foo.getBar().barS.apply()).apply());
  }

  Integer outerX = 0;
  int outerY = 0;

  public void testOuterVarCapture() {
    Lambdas.Zero s = () -> outerX;
    Lambdas.Zero s2 = () -> outerY;
    assertEquals((Integer) 0, s.apply());
    assertEquals((Integer) 0, s2.apply());
    outerX += 42;
    outerY += 42;
    assertEquals((Integer) 42, s.apply());
    assertEquals((Integer) 42, s2.apply());
    outerX++;
    outerY++;
    assertEquals((Integer) 43, s.apply());
    assertEquals((Integer) 43, s2.apply());
    outerX++;
    outerY++;
  }

  public void testFunctionArray() throws Exception {
    List<Lambdas.One> fs = new ArrayList<>();
    int[] nums = { 3, 2, 1, 0 };
    for (int i : nums) {
      fs.add((x) -> i);
    }
    assertEquals(0, fs.get(3).apply("5"));
    assertEquals(1, fs.get(2).apply(new Object()));
    assertEquals(2, fs.get(1).apply(new Object()));
    assertEquals(3, fs.get(0).apply("4"));
  }

  public <T> UnaryOperator<T> yComb(UnaryOperator<UnaryOperator<T>> r) {
    return ((UOToUO<T>) f -> f.apply(f)).apply(f -> r.apply(x -> f.apply(f).apply(x)));
  }

  public void testYCombinator() throws Exception {
    UnaryOperator<UnaryOperator<String>> a = (UnaryOperator<String> f) -> {
      return (x) -> {
        if (x.length() == 5) {
          return x;
        } else {
          return f.apply((char) (x.charAt(0) + 1) + x);
        }
      };
    };
    assertEquals("edcba", yComb(a).apply("a"));
    UnaryOperator<UnaryOperator<Integer>> fibonacci = (UnaryOperator<Integer> f) -> {
      return (Integer x) -> {
        if (x < 1) {
          return 0;
        } else if (x == 1) {
          return x;
        } else {
          return f.apply(x - 1) + f.apply(x - 2);
        }
      };
    };
    assertEquals((Integer) 55, yComb(fibonacci).apply(10));
  }

  Lambdas.One outerF = (x) -> x;

  public void testOuterFunctions() throws Exception {
    assertEquals(42, outerF.apply(42));
  }

  static Lambdas.One staticF = (x) -> x;

  public void testStaticFunctions() throws Exception {
    assertEquals(42, staticF.apply(42));
  }

  public void testNestedLambdas() throws Exception {
    Lambdas.One<String, Lambdas.One<String, String>> f = (x) -> (y) -> x;
    assertEquals(f.apply("Foo").apply("Bar"), "Foo");
    Lambdas.One<Integer, Lambdas.One<Integer, Integer>> f2 = (x) -> (y) -> x;
    assertEquals(f2.apply(42).apply(43), Integer.valueOf(42));
    Lambdas.One<Integer, Lambdas.One<Integer, Integer>> f3 = (y) -> (x) -> x;
    assertEquals(f3.apply(43).apply(42), Integer.valueOf(42));
    Lambdas.One<String, Lambdas.One<String, Integer>> f4 = (x) -> (y) -> Integer.parseInt(
        x);
    assertEquals(f4.apply("42").apply("43"), Integer.valueOf(42));
    Lambdas.One<String, Lambdas.One<Integer, Integer>> f5 = (x) -> (y) -> Integer.parseInt(
        x);
    assertEquals(f5.apply("42").apply(43), Integer.valueOf(42));
    Callable<Callable> c2 = () -> () -> 42;
    assertEquals(c2.call().call(), 42);
    Lambdas.Zero<Lambdas.Zero> s2 = () -> () -> 42;
    assertEquals(s2.apply().apply(), 42);
  }

  // Tests outer reference resolution, and that inner fields are being correctly resolved for
  // lambdas with implicit blocks.
  public void testAdditionInLambda() throws Exception {
    Lambdas.One f = new Lambdas.One<Integer, Integer>() {
        @Override
      public Integer apply(Integer x) {
        return x + 20;
      }
    };
    assertEquals(42, f.apply(22));
    Lambdas.One<Integer, Integer> g = x -> {
      return x + 20;
    };
    assertEquals((Integer) 42, g.apply(22));
    Lambdas.One<Integer, Integer> h = x -> x + 20;
    assertEquals((Integer) 42, h.apply(22));
  }

  public void testBasicAnonymousClass() throws Exception {
    Lambdas.One h = new Lambdas.One() {
        @Override
      public Object apply(Object x) {
        return x;
      }
    };
    assertEquals(42, h.apply(42));
  }

  public void testBasicFunction() throws Exception {
    Lambdas.One f = x -> x;
    assertEquals(42, f.apply(42));
    Lambdas.One<Integer, Integer> f2 = x -> x;
    assertEquals((Integer) 42, f2.apply(42));
    Lambdas.One f3 = x -> {
      int y = 42;
      return y;
    };
    assertEquals(42, f3.apply(null));
    Lambdas.Four<String, Double, Integer, Boolean, String> appendFour = (a, b, c, d) -> a + b + c
        + d;
    assertEquals("Foo4.214true", appendFour.apply("Foo", 4.2, 14, true));
  }

  public void testBasicSupplier() throws Exception {
    Lambdas.Zero s = () -> 42;
    assertEquals(42, s.apply());
  }

  public void testBasicConsumer() throws Exception {
    Object[] ls = new Object[1];
    Lambdas.VoidOne c = (x) -> ls[0] = x;
    c.apply(42);
    assertEquals(42, ls[0]);
  }

  public void testBasicCallable() throws Exception {
    Callable c = () -> 42;
    assertEquals(42, c.call());
  }

  // Adapted from translator/src/test/java/com/google/devtools/j2objc/ast/LambdaExpressionTest.java
  interface NumberFunction<T extends Number, R> {
    R apply(T t);
  }

  static class CaptureTest1 {
    int y;
    NumberFunction f = x -> y + x.intValue();
  }

  static class CaptureTest2 {
    int y;
    class InnerCaptureTest {
      int y;
      NumberFunction fOuter = x -> CaptureTest2.this.y + x.intValue();
      NumberFunction fInner = x -> y + x.intValue();
    }
  }

  public void testImplicitCapture() throws Exception {
    CaptureTest1 t1 = new CaptureTest1();
    assertEquals(1, t1.f.apply(1));
    t1.y = 1;
    assertEquals(3, t1.f.apply(2));

    CaptureTest2 t2 = new CaptureTest2();
    CaptureTest2.InnerCaptureTest t2i = t2.new InnerCaptureTest();
    t2.y = 10;
    t2i.y = 20;
    assertEquals(9, t2i.fOuter.apply(-1));
    assertEquals(19, t2i.fInner.apply(-1));
  }

  interface IntSupplier {
    int get();

    static int f(IntSupplier s) {
      return s.get();
    }
  }

  // x + y * 2
  private int getFromSimpleLambda(int x, int y) {
    return IntSupplier.f(() -> x + y) + y;
  }

  // x + y * 3
  private int getFromNestedLambdas(int x, int y) {
    return IntSupplier.f(() -> IntSupplier.f(() -> x + y) + y) + y;
  }

  // x + y * 3
  private int getFromAnonymousClassesAndLambda(int x, int y) {
    return IntSupplier.f(new IntSupplier() {
      @Override
      public int get() {
        return IntSupplier.f(() -> x + y) + y;
      }
    }) + y;
  }

  // x + y * 3
  private int getFromLambdaAndAnonymousClass(int x, int y) {
    return IntSupplier.f(() -> IntSupplier.f(new IntSupplier() {
      @Override
      public int get() {
        return x + y;
      }
    }) + y) + y;
  }

  // x + y * 5
  private int getFromNestedAnonymousClassesAndLambdas(int x, int y) {
    return IntSupplier.f(new IntSupplier() {
      @Override
      public int get() {
        return IntSupplier.f(() -> IntSupplier.f(new IntSupplier() {
          @Override
          public int get() {
            return IntSupplier.f(() -> x + y) + y;
          }
        }) + y) + y;
      }
    }) + y;
  }

  // x + y * 5
  private int getFromNestedLambdasAndAnonymousClasses(int x, int y) {
    return IntSupplier.f(() -> IntSupplier.f(new IntSupplier() {
      @Override
      public int get() {
        return IntSupplier.f(() -> IntSupplier.f(new IntSupplier() {
          @Override
          public int get() {
            return x + y;
          }
        }) + y) + y;
      }
    }) + y) + y;
  }

  // Putting everything together
  static class ComplexLambda {
    static final int P = 1;
    final int q = 2;
    int r = Integer.MIN_VALUE;

    public class Inner {
      static final int S = 4;
      final int t = 5;
      int u = Integer.MIN_VALUE;

      // Should be x + y * 6 + P + Q + R + S + T + U;
      public int get(int x, int y) {
        return IntSupplier.f(() -> IntSupplier.f(new IntSupplier() {
          @Override
          public int get() {
            return IntSupplier.f(() -> IntSupplier.f(new IntSupplier() {
              @Override
              public int get() {
                return IntSupplier.f(() -> x + y + P) + y + q;
              }
            }) + y + r) + y + S;
          }
        }) + y + t) + y + u;
      }
    }
  }

  public void testNestingLambdasAndAnonymousClasses() throws Exception {
    // Each method is called twice to make sure that all lambdas are capturing ones.
    assertEquals(102, getFromSimpleLambda(100, 1));
    assertEquals(104, getFromSimpleLambda(100, 2));
    assertEquals(109, getFromNestedLambdas(100, 3));
    assertEquals(112, getFromNestedLambdas(100, 4));
    assertEquals(115, getFromAnonymousClassesAndLambda(100, 5));
    assertEquals(118, getFromAnonymousClassesAndLambda(100, 6));
    assertEquals(121, getFromLambdaAndAnonymousClass(100, 7));
    assertEquals(124, getFromLambdaAndAnonymousClass(100, 8));
    assertEquals(145, getFromNestedAnonymousClassesAndLambdas(100, 9));
    assertEquals(150, getFromNestedLambdasAndAnonymousClasses(100, 10));

    int z = 10;
    class Local {
      int w = 1;

      // x + y * 3 + w + z
      private int get(int x, int y) {
        return IntSupplier.f(new IntSupplier() {
          @Override
          public int get() {
            return IntSupplier.f(() -> x + y + z + w) + y;
          }
        }) + y;
      }
    }

    Local l = new Local();
    assertEquals(171, l.get(100, 20));
    assertEquals(186, l.get(100, 25));
    l.w = 500;
    assertEquals(670, l.get(100, 20));
    assertEquals(685, l.get(100, 25));

    ComplexLambda cl = new ComplexLambda();
    cl.r = 3;
    ComplexLambda.Inner inner = cl.new Inner();
    inner.u = 6;

    // Should be 1000 + 20 * 6 + sum(1...6)
    assertEquals(1141, inner.get(1000, 20));

    cl.r += 10000;
    inner.u += 10000;
    // Should be 1000 + 20 * 6 + sum(1...6) + 10000 + 10000;
    assertEquals(21141, inner.get(1000, 20));
  }

  interface IntSupplierSupplier {
    IntSupplier get();
  }

  public void testNestedLambdaCapturesOuterScope() {
    IntSupplier s = new IntSupplier() {
      int i = 1234;
      public int get() {
        IntSupplierSupplier ss = () -> () -> i;
        return ss.get().get();
      }
    };
    assertEquals(1234, s.get());
  }

  interface ImplicitCaptures {
    interface F {
      int f();

      default F g() {
        return () -> f();
      }
    }

    interface G extends F {
      default F g() {
        return () -> F.super.g().f();
      }
    }

    static class P {
      int x = 0;

      void setX(int x) {
        this.x = x;
      }

      int getX() {
        return x;
      }
    }

    static class Q extends P {
      public F getSuperGetX() {
        return () -> super.getX();
      }

      public F getFieldX() {
        return () -> x;
      }

      public F getThisFieldX() {
        return () -> this.x;
      }

      public F getThisGetX() {
        return () -> getX();
      }
    }
  }

  public void testCapturingLambdasFromQualifiedSuperInvocations() throws Exception {
    ImplicitCaptures.G g1 = new ImplicitCaptures.G() {

      @Override
      public int f() {
        return 10;
      }
    };

    ImplicitCaptures.G g2 = new ImplicitCaptures.G() {
      @Override
      public int f() {
        return 20;
      }
    };

    assertEquals(10, g1.g().f());

    // () -> F.super.g().f() must be a non-capturing lambda to return this value correctly.
    assertEquals(20, g2.g().f());
  }

  public void testImplicitLambdaCaptures() throws Exception {
    ImplicitCaptures.Q q1 = new ImplicitCaptures.Q() {
      @Override
      int getX() {
        return 20;
      }
    };

    ImplicitCaptures.Q q2 = new ImplicitCaptures.Q() {
      @Override
      int getX() {
        return 40;
      }
    };

    q1.setX(10);
    assertEquals(10, q1.getSuperGetX().f());
    assertEquals(10, q1.getFieldX().f());
    assertEquals(10, q1.getThisFieldX().f());
    assertEquals(20, q1.getThisGetX().f()); // From q1's overridden getX()

    q2.setX(30);
    assertEquals(30, q2.getSuperGetX().f());
    assertEquals(30, q2.getFieldX().f());
    assertEquals(30, q2.getThisFieldX().f());
    assertEquals(40, q2.getThisGetX().f()); // From q2's overridden getX()
  }
}