<commit_before>//
// Copyright (C) 2013 Matti Schnurbusch (original code)
// Copyright (C) 2015 Michael Kirsche   (smaller fixes, extended WPAN startup and management, ported for INET 2.x)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//

#include "llc.h"
#include "IPSocket.h"

bool llc::firstDevice;

Define_Module(llc);

void llc::initialize()
{
    if (hasPar("llcDebug"))
        llcDebug = par("llcDebug").boolValue();
    else
        llcDebug = false;

    /* This is for Application layers which cannot send out MCPS primitives
     * if a true LLC is available, it will take care of it
     * just make sure the Application is sending cPackets
     */
    double seed = dblrand();
    convertingMode = par("convertMode").boolValue();

    TXoption = par("TXoption");
    logicalChannel = par("LogicalChannel");

    firstDevice = true;
    associateSuccess = false;

    WATCH(firstDevice);
    WATCH(associateSuccess);

    if (convertingMode)
    {
        // Check if startWithoutStartRequest was enabled by user
        if (getModuleByPath("net.IEEE802154Nodes[0].NIC.MAC.IEEE802154Mac")->par("startWithoutStartReq").boolValue() == false)
        {
            llcEV << "Sending Start Request in " << seed << endl;
            selfMsg = new cMessage("LLC-Start");
            selfMsg->setKind(0);
            scheduleAt(seed, selfMsg);
        }
        else
        {
            llcEV << "Starting without an explicit Start Request right now (startwithoutStartReq == true) \n";
        }

        scanChannels = par("ScanChannels");
        scanDuration = par("ScanDuration");
        scanPage = par("ScanPage");
        scanType = par("ScanType");
        pollFreq = par("PollFrequency");

        if (TXoption >= 4)
        {
            pollTimer = new cMessage("LLC-POLL-Timer");
            llcEV << "TXoption set to indirect - starting Poll timer \n";
            pollTimer->setKind(1);
            scheduleAt(pollFreq, pollTimer);
        }
    }

}

MACAddressExt* llc::tokenDest(cMessage* msg)
{
    // get the IPv6 destination address from the IPv6 Control Info block
    IPv6ControlInfo * controlInfo;
    controlInfo = check_and_cast<IPv6ControlInfo*>(msg->getControlInfo());

    IPv6Address destAddr = controlInfo->getDestAddr();

    if (destAddr.isUnspecified())
    {
        error("[802154LLC]: tokenDest ==> no destination address set / address unspecified");
    }

    // Use the internal representation of the IPv6 address to create the 64-bit EUI MAC address
    // create 8 groups with each 16 bit's (aka 8 tupels)
    uint16_t groups[8] = { uint16_t(*&destAddr.words()[0] >> 16), uint16_t(*&destAddr.words()[0] & 0xffff), uint16_t(*&destAddr.words()[1] >> 16), uint16_t(
            *&destAddr.words()[1] & 0xffff), uint16_t(*&destAddr.words()[2] >> 16), uint16_t(*&destAddr.words()[2] & 0xffff), uint16_t(*&destAddr.words()[3] >> 16), uint16_t(
            *&destAddr.words()[3] & 0xffff) };

    std::string destString;

    // take the last four tuples
    for (int i = 4; i < 8; ++i)
    {
        std::string sHelp;
        char cHelp[5];

        // convert uint16_t to hex and to string
        sprintf(cHelp, "%x", groups[i]);
        sHelp.append(cHelp);

        // as IPv6 addresses might be compressed, we need to add up "compressed" zeros
        while (sHelp.length() < 4)
        {
            sHelp.insert(0, "0");
        }
        // write everything into the destination string
        destString.append(sHelp);
    }

    // create a new 64-bit EUI MAC address from the destination string
    MACAddressExt* dest = new MACAddressExt(destString.c_str());
    llcEV << "Tokenized Destination Address from IFI / IPvXTrafGen is: " << dest->str() << endl;
    return dest;
}

void llc::genAssoReq()
{
    AssociationRequest* assoReq = new AssociationRequest("MLME-ASSOCIATE.request");
    MACAddressExt* coordId = new MACAddressExt(coordPANId);
    assoReq->setCoordAddrMode(coordAddrMode);
    assoReq->setCoordPANId(*coordId);
    assoReq->setCoordAddress(coordAddress);
    DevCapability capInfo;
    capInfo.alloShortAddr = true;
    capInfo.FFD = true;
    capInfo.recvOnWhenIdle = true;
    capInfo.secuCapable = false;
    assoReq->setCapabilityInformation(capInfo);
    assoReq->setChannelPage(0);
    assoReq->setLogicalChannel(logicalChannel);

    send(assoReq, "outMngt");
}

void llc::genPollReq()
{
    PollRequest* pollReq = new PollRequest("MLME-POLL.request");
    pollReq->setCoordAddrMode(addrShort);
    pollReq->setCoordPANId(coordPANId);
    pollReq->setCoordAddress(coordAddress);

    send(pollReq, "outMngt");
}

void llc::genScanReq()
{
    ScanRequest* scanReq = new ScanRequest("MLME-SCAN.request");
    scanReq->setScanType(scanType);  // see enum
    scanReq->setScanChannels(scanChannels);  // 27 bit indicating the channels to be scanned
    scanReq->setScanDuration(scanDuration);  // time spent on scanning each channel
    scanReq->setChannelPage(scanPage);

    send(scanReq, "outMngt");
}

void llc::genOrphanResp(OrphanIndication* oi)
{
    OrphanResponse* oR = new OrphanResponse("MLME-ORPHAN.response");
    oR->setOrphanAddress(oi->getOrphanAddress());
    oR->setShortAddress(0xffff);
    oR->setAssociatedMember(false);

    send(oR, "outMngt");
}

void llc::handleMessage(cMessage *msg)
{
    llcEV << "Got Message in LLC - " << msg->getName() << endl;

    if (msg->isSelfMessage())
    {
        if (msg->getKind() == 0)
        {
            llcEV << "Got Startup Msg - Sending out Scan Request \n";
            genScanReq();
            delete (msg);
        }
        else if (msg->getKind() == 1)
        {
            llcEV << "Got POLL Timer - Sending POLL Request \n";
            genPollReq();
            scheduleAt(simTime() + pollFreq, msg);
        }
        return;
    }

    if (msg->arrivedOn("inApp"))
    {
        if ((msg->getKind() == IP_C_REGISTER_PROTOCOL))
        {
            llcEV << "FIXME(!) Register Protocol Message is not handled yet - FullPath: " << msg->getFullPath() << endl;
            delete (msg);
            return;
        }

        if (convertingMode)
        {
            if (!msg->isPacket())
                error("[802154LLC]: Application layer in convertingMode has to send out cPackets!");

            cPacket* pack = check_and_cast<cPacket*>(msg);

            mcpsDataReq* data = new mcpsDataInd("MCPS-DATA.indication");
            data->encapsulate(pack);
            data->setMsduHandle(pack->getId());
            data->setMsduLength(pack->getByteLength());
            data->setTxOptions(TXoption);
            // try to generate the MAC destination address from the packet's IPvX address destination address
            MACAddressExt* destination = tokenDest(msg);
            data->setDstAddr(*destination);

            send(data, "outData");
            return;
        }
        else
        {
            send(msg, "outData");
        }
    } // if (msg->arrivedOn("inApp"))
    else if (msg->arrivedOn("inMngt"))
    {
        if (convertingMode)
        {
            if (dynamic_cast<beaconNotify*>(msg))
            {
                if (associateSuccess == false)
                {
                    beaconNotify* bN = check_and_cast<beaconNotify*>(msg);
                    coordAddrMode = bN->getPANDescriptor().CoordAddrMode;
                    coordPANId = bN->getPANDescriptor().CoordPANId;
                    coordAddress = bN->getPANDescriptor().CoordAddress;  // shared by both 16 bit short address or 64 bit extended address
                    logicalChannel = bN->getPANDescriptor().LogicalChannel;
                    llcEV << "Beacon Notify received an not yet associated -> generate Association Request for the existing PAN Coordinator \n";
                    genAssoReq();
                }
                else
                {
                    llcEV << "Beacon Notify received and associated - no further processing of the Beacon Notify \n";
                }
            }

            if (dynamic_cast<StartConfirm*>(msg))
            {
                // TODO divide between "started your own PAN" and "found a PAN and starting association process" ??
                llcEV << "Got MLME-START.confirm from lower layer \n";
            }

            if (dynamic_cast<ScanConfirm*>(msg))
            {
                ScanConfirm* scanConf = check_and_cast<ScanConfirm*>(msg);

                if (scanConf->getResultListSize() == 0)
                {
                    llcEV << "Got MLME-SCAN.confirm with ResultListSize == 0 \n";

                    if (firstDevice)
                    {
                        llcEV << "First global device without results sends out MLME-START for Coordinator \n";

                        startMsg = new StartRequest("MLME-START.request");
                        startMsg->setPANId(par("PANId"));
                        startMsg->setLogicalChannel(logicalChannel);
                        startMsg->setChannelPage(par("ChannelPage"));
                        startMsg->setStartTime(par("StartTime"));
                        startMsg->setBeaconOrder(par("BeaconOrder"));
                        startMsg->setSuperframeOrder(par("SuperframeOrder"));
                        startMsg->setBatteryLifeExtension(par("BatteryLifeExtension"));
                        startMsg->setPANCoordinator(true);
                        startMsg->setCoordRealignment(false);   // override user parameter here since 1st device starts PAN and doesn't realign it

                        firstDevice = false;
                        send(startMsg, "outMngt");
                    }
                    else
                    {
                        llcEV << "No results - scan again \n";
                        genScanReq();
                    }
                }
                else
                {
                    llcEV << "Got MLME-SCAN.confirm with ResultListSize > 0 \n";

                    unsigned short panId = par("PANId");
                    logicalChannel = par("LogicalChannel");
                    unsigned short channelPage = par("ChannelPage");
                    unsigned int startTime = par("StartTime");
                    unsigned short beaconOrder = par("BeaconOrder");
                    unsigned short superframeOrder = par("SuperframeOrder");
                    bool batteryLifeExtension = par("BatteryLifeExtension");
                    bool coordRealignment = par("CoordRealignment");

                    startMsg = new StartRequest("MLME-START.request");
                    startMsg->setPANId(panId);
                    startMsg->setLogicalChannel(logicalChannel);
                    startMsg->setChannelPage(channelPage);
                    startMsg->setStartTime(startTime);
                    startMsg->setBeaconOrder(beaconOrder);
                    startMsg->setSuperframeOrder(superframeOrder);
                    startMsg->setBatteryLifeExtension(batteryLifeExtension);
                    startMsg->setCoordRealignment(coordRealignment);

                    startMsg->setPANCoordinator(false);
                    send(startMsg, "outMngt");
                }
            }

            if (dynamic_cast<AssociationConfirm*>(msg))
            {
                llcEV << "Association Confirm received - association process was successful \n";
                associateSuccess = true;
            }

            if (dynamic_cast<OrphanIndication*>(msg))
            {
                // just for convenience of functional tests
                OrphanIndication* oi = check_and_cast<OrphanIndication*>(msg);
                genOrphanResp(oi);
            }

            // Since we are converting assume application layer won't understand any MLME messages
            llcEV << "convertingMode -> deleting MLME Message without forwarding it to higher layer -> " << msg->getFullName() << endl;
            delete (msg);
            return;
        }

        llcEV << "Forwarding MLME Message (" << msg->getFullName() << ") to the higher layer \n";
        send(msg, "outApp");

    } // if (msg->arrivedOn("inMngt"))

    if (msg->arrivedOn("inData"))
    {
        if (convertingMode)
        {
            // this can only be a confirm or indication
            if (dynamic_cast<mcpsDataInd*>(msg))
            {
                mcpsDataInd* ind = check_and_cast<mcpsDataInd*>(msg);
                cPacket* payload = ind->decapsulate();
                llcEV << "Forwarding MCPS-Data.indication to the higher layer \n";
                send(payload, "outApp");
            }
            else if (dynamic_cast<mcpsDataConf*>(msg))
            {
                mcpsDataConf* conf = check_and_cast<mcpsDataConf *>(msg);

                llcEV << "Got a Confirmation from MAC entity with Status: " << MCPSStatusToString(MCPSStatus(conf->getStatus())) << " for Message #" << conf->getMsduHandle() << endl;
                delete (conf);
                return;
            }
            else {
                error ("[LLC]: Undefined Message arrived on inData gate!");
            }
        }
        else
        {
            llcEV << "Forwarding MCPS-Data to the higher layer -> " << msg->getFullName() << endl;
            send(msg, "outApp");
        }
    }
}

llc::llc()
{

}

llc::~llc()
{
    if (TXoption >= 4)
    {
        if (pollTimer)
            cancelAndDelete(pollTimer);
    }

}
<commit_msg>Fix for undisposed objects in LLC module Changed generated data message to MCPS-DATA.request (expected at MAC layer)<commit_after>//
// Copyright (C) 2013 Matti Schnurbusch (original code)
// Copyright (C) 2015 Michael Kirsche   (smaller fixes, extended WPAN startup and management, ported for INET 2.x)
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, see <http://www.gnu.org/licenses/>.
//

#include "llc.h"
#include "IPSocket.h"

bool llc::firstDevice;

Define_Module(llc);

void llc::initialize()
{
    if (hasPar("llcDebug"))
        llcDebug = par("llcDebug").boolValue();
    else
        llcDebug = false;

    /* This is for Application layers which cannot send out MCPS primitives
     * if a true LLC is available, it will take care of it
     * just make sure the Application is sending cPackets
     */
    double seed = dblrand();
    convertingMode = par("convertMode").boolValue();

    TXoption = par("TXoption");
    logicalChannel = par("LogicalChannel");

    firstDevice = true;
    associateSuccess = false;

    WATCH(firstDevice);
    WATCH(associateSuccess);

    if (convertingMode)
    {
        // Check if startWithoutStartRequest was enabled by user
        if (getModuleByPath("net.IEEE802154Nodes[0].NIC.MAC.IEEE802154Mac")->par("startWithoutStartReq").boolValue() == false)
        {
            llcEV << "Sending Start Request in " << seed << endl;
            selfMsg = new cMessage("LLC-Start");
            selfMsg->setKind(0);
            scheduleAt(seed, selfMsg);
        }
        else
        {
            llcEV << "Starting without an explicit Start Request right now (startwithoutStartReq == true) \n";
        }

        scanChannels = par("ScanChannels");
        scanDuration = par("ScanDuration");
        scanPage = par("ScanPage");
        scanType = par("ScanType");
        pollFreq = par("PollFrequency");

        if (TXoption >= 4)
        {
            pollTimer = new cMessage("LLC-POLL-Timer");
            llcEV << "TXoption set to indirect - starting Poll timer \n";
            pollTimer->setKind(1);
            scheduleAt(pollFreq, pollTimer);
        }
    }

}

MACAddressExt* llc::tokenDest(cMessage* msg)
{
    // get the IPv6 destination address from the IPv6 Control Info block
    IPv6ControlInfo * controlInfo;
    controlInfo = check_and_cast<IPv6ControlInfo*>(msg->getControlInfo());

    IPv6Address destAddr = controlInfo->getDestAddr();

    if (destAddr.isUnspecified())
    {
        error("[802154LLC]: tokenDest ==> no destination address set / address unspecified");
    }

    // Use the internal representation of the IPv6 address to create the 64-bit EUI MAC address
    // create 8 groups with each 16 bit's (aka 8 tupels)
    uint16_t groups[8] = { uint16_t(*&destAddr.words()[0] >> 16), uint16_t(*&destAddr.words()[0] & 0xffff), uint16_t(*&destAddr.words()[1] >> 16), uint16_t(
            *&destAddr.words()[1] & 0xffff), uint16_t(*&destAddr.words()[2] >> 16), uint16_t(*&destAddr.words()[2] & 0xffff), uint16_t(*&destAddr.words()[3] >> 16), uint16_t(
            *&destAddr.words()[3] & 0xffff) };

    std::string destString;

    // take the last four tuples
    for (int i = 4; i < 8; ++i)
    {
        std::string sHelp;
        char cHelp[5];

        // convert uint16_t to hex and to string
        sprintf(cHelp, "%x", groups[i]);
        sHelp.append(cHelp);

        // as IPv6 addresses might be compressed, we need to add up "compressed" zeros
        while (sHelp.length() < 4)
        {
            sHelp.insert(0, "0");
        }
        // write everything into the destination string
        destString.append(sHelp);
    }

    // create a new 64-bit EUI MAC address from the destination string
    MACAddressExt* dest = new MACAddressExt(destString.c_str());
    llcEV << "Tokenized Destination Address from IFI / IPvXTrafGen is: " << dest->str() << endl;
    return dest;
}

void llc::genAssoReq()
{
    AssociationRequest* assoReq = new AssociationRequest("MLME-ASSOCIATE.request");
    MACAddressExt* coordId = new MACAddressExt(coordPANId);
    assoReq->setCoordAddrMode(coordAddrMode);
    assoReq->setCoordPANId(*coordId);
    assoReq->setCoordAddress(coordAddress);
    DevCapability capInfo;
    capInfo.alloShortAddr = true;
    capInfo.FFD = true;
    capInfo.recvOnWhenIdle = true;
    capInfo.secuCapable = false;
    assoReq->setCapabilityInformation(capInfo);
    assoReq->setChannelPage(0);
    assoReq->setLogicalChannel(logicalChannel);

    send(assoReq, "outMngt");
}

void llc::genPollReq()
{
    PollRequest* pollReq = new PollRequest("MLME-POLL.request");
    pollReq->setCoordAddrMode(addrShort);
    pollReq->setCoordPANId(coordPANId);
    pollReq->setCoordAddress(coordAddress);

    send(pollReq, "outMngt");
}

void llc::genScanReq()
{
    ScanRequest* scanReq = new ScanRequest("MLME-SCAN.request");
    scanReq->setScanType(scanType);  // see enum
    scanReq->setScanChannels(scanChannels);  // 27 bit indicating the channels to be scanned
    scanReq->setScanDuration(scanDuration);  // time spent on scanning each channel
    scanReq->setChannelPage(scanPage);

    send(scanReq, "outMngt");
}

void llc::genOrphanResp(OrphanIndication* oi)
{
    OrphanResponse* oR = new OrphanResponse("MLME-ORPHAN.response");
    oR->setOrphanAddress(oi->getOrphanAddress());
    oR->setShortAddress(0xffff);
    oR->setAssociatedMember(false);

    send(oR, "outMngt");
}

void llc::handleMessage(cMessage *msg)
{
    llcEV << "Got Message in LLC - " << msg->getName() << endl;

    if (msg->isSelfMessage())
    {
        if (msg->getKind() == 0)
        {
            llcEV << "Got Startup Msg - Sending out Scan Request \n";
            genScanReq();
            delete (msg);
        }
        else if (msg->getKind() == 1)
        {
            llcEV << "Got POLL Timer - Sending POLL Request \n";
            genPollReq();
            scheduleAt(simTime() + pollFreq, msg);
        }
        return;
    }

    if (msg->arrivedOn("inApp"))
    {
        if ((msg->getKind() == IP_C_REGISTER_PROTOCOL))
        {
            llcEV << "FIXME(!) Register Protocol Message is not handled yet - FullPath: " << msg->getFullPath() << endl;
            delete (msg);
            return;
        }

        if (convertingMode)
        {
            if (!msg->isPacket())
                error("[802154LLC]: Application layer in convertingMode has to send out cPackets!");

            cPacket* pack = check_and_cast<cPacket*>(msg);

            mcpsDataReq* data = new mcpsDataReq("MCPS-DATA.request");
            data->encapsulate(pack);
            data->setMsduHandle(pack->getId());
            data->setMsduLength(pack->getByteLength());
            data->setTxOptions(TXoption);
            // try to generate the MAC destination address from the packet's IPvX address destination address
            MACAddressExt* destination = tokenDest(msg);
            data->setDstAddr(*destination);

            send(data, "outData");
            return;
        }
        else
        {
            send(msg, "outData");
        }
    } // if (msg->arrivedOn("inApp"))
    else if (msg->arrivedOn("inMngt"))
    {
        if (convertingMode)
        {
            if (dynamic_cast<beaconNotify*>(msg))
            {
                if (associateSuccess == false)
                {
                    beaconNotify* bN = check_and_cast<beaconNotify*>(msg);
                    coordAddrMode = bN->getPANDescriptor().CoordAddrMode;
                    coordPANId = bN->getPANDescriptor().CoordPANId;
                    coordAddress = bN->getPANDescriptor().CoordAddress;  // shared by both 16 bit short address or 64 bit extended address
                    logicalChannel = bN->getPANDescriptor().LogicalChannel;
                    llcEV << "Beacon Notify received an not yet associated -> generate Association Request for the existing PAN Coordinator \n";
                    genAssoReq();
                }
                else
                {
                    llcEV << "Beacon Notify received and associated - no further processing of the Beacon Notify \n";
                }
            }

            if (dynamic_cast<StartConfirm*>(msg))
            {
                // TODO divide between "started your own PAN" and "found a PAN and starting association process" ??
                llcEV << "Got MLME-START.confirm from lower layer \n";
            }

            if (dynamic_cast<ScanConfirm*>(msg))
            {
                ScanConfirm* scanConf = check_and_cast<ScanConfirm*>(msg);

                if (scanConf->getResultListSize() == 0)
                {
                    llcEV << "Got MLME-SCAN.confirm with ResultListSize == 0 \n";

                    if (firstDevice)
                    {
                        llcEV << "First global device without results sends out MLME-START for Coordinator \n";

                        startMsg = new StartRequest("MLME-START.request");
                        startMsg->setPANId(par("PANId"));
                        startMsg->setLogicalChannel(logicalChannel);
                        startMsg->setChannelPage(par("ChannelPage"));
                        startMsg->setStartTime(par("StartTime"));
                        startMsg->setBeaconOrder(par("BeaconOrder"));
                        startMsg->setSuperframeOrder(par("SuperframeOrder"));
                        startMsg->setBatteryLifeExtension(par("BatteryLifeExtension"));
                        startMsg->setPANCoordinator(true);
                        startMsg->setCoordRealignment(false);   // override user parameter here since 1st device starts PAN and doesn't realign it

                        firstDevice = false;
                        send(startMsg, "outMngt");
                    }
                    else
                    {
                        llcEV << "No results - scan again \n";
                        genScanReq();
                    }
                }
                else
                {
                    llcEV << "Got MLME-SCAN.confirm with ResultListSize > 0 \n";

                    unsigned short panId = par("PANId");
                    logicalChannel = par("LogicalChannel");
                    unsigned short channelPage = par("ChannelPage");
                    unsigned int startTime = par("StartTime");
                    unsigned short beaconOrder = par("BeaconOrder");
                    unsigned short superframeOrder = par("SuperframeOrder");
                    bool batteryLifeExtension = par("BatteryLifeExtension");
                    bool coordRealignment = par("CoordRealignment");

                    startMsg = new StartRequest("MLME-START.request");
                    startMsg->setPANId(panId);
                    startMsg->setLogicalChannel(logicalChannel);
                    startMsg->setChannelPage(channelPage);
                    startMsg->setStartTime(startTime);
                    startMsg->setBeaconOrder(beaconOrder);
                    startMsg->setSuperframeOrder(superframeOrder);
                    startMsg->setBatteryLifeExtension(batteryLifeExtension);
                    startMsg->setCoordRealignment(coordRealignment);

                    startMsg->setPANCoordinator(false);
                    send(startMsg, "outMngt");
                }
            }

            if (dynamic_cast<AssociationConfirm*>(msg))
            {
                llcEV << "Association Confirm received - association process was successful \n";
                associateSuccess = true;
            }

            if (dynamic_cast<OrphanIndication*>(msg))
            {
                // just for convenience of functional tests
                OrphanIndication* oi = check_and_cast<OrphanIndication*>(msg);
                genOrphanResp(oi);
            }

            // Since we are converting assume application layer won't understand any MLME messages
            llcEV << "convertingMode -> deleting MLME Message without forwarding it to higher layer -> " << msg->getFullName() << endl;
            delete (msg);
            return;
        }

        llcEV << "Forwarding MLME Message (" << msg->getFullName() << ") to the higher layer \n";
        send(msg, "outApp");

    } // if (msg->arrivedOn("inMngt"))

    if (msg->arrivedOn("inData"))
    {
        if (convertingMode)
        {
            // this can only be a confirm or indication
            if (dynamic_cast<mcpsDataInd*>(msg))
            {
                mcpsDataInd* ind = check_and_cast<mcpsDataInd*>(msg);
                cPacket* payload = ind->decapsulate();
                llcEV << "Forwarding MCPS-Data.indication to the higher layer \n";
                send(payload, "outApp");
                delete(ind); // XXX fix for undisposed object: (mcpsDataInd) net.IEEE802154Nodes[0].Network.stdLLC.MCPS-DATA.indication
            }
            else if (dynamic_cast<mcpsDataConf*>(msg))
            {
                mcpsDataConf* conf = check_and_cast<mcpsDataConf *>(msg);

                llcEV << "Got a Confirmation from MAC entity with Status: " << MCPSStatusToString(MCPSStatus(conf->getStatus())) << " for Message #" << conf->getMsduHandle() << endl;
                delete(conf);
                return;
            }
            else {
                error ("[LLC]: Undefined Message arrived on inData gate!");
            }
        }
        else
        {
            llcEV << "Forwarding MCPS-Data to the higher layer -> " << msg->getFullName() << endl;
            send(msg, "outApp");
        }
    }
}

llc::llc()
{

}

llc::~llc()
{
    if (TXoption >= 4)
    {
        if (pollTimer)
            cancelAndDelete(pollTimer);
    }
}
<|endoftext|>


<commit_before>#include "MoveSystem.h"

#include <iostream>

void MoveSystem::update(int currentStep)
{
    const std::vector<int> &uidList = movementNode.uids();
	for(int i = 0; i < uidList.size(); i++)
	{
		MovementNode &n = movementNode.get(uidList.at(i));

		PositionComponent &p = n.position;
		std::cout << p.positionX;
	}
}<commit_msg>Add: move position component<commit_after>#include "MoveSystem.h"

#include <iostream>

void MoveSystem::update(int currentStep)
{
    const std::vector<int> &uidList = movementNode.uids();
	for(int i = 0; i < uidList.size(); i++)
	{
		MovementNode &n = movementNode.get(uidList.at(i));

		PositionComponent &p = n.position;
		const VelocityComponent &v = n.velocity;
		p.positionX += v.velocityX;
		std::cout << p.positionX << "\n";
	}
}<|endoftext|>


<commit_before>/*
 Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following disclaimer in the documentation
 and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Decoders.h"

using namespace nqr;

#include "mpc/mpcdec.h"
#include "mpc/reader.h"
#include "musepack/libmpcdec/decoder.h"
#include "musepack/libmpcdec/internal.h"

#define MINIMP3_FLOAT_OUTPUT
#define MINIMP3_IMPLEMENTATION
#include "minimp3/minimp3.h"
#include "minimp3/minimp3_ex.h"

#include <cstring>

void mp3_decode_internal(AudioData * d, const std::vector<uint8_t> & fileData)
{
    mp3dec_t mp3d;
    mp3dec_file_info_t info;
    mp3dec_load_buf(&mp3d, (const uint8_t*)fileData.data(), fileData.size(), &info, 0, 0);

    d->sampleRate = info.hz;
    d->channelCount = info.channels;
    d->sourceFormat = MakeFormatForBits(32, true, false);
    d->lengthSeconds = ((float)info.samples / (float)d->channelCount) / (float)d->sampleRate;

    if (info.samples == 0) throw std::runtime_error("mp3: could not read any data");

    d->samples.resize(info.samples);
    std::memcpy(d->samples.data(), info.buffer, sizeof(float) * info.samples);
}

//////////////////////
// Public Interface //
//////////////////////

void Mp3Decoder::LoadFromPath(AudioData * data, const std::string & path)
{
    auto fileBuffer = nqr::ReadFile(path);
    mp3_decode_internal(data, fileBuffer.buffer);
}

void Mp3Decoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
    mp3_decode_internal(data, memory);
}

std::vector<std::string> Mp3Decoder::GetSupportedFileExtensions()
{
    return {"mp3"};
}
<commit_msg>Fix memory leak when decoding mp3 file.<commit_after>/*
 Copyright (c) 2019, Dimitri Diakopoulos All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
 list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
 this list of conditions and the following disclaimer in the documentation
 and/or other materials provided with the distribution.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "Decoders.h"

using namespace nqr;

#include "mpc/mpcdec.h"
#include "mpc/reader.h"
#include "musepack/libmpcdec/decoder.h"
#include "musepack/libmpcdec/internal.h"

#define MINIMP3_FLOAT_OUTPUT
#define MINIMP3_IMPLEMENTATION
#include "minimp3/minimp3.h"
#include "minimp3/minimp3_ex.h"

#include <cstring>

void mp3_decode_internal(AudioData * d, const std::vector<uint8_t> & fileData)
{
    mp3dec_t mp3d;
    mp3dec_file_info_t info;
    mp3dec_load_buf(&mp3d, (const uint8_t*)fileData.data(), fileData.size(), &info, 0, 0);

    d->sampleRate = info.hz;
    d->channelCount = info.channels;
    d->sourceFormat = MakeFormatForBits(32, true, false);
    d->lengthSeconds = ((float)info.samples / (float)d->channelCount) / (float)d->sampleRate;

    if (info.samples == 0) throw std::runtime_error("mp3: could not read any data");

    d->samples.resize(info.samples);
    std::memcpy(d->samples.data(), info.buffer, sizeof(float) * info.samples);

    delete info.buffer;
}

//////////////////////
// Public Interface //
//////////////////////

void Mp3Decoder::LoadFromPath(AudioData * data, const std::string & path)
{
    auto fileBuffer = nqr::ReadFile(path);
    mp3_decode_internal(data, fileBuffer.buffer);
}

void Mp3Decoder::LoadFromBuffer(AudioData * data, const std::vector<uint8_t> & memory)
{
    mp3_decode_internal(data, memory);
}

std::vector<std::string> Mp3Decoder::GetSupportedFileExtensions()
{
    return {"mp3"};
}
<|endoftext|>


<commit_before>#include "contractor/files.hpp"
#include "contractor/graph_contractor_adaptors.hpp"

#include "../common/range_tools.hpp"
#include "../common/temporary_file.hpp"
#include "helper.hpp"

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(tar)

using namespace osrm;
using namespace osrm::contractor;
using namespace osrm::unit_test;

BOOST_AUTO_TEST_CASE(read_write_hsgr)
{
    auto reference_checksum = 0xFF00FF00;
    auto reference_connectivity_checksum = 0xDEADBEEF;
    std::vector<TestEdge> edges = {TestEdge{0, 1, 3},
                                   TestEdge{0, 5, 1},
                                   TestEdge{1, 3, 3},
                                   TestEdge{1, 4, 1},
                                   TestEdge{3, 1, 1},
                                   TestEdge{4, 3, 1},
                                   TestEdge{5, 1, 1}};
    auto reference_graph = QueryGraph{6, toEdges<QueryEdge>(makeGraph(edges))};
    std::vector<std::vector<bool>> reference_filters = {
        {false, false, true, true, false, false, true},
        {true, false, true, false, true, false, true},
        {false, false, false, false, false, false, false},
        {true, true, true, true, true, true, true},
    };

    std::unordered_map<std::string, ContractedMetric> reference_metrics = {
        {"duration", {std::move(reference_graph), std::move(reference_filters)}}};

    TemporaryFile tmp{TEST_DATA_DIR "/read_write_hsgr_test.osrm.hsgr"};
    contractor::files::writeGraph(
        tmp.path, reference_checksum, reference_metrics, reference_connectivity_checksum);

    unsigned checksum;
    unsigned connectivity_checksum;

    std::unordered_map<std::string, ContractedMetric> metrics = {{"duration", {}}};
    contractor::files::readGraph(tmp.path, checksum, metrics, connectivity_checksum);

    BOOST_CHECK_EQUAL(checksum, reference_checksum);
    BOOST_CHECK_EQUAL(connectivity_checksum, reference_connectivity_checksum);
    BOOST_CHECK_EQUAL(metrics["duration"].edge_filter.size(),
                      reference_metrics["duration"].edge_filter.size());
    CHECK_EQUAL_COLLECTIONS(metrics["duration"].edge_filter[0],
                            reference_metrics["duration"].edge_filter[0]);
    CHECK_EQUAL_COLLECTIONS(metrics["duration"].edge_filter[1],
                            reference_metrics["duration"].edge_filter[1]);
    CHECK_EQUAL_COLLECTIONS(metrics["duration"].edge_filter[2],
                            reference_metrics["duration"].edge_filter[2]);
    CHECK_EQUAL_COLLECTIONS(metrics["duration"].edge_filter[3],
                            reference_metrics["duration"].edge_filter[3]);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Fix unit-test compilation due to broken readGraph<commit_after>#include "contractor/files.hpp"
#include "contractor/graph_contractor_adaptors.hpp"

#include "../common/range_tools.hpp"
#include "../common/temporary_file.hpp"
#include "helper.hpp"

#include <boost/test/unit_test.hpp>

BOOST_AUTO_TEST_SUITE(tar)

using namespace osrm;
using namespace osrm::contractor;
using namespace osrm::unit_test;

BOOST_AUTO_TEST_CASE(read_write_hsgr)
{
    auto reference_connectivity_checksum = 0xDEADBEEF;
    std::vector<TestEdge> edges = {TestEdge{0, 1, 3},
                                   TestEdge{0, 5, 1},
                                   TestEdge{1, 3, 3},
                                   TestEdge{1, 4, 1},
                                   TestEdge{3, 1, 1},
                                   TestEdge{4, 3, 1},
                                   TestEdge{5, 1, 1}};
    auto reference_graph = QueryGraph{6, toEdges<QueryEdge>(makeGraph(edges))};
    std::vector<std::vector<bool>> reference_filters = {
        {false, false, true, true, false, false, true},
        {true, false, true, false, true, false, true},
        {false, false, false, false, false, false, false},
        {true, true, true, true, true, true, true},
    };

    std::unordered_map<std::string, ContractedMetric> reference_metrics = {
        {"duration", {std::move(reference_graph), std::move(reference_filters)}}};

    TemporaryFile tmp{TEST_DATA_DIR "/read_write_hsgr_test.osrm.hsgr"};
    contractor::files::writeGraph(tmp.path, reference_metrics, reference_connectivity_checksum);

    unsigned connectivity_checksum;

    std::unordered_map<std::string, ContractedMetric> metrics = {{"duration", {}}};
    contractor::files::readGraph(tmp.path, metrics, connectivity_checksum);

    BOOST_CHECK_EQUAL(connectivity_checksum, reference_connectivity_checksum);
    BOOST_CHECK_EQUAL(metrics["duration"].edge_filter.size(),
                      reference_metrics["duration"].edge_filter.size());
    CHECK_EQUAL_COLLECTIONS(metrics["duration"].edge_filter[0],
                            reference_metrics["duration"].edge_filter[0]);
    CHECK_EQUAL_COLLECTIONS(metrics["duration"].edge_filter[1],
                            reference_metrics["duration"].edge_filter[1]);
    CHECK_EQUAL_COLLECTIONS(metrics["duration"].edge_filter[2],
                            reference_metrics["duration"].edge_filter[2]);
    CHECK_EQUAL_COLLECTIONS(metrics["duration"].edge_filter[3],
                            reference_metrics["duration"].edge_filter[3]);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>// Copyright 2018 Google LLC
//
// 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.

#include "test/syscalls/linux/socket_stream_blocking.h"

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>

#include "gtest/gtest.h"
#include "gtest/gtest.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "test/syscalls/linux/socket_test_util.h"
#include "test/syscalls/linux/unix_domain_socket_test_util.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"
#include "test/util/timer_util.h"

namespace gvisor {
namespace testing {

TEST_P(BlockingStreamSocketPairTest, BlockPartialWriteClosed) {
    // FIXME: gVisor doesn't support SO_SNDBUF on UDS, nor does it
    // enforce any limit; it will write arbitrary amounts of data without
    // blocking.
    SKIP_IF(IsRunningOnGvisor());

    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

    int buffer_size;
    socklen_t length = sizeof(buffer_size);
    ASSERT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF,
                           &buffer_size, &length),
                SyscallSucceeds());

    int wfd = sockets->first_fd();
    ScopedThread t([wfd, buffer_size]() {
      std::vector<char> buf(2 * buffer_size);
      // Write more than fits in the buffer. Blocks then returns partial write
      // when the other end is closed. The next call returns EPIPE.
      //
      // N.B. writes occur in chunks, so we may see less than buffer_size from
      // the first call.
      ASSERT_THAT(write(wfd, buf.data(), buf.size()),
                  SyscallSucceedsWithValue(::testing::Gt(0)));
      ASSERT_THAT(write(wfd, buf.data(), buf.size()),
                  ::testing::AnyOf(SyscallFailsWithErrno(EPIPE),
                                   SyscallFailsWithErrno(ECONNRESET)));
    });

    // Leave time for write to become blocked.
    absl::SleepFor(absl::Seconds(1.0));

    ASSERT_THAT(close(sockets->release_second_fd()), SyscallSucceeds());
}

TEST_P(BlockingStreamSocketPairTest, SendMsgTooLarge) {
  auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

  int sndbuf;
  socklen_t length = sizeof(sndbuf);
  ASSERT_THAT(
      getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF, &sndbuf, &length),
      SyscallSucceeds());

  // Make the call too large to fit in the send buffer.
  const int buffer_size = 3 * sndbuf;

  EXPECT_THAT(SendLargeSendMsg(sockets, buffer_size, true /* reader */),
              SyscallSucceedsWithValue(buffer_size));
}

TEST_P(BlockingStreamSocketPairTest, RecvLessThanBuffer) {
  auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

  char sent_data[100];
  RandomizeBuffer(sent_data, sizeof(sent_data));

  ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
              SyscallSucceedsWithValue(sizeof(sent_data)));

  char received_data[200] = {};
  ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
                               sizeof(received_data), 0),
              SyscallSucceedsWithValue(sizeof(sent_data)));
}

// Test that MSG_WAITALL causes recv to block until all requested data is
// received. Random save can interrupt blocking and cause received data to be
// returned, even if the amount received is less than the full requested amount.
TEST_P(BlockingStreamSocketPairTest, RecvLessThanBufferWaitAll_NoRandomSave) {
  auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

  char sent_data[100];
  RandomizeBuffer(sent_data, sizeof(sent_data));

  ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
              SyscallSucceedsWithValue(sizeof(sent_data)));

  constexpr auto kDuration = absl::Milliseconds(200);
  auto before = Now(CLOCK_MONOTONIC);

  const ScopedThread t([&]() {
    absl::SleepFor(kDuration);

    // Don't let saving after the write interrupt the blocking recv.
    const DisableSave ds;

    ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
                SyscallSucceedsWithValue(sizeof(sent_data)));
  });

  char received_data[sizeof(sent_data) * 2] = {};
  ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
                               sizeof(received_data), MSG_WAITALL),
              SyscallSucceedsWithValue(sizeof(received_data)));

  auto after = Now(CLOCK_MONOTONIC);
  EXPECT_GE(after - before, kDuration);
}

TEST_P(BlockingStreamSocketPairTest, SendTimeout) {
  auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

  struct timeval tv {
    .tv_sec = 0, .tv_usec = 10
  };
  EXPECT_THAT(
      setsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),
      SyscallSucceeds());

  char buf[100] = {};
  for (;;) {
    int ret;
    ASSERT_THAT(
        ret = RetryEINTR(send)(sockets->first_fd(), buf, sizeof(buf), 0),
        ::testing::AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EAGAIN)));
    if (ret == -1) {
      break;
    }
  }
}

}  // namespace testing
}  // namespace gvisor
<commit_msg>Deflake socket_stream_blocking tests.<commit_after>// Copyright 2018 Google LLC
//
// 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.

#include "test/syscalls/linux/socket_stream_blocking.h"

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h>

#include "gtest/gtest.h"
#include "gtest/gtest.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "test/syscalls/linux/socket_test_util.h"
#include "test/syscalls/linux/unix_domain_socket_test_util.h"
#include "test/util/test_util.h"
#include "test/util/thread_util.h"
#include "test/util/timer_util.h"

namespace gvisor {
namespace testing {

TEST_P(BlockingStreamSocketPairTest, BlockPartialWriteClosed) {
    // FIXME: gVisor doesn't support SO_SNDBUF on UDS, nor does it
    // enforce any limit; it will write arbitrary amounts of data without
    // blocking.
    SKIP_IF(IsRunningOnGvisor());

    auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

    int buffer_size;
    socklen_t length = sizeof(buffer_size);
    ASSERT_THAT(getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF,
                           &buffer_size, &length),
                SyscallSucceeds());

    int wfd = sockets->first_fd();
    ScopedThread t([wfd, buffer_size]() {
      std::vector<char> buf(2 * buffer_size);
      // Write more than fits in the buffer. Blocks then returns partial write
      // when the other end is closed. The next call returns EPIPE.
      //
      // N.B. writes occur in chunks, so we may see less than buffer_size from
      // the first call.
      ASSERT_THAT(write(wfd, buf.data(), buf.size()),
                  SyscallSucceedsWithValue(::testing::Gt(0)));
      ASSERT_THAT(write(wfd, buf.data(), buf.size()),
                  ::testing::AnyOf(SyscallFailsWithErrno(EPIPE),
                                   SyscallFailsWithErrno(ECONNRESET)));
    });

    // Leave time for write to become blocked.
    absl::SleepFor(absl::Seconds(1));

    ASSERT_THAT(close(sockets->release_second_fd()), SyscallSucceeds());
}

// Random save may interrupt the call to sendmsg() in SendLargeSendMsg(),
// causing the write to be incomplete and the test to hang.
TEST_P(BlockingStreamSocketPairTest, SendMsgTooLarge_NoRandomSave) {
  auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

  int sndbuf;
  socklen_t length = sizeof(sndbuf);
  ASSERT_THAT(
      getsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDBUF, &sndbuf, &length),
      SyscallSucceeds());

  // Make the call too large to fit in the send buffer.
  const int buffer_size = 3 * sndbuf;

  EXPECT_THAT(SendLargeSendMsg(sockets, buffer_size, true /* reader */),
              SyscallSucceedsWithValue(buffer_size));
}

TEST_P(BlockingStreamSocketPairTest, RecvLessThanBuffer) {
  auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

  char sent_data[100];
  RandomizeBuffer(sent_data, sizeof(sent_data));

  ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
              SyscallSucceedsWithValue(sizeof(sent_data)));

  char received_data[200] = {};
  ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
                               sizeof(received_data), 0),
              SyscallSucceedsWithValue(sizeof(sent_data)));
}

// Test that MSG_WAITALL causes recv to block until all requested data is
// received. Random save can interrupt blocking and cause received data to be
// returned, even if the amount received is less than the full requested amount.
TEST_P(BlockingStreamSocketPairTest, RecvLessThanBufferWaitAll_NoRandomSave) {
  auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

  char sent_data[100];
  RandomizeBuffer(sent_data, sizeof(sent_data));

  ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
              SyscallSucceedsWithValue(sizeof(sent_data)));

  constexpr auto kDuration = absl::Milliseconds(200);
  auto before = Now(CLOCK_MONOTONIC);

  const ScopedThread t([&]() {
    absl::SleepFor(kDuration);

    // Don't let saving after the write interrupt the blocking recv.
    const DisableSave ds;

    ASSERT_THAT(write(sockets->first_fd(), sent_data, sizeof(sent_data)),
                SyscallSucceedsWithValue(sizeof(sent_data)));
  });

  char received_data[sizeof(sent_data) * 2] = {};
  ASSERT_THAT(RetryEINTR(recv)(sockets->second_fd(), received_data,
                               sizeof(received_data), MSG_WAITALL),
              SyscallSucceedsWithValue(sizeof(received_data)));

  auto after = Now(CLOCK_MONOTONIC);
  EXPECT_GE(after - before, kDuration);
}

TEST_P(BlockingStreamSocketPairTest, SendTimeout) {
  auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());

  struct timeval tv {
    .tv_sec = 0, .tv_usec = 10
  };
  EXPECT_THAT(
      setsockopt(sockets->first_fd(), SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)),
      SyscallSucceeds());

  std::vector<char> buf(kPageSize);
  // We don't know how much data the socketpair will buffer, so we may do an
  // arbitrarily large number of writes; saving after each write causes this
  // test's time to explode.
  const DisableSave ds;
  for (;;) {
    int ret;
    ASSERT_THAT(
        ret = RetryEINTR(send)(sockets->first_fd(), buf.data(), buf.size(), 0),
        ::testing::AnyOf(SyscallSucceeds(), SyscallFailsWithErrno(EAGAIN)));
    if (ret == -1) {
      break;
    }
  }
}

}  // namespace testing
}  // namespace gvisor
<|endoftext|>


<commit_before>//===--------------- test_exception_storage_nodynmem.cpp ------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: libcxxabi-no-exceptions

// cxa_exception_storage does not use dynamic memory in the single thread mode.
// UNSUPPORTED: libcpp-has-no-threads

// Our overwritten calloc() is not compatible with these sanitizers.
// UNSUPPORTED: msan, tsan

#include <assert.h>
#include <cstdlib>

static bool OverwrittenCallocCalled = false;

// Override calloc to simulate exhaustion of dynamic memory
void *calloc(size_t, size_t) {
    OverwrittenCallocCalled = true;
    return 0;
}

int main(int argc, char *argv[]) {
    // Run the test a couple of times
    // to ensure that fallback memory doesn't leak.
    for (int I = 0; I < 1000; ++I)
        try {
            throw 42;
        } catch (...) {
        }

    assert(OverwrittenCallocCalled);
    return 0;
}
<commit_msg>[libc++abi] Remove the test for checking using of fallback malloc in case of dynamic memory exhaustion.<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 *  Gap2Seq
 *  Copyright (C) Leena Salmela, Kristoffer Sahlin, Veli Mäkinen,
 *  Alexandru Tomescu, Riku Walve 2017
 *
 *  Contact: leena.salmela@cs.helsinki.fi
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/

#include <sys/types.h>

#include <string>
#include <vector>

// GATB-core Bloom filter requires hash1 function for items
inline u_int64_t hash1(const std::string &key, u_int64_t seed = 0)
{
  (void) seed;
  return std::hash<std::string>{}(key);
}

#include <gatb/gatb_core.hpp>

#include <htslib/sam.h>

/*****************************************************************************/

static const char *STR_ALIGNMENT = "-bam";
static const char *STR_OUTPUT = "-reads";

static const char *STR_MEAN = "-mean";
static const char *STR_STD_DEV = "-std-dev";

static const char *STR_SCAFFOLD = "-scaffold";
static const char *STR_GAP_BREAKPOINT = "-breakpoint";

static const char *STR_FLANK_LENGTH = "-flank-length";

static const char *STR_GAP_LENGTH = "-gap-length";
// static const char *STR_THRESHOLD = "-unmapped";

static const char *STR_ONLY_UNMAPPED = "-unmapped-only";

/*****************************************************************************/

class io_t
{
public:
  samFile *sam = NULL;
  bam_hdr_t *header = NULL;
  hts_idx_t *idx = NULL;
  bool loaded = false;

  io_t(const std::string &);

  void unload()
  {
    bam_hdr_destroy(this->header);
    sam_close(this->sam);
    loaded = false;
  }
};

// Loads a bam/sam file into an IO object
io_t::io_t(const std::string &samFilename)
{
  this->sam = sam_open(samFilename.c_str(), "r");
  if (this->sam == NULL) {
    return;
  }

  this->header = sam_hdr_read(this->sam);
  if (this->header == NULL) {
    return;
  }

  this->idx = sam_index_load(this->sam, samFilename.c_str());
  if (this->idx == NULL) {
    return;
  }

  this->loaded = true;
}

/*****************************************************************************/

inline uint8_t complement(const uint8_t n)
{
  switch (n) {
  case 1:
    return 8;
  case 2:
    return 4;
  case 4:
    return 2;
  case 8:
    return 1;
  case 15:
  default:
    return 15;
  }
}

inline uint8_t querySequence(const uint8_t *query, const int32_t length,
                             const int32_t index, const bool reverse)
{
  if (!reverse) {
    return bam_seqi(query, index);
  }

  return complement(bam_seqi(query, length - 1 - index));
}

/*****************************************************************************/

// Converts an alignment to std::string. Handles reverse complements.
std::string convertToString(const uint8_t *query, const int32_t length,
                            const bool reverse, char *buffer)
{
  for (int32_t i = 0; i < length; i++) {
    switch (querySequence(query, length, i, reverse)) {
    case 0x1:
      buffer[i] = 'A';
      break;
    case 0x2:
      buffer[i] = 'C';
      break;
    case 0x4:
      buffer[i] = 'G';
      break;
    case 0x8:
      buffer[i] = 'T';
      break;
    case 0x15:
    default:
      buffer[i] = 'N';
      break;
    }
  }

  buffer[length] = '\0';
  return std::string(buffer);
}

/*****************************************************************************/

static inline const std::string bam2string(const bam1_t *bam)
{
  return std::string(bam_get_qname(bam)) + (((bam->core.flag & BAM_FREAD1) != 0) ? "/1" : "/2");
}

static inline const std::string bam2string_mate(const bam1_t *bam)
{
  return std::string(bam_get_qname(bam)) + (((bam->core.flag & BAM_FREAD1) != 0) ? "/2" : "/1");
}

/*****************************************************************************/

class sam_iterator
{
private:
  samFile *m_sam;
  hts_itr_t *m_iter;

public:
  bam1_t *bam;

  sam_iterator(const io_t io, const int tid, const int start, const int end)
      : m_sam(io.sam), bam(bam_init1())
  {
    m_iter = sam_itr_queryi(io.idx, tid, start, end);
    if (m_iter == NULL) {
      std::cerr << "WARNING: SAM iterator is NULL!" << std::endl;
    }
  }

  sam_iterator(const io_t io, const char *string)
      : m_sam(io.sam), bam(bam_init1())
  {
    m_iter = sam_itr_querys(io.idx, io.header, string);
    if (m_iter == NULL) {
      std::cerr << "WARNING: SAM iterator is NULL!" << std::endl;
    }
  }

  ~sam_iterator()
  {
    hts_itr_destroy(m_iter);
    bam_destroy1(bam);
  }

  inline bool next()
  {
    if (m_iter == NULL) {
      return false;
    }

    return (sam_itr_next(m_sam, m_iter, bam) >= 0);
  }
};

// Counts the number of reads by iterating through the alignment file
uint64_t count_reads(const std::string &filename, int32_t *read_length)
{
  io_t io(filename);
  sam_iterator iter(io, ".");

  uint64_t count = 0;
  int32_t max_length = 0;
  while (iter.next()) {
    count++;
    max_length = max(max_length, iter.bam->core.l_qseq);
  }

  io.unload();
  *read_length = max_length;
  return count;
}

/*****************************************************************************/

class ReadFilter : public Tool
{
public:
  ReadFilter();
  void execute();

  // Prints an alignment in fasta format
  void print_fasta(const bam1_t *, char *, BankFasta *);

  // Prints all alignments in a region
  void process_region(const io_t &, const int, const int, const int, char *, IBloom<std::string> *, BankFasta *, int *, int *);
  void process_mates(const io_t &, const int, const int, const int, IBloom<std::string> *);
  void find_mates(const io_t &, char *, IBloom<std::string> *, BankFasta *, int *, int *);
  void process_unmapped(const io_t &, char *, IBloom<std::string> *, BankFasta *, int *);
};

ReadFilter::ReadFilter() : Tool("ReadFilter")
{
  // Input / output
  getParser()->push_front(new OptionOneParam(STR_ALIGNMENT, "Aligned BAM file", true));
  getParser()->push_front(new OptionOneParam(STR_OUTPUT, "FASTA-formatted output file", true));

  // Read library parameters
  getParser()->push_front(new OptionOneParam(STR_MEAN, "Mean insert size", true));
  getParser()->push_front(new OptionOneParam(STR_STD_DEV, "Insert size standard deviation", true));

  // Gap parameters
  getParser()->push_front(new OptionOneParam(STR_SCAFFOLD, "Scaffold name", true));
  getParser()->push_front(new OptionOneParam(STR_GAP_BREAKPOINT, "Gap breakpoint position", true));
  getParser()->push_front(new OptionOneParam(STR_GAP_LENGTH, "Gap length (in the scaffold)", false, "-1"));
  getParser()->push_front(new OptionOneParam(STR_FLANK_LENGTH, "Flank length", false, "-1"));

  getParser()->push_front(new OptionNoParam(STR_ONLY_UNMAPPED, "Output unmapped reads"));
}

/*****************************************************************************/

// Output a bam object into GATB fasta bank
void ReadFilter::print_fasta(const bam1_t *bam, char *buffer, BankFasta *bank)
{
  const std::string sequence = convertToString(bam_get_seq(bam),
                                               bam->core.l_qseq, bam_is_rev(bam), buffer);

  Sequence seq(buffer);
  seq._comment = bam2string(bam);
  bank->insert(seq);
}

// Output reads that map to a region in a scaffold and not in the Bloom filter.
void ReadFilter::process_region(const io_t &io, const int tid, const int start,
                                const int end, char *buffer, IBloom<std::string> *bloom, BankFasta *bank,
                                int *seqlen, int *num_of_reads)
{
  sam_iterator iter(io, tid, start, end);
  while (iter.next()) {
    if (!bloom->contains(bam2string(iter.bam))) {
      print_fasta(iter.bam, buffer, bank);
      *seqlen += strlen(buffer);
      (*num_of_reads)++;
    }
  }
}

// Add read mates to Bloom filter
void ReadFilter::process_mates(const io_t &io, const int tid, const int start,
                               const int end, IBloom<std::string> *bloom)
{
  sam_iterator iter(io, tid, start, end);
  while (iter.next()) {
    if ((iter.bam->core.flag & BAM_FMUNMAP) != 0) {
      bloom->insert(bam2string(iter.bam));
    }
  }
}

// Output read mates from Bloom filter
void ReadFilter::find_mates(const io_t &io, char *buffer, IBloom<std::string> *bloom,
                            BankFasta *bank, int *seqlen, int *num_of_reads)
{
  sam_iterator iter(io, ".");
  while (iter.next()) {
    if (bloom->contains(bam2string_mate(iter.bam))) {
      print_fasta(iter.bam, buffer, bank);
      *seqlen += strlen(buffer);
      (*num_of_reads)++;
    }
  }
}

// Output all unmapped reads
void ReadFilter::process_unmapped(const io_t &io, char *buffer,
                                  IBloom<std::string> *bloom, BankFasta *bank, int *num_of_reads)
{
  sam_iterator iter(io, ".");
  while (iter.next()) {
    if ((iter.bam->core.flag & BAM_FUNMAP) != 0 &&
        !bloom->contains(bam2string(iter.bam))) {
      print_fasta(iter.bam, buffer, bank);
      (*num_of_reads)++;
    }
  }
}

void ReadFilter::execute()
{
  const std::string alignment = getInput()->getStr(STR_ALIGNMENT);
  const std::string output = getInput()->getStr(STR_OUTPUT);

  const int mean_insert = static_cast<int>(getInput()->getInt(STR_MEAN));
  const int std_dev = static_cast<int>(getInput()->getInt(STR_STD_DEV));

  const std::string scaffold = getInput()->getStr(STR_SCAFFOLD);
  const int breakpoint = static_cast<int>(getInput()->getInt(STR_GAP_BREAKPOINT));
  const int flank_length = static_cast<int>(getInput()->getInt(STR_FLANK_LENGTH));
  const int gap_length = static_cast<int>(getInput()->getInt(STR_GAP_LENGTH));

  const bool unmapped_only = getParser()->saw(STR_ONLY_UNMAPPED);

  // Load alignment file
  io_t io(alignment);
  if (!io.loaded) {
    std::cerr << "Error loading alignments" << std::endl;
    return;
  }

  // Use basic Bloom filter from GATB
  int32_t read_length = 0;
  const uint64_t num_of_reads = count_reads(alignment, &read_length);
  IBloom<std::string> *bloom = new BloomSynchronized<std::string>(5 * num_of_reads);

  // Allocate memory for string conversions
  char *buffer = new char[read_length + 1];

  // Open output file
  BankFasta reads(output);
  int seqlen = 0, reads_extracted = 0;

  if (!unmapped_only) {
    // Compute scaffold id from scaffold name
    const int tid = bam_name2id(io.header, scaffold.c_str());

    // Extract pairs from the left mappings
    const int left_start = breakpoint - (mean_insert + 3 * std_dev + 2 * read_length);
    const int left_end = breakpoint - (mean_insert - 3 * std_dev + read_length);
    process_mates(io, tid, left_start, left_end, bloom);

    // Extract pairs from the right mappings
    const int right_start = breakpoint + (mean_insert + 3 * std_dev + read_length) + gap_length;
    const int right_end = breakpoint + (mean_insert - 3 * std_dev + read_length) + gap_length;
    process_mates(io, tid, right_start, right_end, bloom);

    // Output reads and count length
    find_mates(io, buffer, bloom, &reads, &seqlen, &reads_extracted);

    // Output overlapping reads
    if (flank_length != -1) {
      const int start = breakpoint - flank_length;
      const int end = breakpoint + flank_length + gap_length;
      process_region(io, tid, start, end, buffer, bloom, &reads, &seqlen, &reads_extracted);
    }
  }

  // Output unmapped reads
  if (unmapped_only) {
    process_unmapped(io, buffer, bloom, &reads, &reads_extracted);
  }

  std::cout << "Extracted " << reads_extracted << " out of " << num_of_reads << " reads" << std::endl;

  // Cleanup
  reads.flush();
  delete[] buffer;
  delete bloom;
  io.unload();
}

int main(int argc, char *argv[])
{
  try {
    ReadFilter().run(argc, argv);
  } catch (Exception &e) {
    std::cout << "EXCEPTION: " << e.getMessage() << std::endl;
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<commit_msg>include subset of GATB in ReadFilter to fix definition conflicts<commit_after>/*****************************************************************************
 *  Gap2Seq
 *  Copyright (C) Leena Salmela, Kristoffer Sahlin, Veli Mäkinen,
 *  Alexandru Tomescu, Riku Walve 2017
 *
 *  Contact: leena.salmela@cs.helsinki.fi
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as
 *  published by the Free Software Foundation, either version 3 of the
 *  License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/

#include <sys/types.h>

#include <string>
#include <vector>

// GATB-core Bloom filter requires hash1 function for items
inline u_int64_t hash1(const std::string &key, u_int64_t seed = 0)
{
  (void) seed;
  return std::hash<std::string>{}(key);
}

#include <gatb/tools/misc/impl/Tool.hpp>
#include <gatb/tools/collections/impl/Bloom.hpp>
#include <gatb/bank/impl/BankFasta.hpp>

#include <htslib/sam.h>

using namespace gatb::core::tools::misc;
using namespace gatb::core::tools::misc::impl;
using namespace gatb::core::tools::collections;
using namespace gatb::core::tools::collections::impl;
using namespace gatb::core::bank;
using namespace gatb::core::bank::impl;

/*****************************************************************************/

static const char *STR_ALIGNMENT = "-bam";
static const char *STR_OUTPUT = "-reads";

static const char *STR_MEAN = "-mean";
static const char *STR_STD_DEV = "-std-dev";

static const char *STR_SCAFFOLD = "-scaffold";
static const char *STR_GAP_BREAKPOINT = "-breakpoint";

static const char *STR_FLANK_LENGTH = "-flank-length";
static const char *STR_GAP_LENGTH = "-gap-length";

static const char *STR_ONLY_UNMAPPED = "-unmapped-only";

/*****************************************************************************/

class io_t
{
public:
  samFile *sam = NULL;
  bam_hdr_t *header = NULL;
  hts_idx_t *idx = NULL;
  bool loaded = false;

  io_t(const std::string &);

  void unload()
  {
    bam_hdr_destroy(this->header);
    sam_close(this->sam);
    loaded = false;
  }
};

// Loads a bam/sam file into an IO object
io_t::io_t(const std::string &samFilename)
{
  this->sam = sam_open(samFilename.c_str(), "r");
  if (this->sam == NULL) {
    return;
  }

  this->header = sam_hdr_read(this->sam);
  if (this->header == NULL) {
    return;
  }

  this->idx = sam_index_load(this->sam, samFilename.c_str());
  if (this->idx == NULL) {
    return;
  }

  this->loaded = true;
}

/*****************************************************************************/

inline uint8_t complement(const uint8_t n)
{
  switch (n) {
  case 1:
    return 8;
  case 2:
    return 4;
  case 4:
    return 2;
  case 8:
    return 1;
  case 15:
  default:
    return 15;
  }
}

inline uint8_t querySequence(const uint8_t *query, const int32_t length,
                             const int32_t index, const bool reverse)
{
  if (!reverse) {
    return bam_seqi(query, index);
  }

  return complement(bam_seqi(query, length - 1 - index));
}

/*****************************************************************************/

// Converts an alignment to std::string. Handles reverse complements.
std::string convertToString(const uint8_t *query, const int32_t length,
                            const bool reverse, char *buffer)
{
  for (int32_t i = 0; i < length; i++) {
    switch (querySequence(query, length, i, reverse)) {
    case 0x1:
      buffer[i] = 'A';
      break;
    case 0x2:
      buffer[i] = 'C';
      break;
    case 0x4:
      buffer[i] = 'G';
      break;
    case 0x8:
      buffer[i] = 'T';
      break;
    case 0x15:
    default:
      buffer[i] = 'N';
      break;
    }
  }

  buffer[length] = '\0';
  return std::string(buffer);
}

/*****************************************************************************/

static inline const std::string bam2string(const bam1_t *bam)
{
  return std::string(bam_get_qname(bam)) + (((bam->core.flag & BAM_FREAD1) != 0) ? "/1" : "/2");
}

static inline const std::string bam2string_mate(const bam1_t *bam)
{
  return std::string(bam_get_qname(bam)) + (((bam->core.flag & BAM_FREAD1) != 0) ? "/2" : "/1");
}

/*****************************************************************************/

class sam_iterator
{
private:
  samFile *m_sam;
  hts_itr_t *m_iter;

public:
  bam1_t *bam;

  sam_iterator(const io_t io, const int tid, const int start, const int end)
      : m_sam(io.sam), bam(bam_init1())
  {
    m_iter = sam_itr_queryi(io.idx, tid, start, end);
    if (m_iter == NULL) {
      std::cerr << "WARNING: SAM iterator is NULL!" << std::endl;
    }
  }

  sam_iterator(const io_t io, const char *string)
      : m_sam(io.sam), bam(bam_init1())
  {
    m_iter = sam_itr_querys(io.idx, io.header, string);
    if (m_iter == NULL) {
      std::cerr << "WARNING: SAM iterator is NULL!" << std::endl;
    }
  }

  ~sam_iterator()
  {
    hts_itr_destroy(m_iter);
    bam_destroy1(bam);
  }

  inline bool next()
  {
    if (m_iter == NULL) {
      return false;
    }

    return (sam_itr_next(m_sam, m_iter, bam) >= 0);
  }
};

// Counts the number of reads by iterating through the alignment file
uint64_t count_reads(const std::string &filename, int32_t *read_length)
{
  io_t io(filename);
  sam_iterator iter(io, ".");

  uint64_t count = 0;
  int32_t max_length = 0;
  while (iter.next()) {
    count++;
    max_length = (iter.bam->core.l_qseq > max_length) ? iter.bam->core.l_qseq : max_length;
  }

  io.unload();
  *read_length = max_length;
  return count;
}

/*****************************************************************************/

class ReadFilter : public Tool
{
public:
  ReadFilter();
  void execute();

  // Prints an alignment in fasta format
  void print_fasta(const bam1_t *, char *, BankFasta *);

  // Prints all alignments in a region
  void process_region(const io_t &, const int, const int, const int, char *, IBloom<std::string> *, BankFasta *, int *, int *);
  void process_mates(const io_t &, const int, const int, const int, IBloom<std::string> *);
  void find_mates(const io_t &, char *, IBloom<std::string> *, BankFasta *, int *, int *);
  void process_unmapped(const io_t &, char *, IBloom<std::string> *, BankFasta *, int *);
};

ReadFilter::ReadFilter() : Tool("ReadFilter")
{
  // Input / output
  getParser()->push_front(new OptionOneParam(STR_ALIGNMENT, "Aligned BAM file", true));
  getParser()->push_front(new OptionOneParam(STR_OUTPUT, "FASTA-formatted output file", true));

  // Read library parameters
  getParser()->push_front(new OptionOneParam(STR_MEAN, "Mean insert size", true));
  getParser()->push_front(new OptionOneParam(STR_STD_DEV, "Insert size standard deviation", true));

  // Gap parameters
  getParser()->push_front(new OptionOneParam(STR_SCAFFOLD, "Scaffold name", true));
  getParser()->push_front(new OptionOneParam(STR_GAP_BREAKPOINT, "Gap breakpoint position", true));
  getParser()->push_front(new OptionOneParam(STR_GAP_LENGTH, "Gap length (in the scaffold)", false, "-1"));
  getParser()->push_front(new OptionOneParam(STR_FLANK_LENGTH, "Flank length", false, "-1"));

  getParser()->push_front(new OptionNoParam(STR_ONLY_UNMAPPED, "Output unmapped reads"));
}

/*****************************************************************************/

// Output a bam object into GATB fasta bank
void ReadFilter::print_fasta(const bam1_t *bam, char *buffer, BankFasta *bank)
{
  const std::string sequence = convertToString(bam_get_seq(bam),
                                               bam->core.l_qseq, bam_is_rev(bam), buffer);

  Sequence seq(buffer);
  seq._comment = bam2string(bam);
  bank->insert(seq);
}

// Output reads that map to a region in a scaffold and not in the Bloom filter.
void ReadFilter::process_region(const io_t &io, const int tid, const int start,
                                const int end, char *buffer, IBloom<std::string> *bloom, BankFasta *bank,
                                int *seqlen, int *num_of_reads)
{
  sam_iterator iter(io, tid, start, end);
  while (iter.next()) {
    if (!bloom->contains(bam2string(iter.bam))) {
      print_fasta(iter.bam, buffer, bank);
      *seqlen += strlen(buffer);
      (*num_of_reads)++;
    }
  }
}

// Add read mates to Bloom filter
void ReadFilter::process_mates(const io_t &io, const int tid, const int start,
                               const int end, IBloom<std::string> *bloom)
{
  sam_iterator iter(io, tid, start, end);
  while (iter.next()) {
    if ((iter.bam->core.flag & BAM_FMUNMAP) != 0) {
      bloom->insert(bam2string(iter.bam));
    }
  }
}

// Output read mates from Bloom filter
void ReadFilter::find_mates(const io_t &io, char *buffer, IBloom<std::string> *bloom,
                            BankFasta *bank, int *seqlen, int *num_of_reads)
{
  sam_iterator iter(io, ".");
  while (iter.next()) {
    if (bloom->contains(bam2string_mate(iter.bam))) {
      print_fasta(iter.bam, buffer, bank);
      *seqlen += strlen(buffer);
      (*num_of_reads)++;
    }
  }
}

// Output all unmapped reads
void ReadFilter::process_unmapped(const io_t &io, char *buffer,
                                  IBloom<std::string> *bloom, BankFasta *bank, int *num_of_reads)
{
  sam_iterator iter(io, ".");
  while (iter.next()) {
    if ((iter.bam->core.flag & BAM_FUNMAP) != 0 &&
        !bloom->contains(bam2string(iter.bam))) {
      print_fasta(iter.bam, buffer, bank);
      (*num_of_reads)++;
    }
  }
}

void ReadFilter::execute()
{
  const std::string alignment = getInput()->getStr(STR_ALIGNMENT);
  const std::string output = getInput()->getStr(STR_OUTPUT);

  const int mean_insert = static_cast<int>(getInput()->getInt(STR_MEAN));
  const int std_dev = static_cast<int>(getInput()->getInt(STR_STD_DEV));

  const std::string scaffold = getInput()->getStr(STR_SCAFFOLD);
  const int breakpoint = static_cast<int>(getInput()->getInt(STR_GAP_BREAKPOINT));
  const int flank_length = static_cast<int>(getInput()->getInt(STR_FLANK_LENGTH));
  const int gap_length = static_cast<int>(getInput()->getInt(STR_GAP_LENGTH));

  const bool unmapped_only = getParser()->saw(STR_ONLY_UNMAPPED);

  // Load alignment file
  io_t io(alignment);
  if (!io.loaded) {
    std::cerr << "Error loading alignments" << std::endl;
    return;
  }

  // Use basic Bloom filter from GATB
  int32_t read_length = 0;
  const uint64_t num_of_reads = count_reads(alignment, &read_length);
  IBloom<std::string> *bloom = new BloomSynchronized<std::string>(5 * num_of_reads);

  // Allocate memory for string conversions
  char *buffer = new char[read_length + 1];

  // Open output file
  BankFasta reads(output);
  int seqlen = 0, reads_extracted = 0;

  if (!unmapped_only) {
    // Compute scaffold id from scaffold name
    const int tid = bam_name2id(io.header, scaffold.c_str());

    // Extract pairs from the left mappings
    const int left_start = breakpoint - (mean_insert + 3 * std_dev + 2 * read_length);
    const int left_end = breakpoint - (mean_insert - 3 * std_dev + read_length);
    process_mates(io, tid, left_start, left_end, bloom);

    // Extract pairs from the right mappings
    const int right_start = breakpoint + (mean_insert + 3 * std_dev + read_length) + gap_length;
    const int right_end = breakpoint + (mean_insert - 3 * std_dev + read_length) + gap_length;
    process_mates(io, tid, right_start, right_end, bloom);

    // Output reads and count length
    find_mates(io, buffer, bloom, &reads, &seqlen, &reads_extracted);

    // Output overlapping reads
    if (flank_length != -1) {
      const int start = breakpoint - flank_length;
      const int end = breakpoint + flank_length + gap_length;
      process_region(io, tid, start, end, buffer, bloom, &reads, &seqlen, &reads_extracted);
    }
  }

  // Output unmapped reads
  if (unmapped_only) {
    process_unmapped(io, buffer, bloom, &reads, &reads_extracted);
  }

  std::cout << "Extracted " << reads_extracted << " out of " << num_of_reads << " reads" << std::endl;

  // Cleanup
  reads.flush();
  delete[] buffer;
  delete bloom;
  io.unload();
}

int main(int argc, char *argv[])
{
  ReadFilter().run(argc, argv);
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// 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.
//
#include "common.h"

const char *SVMPointerPassing_test_kernel[] = {
  "__kernel void verify_char(__global uchar* pChar, volatile __global uint* num_correct, uchar expected)\n"
  "{\n"
  "    if(0 == get_global_id(0))\n"
  "    {\n"
  "        *num_correct = 0;\n"
  "        if(*pChar == expected)\n"
  "        {\n"
  "                    *num_correct=1;\n"
  "        }\n"
  "    }\n"
  "}\n"
};

// Test that arbitrarily aligned char pointers into shared buffers can be passed directly to a kernel.
// This iterates through a buffer passing a pointer to each location to the kernel.
// The buffer is initialized to known values at each location.
// The kernel checks that it finds the expected value at each location.
// TODO: possibly make this work across all base types (including typeN?), also check ptr arithmetic ++,--.
int test_svm_pointer_passing(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
{
  clContextWrapper    context = NULL;
  clProgramWrapper    program = NULL;
  cl_uint     num_devices = 0;
  cl_int      error = CL_SUCCESS;
  clCommandQueueWrapper queues[MAXQ];

  error = create_cl_objects(deviceID, &SVMPointerPassing_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
  if(error) return -1;

  clKernelWrapper kernel_verify_char = clCreateKernel(program, "verify_char", &error);
  test_error(error,"clCreateKernel failed");

  size_t bufSize = 256;
  char *pbuf = (char*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_uchar)*bufSize, 0);

  cl_int *pNumCorrect = NULL;
  pNumCorrect = (cl_int*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_int), 0);

  {
    clMemWrapper buf = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(cl_uchar)*bufSize, pbuf, &error);
    test_error(error, "clCreateBuffer failed.");

    clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(cl_int), pNumCorrect, &error);
    test_error(error, "clCreateBuffer failed.");

    error = clSetKernelArg(kernel_verify_char, 1, sizeof(void*), (void *) &num_correct);
    test_error(error, "clSetKernelArg failed");

    // put values into buf so that we can expect to see these values in the kernel when we pass a pointer to them.
    cl_command_queue cmdq = queues[0];
    cl_uchar* pBuf = (cl_uchar*) clEnqueueMapBuffer(cmdq, buf, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_uchar)*bufSize, 0, NULL,NULL, &error);
    test_error2(error, pBuf, "clEnqueueMapBuffer failed");
    for(int i = 0; i<(int)bufSize; i++)
    {
      pBuf[i]= (cl_uchar)i;
    }
    error = clEnqueueUnmapMemObject(cmdq, buf, pBuf, 0,NULL,NULL);
    test_error(error, "clEnqueueUnmapMemObject failed.");

    for (cl_uint ii = 0; ii<num_devices; ++ii)  // iterate over all devices in the platform.
    {
      cmdq = queues[ii];
      for(int i = 0; i<(int)bufSize; i++)
      {
        cl_uchar* pChar = &pBuf[i];
        error = clSetKernelArgSVMPointer(kernel_verify_char, 0, pChar); // pass a pointer to a location within the buffer
        test_error(error, "clSetKernelArg failed");
        error = clSetKernelArg(kernel_verify_char, 2, sizeof(cl_uchar), (void *) &i );  // pass the expected value at the above location.
        test_error(error, "clSetKernelArg failed");
        error = clEnqueueNDRangeKernel(cmdq, kernel_verify_char, 1, NULL, &bufSize, NULL, 0, NULL, NULL);
        test_error(error,"clEnqueueNDRangeKernel failed");

        pNumCorrect = (cl_int*) clEnqueueMapBuffer(cmdq, num_correct, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_int), 0, NULL,NULL, &error);
        test_error2(error, pNumCorrect, "clEnqueueMapBuffer failed");
        cl_int correct_count = *pNumCorrect;
        error = clEnqueueUnmapMemObject(cmdq, num_correct, pNumCorrect, 0,NULL,NULL);
        test_error(error, "clEnqueueUnmapMemObject failed.");

        if(correct_count != 1)
        {
          log_error("Passing pointer directly to kernel for byte #%d failed on device %d\n", i, ii);
          return -1;
        }
      }
    }

    error = clFinish(cmdq);
    test_error(error, "clFinish failed");
  }

  clSVMFree(context, pbuf);
  clSVMFree(context, pNumCorrect);

  return 0;
}
<commit_msg>Test SVM: Fix - do not use unmapped pointer. (#661)<commit_after>//
// Copyright (c) 2017 The Khronos Group Inc.
//
// 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.
//
#include "common.h"

const char *SVMPointerPassing_test_kernel[] = {
  "__kernel void verify_char(__global uchar* pChar, volatile __global uint* num_correct, uchar expected)\n"
  "{\n"
  "    if(0 == get_global_id(0))\n"
  "    {\n"
  "        *num_correct = 0;\n"
  "        if(*pChar == expected)\n"
  "        {\n"
  "                    *num_correct=1;\n"
  "        }\n"
  "    }\n"
  "}\n"
};

// Test that arbitrarily aligned char pointers into shared buffers can be passed directly to a kernel.
// This iterates through a buffer passing a pointer to each location to the kernel.
// The buffer is initialized to known values at each location.
// The kernel checks that it finds the expected value at each location.
// TODO: possibly make this work across all base types (including typeN?), also check ptr arithmetic ++,--.
int test_svm_pointer_passing(cl_device_id deviceID, cl_context context2, cl_command_queue queue, int num_elements)
{
  clContextWrapper    context = NULL;
  clProgramWrapper    program = NULL;
  cl_uint     num_devices = 0;
  cl_int      error = CL_SUCCESS;
  clCommandQueueWrapper queues[MAXQ];

  error = create_cl_objects(deviceID, &SVMPointerPassing_test_kernel[0], &context, &program, &queues[0], &num_devices, CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
  if(error) return -1;

  clKernelWrapper kernel_verify_char = clCreateKernel(program, "verify_char", &error);
  test_error(error,"clCreateKernel failed");

  size_t bufSize = 256;
  cl_uchar *pbuf_svm_alloc = (cl_uchar*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_uchar)*bufSize, 0);

  cl_int *pNumCorrect = NULL;
  pNumCorrect = (cl_int*) clSVMAlloc(context, CL_MEM_READ_WRITE, sizeof(cl_int), 0);

  {
    clMemWrapper buf = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(cl_uchar)*bufSize, pbuf_svm_alloc, &error);
    test_error(error, "clCreateBuffer failed.");

    clMemWrapper num_correct = clCreateBuffer(context, CL_MEM_USE_HOST_PTR, sizeof(cl_int), pNumCorrect, &error);
    test_error(error, "clCreateBuffer failed.");

    error = clSetKernelArg(kernel_verify_char, 1, sizeof(void*), (void *) &num_correct);
    test_error(error, "clSetKernelArg failed");

    // put values into buf so that we can expect to see these values in the kernel when we pass a pointer to them.
    cl_command_queue cmdq = queues[0];
    cl_uchar* pbuf_map_buffer = (cl_uchar*) clEnqueueMapBuffer(cmdq, buf, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_uchar)*bufSize, 0, NULL,NULL, &error);
    test_error2(error, pbuf_map_buffer, "clEnqueueMapBuffer failed");
    for(int i = 0; i<(int)bufSize; i++)
    {
      pbuf_map_buffer[i]= (cl_uchar)i;
    }
    error = clEnqueueUnmapMemObject(cmdq, buf, pbuf_map_buffer, 0,NULL,NULL);
    test_error(error, "clEnqueueUnmapMemObject failed.");

    for (cl_uint ii = 0; ii<num_devices; ++ii)  // iterate over all devices in the platform.
    {
      cmdq = queues[ii];
      for(int i = 0; i<(int)bufSize; i++)
      {
        cl_uchar* pChar = &pbuf_svm_alloc[i];
        error = clSetKernelArgSVMPointer(kernel_verify_char, 0, pChar); // pass a pointer to a location within the buffer
        test_error(error, "clSetKernelArg failed");
        error = clSetKernelArg(kernel_verify_char, 2, sizeof(cl_uchar), (void *) &i );  // pass the expected value at the above location.
        test_error(error, "clSetKernelArg failed");
        error = clEnqueueNDRangeKernel(cmdq, kernel_verify_char, 1, NULL, &bufSize, NULL, 0, NULL, NULL);
        test_error(error,"clEnqueueNDRangeKernel failed");

        pNumCorrect = (cl_int*) clEnqueueMapBuffer(cmdq, num_correct, CL_TRUE, CL_MAP_READ | CL_MAP_WRITE, 0, sizeof(cl_int), 0, NULL,NULL, &error);
        test_error2(error, pNumCorrect, "clEnqueueMapBuffer failed");
        cl_int correct_count = *pNumCorrect;
        error = clEnqueueUnmapMemObject(cmdq, num_correct, pNumCorrect, 0,NULL,NULL);
        test_error(error, "clEnqueueUnmapMemObject failed.");

        if(correct_count != 1)
        {
          log_error("Passing pointer directly to kernel for byte #%d failed on device %d\n", i, ii);
          return -1;
        }
      }
    }

    error = clFinish(cmdq);
    test_error(error, "clFinish failed");
  }

  clSVMFree(context, pbuf_svm_alloc);
  clSVMFree(context, pNumCorrect);

  return 0;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "vcl/printerinfomanager.hxx"

#include "generic/gendata.hxx"

using namespace psp;
using namespace osl;

using ::rtl::OUString;
using ::rtl::OString;
using ::rtl::OStringToOUString;
using ::rtl::OUStringHash;

PrinterInfoManager& PrinterInfoManager::get()
{
    SalData* pSalData = GetSalData();
    if( ! pSalData->m_pPIManager )
        pSalData->m_pPIManager = new PrinterInfoManager();
    return *pSalData->m_pPIManager;
}

void PrinterInfoManager::release()
{
    SalData* pSalData = GetSalData();
    delete pSalData->m_pPIManager;
    pSalData->m_pPIManager = NULL;
}

PrinterInfoManager::PrinterInfoManager( Type eType ) :
    m_pQueueInfo( NULL ),
    m_eType( eType ),
    m_bUseIncludeFeature( false ),
    m_bUseJobPatch( true ),
    m_aSystemDefaultPaper( RTL_CONSTASCII_USTRINGPARAM( "A4" ) ),
    m_bDisableCUPS( false )
{
    // initSystemDefaultPaper();
}

void PrinterInfoManager::listPrinters( ::std::list< OUString >& rList ) const
{
    rList.clear();
}

const PrinterInfo& PrinterInfoManager::getPrinterInfo( const OUString& /* rPrinter */ ) const
{
    static PrinterInfo aEmptyInfo;

    return aEmptyInfo;
}

bool PrinterInfoManager::checkFeatureToken( const rtl::OUString& /* rPrinterName */, const char* /* pToken */ ) const
{
    return false;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Apparently need more (all?) methods<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#include "vcl/printerinfomanager.hxx"

#include "generic/gendata.hxx"

using namespace psp;
using namespace osl;

using ::rtl::OUString;
using ::rtl::OString;
using ::rtl::OStringToOUString;
using ::rtl::OUStringHash;

PrinterInfoManager& PrinterInfoManager::get()
{
    SalData* pSalData = GetSalData();
    if( ! pSalData->m_pPIManager )
        pSalData->m_pPIManager = new PrinterInfoManager();
    return *pSalData->m_pPIManager;
}

void PrinterInfoManager::release()
{
    SalData* pSalData = GetSalData();
    delete pSalData->m_pPIManager;
    pSalData->m_pPIManager = NULL;
}

PrinterInfoManager::PrinterInfoManager( Type eType ) :
    m_pQueueInfo( NULL ),
    m_eType( eType ),
    m_bUseIncludeFeature( false ),
    m_bUseJobPatch( true ),
    m_aSystemDefaultPaper( RTL_CONSTASCII_USTRINGPARAM( "A4" ) ),
    m_bDisableCUPS( false )
{
    // initSystemDefaultPaper();
}

PrinterInfoManager::~PrinterInfoManager()
{

}

bool PrinterInfoManager::checkPrintersChanged( bool /* bWait */ )
{
    return false;
}

void PrinterInfoManager::initialize()
{
    // ???
}

void PrinterInfoManager::listPrinters( ::std::list< OUString >& rList ) const
{
    rList.clear();
}

const PrinterInfo& PrinterInfoManager::getPrinterInfo( const OUString& /* rPrinter */ ) const
{
    static PrinterInfo aEmptyInfo;

    return aEmptyInfo;
}

void PrinterInfoManager::changePrinterInfo( const OUString& /* rPrinter */, const PrinterInfo& /* rNewInfo */ )
{

}

bool PrinterInfoManager::writePrinterConfig()
{
    return false;
}

bool PrinterInfoManager::addPrinter( const OUString& /* rPrinterName */, const OUString& /* rDriverName */ )
{
    return false;
}

bool PrinterInfoManager::removePrinter( const OUString& /* rPrinterName */, bool /* bCheckOnly */ )
{
    return false;
}

bool PrinterInfoManager::setDefaultPrinter( const OUString& /* rPrinterName */ )
{
    return false;
}

bool PrinterInfoManager::addOrRemovePossible() const
{
    return false;
}

void PrinterInfoManager::fillFontSubstitutions( PrinterInfo& /* rInfo */ ) const
{

}

void PrinterInfoManager::getSystemPrintCommands( std::list< OUString >& /* rCommands */ )
{

}

const std::list< PrinterInfoManager::SystemPrintQueue >& PrinterInfoManager::getSystemPrintQueues()
{
    return m_aSystemPrintQueues;
}

bool PrinterInfoManager::checkFeatureToken( const rtl::OUString& /* rPrinterName */, const char* /* pToken */ ) const
{
    return false;
}

FILE* PrinterInfoManager::startSpool( const OUString& /* rPrintername */, bool /* bQuickCommand */ )
{
    return NULL;
}

int PrinterInfoManager::endSpool( const OUString& /*rPrintername*/, const OUString& /*rJobTitle*/, FILE* /* pFile */, const JobData& /*rDocumentJobData*/, bool /*bBanner*/ )
{
    return true;
}

void PrinterInfoManager::setupJobContextData( JobData& /* rData */ )
{

}

void PrinterInfoManager::setDefaultPaper( PPDContext& /* rContext */ ) const
{

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>