<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <Windows.h>
#endif

#include    "../../../Foundation/Characters/CString/Utilities.h"
#include    "../../../Foundation/Characters/String_Constant.h"
#include    "../../../Foundation/Characters/String2Float.h"
#include    "../../../Foundation/Containers/Sequence.h"
#include    "../../../Foundation/DataExchange/CharacterDelimitedLines/Reader.h"
#include    "../../../Foundation/Debug/Assertions.h"
#include    "../../../Foundation/Execution/ProcessRunner.h"
#include    "../../../Foundation/IO/FileSystem/BinaryFileInputStream.h"
#include    "../../../Foundation/Streams/BasicBinaryInputOutputStream.h"
#include    "../../../Foundation/Streams/TextInputStreamBinaryAdapter.h"

#include    "../CommonMeasurementTypes.h"

#include    "MountedFilesystemUsage.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::DataExchange;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::Memory;

using   namespace   Stroika::Frameworks;
using   namespace   Stroika::Frameworks::SystemPerformance;
using   namespace   Stroika::Frameworks::SystemPerformance::Instruments::MountedFilesystemUsage;

using   Characters::String_Constant;

#if     qPlatform_Windows
namespace {
    Sequence<VolumeInfo> capture_Windows_GetVolumeInfo_ ()
    {
        Sequence<VolumeInfo>   result;
        TCHAR volumeNameBuf[1024];
        for (HANDLE hVol = FindFirstVolume (volumeNameBuf, NEltsOf(volumeNameBuf)); hVol != INVALID_HANDLE_VALUE; ) {
            DWORD lpMaximumComponentLength;
            DWORD dwSysFlags;
            TCHAR FileSysNameBuf[1024];
            if (::GetVolumeInformation( volumeNameBuf, NULL, NEltsOf(volumeNameBuf), NULL, &lpMaximumComponentLength, &dwSysFlags, FileSysNameBuf, NEltsOf(FileSysNameBuf))) {
                VolumeInfo v;
                v.fFileSystemType = String::FromSDKString (FileSysNameBuf);
                v.fVolumeID = String::FromSDKString (volumeNameBuf);
                {
                    // @todo - use
                    //      http://msdn.microsoft.com/en-us/library/windows/desktop/cc542456(v=vs.85).aspx
                    //      CharCount = QueryDosDeviceW(&VolumeName[4], DeviceName, ARRAYSIZE(DeviceName));
                    //      to get DEVICENAME
                    //
                    TCHAR volPathsBuf[1024];
                    DWORD retLen = 0;
                    DWORD x = GetVolumePathNamesForVolumeName (volumeNameBuf, volPathsBuf, NEltsOf(volPathsBuf), &retLen);
                    if (volPathsBuf[0] == 0) {
                        v.fMountedOnName.clear ();
                        result.push_back (v);
                    }
                    else {
                        for (const TCHAR* NameIdx = volPathsBuf; NameIdx[0] != L'\0'; NameIdx += Characters::CString::Length (NameIdx) + 1) {
                            v.fMountedOnName = String::FromSDKString (NameIdx);
                            {
                                ULARGE_INTEGER freeBytesAvailable;
                                ULARGE_INTEGER totalNumberOfBytes;
                                ULARGE_INTEGER totalNumberOfFreeBytes;
                                memset (&freeBytesAvailable, 0, sizeof (freeBytesAvailable));
                                memset (&totalNumberOfBytes, 0, sizeof (totalNumberOfBytes));
                                memset (&totalNumberOfFreeBytes, 0, sizeof (totalNumberOfFreeBytes));
                                DWORD xxx = GetDiskFreeSpaceEx (v.fMountedOnName.AsSDKString ().c_str (), &freeBytesAvailable, &totalNumberOfBytes, &totalNumberOfFreeBytes);
                                v.fDiskSizeInBytes = static_cast<double> (totalNumberOfBytes.QuadPart);
                                v.fUsedSizeInBytes = *v.fDiskSizeInBytes  - freeBytesAvailable.QuadPart;
                            }
                            result.push_back (v);
                        }
                    }
                }
            }
            else {
                // warning...
            }

            // find next
            if (not ::FindNextVolume (hVol, volumeNameBuf, NEltsOf(volumeNameBuf))) {
                FindVolumeClose (hVol);
                hVol = INVALID_HANDLE_VALUE;
            }
        }
        return result;
    }
}
#endif

#if     qPlatform_POSIX
namespace {
    Sequence<VolumeInfo> capture_Process_Run_DF_ ()
    {
        Sequence<VolumeInfo>   result;
        //
        // I looked through the /proc filesystem stuff and didnt see anything obvious to retrive this info...
        // run def with ProcessRunner
        //
        //  NEW NOTE - I THINK ITS IN THERE.... RE-EXAMINE proc/filesystems proc/partitions, and http://en.wikipedia.org/wiki/Procfs
        //      -- LGP 2014-08-01
        ProcessRunner pr (L"/bin/df -k -T");
        Streams::BasicBinaryInputOutputStream   useStdOut;
        pr.SetStdOut (useStdOut);
        pr.Run ();
        String out;
        Streams::TextInputStreamBinaryAdapter   stdOut  =   Streams::TextInputStreamBinaryAdapter (useStdOut);
        bool skippedHeader = false;
        for (String i = stdOut.ReadLine (); not i.empty (); i = stdOut.ReadLine ()) {
            if (not skippedHeader) {
                skippedHeader = true;
                continue;
            }
            Sequence<String>    l    =  i.Tokenize (Set<Characters::Character> { ' ' });
            if (l.size () < 7) {
                DbgTrace ("skipping line cuz len=%d", l.size ());
                continue;
            }
            VolumeInfo v;
            v.fFileSystemType = l[1].Trim ();
            v.fMountedOnName = l[6].Trim ();
            {
                String  d   =   l[0].Trim ();
                if (not d.empty () and d != L"none") {
                    v.fDeviceOrVolumeName = d;
                }
            }
            v.fDiskSizeInBytes = Characters::String2Float<double> (l[2]) * 1024;
            v.fUsedSizeInBytes = Characters::String2Float<double> (l[3]) * 1024;
            result.Append (v);
        }
        return result;
    }
}
#endif

#if     qPlatform_POSIX
namespace {
    struct PerfStats_ {
        double  fSectorsRead {};
        double  fTimeSpentReading {};
        double  fSectorsWritten {};
        double  fTimeSpentWritingMS {};
    };
    Mapping<String, PerfStats_> capture_ProcFSDiskStats_ ()
    {
        using   IO::FileSystem::BinaryFileInputStream;
        using   Characters::String2Float;
        Mapping<String, PerfStats_>   result;
        DataExchange::CharacterDelimitedLines::Reader reader {{' ', '\t' }};
        const   String_Constant kProcMemInfoFileName_ { L"/proc/diskstats" };
        // Note - /procfs files always unseekable
        for (Sequence<String> line : reader.ReadMatrix (BinaryFileInputStream::mk (kProcMemInfoFileName_, BinaryFileInputStream::eNotSeekable))) {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"***in Instruments::MountedFilesystemUsage::capture_ProcFSDiskStats_ linesize=%d, line[0]=%s", line.size(), line.empty () ? L"" : line[0].c_str ());
#endif
            //
            // https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
            //
            //  3 - device name
            //  6 - sectors read
            //  7 - time spent reading (ms)
            //  10 - sectors written
            //  11 - time spent writing (ms)
            //
            if (line.size () >= 13) {
                String  devName = line[3 - 1];
                String  sectorsRead = line[6 - 1];
                String  timeSpentReadingMS = line[7 - 1];
                String  sectorsWritten = line[10 - 1];
                String  timeSpentWritingMS = line[11 - 1];
                result.Add (
                    devName,
                    PerfStats_ { String2Float (sectorsRead), String2Float (timeSpentReadingMS) / 1000,  String2Float (sectorsWritten),  String2Float (timeSpentWritingMS) / 1000 }
                );
            }
        }
        return result;
    }
}
#endif

namespace {
    Sequence<VolumeInfo> capture_ ()
    {
        Sequence<VolumeInfo>   results;
#if     qPlatform_Windows
        results = capture_Windows_GetVolumeInfo_ ();
#elif   qPlatform_POSIX
        results = capture_Process_Run_DF_ ();
        try {
            Mapping<String, PerfStats_> diskStats = capture_ProcFSDiskStats_ ();
            Sequence<VolumeInfo>    newV;
            for (VolumneInfo v : results) {
                if (v.fDeviceOrVolumeName.IsPresent ()) {
                    String  devNameLessSlashes = *v.fDeviceOrVolumeName;
                    size_t i = d.RFind ('/');
                    if (i != string::npos) {
                        devNameLessSlashes = devNameLessSlashes.SubString (i + 1);
                    }
                    Optional<PerfStats_>    o = diskStats.Lookup (devNameLessSlashes);
                    if (o.IsPresent ()) {
                        v.fReadIOStats.fBytes = a;
                        v.fReadIOStats.fTimeTransfering = a;
                        v.fWriteIOStats.fBytes = a;
                        v.fWriteIOStats.fTimeTransfering = fTimeTransfering;

                        v.fIOStats.fBytes = v.fReadIOStats.fBytes + v.fWriteIOStats.fBytes;
                        v.fIOStats.fTimeTransfering = v.fReadIOStats.fTimeTransfering + v.fWriteIOStats.fTimeTransfering;
                    }
                }
                newV.Append (v);
            }
            results = newV;
        }
        catch (...) {
        }
#endif
        return results;
    }
}

/*
 ********************************************************************************
 ********** Instruments::MountedFilesystemUsage::GetObjectVariantMapper *********
 ********************************************************************************
 */
ObjectVariantMapper Instruments::MountedFilesystemUsage::GetObjectVariantMapper ()
{
    using   StructureFieldInfo = ObjectVariantMapper::StructureFieldInfo;
    ObjectVariantMapper sMapper_ = [] () -> ObjectVariantMapper {
        ObjectVariantMapper mapper;
        mapper.AddCommonType<Optional<double>> ();
        mapper.AddCommonType<Optional<String>> ();
        DISABLE_COMPILER_CLANG_WARNING_START("clang diagnostic ignored \"-Winvalid-offsetof\"");   // Really probably an issue, but not to debug here -- LGP 2014-01-04
        DISABLE_COMPILER_GCC_WARNING_START("GCC diagnostic ignored \"-Winvalid-offsetof\"");       // Really probably an issue, but not to debug here -- LGP 2014-01-04
        mapper.AddClass<VolumeInfo::IOStats> (initializer_list<StructureFieldInfo> {
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo::IOStats, fBytes), String_Constant (L"Bytes"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo::IOStats, fTimeTransfering), String_Constant (L"Time-Transfering"), StructureFieldInfo::NullFieldHandling::eOmit },
        });
        mapper.AddClass<VolumeInfo> (initializer_list<StructureFieldInfo> {
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fFileSystemType), String_Constant (L"Filesystem-Type"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fDeviceOrVolumeName), String_Constant (L"Device-Name"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fVolumeID), String_Constant (L"Volume-ID"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fMountedOnName), String_Constant (L"Mounted-On") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fDiskSizeInBytes), String_Constant (L"Disk-Size"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fUsedSizeInBytes), String_Constant (L"Disk-Used-Size"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fReadIOStats), String_Constant (L"fReadIOStats") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fWriteIOStats), String_Constant (L"fWriteIOStats") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fIOStats), String_Constant (L"fIOStats") },
        });
        DISABLE_COMPILER_GCC_WARNING_END("GCC diagnostic ignored \"-Winvalid-offsetof\"");
        DISABLE_COMPILER_CLANG_WARNING_END("clang diagnostic ignored \"-Winvalid-offsetof\"");
        mapper.AddCommonType<Collection<VolumeInfo>> ();
        mapper.AddCommonType<Sequence<VolumeInfo>> ();
        return mapper;
    } ();
    return sMapper_;
}

/*
 ********************************************************************************
 ************* Instruments::MountedFilesystemUsage::GetInstrument ***************
 ********************************************************************************
 */
Instrument  SystemPerformance::Instruments::MountedFilesystemUsage::GetInstrument ()
{
    static  Instrument  kInstrument_    = Instrument (
            InstrumentNameType (String_Constant (L"Mounted-Filesystem-Usage")),
    [] () -> MeasurementSet {
        MeasurementSet    results;
        DateTime    before = DateTime::Now ();
        Sequence<VolumeInfo> volumes   =   capture_ ();
        results.fMeasuredAt = DateTimeRange (before, DateTime::Now ());
        Measurement m;
        m.fValue = MountedFilesystemUsage::GetObjectVariantMapper ().FromObject (volumes);
        m.fType = kMountedVolumeUsage;
        results.fMeasurements.Add (m);
        return results;
    },
    {kMountedVolumeUsage},
    GetObjectVariantMapper ()
                                          );
    return kInstrument_;
}

Instrument  SystemPerformance::Instruments::GetMountedFilesystemUsage ()
{
    return MountedFilesystemUsage::GetInstrument ();
}
<commit_msg>posix mounted filesystem usage iostats fixes<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2014.  All rights reserved
 */
#include    "../../StroikaPreComp.h"

#if     qPlatform_Windows
#include    <Windows.h>
#endif

#include    "../../../Foundation/Characters/CString/Utilities.h"
#include    "../../../Foundation/Characters/String_Constant.h"
#include    "../../../Foundation/Characters/String2Float.h"
#include    "../../../Foundation/Containers/Sequence.h"
#include    "../../../Foundation/DataExchange/CharacterDelimitedLines/Reader.h"
#include    "../../../Foundation/Debug/Assertions.h"
#include    "../../../Foundation/Execution/ProcessRunner.h"
#include    "../../../Foundation/IO/FileSystem/BinaryFileInputStream.h"
#include    "../../../Foundation/Streams/BasicBinaryInputOutputStream.h"
#include    "../../../Foundation/Streams/TextInputStreamBinaryAdapter.h"

#include    "../CommonMeasurementTypes.h"

#include    "MountedFilesystemUsage.h"

using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Containers;
using   namespace   Stroika::Foundation::DataExchange;
using   namespace   Stroika::Foundation::Execution;
using   namespace   Stroika::Foundation::Memory;

using   namespace   Stroika::Frameworks;
using   namespace   Stroika::Frameworks::SystemPerformance;
using   namespace   Stroika::Frameworks::SystemPerformance::Instruments::MountedFilesystemUsage;

using   Characters::String_Constant;

#if     qPlatform_Windows
namespace {
    Sequence<VolumeInfo> capture_Windows_GetVolumeInfo_ ()
    {
        Sequence<VolumeInfo>   result;
        TCHAR volumeNameBuf[1024];
        for (HANDLE hVol = FindFirstVolume (volumeNameBuf, NEltsOf(volumeNameBuf)); hVol != INVALID_HANDLE_VALUE; ) {
            DWORD lpMaximumComponentLength;
            DWORD dwSysFlags;
            TCHAR FileSysNameBuf[1024];
            if (::GetVolumeInformation( volumeNameBuf, NULL, NEltsOf(volumeNameBuf), NULL, &lpMaximumComponentLength, &dwSysFlags, FileSysNameBuf, NEltsOf(FileSysNameBuf))) {
                VolumeInfo v;
                v.fFileSystemType = String::FromSDKString (FileSysNameBuf);
                v.fVolumeID = String::FromSDKString (volumeNameBuf);
                {
                    // @todo - use
                    //      http://msdn.microsoft.com/en-us/library/windows/desktop/cc542456(v=vs.85).aspx
                    //      CharCount = QueryDosDeviceW(&VolumeName[4], DeviceName, ARRAYSIZE(DeviceName));
                    //      to get DEVICENAME
                    //
                    TCHAR volPathsBuf[1024];
                    DWORD retLen = 0;
                    DWORD x = GetVolumePathNamesForVolumeName (volumeNameBuf, volPathsBuf, NEltsOf(volPathsBuf), &retLen);
                    if (volPathsBuf[0] == 0) {
                        v.fMountedOnName.clear ();
                        result.push_back (v);
                    }
                    else {
                        for (const TCHAR* NameIdx = volPathsBuf; NameIdx[0] != L'\0'; NameIdx += Characters::CString::Length (NameIdx) + 1) {
                            v.fMountedOnName = String::FromSDKString (NameIdx);
                            {
                                ULARGE_INTEGER freeBytesAvailable;
                                ULARGE_INTEGER totalNumberOfBytes;
                                ULARGE_INTEGER totalNumberOfFreeBytes;
                                memset (&freeBytesAvailable, 0, sizeof (freeBytesAvailable));
                                memset (&totalNumberOfBytes, 0, sizeof (totalNumberOfBytes));
                                memset (&totalNumberOfFreeBytes, 0, sizeof (totalNumberOfFreeBytes));
                                DWORD xxx = GetDiskFreeSpaceEx (v.fMountedOnName.AsSDKString ().c_str (), &freeBytesAvailable, &totalNumberOfBytes, &totalNumberOfFreeBytes);
                                v.fDiskSizeInBytes = static_cast<double> (totalNumberOfBytes.QuadPart);
                                v.fUsedSizeInBytes = *v.fDiskSizeInBytes  - freeBytesAvailable.QuadPart;
                            }
                            result.push_back (v);
                        }
                    }
                }
            }
            else {
                // warning...
            }

            // find next
            if (not ::FindNextVolume (hVol, volumeNameBuf, NEltsOf(volumeNameBuf))) {
                FindVolumeClose (hVol);
                hVol = INVALID_HANDLE_VALUE;
            }
        }
        return result;
    }
}
#endif

#if     qPlatform_POSIX
namespace {
    Sequence<VolumeInfo> capture_Process_Run_DF_ ()
    {
        Sequence<VolumeInfo>   result;
        //
        // I looked through the /proc filesystem stuff and didnt see anything obvious to retrive this info...
        // run def with ProcessRunner
        //
        //  NEW NOTE - I THINK ITS IN THERE.... RE-EXAMINE proc/filesystems proc/partitions, and http://en.wikipedia.org/wiki/Procfs
        //      -- LGP 2014-08-01
        ProcessRunner pr (L"/bin/df -k -T");
        Streams::BasicBinaryInputOutputStream   useStdOut;
        pr.SetStdOut (useStdOut);
        pr.Run ();
        String out;
        Streams::TextInputStreamBinaryAdapter   stdOut  =   Streams::TextInputStreamBinaryAdapter (useStdOut);
        bool skippedHeader = false;
        for (String i = stdOut.ReadLine (); not i.empty (); i = stdOut.ReadLine ()) {
            if (not skippedHeader) {
                skippedHeader = true;
                continue;
            }
            Sequence<String>    l    =  i.Tokenize (Set<Characters::Character> { ' ' });
            if (l.size () < 7) {
                DbgTrace ("skipping line cuz len=%d", l.size ());
                continue;
            }
            VolumeInfo v;
            v.fFileSystemType = l[1].Trim ();
            v.fMountedOnName = l[6].Trim ();
            {
                String  d   =   l[0].Trim ();
                if (not d.empty () and d != L"none") {
                    v.fDeviceOrVolumeName = d;
                }
            }
            v.fDiskSizeInBytes = Characters::String2Float<double> (l[2]) * 1024;
            v.fUsedSizeInBytes = Characters::String2Float<double> (l[3]) * 1024;
            result.Append (v);
        }
        return result;
    }
}
#endif

#if     qPlatform_POSIX
namespace {
    struct PerfStats_ {
        double  fSectorsRead;
        double  fTimeSpentReading;
        double  fSectorsWritten;
        double  fTimeSpentWritingMS;
    };
    Mapping<String, PerfStats_> capture_ProcFSDiskStats_ ()
    {
        using   IO::FileSystem::BinaryFileInputStream;
        using   Characters::String2Float;
        Mapping<String, PerfStats_>   result;
        DataExchange::CharacterDelimitedLines::Reader reader {{' ', '\t' }};
        const   String_Constant kProcMemInfoFileName_ { L"/proc/diskstats" };
        // Note - /procfs files always unseekable
        for (Sequence<String> line : reader.ReadMatrix (BinaryFileInputStream::mk (kProcMemInfoFileName_, BinaryFileInputStream::eNotSeekable))) {
#if     USE_NOISY_TRACE_IN_THIS_MODULE_
            DbgTrace (L"***in Instruments::MountedFilesystemUsage::capture_ProcFSDiskStats_ linesize=%d, line[0]=%s", line.size(), line.empty () ? L"" : line[0].c_str ());
#endif
            //
            // https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
            //
            //  3 - device name
            //  6 - sectors read
            //  7 - time spent reading (ms)
            //  10 - sectors written
            //  11 - time spent writing (ms)
            //
            if (line.size () >= 13) {
                String  devName = line[3 - 1];
                String  sectorsRead = line[6 - 1];
                String  timeSpentReadingMS = line[7 - 1];
                String  sectorsWritten = line[10 - 1];
                String  timeSpentWritingMS = line[11 - 1];
                result.Add (
                    devName,
                    PerfStats_ { String2Float (sectorsRead), String2Float (timeSpentReadingMS) / 1000,  String2Float (sectorsWritten),  String2Float (timeSpentWritingMS) / 1000 }
                );
            }
        }
        return result;
    }
}
#endif

namespace {
    Sequence<VolumeInfo> capture_ ()
    {
        Sequence<VolumeInfo>   results;
#if     qPlatform_Windows
        results = capture_Windows_GetVolumeInfo_ ();
#elif   qPlatform_POSIX
        results = capture_Process_Run_DF_ ();
        try {
            Mapping<String, PerfStats_> diskStats = capture_ProcFSDiskStats_ ();
            Sequence<VolumeInfo>    newV;
            for (VolumneInfo v : results) {
                if (v.fDeviceOrVolumeName.IsPresent ()) {
                    String  devNameLessSlashes = *v.fDeviceOrVolumeName;
                    size_t i = devNameLessSlashes.RFind ('/');
                    if (i != string::npos) {
                        devNameLessSlashes = devNameLessSlashes.SubString (i + 1);
                    }
                    Optional<PerfStats_>    o = diskStats.Lookup (devNameLessSlashes);
                    if (o.IsPresent ()) {
                        const unsigned int kSectorSizeTmpHack_ = 4 * 1024;  // @todo GET from disk stats
                        v.fReadIOStats.fBytes = o->fSectorsRead * kSectorSizeTmpHack_;
                        v.fReadIOStats.fTimeTransfering = o->fTimeSpentReading;
                        v.fWriteIOStats.fBytes = o->fSectorsWritten * kSectorSizeTmpHack_;
                        v.fWriteIOStats.fTimeTransfering = o->fTimeSpentReading;

                        v.fIOStats.fBytes = v.fReadIOStats.fBytes + v.fWriteIOStats.fBytes;
                        v.fIOStats.fTimeTransfering = v.fReadIOStats.fTimeTransfering + v.fWriteIOStats.fTimeTransfering;
                    }
                }
                newV.Append (v);
            }
            results = newV;
        }
        catch (...) {
        }
#endif
        return results;
    }
}

/*
 ********************************************************************************
 ********** Instruments::MountedFilesystemUsage::GetObjectVariantMapper *********
 ********************************************************************************
 */
ObjectVariantMapper Instruments::MountedFilesystemUsage::GetObjectVariantMapper ()
{
    using   StructureFieldInfo = ObjectVariantMapper::StructureFieldInfo;
    ObjectVariantMapper sMapper_ = [] () -> ObjectVariantMapper {
        ObjectVariantMapper mapper;
        mapper.AddCommonType<Optional<double>> ();
        mapper.AddCommonType<Optional<String>> ();
        DISABLE_COMPILER_CLANG_WARNING_START("clang diagnostic ignored \"-Winvalid-offsetof\"");   // Really probably an issue, but not to debug here -- LGP 2014-01-04
        DISABLE_COMPILER_GCC_WARNING_START("GCC diagnostic ignored \"-Winvalid-offsetof\"");       // Really probably an issue, but not to debug here -- LGP 2014-01-04
        mapper.AddClass<VolumeInfo::IOStats> (initializer_list<StructureFieldInfo> {
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo::IOStats, fBytes), String_Constant (L"Bytes"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo::IOStats, fTimeTransfering), String_Constant (L"Time-Transfering"), StructureFieldInfo::NullFieldHandling::eOmit },
        });
        mapper.AddClass<VolumeInfo> (initializer_list<StructureFieldInfo> {
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fFileSystemType), String_Constant (L"Filesystem-Type"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fDeviceOrVolumeName), String_Constant (L"Device-Name"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fVolumeID), String_Constant (L"Volume-ID"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fMountedOnName), String_Constant (L"Mounted-On") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fDiskSizeInBytes), String_Constant (L"Disk-Size"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fUsedSizeInBytes), String_Constant (L"Disk-Used-Size"), StructureFieldInfo::NullFieldHandling::eOmit },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fReadIOStats), String_Constant (L"fReadIOStats") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fWriteIOStats), String_Constant (L"fWriteIOStats") },
            { Stroika_Foundation_DataExchange_ObjectVariantMapper_FieldInfoKey (VolumeInfo, fIOStats), String_Constant (L"fIOStats") },
        });
        DISABLE_COMPILER_GCC_WARNING_END("GCC diagnostic ignored \"-Winvalid-offsetof\"");
        DISABLE_COMPILER_CLANG_WARNING_END("clang diagnostic ignored \"-Winvalid-offsetof\"");
        mapper.AddCommonType<Collection<VolumeInfo>> ();
        mapper.AddCommonType<Sequence<VolumeInfo>> ();
        return mapper;
    } ();
    return sMapper_;
}

/*
 ********************************************************************************
 ************* Instruments::MountedFilesystemUsage::GetInstrument ***************
 ********************************************************************************
 */
Instrument  SystemPerformance::Instruments::MountedFilesystemUsage::GetInstrument ()
{
    static  Instrument  kInstrument_    = Instrument (
            InstrumentNameType (String_Constant (L"Mounted-Filesystem-Usage")),
    [] () -> MeasurementSet {
        MeasurementSet    results;
        DateTime    before = DateTime::Now ();
        Sequence<VolumeInfo> volumes   =   capture_ ();
        results.fMeasuredAt = DateTimeRange (before, DateTime::Now ());
        Measurement m;
        m.fValue = MountedFilesystemUsage::GetObjectVariantMapper ().FromObject (volumes);
        m.fType = kMountedVolumeUsage;
        results.fMeasurements.Add (m);
        return results;
    },
    {kMountedVolumeUsage},
    GetObjectVariantMapper ()
                                          );
    return kInstrument_;
}

Instrument  SystemPerformance::Instruments::GetMountedFilesystemUsage ()
{
    return MountedFilesystemUsage::GetInstrument ();
}
<|endoftext|>


<commit_before>//===-- SchedInfo.cpp - Generic code to support target schedulers ----------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the generic part of a Scheduler description for a
// target.  This functionality is defined in the llvm/Target/SchedInfo.h file.
//
//===----------------------------------------------------------------------===//

#include "llvm/Config/alloca.h"
#include "llvm/Target/TargetSchedInfo.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <iostream>
using namespace llvm;

resourceId_t llvm::CPUResource::nextId = 0;
static std::vector<CPUResource*> *CPUResourceMap = 0;

CPUResource::CPUResource(const std::string& resourceName, int maxUsers)
    : rname(resourceName), rid(nextId++), maxNumUsers(maxUsers) {
  if(!CPUResourceMap)
    CPUResourceMap = new std::vector<CPUResource*>;

  //Put Resource in the map
  CPUResourceMap->push_back(this);
}

///Get CPUResource if you only have the resource ID
CPUResource* CPUResource::getCPUResource(resourceId_t id) {
  return (*CPUResourceMap)[id];
}

// Check if fromRVec and toRVec have *any* common entries.
// Assume the vectors are sorted in increasing order.
// Algorithm copied from function set_intersection() for sorted ranges
// (stl_algo.h).
//
inline static bool
RUConflict(const std::vector<resourceId_t>& fromRVec,
	   const std::vector<resourceId_t>& toRVec)
{

  unsigned fN = fromRVec.size(), tN = toRVec.size();
  unsigned fi = 0, ti = 0;

  while (fi < fN && ti < tN) {
    if (fromRVec[fi] < toRVec[ti])
      ++fi;
    else if (toRVec[ti] < fromRVec[fi])
      ++ti;
    else
      return true;
  }
  return false;
}

static cycles_t
ComputeMinGap(const InstrRUsage &fromRU,
	      const InstrRUsage &toRU)
{
  cycles_t minGap = 0;

  if (fromRU.numBubbles > 0)
    minGap = fromRU.numBubbles;

  if (minGap < fromRU.numCycles) {
    // only need to check from cycle `minGap' onwards
    for (cycles_t gap=minGap; gap <= fromRU.numCycles-1; gap++) {
      // check if instr. #2 can start executing `gap' cycles after #1
      // by checking for resource conflicts in each overlapping cycle
      cycles_t numOverlap =std::min(fromRU.numCycles - gap, toRU.numCycles);
      for (cycles_t c = 0; c <= numOverlap-1; c++)
        if (RUConflict(fromRU.resourcesByCycle[gap + c],
                       toRU.resourcesByCycle[c])) {
          // conflict found so minGap must be more than `gap'
          minGap = gap+1;
          break;
        }
    }
  }

  return minGap;
}

//---------------------------------------------------------------------------
// class TargetSchedInfo
//	Interface to machine description for instruction scheduling
//---------------------------------------------------------------------------

TargetSchedInfo::TargetSchedInfo(const TargetMachine&    tgt,
                                 int                     NumSchedClasses,
                                 const InstrClassRUsage* ClassRUsages,
                                 const InstrRUsageDelta* UsageDeltas,
                                 const InstrIssueDelta*  IssueDeltas,
                                 unsigned NumUsageDeltas,
                                 unsigned NumIssueDeltas)
  : target(tgt),
    numSchedClasses(NumSchedClasses), mii(tgt.getInstrInfo()),
    classRUsages(ClassRUsages), usageDeltas(UsageDeltas),
    issueDeltas(IssueDeltas), numUsageDeltas(NumUsageDeltas),
    numIssueDeltas(NumIssueDeltas)
{}

void
TargetSchedInfo::initializeResources()
{
  assert(MAX_NUM_SLOTS >= (int)getMaxNumIssueTotal()
	 && "Insufficient slots for static data! Increase MAX_NUM_SLOTS");

  // First, compute common resource usage info for each class because
  // most instructions will probably behave the same as their class.
  // Cannot allocate a vector of InstrRUsage so new each one.
  //
  std::vector<InstrRUsage> instrRUForClasses;
  instrRUForClasses.resize(numSchedClasses);
  for (InstrSchedClass sc = 0; sc < numSchedClasses; sc++) {
    // instrRUForClasses.push_back(new InstrRUsage);
    instrRUForClasses[sc].setMaxSlots(getMaxNumIssueTotal());
    instrRUForClasses[sc].setTo(classRUsages[sc]);
  }

  computeInstrResources(instrRUForClasses);
  computeIssueGaps(instrRUForClasses);
}

void
TargetSchedInfo::computeInstrResources(const std::vector<InstrRUsage>&
					instrRUForClasses)
{
  int numOpCodes =  mii->getNumOpcodes();
  instrRUsages.resize(numOpCodes);

  // First get the resource usage information from the class resource usages.
  for (MachineOpCode op = 0; op < numOpCodes; ++op) {
    InstrSchedClass sc = getSchedClass(op);
    assert(sc < numSchedClasses);
    instrRUsages[op] = instrRUForClasses[sc];
  }

  // Now, modify the resource usages as specified in the deltas.
  for (unsigned i = 0; i < numUsageDeltas; ++i) {
    MachineOpCode op = usageDeltas[i].opCode;
    assert(op < numOpCodes);
    instrRUsages[op].addUsageDelta(usageDeltas[i]);
  }

  // Then modify the issue restrictions as specified in the deltas.
  for (unsigned i = 0; i < numIssueDeltas; ++i) {
    MachineOpCode op = issueDeltas[i].opCode;
    assert(op < numOpCodes);
    instrRUsages[issueDeltas[i].opCode].addIssueDelta(issueDeltas[i]);
  }
}

void
TargetSchedInfo::computeIssueGaps(const std::vector<InstrRUsage>&
				   instrRUForClasses)
{
  int numOpCodes =  mii->getNumOpcodes();
  issueGaps.resize(numOpCodes);
  conflictLists.resize(numOpCodes);

  assert(numOpCodes < (1 << MAX_OPCODE_SIZE) - 1
         && "numOpCodes invalid for implementation of class OpCodePair!");

  // First, compute issue gaps between pairs of classes based on common
  // resources usages for each class, because most instruction pairs will
  // usually behave the same as their class.
  //
  int* classPairGaps =
    static_cast<int*>(alloca(sizeof(int) * numSchedClasses * numSchedClasses));
  for (InstrSchedClass fromSC=0; fromSC < numSchedClasses; fromSC++)
    for (InstrSchedClass toSC=0; toSC < numSchedClasses; toSC++) {
      int classPairGap = ComputeMinGap(instrRUForClasses[fromSC],
                                       instrRUForClasses[toSC]);
      classPairGaps[fromSC*numSchedClasses + toSC] = classPairGap;
    }

  // Now, for each pair of instructions, use the class pair gap if both
  // instructions have identical resource usage as their respective classes.
  // If not, recompute the gap for the pair from scratch.

  longestIssueConflict = 0;

  for (MachineOpCode fromOp=0; fromOp < numOpCodes; fromOp++)
    for (MachineOpCode toOp=0; toOp < numOpCodes; toOp++) {
      int instrPairGap =
        (instrRUsages[fromOp].sameAsClass && instrRUsages[toOp].sameAsClass)
        ? classPairGaps[getSchedClass(fromOp)*numSchedClasses + getSchedClass(toOp)]
        : ComputeMinGap(instrRUsages[fromOp], instrRUsages[toOp]);

      if (instrPairGap > 0) {
        this->setGap(instrPairGap, fromOp, toOp);
        conflictLists[fromOp].push_back(toOp);
        longestIssueConflict=std::max(longestIssueConflict, instrPairGap);
      }
    }
}

void InstrRUsage::setTo(const InstrClassRUsage& classRU) {
  sameAsClass	= true;
  isSingleIssue = classRU.isSingleIssue;
  breaksGroup   = classRU.breaksGroup;
  numBubbles    = classRU.numBubbles;

  for (unsigned i=0; i < classRU.numSlots; i++) {
    unsigned slot = classRU.feasibleSlots[i];
    assert(slot < feasibleSlots.size() && "Invalid slot specified!");
    this->feasibleSlots[slot] = true;
  }

  numCycles   = classRU.totCycles;
  resourcesByCycle.resize(this->numCycles);

  for (unsigned i=0; i < classRU.numRUEntries; i++)
    for (unsigned c=classRU.V[i].startCycle, NC = c + classRU.V[i].numCycles;
	 c < NC; c++)
      this->resourcesByCycle[c].push_back(classRU.V[i].resourceId);

  // Sort each resource usage vector by resourceId_t to speed up conflict
  // checking
  for (unsigned i=0; i < this->resourcesByCycle.size(); i++)
    std::sort(resourcesByCycle[i].begin(), resourcesByCycle[i].end());
}

// Add the extra resource usage requirements specified in the delta.
// Note that a negative value of `numCycles' means one entry for that
// resource should be deleted for each cycle.
//
void InstrRUsage::addUsageDelta(const InstrRUsageDelta &delta) {
  int NC = delta.numCycles;
  sameAsClass = false;

  // resize the resources vector if more cycles are specified
  unsigned maxCycles = this->numCycles;
  maxCycles = std::max(maxCycles, delta.startCycle + abs(NC) - 1);
  if (maxCycles > this->numCycles) {
    this->resourcesByCycle.resize(maxCycles);
    this->numCycles = maxCycles;
  }

  if (NC >= 0)
    for (unsigned c=delta.startCycle, last=c+NC-1; c <= last; c++)
      this->resourcesByCycle[c].push_back(delta.resourceId);
  else
    // Remove the resource from all NC cycles.
    for (unsigned c=delta.startCycle, last=(c-NC)-1; c <= last; c++) {
      // Look for the resource backwards so we remove the last entry
      // for that resource in each cycle.
      std::vector<resourceId_t>& rvec = this->resourcesByCycle[c];
      int r;
      for (r = rvec.size() - 1; r >= 0; r--)
        if (rvec[r] == delta.resourceId) {
          // found last entry for the resource
          rvec.erase(rvec.begin() + r);
          break;
        }
      assert(r >= 0 && "Resource to remove was unused in cycle c!");
    }
}
<commit_msg>Remove dead assert<commit_after>//===-- SchedInfo.cpp - Generic code to support target schedulers ----------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the generic part of a Scheduler description for a
// target.  This functionality is defined in the llvm/Target/SchedInfo.h file.
//
//===----------------------------------------------------------------------===//

#include "llvm/Config/alloca.h"
#include "llvm/Target/TargetSchedInfo.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <iostream>
using namespace llvm;

resourceId_t llvm::CPUResource::nextId = 0;
static std::vector<CPUResource*> *CPUResourceMap = 0;

CPUResource::CPUResource(const std::string& resourceName, int maxUsers)
    : rname(resourceName), rid(nextId++), maxNumUsers(maxUsers) {
  if(!CPUResourceMap)
    CPUResourceMap = new std::vector<CPUResource*>;

  //Put Resource in the map
  CPUResourceMap->push_back(this);
}

///Get CPUResource if you only have the resource ID
CPUResource* CPUResource::getCPUResource(resourceId_t id) {
  return (*CPUResourceMap)[id];
}

// Check if fromRVec and toRVec have *any* common entries.
// Assume the vectors are sorted in increasing order.
// Algorithm copied from function set_intersection() for sorted ranges
// (stl_algo.h).
//
inline static bool
RUConflict(const std::vector<resourceId_t>& fromRVec,
	   const std::vector<resourceId_t>& toRVec)
{

  unsigned fN = fromRVec.size(), tN = toRVec.size();
  unsigned fi = 0, ti = 0;

  while (fi < fN && ti < tN) {
    if (fromRVec[fi] < toRVec[ti])
      ++fi;
    else if (toRVec[ti] < fromRVec[fi])
      ++ti;
    else
      return true;
  }
  return false;
}

static cycles_t
ComputeMinGap(const InstrRUsage &fromRU,
	      const InstrRUsage &toRU)
{
  cycles_t minGap = 0;

  if (fromRU.numBubbles > 0)
    minGap = fromRU.numBubbles;

  if (minGap < fromRU.numCycles) {
    // only need to check from cycle `minGap' onwards
    for (cycles_t gap=minGap; gap <= fromRU.numCycles-1; gap++) {
      // check if instr. #2 can start executing `gap' cycles after #1
      // by checking for resource conflicts in each overlapping cycle
      cycles_t numOverlap =std::min(fromRU.numCycles - gap, toRU.numCycles);
      for (cycles_t c = 0; c <= numOverlap-1; c++)
        if (RUConflict(fromRU.resourcesByCycle[gap + c],
                       toRU.resourcesByCycle[c])) {
          // conflict found so minGap must be more than `gap'
          minGap = gap+1;
          break;
        }
    }
  }

  return minGap;
}

//---------------------------------------------------------------------------
// class TargetSchedInfo
//	Interface to machine description for instruction scheduling
//---------------------------------------------------------------------------

TargetSchedInfo::TargetSchedInfo(const TargetMachine&    tgt,
                                 int                     NumSchedClasses,
                                 const InstrClassRUsage* ClassRUsages,
                                 const InstrRUsageDelta* UsageDeltas,
                                 const InstrIssueDelta*  IssueDeltas,
                                 unsigned NumUsageDeltas,
                                 unsigned NumIssueDeltas)
  : target(tgt),
    numSchedClasses(NumSchedClasses), mii(tgt.getInstrInfo()),
    classRUsages(ClassRUsages), usageDeltas(UsageDeltas),
    issueDeltas(IssueDeltas), numUsageDeltas(NumUsageDeltas),
    numIssueDeltas(NumIssueDeltas)
{}

void
TargetSchedInfo::initializeResources()
{
  assert(MAX_NUM_SLOTS >= (int)getMaxNumIssueTotal()
	 && "Insufficient slots for static data! Increase MAX_NUM_SLOTS");

  // First, compute common resource usage info for each class because
  // most instructions will probably behave the same as their class.
  // Cannot allocate a vector of InstrRUsage so new each one.
  //
  std::vector<InstrRUsage> instrRUForClasses;
  instrRUForClasses.resize(numSchedClasses);
  for (InstrSchedClass sc = 0; sc < numSchedClasses; sc++) {
    // instrRUForClasses.push_back(new InstrRUsage);
    instrRUForClasses[sc].setMaxSlots(getMaxNumIssueTotal());
    instrRUForClasses[sc].setTo(classRUsages[sc]);
  }

  computeInstrResources(instrRUForClasses);
  computeIssueGaps(instrRUForClasses);
}

void
TargetSchedInfo::computeInstrResources(const std::vector<InstrRUsage>&
					instrRUForClasses)
{
  int numOpCodes =  mii->getNumOpcodes();
  instrRUsages.resize(numOpCodes);

  // First get the resource usage information from the class resource usages.
  for (MachineOpCode op = 0; op < numOpCodes; ++op) {
    InstrSchedClass sc = getSchedClass(op);
    assert(sc < numSchedClasses);
    instrRUsages[op] = instrRUForClasses[sc];
  }

  // Now, modify the resource usages as specified in the deltas.
  for (unsigned i = 0; i < numUsageDeltas; ++i) {
    MachineOpCode op = usageDeltas[i].opCode;
    assert(op < numOpCodes);
    instrRUsages[op].addUsageDelta(usageDeltas[i]);
  }

  // Then modify the issue restrictions as specified in the deltas.
  for (unsigned i = 0; i < numIssueDeltas; ++i) {
    MachineOpCode op = issueDeltas[i].opCode;
    assert(op < numOpCodes);
    instrRUsages[issueDeltas[i].opCode].addIssueDelta(issueDeltas[i]);
  }
}

void
TargetSchedInfo::computeIssueGaps(const std::vector<InstrRUsage>&
				   instrRUForClasses)
{
  int numOpCodes =  mii->getNumOpcodes();
  issueGaps.resize(numOpCodes);
  conflictLists.resize(numOpCodes);

  // First, compute issue gaps between pairs of classes based on common
  // resources usages for each class, because most instruction pairs will
  // usually behave the same as their class.
  //
  int* classPairGaps =
    static_cast<int*>(alloca(sizeof(int) * numSchedClasses * numSchedClasses));
  for (InstrSchedClass fromSC=0; fromSC < numSchedClasses; fromSC++)
    for (InstrSchedClass toSC=0; toSC < numSchedClasses; toSC++) {
      int classPairGap = ComputeMinGap(instrRUForClasses[fromSC],
                                       instrRUForClasses[toSC]);
      classPairGaps[fromSC*numSchedClasses + toSC] = classPairGap;
    }

  // Now, for each pair of instructions, use the class pair gap if both
  // instructions have identical resource usage as their respective classes.
  // If not, recompute the gap for the pair from scratch.

  longestIssueConflict = 0;

  for (MachineOpCode fromOp=0; fromOp < numOpCodes; fromOp++)
    for (MachineOpCode toOp=0; toOp < numOpCodes; toOp++) {
      int instrPairGap =
        (instrRUsages[fromOp].sameAsClass && instrRUsages[toOp].sameAsClass)
        ? classPairGaps[getSchedClass(fromOp)*numSchedClasses + getSchedClass(toOp)]
        : ComputeMinGap(instrRUsages[fromOp], instrRUsages[toOp]);

      if (instrPairGap > 0) {
        this->setGap(instrPairGap, fromOp, toOp);
        conflictLists[fromOp].push_back(toOp);
        longestIssueConflict=std::max(longestIssueConflict, instrPairGap);
      }
    }
}

void InstrRUsage::setTo(const InstrClassRUsage& classRU) {
  sameAsClass	= true;
  isSingleIssue = classRU.isSingleIssue;
  breaksGroup   = classRU.breaksGroup;
  numBubbles    = classRU.numBubbles;

  for (unsigned i=0; i < classRU.numSlots; i++) {
    unsigned slot = classRU.feasibleSlots[i];
    assert(slot < feasibleSlots.size() && "Invalid slot specified!");
    this->feasibleSlots[slot] = true;
  }

  numCycles   = classRU.totCycles;
  resourcesByCycle.resize(this->numCycles);

  for (unsigned i=0; i < classRU.numRUEntries; i++)
    for (unsigned c=classRU.V[i].startCycle, NC = c + classRU.V[i].numCycles;
	 c < NC; c++)
      this->resourcesByCycle[c].push_back(classRU.V[i].resourceId);

  // Sort each resource usage vector by resourceId_t to speed up conflict
  // checking
  for (unsigned i=0; i < this->resourcesByCycle.size(); i++)
    std::sort(resourcesByCycle[i].begin(), resourcesByCycle[i].end());
}

// Add the extra resource usage requirements specified in the delta.
// Note that a negative value of `numCycles' means one entry for that
// resource should be deleted for each cycle.
//
void InstrRUsage::addUsageDelta(const InstrRUsageDelta &delta) {
  int NC = delta.numCycles;
  sameAsClass = false;

  // resize the resources vector if more cycles are specified
  unsigned maxCycles = this->numCycles;
  maxCycles = std::max(maxCycles, delta.startCycle + abs(NC) - 1);
  if (maxCycles > this->numCycles) {
    this->resourcesByCycle.resize(maxCycles);
    this->numCycles = maxCycles;
  }

  if (NC >= 0)
    for (unsigned c=delta.startCycle, last=c+NC-1; c <= last; c++)
      this->resourcesByCycle[c].push_back(delta.resourceId);
  else
    // Remove the resource from all NC cycles.
    for (unsigned c=delta.startCycle, last=(c-NC)-1; c <= last; c++) {
      // Look for the resource backwards so we remove the last entry
      // for that resource in each cycle.
      std::vector<resourceId_t>& rvec = this->resourcesByCycle[c];
      int r;
      for (r = rvec.size() - 1; r >= 0; r--)
        if (rvec[r] == delta.resourceId) {
          // found last entry for the resource
          rvec.erase(rvec.begin() + r);
          break;
        }
      assert(r >= 0 && "Resource to remove was unused in cycle c!");
    }
}
<|endoftext|>


<commit_before>//===-- LiveRegMatrix.cpp - Track register interference -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LiveRegMatrix analysis pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "regalloc"
#include "llvm/CodeGen/LiveRegMatrix.h"
#include "RegisterCoalescer.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"

using namespace llvm;

STATISTIC(NumAssigned   , "Number of registers assigned");
STATISTIC(NumUnassigned , "Number of registers unassigned");

char LiveRegMatrix::ID = 0;
INITIALIZE_PASS_BEGIN(LiveRegMatrix, "liveregmatrix",
                      "Live Register Matrix", false, false)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
INITIALIZE_PASS_DEPENDENCY(VirtRegMap)
INITIALIZE_PASS_END(LiveRegMatrix, "liveregmatrix",
                    "Live Register Matrix", false, false)

LiveRegMatrix::LiveRegMatrix() : MachineFunctionPass(ID),
  UserTag(0), RegMaskTag(0), RegMaskVirtReg(0) {}

void LiveRegMatrix::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequiredTransitive<LiveIntervals>();
  AU.addRequiredTransitive<VirtRegMap>();
  MachineFunctionPass::getAnalysisUsage(AU);
}

bool LiveRegMatrix::runOnMachineFunction(MachineFunction &MF) {
  TRI = MF.getTarget().getRegisterInfo();
  MRI = &MF.getRegInfo();
  LIS = &getAnalysis<LiveIntervals>();
  VRM = &getAnalysis<VirtRegMap>();

  unsigned NumRegUnits = TRI->getNumRegUnits();
  if (NumRegUnits != Matrix.size())
    Queries.reset(new LiveIntervalUnion::Query[NumRegUnits]);
  Matrix.init(LIUAlloc, NumRegUnits);

  // Make sure no stale queries get reused.
  invalidateVirtRegs();
  return false;
}

void LiveRegMatrix::releaseMemory() {
  for (unsigned i = 0, e = Matrix.size(); i != e; ++i) {
    Matrix[i].clear();
    Queries[i].clear();
  }
}

void LiveRegMatrix::assign(LiveInterval &VirtReg, unsigned PhysReg) {
  DEBUG(dbgs() << "assigning " << PrintReg(VirtReg.reg, TRI)
               << " to " << PrintReg(PhysReg, TRI) << ':');
  assert(!VRM->hasPhys(VirtReg.reg) && "Duplicate VirtReg assignment");
  VRM->assignVirt2Phys(VirtReg.reg, PhysReg);
  MRI->setPhysRegUsed(PhysReg);
  for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
    DEBUG(dbgs() << ' ' << PrintRegUnit(*Units, TRI));
    Matrix[*Units].unify(VirtReg);
  }
  ++NumAssigned;
  DEBUG(dbgs() << '\n');
}

void LiveRegMatrix::unassign(LiveInterval &VirtReg) {
  unsigned PhysReg = VRM->getPhys(VirtReg.reg);
  DEBUG(dbgs() << "unassigning " << PrintReg(VirtReg.reg, TRI)
               << " from " << PrintReg(PhysReg, TRI) << ':');
  VRM->clearVirt(VirtReg.reg);
  for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
    DEBUG(dbgs() << ' ' << PrintRegUnit(*Units, TRI));
    Matrix[*Units].extract(VirtReg);
  }
  ++NumUnassigned;
  DEBUG(dbgs() << '\n');
}

bool LiveRegMatrix::checkRegMaskInterference(LiveInterval &VirtReg,
                                             unsigned PhysReg) {
  // Check if the cached information is valid.
  // The same BitVector can be reused for all PhysRegs.
  // We could cache multiple VirtRegs if it becomes necessary.
  if (RegMaskVirtReg != VirtReg.reg || RegMaskTag != UserTag) {
    RegMaskVirtReg = VirtReg.reg;
    RegMaskTag = UserTag;
    RegMaskUsable.clear();
    LIS->checkRegMaskInterference(VirtReg, RegMaskUsable);
  }

  // The BitVector is indexed by PhysReg, not register unit.
  // Regmask interference is more fine grained than regunits.
  // For example, a Win64 call can clobber %ymm8 yet preserve %xmm8.
  return !RegMaskUsable.empty() && (!PhysReg || !RegMaskUsable.test(PhysReg));
}

bool LiveRegMatrix::checkRegUnitInterference(LiveInterval &VirtReg,
                                             unsigned PhysReg) {
  if (VirtReg.empty())
    return false;
  CoalescerPair CP(VirtReg.reg, PhysReg, *TRI);
  for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
    const LiveRange &UnitRange = LIS->getRegUnit(*Units);
    if (VirtReg.overlaps(UnitRange, CP, *LIS->getSlotIndexes()))
      return true;
  }
  return false;
}

LiveIntervalUnion::Query &LiveRegMatrix::query(LiveInterval &VirtReg,
                                               unsigned RegUnit) {
  LiveIntervalUnion::Query &Q = Queries[RegUnit];
  Q.init(UserTag, &VirtReg, &Matrix[RegUnit]);
  return Q;
}

LiveRegMatrix::InterferenceKind
LiveRegMatrix::checkInterference(LiveInterval &VirtReg, unsigned PhysReg) {
  if (VirtReg.empty())
    return IK_Free;

  // Regmask interference is the fastest check.
  if (checkRegMaskInterference(VirtReg, PhysReg))
    return IK_RegMask;

  // Check for fixed interference.
  if (checkRegUnitInterference(VirtReg, PhysReg))
    return IK_RegUnit;

  // Check the matrix for virtual register interference.
  for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units)
    if (query(VirtReg, *Units).checkInterference())
      return IK_VirtReg;

  return IK_Free;
}
<commit_msg>This small change reduces compile time for small programs on targets that have large register files. The omission of Queries.clear() is perfectly safe because LiveIntervalUnion::Query doesn't contain any data that needs freeing and because LiveRegMatrix::runOnFunction happens to reset the OwningArrayPtr holding Queries every time it is run, so there's no need to zero out the queries either. Not having to do this for very large numbers of physregs is a noticeable constant cost reduction in compilation of small programs.<commit_after>//===-- LiveRegMatrix.cpp - Track register interference -------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the LiveRegMatrix analysis pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "regalloc"
#include "llvm/CodeGen/LiveRegMatrix.h"
#include "RegisterCoalescer.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/LiveIntervalAnalysis.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/VirtRegMap.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"

using namespace llvm;

STATISTIC(NumAssigned   , "Number of registers assigned");
STATISTIC(NumUnassigned , "Number of registers unassigned");

char LiveRegMatrix::ID = 0;
INITIALIZE_PASS_BEGIN(LiveRegMatrix, "liveregmatrix",
                      "Live Register Matrix", false, false)
INITIALIZE_PASS_DEPENDENCY(LiveIntervals)
INITIALIZE_PASS_DEPENDENCY(VirtRegMap)
INITIALIZE_PASS_END(LiveRegMatrix, "liveregmatrix",
                    "Live Register Matrix", false, false)

LiveRegMatrix::LiveRegMatrix() : MachineFunctionPass(ID),
  UserTag(0), RegMaskTag(0), RegMaskVirtReg(0) {}

void LiveRegMatrix::getAnalysisUsage(AnalysisUsage &AU) const {
  AU.setPreservesAll();
  AU.addRequiredTransitive<LiveIntervals>();
  AU.addRequiredTransitive<VirtRegMap>();
  MachineFunctionPass::getAnalysisUsage(AU);
}

bool LiveRegMatrix::runOnMachineFunction(MachineFunction &MF) {
  TRI = MF.getTarget().getRegisterInfo();
  MRI = &MF.getRegInfo();
  LIS = &getAnalysis<LiveIntervals>();
  VRM = &getAnalysis<VirtRegMap>();

  unsigned NumRegUnits = TRI->getNumRegUnits();
  if (NumRegUnits != Matrix.size())
    Queries.reset(new LiveIntervalUnion::Query[NumRegUnits]);
  Matrix.init(LIUAlloc, NumRegUnits);

  // Make sure no stale queries get reused.
  invalidateVirtRegs();
  return false;
}

void LiveRegMatrix::releaseMemory() {
  for (unsigned i = 0, e = Matrix.size(); i != e; ++i) {
    Matrix[i].clear();
    // No need to clear Queries here, since LiveIntervalUnion::Query doesn't
    // have anything important to clear and LiveRegMatrix's runOnFunction()
    // does a OwningPtr::reset anyways.
  }
}

void LiveRegMatrix::assign(LiveInterval &VirtReg, unsigned PhysReg) {
  DEBUG(dbgs() << "assigning " << PrintReg(VirtReg.reg, TRI)
               << " to " << PrintReg(PhysReg, TRI) << ':');
  assert(!VRM->hasPhys(VirtReg.reg) && "Duplicate VirtReg assignment");
  VRM->assignVirt2Phys(VirtReg.reg, PhysReg);
  MRI->setPhysRegUsed(PhysReg);
  for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
    DEBUG(dbgs() << ' ' << PrintRegUnit(*Units, TRI));
    Matrix[*Units].unify(VirtReg);
  }
  ++NumAssigned;
  DEBUG(dbgs() << '\n');
}

void LiveRegMatrix::unassign(LiveInterval &VirtReg) {
  unsigned PhysReg = VRM->getPhys(VirtReg.reg);
  DEBUG(dbgs() << "unassigning " << PrintReg(VirtReg.reg, TRI)
               << " from " << PrintReg(PhysReg, TRI) << ':');
  VRM->clearVirt(VirtReg.reg);
  for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
    DEBUG(dbgs() << ' ' << PrintRegUnit(*Units, TRI));
    Matrix[*Units].extract(VirtReg);
  }
  ++NumUnassigned;
  DEBUG(dbgs() << '\n');
}

bool LiveRegMatrix::checkRegMaskInterference(LiveInterval &VirtReg,
                                             unsigned PhysReg) {
  // Check if the cached information is valid.
  // The same BitVector can be reused for all PhysRegs.
  // We could cache multiple VirtRegs if it becomes necessary.
  if (RegMaskVirtReg != VirtReg.reg || RegMaskTag != UserTag) {
    RegMaskVirtReg = VirtReg.reg;
    RegMaskTag = UserTag;
    RegMaskUsable.clear();
    LIS->checkRegMaskInterference(VirtReg, RegMaskUsable);
  }

  // The BitVector is indexed by PhysReg, not register unit.
  // Regmask interference is more fine grained than regunits.
  // For example, a Win64 call can clobber %ymm8 yet preserve %xmm8.
  return !RegMaskUsable.empty() && (!PhysReg || !RegMaskUsable.test(PhysReg));
}

bool LiveRegMatrix::checkRegUnitInterference(LiveInterval &VirtReg,
                                             unsigned PhysReg) {
  if (VirtReg.empty())
    return false;
  CoalescerPair CP(VirtReg.reg, PhysReg, *TRI);
  for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
    const LiveRange &UnitRange = LIS->getRegUnit(*Units);
    if (VirtReg.overlaps(UnitRange, CP, *LIS->getSlotIndexes()))
      return true;
  }
  return false;
}

LiveIntervalUnion::Query &LiveRegMatrix::query(LiveInterval &VirtReg,
                                               unsigned RegUnit) {
  LiveIntervalUnion::Query &Q = Queries[RegUnit];
  Q.init(UserTag, &VirtReg, &Matrix[RegUnit]);
  return Q;
}

LiveRegMatrix::InterferenceKind
LiveRegMatrix::checkInterference(LiveInterval &VirtReg, unsigned PhysReg) {
  if (VirtReg.empty())
    return IK_Free;

  // Regmask interference is the fastest check.
  if (checkRegMaskInterference(VirtReg, PhysReg))
    return IK_RegMask;

  // Check for fixed interference.
  if (checkRegUnitInterference(VirtReg, PhysReg))
    return IK_RegUnit;

  // Check the matrix for virtual register interference.
  for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units)
    if (query(VirtReg, *Units).checkInterference())
      return IK_VirtReg;

  return IK_Free;
}
<|endoftext|>


<commit_before>//===--- Action.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open
// Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Action class - implementation and auxiliary functions.
//
//===----------------------------------------------------------------------===//

#include "llvm/CompilerDriver/Action.h"
#include "llvm/CompilerDriver/BuiltinOptions.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/System/Program.h"
#include "llvm/System/TimeValue.h"

#include <stdexcept>
#include <string>

using namespace llvm;
using namespace llvmc;

namespace llvmc {

extern int Main(int argc, char** argv);
extern const char* ProgramName;

}

namespace {

  void PrintString (const std::string& str) {
    errs() << str << ' ';
  }

  void PrintCommand (const std::string& Cmd, const StrVector& Args) {
    errs() << Cmd << " ";
    std::for_each(Args.begin(), Args.end(), &PrintString);
    errs() << '\n';
  }

  bool IsSegmentationFault (int returnCode) {
#ifdef LLVM_ON_WIN32
    return (returnCode >= 0xc0000000UL)
#else
    return (returnCode < 0);
#endif
  }

  int ExecuteProgram (const std::string& name,
                      const StrVector& args) {
    sys::Path prog = sys::Program::FindProgramByName(name);

    if (prog.isEmpty()) {
      prog = FindExecutable(name, ProgramName, (void *)(intptr_t)&Main);
      if (prog.isEmpty())
        throw std::runtime_error("Can't find program '" + name + "'");
    }
    if (!prog.canExecute())
      throw std::runtime_error("Program '" + name + "' is not executable.");

    // Build the command line vector and the redirects array.
    const sys::Path* redirects[3] = {0,0,0};
    sys::Path stdout_redirect;

    std::vector<const char*> argv;
    argv.reserve((args.size()+2));
    argv.push_back(name.c_str());

    for (StrVector::const_iterator B = args.begin(), E = args.end();
         B!=E; ++B) {
      if (*B == ">") {
        ++B;
        stdout_redirect.set(*B);
        redirects[1] = &stdout_redirect;
      }
      else {
        argv.push_back((*B).c_str());
      }
    }
    argv.push_back(0);  // null terminate list.

    // Invoke the program.
    int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);

    if (IsSegmentationFault(ret)) {
      errs() << "Segmentation fault:";
      PrintCommand(name, args);
    }

    return ret;
  }
}

namespace llvmc {
  void AppendToGlobalTimeLog (const std::string& cmd, double time);
}

int llvmc::Action::Execute () const {
  if (DryRun || VerboseMode)
    PrintCommand(Command_, Args_);

  if (!DryRun) {
    if (Time) {
      sys::TimeValue now = sys::TimeValue::now();
      int ret = ExecuteProgram(Command_, Args_);
      sys::TimeValue now2 = sys::TimeValue::now();
      now2 -= now;
      double elapsed = now2.seconds()  + now2.microseconds()  / 1000000.0;
      AppendToGlobalTimeLog(Command_, elapsed);

      return ret;
    }
    else {
      return ExecuteProgram(Command_, Args_);
    }
  }

  return 0;
}
<commit_msg>Print a space after the colon.<commit_after>//===--- Action.cpp - The LLVM Compiler Driver ------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open
// Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  Action class - implementation and auxiliary functions.
//
//===----------------------------------------------------------------------===//

#include "llvm/CompilerDriver/Action.h"
#include "llvm/CompilerDriver/BuiltinOptions.h"

#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/System/Program.h"
#include "llvm/System/TimeValue.h"

#include <stdexcept>
#include <string>

using namespace llvm;
using namespace llvmc;

namespace llvmc {

extern int Main(int argc, char** argv);
extern const char* ProgramName;

}

namespace {

  void PrintString (const std::string& str) {
    errs() << str << ' ';
  }

  void PrintCommand (const std::string& Cmd, const StrVector& Args) {
    errs() << Cmd << ' ';
    std::for_each(Args.begin(), Args.end(), &PrintString);
    errs() << '\n';
  }

  bool IsSegmentationFault (int returnCode) {
#ifdef LLVM_ON_WIN32
    return (returnCode >= 0xc0000000UL)
#else
    return (returnCode < 0);
#endif
  }

  int ExecuteProgram (const std::string& name,
                      const StrVector& args) {
    sys::Path prog = sys::Program::FindProgramByName(name);

    if (prog.isEmpty()) {
      prog = FindExecutable(name, ProgramName, (void *)(intptr_t)&Main);
      if (prog.isEmpty())
        throw std::runtime_error("Can't find program '" + name + "'");
    }
    if (!prog.canExecute())
      throw std::runtime_error("Program '" + name + "' is not executable.");

    // Build the command line vector and the redirects array.
    const sys::Path* redirects[3] = {0,0,0};
    sys::Path stdout_redirect;

    std::vector<const char*> argv;
    argv.reserve((args.size()+2));
    argv.push_back(name.c_str());

    for (StrVector::const_iterator B = args.begin(), E = args.end();
         B!=E; ++B) {
      if (*B == ">") {
        ++B;
        stdout_redirect.set(*B);
        redirects[1] = &stdout_redirect;
      }
      else {
        argv.push_back((*B).c_str());
      }
    }
    argv.push_back(0);  // null terminate list.

    // Invoke the program.
    int ret = sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);

    if (IsSegmentationFault(ret)) {
      errs() << "Segmentation fault: ";
      PrintCommand(name, args);
    }

    return ret;
  }
}

namespace llvmc {
  void AppendToGlobalTimeLog (const std::string& cmd, double time);
}

int llvmc::Action::Execute () const {
  if (DryRun || VerboseMode)
    PrintCommand(Command_, Args_);

  if (!DryRun) {
    if (Time) {
      sys::TimeValue now = sys::TimeValue::now();
      int ret = ExecuteProgram(Command_, Args_);
      sys::TimeValue now2 = sys::TimeValue::now();
      now2 -= now;
      double elapsed = now2.seconds()  + now2.microseconds()  / 1000000.0;
      AppendToGlobalTimeLog(Command_, elapsed);

      return ret;
    }
    else {
      return ExecuteProgram(Command_, Args_);
    }
  }

  return 0;
}
<|endoftext|>


<commit_before>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TH2F.h>
#include <TGrid.h>
#include <TCanvas.h>
#include <TStopwatch.h>
#include <TStyle.h>
#include "AliRawReaderDate.h"
#include "AliRawReaderRoot.h"
#include "AliITSRawStreamSDD.h"
#include "AliITSRawStreamSDDCompressed.h"
#endif

// Macro to display the SDD Raw Data for 1 DDL
// Origin: F. Prino,   prino@to.infn.it

void PlotSDDRawData(Char_t datafil[100], Int_t nDDL, Int_t firstEv=18, Int_t lastEv=20){

  const Int_t nHybrids=24;
  Bool_t writtenoutput=kFALSE;
  TH2F** histo = new TH2F*[nHybrids];
  Char_t nome[20];
  for(Int_t i=0;i<nHybrids;i++){
    sprintf(nome,"histo%d",i);
    histo[i]=new TH2F(nome,"",256,-0.5,255.5,256,-0.5,255.5);
    histo[i]->SetStats(0);
  }

  Int_t iev=firstEv;
  AliRawReader *rd;
  if(strstr(datafil,".root")!=0){
    rd=new AliRawReaderRoot(datafil,iev);
  }else{
    rd=new AliRawReaderDate(datafil,iev);
  }
  TStopwatch *evtime=new TStopwatch();
  TCanvas* c0 = new TCanvas("cd0","c0",900,900);
  gStyle->SetPalette(1);

  do{
    c0->Clear();
    c0->Divide(4,6,0.001,0.001);

    evtime->Start();
    printf("Event # %d\n",iev);
    rd->Reset();
    for(Int_t i=0;i<nHybrids;i++) histo[i]->Reset();
    UChar_t cdhAttr=AliITSRawStreamSDD::ReadBlockAttributes(rd);
    UInt_t amSamplFreq=AliITSRawStreamSDD::ReadAMSamplFreqFromCDH(cdhAttr);
    AliITSRawStream* s=AliITSRawStreamSDD::CreateRawStreamSDD(rd,cdhAttr);
    if(!writtenoutput){
      printf("Use %s raw stream, sampling frequency %d MHz\n",s->ClassName(),amSamplFreq);
      writtenoutput=kTRUE;
    }

    Int_t iCountNext=0;
    while(s->Next()){
      iCountNext++;
      if(s->IsCompletedModule()==kFALSE && s->IsCompletedDDL()==kFALSE){
 	Int_t i=s->GetCarlosId()*2+s->GetChannel();
	if(rd->GetDDLID()==nDDL) histo[i]->Fill(s->GetCoord2(),s->GetCoord1(),s->GetSignal());
      }
    }
    evtime->Stop();
    printf("**** Event=%d  \n",iev);
    evtime->Print("u");
    evtime->Reset();
    iev++;

    for(Int_t i=0;i<nHybrids;i++){
      c0->cd(i+1);
      histo[i]->DrawCopy("colz");
    }
    c0->Update();
  }while(rd->NextEvent()&&iev<=lastEv);

}

void PlotSDDRawData(Int_t nrun, Int_t n2, Int_t year=2009, Char_t* dir="LHC09b_SDD",
		    Int_t nDDL=0,
		    Int_t firstEv=18,
		    Int_t lastEv=20){

  TGrid::Connect("alien:",0,0,"t");
  Char_t filnam[200];
  sprintf(filnam,"alien:///alice/data/%d/%s/%09d/raw/%02d%09d%03d.10.root",year,dir,nrun,year-2000,nrun,n2);
  printf("Open file %s\n",filnam);
  PlotSDDRawData(filnam,nDDL,firstEv,lastEv);
}

<commit_msg>New feature to plot raw data of single module<commit_after>#if !defined(__CINT__) || defined(__MAKECINT__)
#include <TH2F.h>
#include <TGrid.h>
#include <TCanvas.h>
#include <TStopwatch.h>
#include <TStyle.h>
#include "AliRawReaderDate.h"
#include "AliRawReaderRoot.h"
#include "AliITSRawStreamSDD.h"
#include "AliITSRawStreamSDDCompressed.h"
#endif

// Macro to display the SDD Raw Data for 1 DDL
// Origin: F. Prino,   prino@to.infn.it

void PlotSDDRawData(Char_t datafil[100], Int_t nDDL, Int_t firstEv=18, Int_t lastEv=20){

  const Int_t nHybrids=24;
  Bool_t writtenoutput=kFALSE;
  TH2F** histo = new TH2F*[nHybrids];
  for(Int_t i=0;i<nHybrids;i++){
    histo[i]=new TH2F(Form("histo%d",i),"",256,-0.5,255.5,256,-0.5,255.5);
    histo[i]->SetStats(0);
  }

  Bool_t isSingleMod=kFALSE;
  Int_t npx=4;
  Int_t npy=6;
  Int_t xsiz=900;
  Int_t ysiz=900;
  Int_t nHybrToPlot=24;
  Int_t iMod=-1;
  if(nDDL>=240 && nDDL<500){
    iMod=nDDL;
    AliITSDDLModuleMapSDD* dmap=new AliITSDDLModuleMapSDD();
    dmap->SetJun09Map();
    Int_t nCarlos;
    dmap->FindInDDLMap(iMod,nDDL,nCarlos);
    histo[nCarlos*2]->SetTitle(Form("Module %d Side 0",iMod));
    histo[nCarlos*2+1]->SetTitle(Form("Module %d Side 0",iMod));
    isSingleMod=kTRUE;
    npx=2;
    npy=1;
    xsiz=900;
    ysiz=450;
    nHybrToPlot=2;
  }

  Int_t iev=firstEv;
  AliRawReader *rd;
  if(strstr(datafil,".root")!=0){
    rd=new AliRawReaderRoot(datafil,iev);
  }else{
    rd=new AliRawReaderDate(datafil,iev);
  }
  TStopwatch *evtime=new TStopwatch();
  TCanvas* c0 = new TCanvas("cd0","c0",xsiz,ysiz);
  gStyle->SetPalette(1);

  do{
    c0->Clear();
    c0->Divide(npx,npy,0.001,0.001);

    evtime->Start();
    printf("Event # %d\n",iev);
    rd->Reset();
    for(Int_t i=0;i<nHybrids;i++) histo[i]->Reset();
    UChar_t cdhAttr=AliITSRawStreamSDD::ReadBlockAttributes(rd);
    UInt_t amSamplFreq=AliITSRawStreamSDD::ReadAMSamplFreqFromCDH(cdhAttr);
    AliITSRawStream* s=AliITSRawStreamSDD::CreateRawStreamSDD(rd,cdhAttr);
    if(!writtenoutput){
      printf("Use %s raw stream, sampling frequency %d MHz\n",s->ClassName(),amSamplFreq);
      writtenoutput=kTRUE;
    }

    Int_t iCountNext=0;
    while(s->Next()){
      iCountNext++;
      if(s->IsCompletedModule()==kFALSE && s->IsCompletedDDL()==kFALSE){
 	Int_t i=s->GetCarlosId()*2+s->GetChannel();
	if(rd->GetDDLID()==nDDL) histo[i]->Fill(s->GetCoord2(),s->GetCoord1(),s->GetSignal());
      }
    }
    evtime->Stop();
    printf("**** Event=%d  \n",iev);
    evtime->Print("u");
    evtime->Reset();
    iev++;

    for(Int_t i=0;i<nHybrToPlot;i++){
      c0->cd(i+1);
      if(isSingleMod){
	histo[nCarlos*2+i]->DrawCopy("colz");
      }else{
	histo[i]->DrawCopy("colz");
      }
    }
    c0->Update();
    if(histo[nCarlos*2]->GetMaximum()>1) getchar();
  }while(rd->NextEvent()&&iev<=lastEv);

}

void PlotSDDRawData(Int_t nrun, Int_t n2, Int_t year=2009, Char_t* dir="LHC09b_SDD",
		    Int_t nDDL=0,
		    Int_t firstEv=18,
		    Int_t lastEv=20){

  TGrid::Connect("alien:",0,0,"t");
  Char_t filnam[200];
  sprintf(filnam,"alien:///alice/data/%d/%s/%09d/raw/%02d%09d%03d.10.root",year,dir,nrun,year-2000,nrun,n2);
  printf("Open file %s\n",filnam);
  PlotSDDRawData(filnam,nDDL,firstEv,lastEv);
}

<|endoftext|>


<commit_before>/**
* @file IntegralImageProvider.cpp
*
* Implementation of class IntegralImageProvider
*
*/

#include "IntegralImageProvider.h"

IntegralImageProvider::IntegralImageProvider()
{
}

IntegralImageProvider::~IntegralImageProvider()
{
}

void IntegralImageProvider::execute(CameraInfo::CameraID id)
{
  cameraID = id;
  makeIntegralBild(getBallDetectorIntegralImage());
}

void IntegralImageProvider::makeIntegralBild(BallDetectorIntegralImage& integralImage) const
{
  const int32_t FACTOR = integralImage.FACTOR;
  const uint32_t MAX_COLOR = integralImage.MAX_COLOR;

  const uint32_t imgWidth = getImage().width()/FACTOR;
	const uint32_t imgHeight = getImage().height()/FACTOR;
	integralImage.setDimension(imgWidth, imgHeight);

  uint32_t* dataPtr = integralImage.getDataPointer();

  uint32_t* prevRowPtr = dataPtr;
	uint32_t* curRowPtr  = dataPtr + imgWidth*MAX_COLOR;

  // NOTE: we use the byte-wise access to the image, so we skipp every 2nd pixel
  const Pixel* imgPtr = reinterpret_cast<Pixel*>(getImage().data());

  const int32_t FACTOR_HALF = integralImage.FACTOR/2;
  // initial offset in the y direction
  const uint32_t yImageOffsetInitial = getImage().width() * FACTOR_HALF;
  // In each line we iterate over imgWidth-1 pixel. Because the pixel pointer is accumulated,
  // we have to subtract it from the subsequent offset in the y-axis
  const uint32_t yImageOffsetIteration = yImageOffsetInitial - (imgWidth-1) * FACTOR_HALF;

  // initial y-offset
  imgPtr += yImageOffsetInitial;

  for(uint16_t y = 1; y < imgHeight; ++y)
  {
    uint32_t akk[MAX_COLOR] = { 0 };

    prevRowPtr += MAX_COLOR;
    curRowPtr  += MAX_COLOR;

    for(uint16_t x = 1; x < imgWidth; ++x)
    {
      imgPtr += FACTOR_HALF;

      if(getFieldColorPercept().greenHSISeparator.isColor(*imgPtr)) {
        ++akk[1];
      } else {
        akk[0] += (imgPtr->y0);
      }

      for(uint32_t i = 0; i < MAX_COLOR; ++i) {
        curRowPtr[i] = akk[i] + prevRowPtr[i];
      }

      curRowPtr  += MAX_COLOR;
      prevRowPtr += MAX_COLOR;
    }

    // iteration y-offset
    imgPtr += yImageOffsetIteration;
  }
}<commit_msg>remove tabs<commit_after>/**
* @file IntegralImageProvider.cpp
*
* Implementation of class IntegralImageProvider
*
*/

#include "IntegralImageProvider.h"

IntegralImageProvider::IntegralImageProvider()
{
}

IntegralImageProvider::~IntegralImageProvider()
{
}

void IntegralImageProvider::execute(CameraInfo::CameraID id)
{
  cameraID = id;
  makeIntegralBild(getBallDetectorIntegralImage());
}

void IntegralImageProvider::makeIntegralBild(BallDetectorIntegralImage& integralImage) const
{
  const int32_t FACTOR = integralImage.FACTOR;
  const uint32_t MAX_COLOR = integralImage.MAX_COLOR;

  const uint32_t imgWidth = getImage().width()/FACTOR;
  const uint32_t imgHeight = getImage().height()/FACTOR;
  integralImage.setDimension(imgWidth, imgHeight);

  uint32_t* dataPtr = integralImage.getDataPointer();

  uint32_t* prevRowPtr = dataPtr;
  uint32_t* curRowPtr  = dataPtr + imgWidth*MAX_COLOR;

  // NOTE: we use the byte-wise access to the image, so we skipp every 2nd pixel
  const Pixel* imgPtr = reinterpret_cast<Pixel*>(getImage().data());

  const int32_t FACTOR_HALF = integralImage.FACTOR/2;
  // initial offset in the y direction
  const uint32_t yImageOffsetInitial = getImage().width() * FACTOR_HALF;
  // In each line we iterate over imgWidth-1 pixel. Because the pixel pointer is accumulated,
  // we have to subtract it from the subsequent offset in the y-axis
  const uint32_t yImageOffsetIteration = yImageOffsetInitial - (imgWidth-1) * FACTOR_HALF;

  // initial y-offset
  imgPtr += yImageOffsetInitial;

  for(uint16_t y = 1; y < imgHeight; ++y)
  {
    uint32_t akk[MAX_COLOR] = { 0 };

    prevRowPtr += MAX_COLOR;
    curRowPtr  += MAX_COLOR;

    for(uint16_t x = 1; x < imgWidth; ++x)
    {
      imgPtr += FACTOR_HALF;

      if(getFieldColorPercept().greenHSISeparator.isColor(*imgPtr)) {
        ++akk[1];
      } else {
        akk[0] += (imgPtr->y0);
      }

      for(uint32_t i = 0; i < MAX_COLOR; ++i) {
        curRowPtr[i] = akk[i] + prevRowPtr[i];
      }

      curRowPtr  += MAX_COLOR;
      prevRowPtr += MAX_COLOR;
    }

    // iteration y-offset
    imgPtr += yImageOffsetIteration;
  }
}<|endoftext|>


<commit_before>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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
 * FOUNDATION 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 "cgi/Address.hxx"
#include "AllocatorPtr.hxx"
#include "TestPool.hxx"

#include <gtest/gtest.h>

TEST(CgiAddressTest, Uri)
{
	TestPool pool;
	AllocatorPtr alloc(pool);

	CgiAddress a("/usr/bin/cgi");
	ASSERT_FALSE(a.IsExpandable());
	ASSERT_STREQ(a.GetURI(alloc), "/");

	a.script_name = "/";
	ASSERT_STREQ(a.GetURI(alloc), "/");

	a.path_info = "foo";
	ASSERT_STREQ(a.GetURI(alloc), "/foo");

	a.query_string = "";
	ASSERT_STREQ(a.GetURI(alloc), "/foo?");

	a.query_string = "a=b";
	ASSERT_STREQ(a.GetURI(alloc), "/foo?a=b");

	a.path_info = "";
	ASSERT_STREQ(a.GetURI(alloc), "/?a=b");

	a.path_info = nullptr;
	ASSERT_STREQ(a.GetURI(alloc), "/?a=b");

	a.script_name = "/test.cgi";
	a.path_info = nullptr;
	a.query_string = nullptr;
	ASSERT_STREQ(a.GetURI(alloc), "/test.cgi");

	a.path_info = "/foo";
	ASSERT_STREQ(a.GetURI(alloc), "/test.cgi/foo");

	a.script_name = "/bar/";
	ASSERT_STREQ(a.GetURI(alloc), "/bar/foo");

	a.script_name = "/";
	ASSERT_STREQ(a.GetURI(alloc), "/foo");

	a.script_name = nullptr;
	ASSERT_STREQ(a.GetURI(alloc), "/foo");
}

TEST(CgiAddressTest, Apply)
{
	TestPool pool;
	AllocatorPtr alloc(pool);

	CgiAddress a("/usr/bin/cgi");
	a.script_name = "/test.pl";
	a.path_info = "/foo";

	auto b = a.Apply(alloc, "");
	ASSERT_EQ((const CgiAddress *)&a, b);

	b = a.Apply(alloc, "bar");
	ASSERT_NE(b, nullptr);
	ASSERT_NE(b, &a);
	ASSERT_FALSE(b->IsValidBase());
	ASSERT_STREQ(b->path, a.path);
	ASSERT_STREQ(b->script_name, a.script_name);
	ASSERT_STREQ(b->path_info, "/bar");

	a.path_info = "/foo/";
	ASSERT_EQ(true, a.IsValidBase());

	b = a.Apply(alloc, "bar");
	ASSERT_NE(b, nullptr);
	ASSERT_NE(b, &a);
	ASSERT_FALSE(b->IsValidBase());
	ASSERT_STREQ(b->path, a.path);
	ASSERT_STREQ(b->script_name, a.script_name);
	ASSERT_STREQ(b->path_info, "/foo/bar");

	b = a.Apply(alloc, "/bar");
	ASSERT_NE(b, nullptr);
	ASSERT_NE(b, &a);
	ASSERT_FALSE(b->IsValidBase());
	ASSERT_STREQ(b->path, a.path);
	ASSERT_STREQ(b->script_name, a.script_name);
	ASSERT_STREQ(b->path_info, "/bar");
}
<commit_msg>test/t_cgi_address: add RelativeTo() test<commit_after>/*
 * Copyright 2007-2020 CM4all GmbH
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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
 * FOUNDATION 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 "cgi/Address.hxx"
#include "AllocatorPtr.hxx"
#include "TestPool.hxx"

#include <gtest/gtest.h>

TEST(CgiAddressTest, Uri)
{
	TestPool pool;
	AllocatorPtr alloc(pool);

	CgiAddress a("/usr/bin/cgi");
	ASSERT_FALSE(a.IsExpandable());
	ASSERT_STREQ(a.GetURI(alloc), "/");

	a.script_name = "/";
	ASSERT_STREQ(a.GetURI(alloc), "/");

	a.path_info = "foo";
	ASSERT_STREQ(a.GetURI(alloc), "/foo");

	a.query_string = "";
	ASSERT_STREQ(a.GetURI(alloc), "/foo?");

	a.query_string = "a=b";
	ASSERT_STREQ(a.GetURI(alloc), "/foo?a=b");

	a.path_info = "";
	ASSERT_STREQ(a.GetURI(alloc), "/?a=b");

	a.path_info = nullptr;
	ASSERT_STREQ(a.GetURI(alloc), "/?a=b");

	a.script_name = "/test.cgi";
	a.path_info = nullptr;
	a.query_string = nullptr;
	ASSERT_STREQ(a.GetURI(alloc), "/test.cgi");

	a.path_info = "/foo";
	ASSERT_STREQ(a.GetURI(alloc), "/test.cgi/foo");

	a.script_name = "/bar/";
	ASSERT_STREQ(a.GetURI(alloc), "/bar/foo");

	a.script_name = "/";
	ASSERT_STREQ(a.GetURI(alloc), "/foo");

	a.script_name = nullptr;
	ASSERT_STREQ(a.GetURI(alloc), "/foo");
}

TEST(CgiAddressTest, Apply)
{
	TestPool pool;
	AllocatorPtr alloc(pool);

	CgiAddress a("/usr/bin/cgi");
	a.script_name = "/test.pl";
	a.path_info = "/foo";

	auto b = a.Apply(alloc, "");
	ASSERT_EQ((const CgiAddress *)&a, b);

	b = a.Apply(alloc, "bar");
	ASSERT_NE(b, nullptr);
	ASSERT_NE(b, &a);
	ASSERT_FALSE(b->IsValidBase());
	ASSERT_STREQ(b->path, a.path);
	ASSERT_STREQ(b->script_name, a.script_name);
	ASSERT_STREQ(b->path_info, "/bar");

	a.path_info = "/foo/";
	ASSERT_EQ(true, a.IsValidBase());

	b = a.Apply(alloc, "bar");
	ASSERT_NE(b, nullptr);
	ASSERT_NE(b, &a);
	ASSERT_FALSE(b->IsValidBase());
	ASSERT_STREQ(b->path, a.path);
	ASSERT_STREQ(b->script_name, a.script_name);
	ASSERT_STREQ(b->path_info, "/foo/bar");

	b = a.Apply(alloc, "/bar");
	ASSERT_NE(b, nullptr);
	ASSERT_NE(b, &a);
	ASSERT_FALSE(b->IsValidBase());
	ASSERT_STREQ(b->path, a.path);
	ASSERT_STREQ(b->script_name, a.script_name);
	ASSERT_STREQ(b->path_info, "/bar");
}

gcc_pure
static auto
MakeCgiAddress(const char *executable_path, const char *script_name,
	       const char *path_info) noexcept
{
	CgiAddress address(executable_path);
	address.script_name = script_name;
	address.path_info = path_info;
	return address;
}

static bool
operator==(const StringView a, const StringView b) noexcept
{
	if (a.IsNull() || b.IsNull())
		return a.IsNull() && b.IsNull();

	if (a.size != b.size)
		return false;

	return memcmp(a.data, b.data, a.size) == 0;
}

static bool
operator==(const StringView a, const char *b) noexcept
{
	return a == StringView(b);
}

static bool
operator==(const StringView a, std::nullptr_t b) noexcept
{
	return a == StringView(b);
}

TEST(CgiAddressTest, RelativeTo)
{
	TestPool pool;
	AllocatorPtr alloc(pool);

	const auto base = MakeCgiAddress("/usr/bin/cgi", "/test.pl", "/foo/");

	ASSERT_EQ(MakeCgiAddress("/usr/bin/other-cgi", "/test.pl", "/foo/").RelativeTo(base), nullptr);

	ASSERT_EQ(MakeCgiAddress("/usr/bin/cgi", "/test.pl", nullptr).RelativeTo(base), nullptr);
	ASSERT_EQ(MakeCgiAddress("/usr/bin/cgi", "/test.pl", "/").RelativeTo(base), nullptr);
	ASSERT_EQ(MakeCgiAddress("/usr/bin/cgi", "/test.pl", "/foo").RelativeTo(base), nullptr);
	ASSERT_EQ(MakeCgiAddress("/usr/bin/cgi", "/test.pl", "/foo/").RelativeTo(base), "");
	ASSERT_EQ(MakeCgiAddress("/usr/bin/cgi", "/test.pl", "/foo/bar").RelativeTo(base), "bar");
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#define DUNE_STUFF_FUNCTIONS_DISABLE_CHECKS

// This one has to come first (includes the config.h)!
#include <dune/stuff/test/test_common.hh>

#ifdef HAVE_FASP
# undef HAVE_FASP
#endif

#include <dune/common/exceptions.hh>

#if HAVE_ALUGRID_SERIAL_H || HAVE_ALUGRID_PARALLEL_H
# define ENABLE_ALUGRID 1
# include <dune/grid/alugrid.hh>
#else
# error This test requires ALUGrid!
#endif

#include <dune/stuff/common/color.hh>
#include <dune/stuff/common/print.hh>
#include <dune/stuff/common/float_cmp.hh>

#include "elliptic-testcases.hh"
#include "elliptic-cg-discretization.hh"
#include "elliptic-sipdg-discretization.hh"
#include "elliptic-swipdg-discretization.hh"

class errors_are_not_as_expected
  : public Dune::Exception
{};

typedef Dune::ALUConformGrid< 2, 2 > AluConform2dGridType;

// change this to toggle output
std::ostream& test_out = std::cout;
//std::ostream& test_out = DSC_LOG.devnull();

typedef testing::Types< EllipticTestCase::ESV07< AluConform2dGridType >
                      , EllipticTestCase::LocalThermalBlock< AluConform2dGridType >
                      , EllipticTestCase::ER07< AluConform2dGridType >
                      , EllipticTestCase::MixedBoundaryTypes< AluConform2dGridType >
//                      , EllipticTestCase::Spe10Model1< AluConform2dGridType >
                      > AluConform2dTestCases;

std::vector< double > truncate_vector(const std::vector< double >& in, const size_t size)
{
  assert(size <= in.size());
  if (size == in.size())
    return in;
  else {
    std::vector< double > out(size);
    for (size_t ii = 0; ii < size; ++ii)
      out[ii] = in[ii];
    return out;
  }
} // ... truncate_vector(...)

template< class TestCase >
struct EllipticCGDiscretization
  : public ::testing::Test
{
  void produces_correct_results() const
  {
    const TestCase test_case;
    test_case.print_header(test_out);
    test_out << std::endl;
    EllipticCG::EocStudy< TestCase, 1 > eoc_study(test_case);
    auto errors = eoc_study.run(test_out);
    for (const auto& norm : eoc_study.provided_norms()) {
      if (!Dune::Stuff::Common::FloatCmp::lt(errors[norm],
                                             truncate_vector(eoc_study.expected_results(norm), errors[norm].size()))) {
        std::stringstream ss;
        Dune::Stuff::Common::print(errors[norm],                        "errors           (" + norm + ")", ss);
        Dune::Stuff::Common::print(eoc_study.expected_results(norm), "   expected results (" + norm + ")", ss);
        DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
      }
    }
  }
}; // EllipticCGDiscretization

template< class TestCase >
struct EllipticSIPDGDiscretization
  : public ::testing::Test
{
  void produces_correct_results() const
  {
    if (std::is_same< TestCase, EllipticTestCase::Spe10Model1< Dune::ALUConformGrid< 2, 2 > > >::value) {
      std::cerr
          << Dune::Stuff::Common::colorStringRed("EllipticSIPDGDiscretization does not work for "
                                                 "EllipticTestCase::Spe10Model1< Dune::ALUConformGrid< 2, 2 > >!")
          << std::endl;
    } else {
      const TestCase test_case;
      test_case.print_header(test_out);
      test_out << std::endl;
      EllipticSIPDG::EocStudy< TestCase, 1 > eoc_study_1(test_case);
      auto errors_1 = eoc_study_1.run(test_out);
      for (const auto& norm : eoc_study_1.provided_norms()) {
        if (!Dune::Stuff::Common::FloatCmp::lt(errors_1[norm], eoc_study_1.expected_results(norm))) {
          std::stringstream ss;
          Dune::Stuff::Common::print(errors_1[norm],                     "errors           (" + norm + ")", ss);
          Dune::Stuff::Common::print(eoc_study_1.expected_results(norm), "   expected results (" + norm + ")", ss);
          DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
        }
      }
      test_out << std::endl;
      EllipticSIPDG::EocStudy< TestCase, 2 > eoc_study_2(test_case);
      auto errors_2 = eoc_study_2.run(test_out);
      for (const auto& norm : eoc_study_2.provided_norms())
        if (!Dune::Stuff::Common::FloatCmp::lt(errors_2[norm], eoc_study_2.expected_results(norm))) {
          std::stringstream ss;
          Dune::Stuff::Common::print(errors_2[norm],                     "errors           (" + norm + ")", ss);
          Dune::Stuff::Common::print(eoc_study_2.expected_results(norm), "   expected results (" + norm + ")", ss);
          DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
        }
    }
  }
}; // EllipticSIPDGDiscretization

template< class TestCase >
struct EllipticSWIPDGDiscretization
  : public ::testing::Test
{
  void produces_correct_results() const
  {
    const TestCase test_case;
    test_case.print_header(test_out);
    test_out << std::endl;
    EllipticSWIPDG::EocStudy< TestCase, 1 > eoc_study_1(test_case);
    auto errors_1 = eoc_study_1.run(test_out);
    for (const auto& norm : eoc_study_1.provided_norms()) {
      if (!Dune::Stuff::Common::FloatCmp::lt(errors_1[norm], eoc_study_1.expected_results(norm))) {
        std::stringstream ss;
        Dune::Stuff::Common::print(errors_1[norm],                     "errors           (" + norm + ")", ss);
        Dune::Stuff::Common::print(eoc_study_1.expected_results(norm), "   expected results (" + norm + ")", ss);
        DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
      }
    }
    test_out << std::endl;
    EllipticSWIPDG::EocStudy< TestCase, 2 > eoc_study_2(test_case);
    auto errors_2 = eoc_study_2.run(test_out);
    for (const auto& norm : eoc_study_2.provided_norms())
      if (!Dune::Stuff::Common::FloatCmp::lt(errors_2[norm], eoc_study_2.expected_results(norm))) {
        std::stringstream ss;
        Dune::Stuff::Common::print(errors_2[norm],                     "errors           (" + norm + ")", ss);
        Dune::Stuff::Common::print(eoc_study_2.expected_results(norm), "   expected results (" + norm + ")", ss);
        DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
      }
  }
};

TYPED_TEST_CASE(EllipticCGDiscretization, AluConform2dTestCases);
TYPED_TEST(EllipticCGDiscretization, produces_correct_results) {
  this->produces_correct_results();
}

TYPED_TEST_CASE(EllipticSIPDGDiscretization, AluConform2dTestCases);
TYPED_TEST(EllipticSIPDGDiscretization, produces_correct_results) {
  this->produces_correct_results();
}

TYPED_TEST_CASE(EllipticSWIPDGDiscretization, AluConform2dTestCases);
TYPED_TEST(EllipticSWIPDGDiscretization, produces_correct_results) {
  this->produces_correct_results();
}

int main(int argc, char** argv)
{
  try {
    test_init(argc, argv);
    return RUN_ALL_TESTS();
  } catch (Dune::Exception& e) {
    std::cerr << "\nDune reported error: " << e.what() << std::endl;
    std::abort();
  } catch (std::exception& e) {
    std::cerr << "\n" << e.what() << std::endl;
    std::abort();
  } catch (...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
    std::abort();
  } // try
}
<commit_msg>[tests.elliptic-discretizations] disabled DG for the moment<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Albrecht
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#define DUNE_STUFF_FUNCTIONS_DISABLE_CHECKS

// This one has to come first (includes the config.h)!
#include <dune/stuff/test/test_common.hh>

#ifdef HAVE_FASP
# undef HAVE_FASP
#endif

#include <dune/common/exceptions.hh>

#if HAVE_ALUGRID_SERIAL_H || HAVE_ALUGRID_PARALLEL_H
# define ENABLE_ALUGRID 1
# include <dune/grid/alugrid.hh>
#else
# error This test requires ALUGrid!
#endif

#include <dune/stuff/common/color.hh>
#include <dune/stuff/common/print.hh>
#include <dune/stuff/common/float_cmp.hh>

#include "elliptic-testcases.hh"
#include "elliptic-cg-discretization.hh"
//#include "elliptic-sipdg-discretization.hh"
//#include "elliptic-swipdg-discretization.hh"

class errors_are_not_as_expected
  : public Dune::Exception
{};

typedef Dune::ALUConformGrid< 2, 2 > AluConform2dGridType;

// change this to toggle output
std::ostream& test_out = std::cout;
//std::ostream& test_out = DSC_LOG.devnull();

typedef testing::Types< EllipticTestCase::ESV07< AluConform2dGridType >
                      , EllipticTestCase::LocalThermalBlock< AluConform2dGridType >
                      , EllipticTestCase::ER07< AluConform2dGridType >
                      , EllipticTestCase::MixedBoundaryTypes< AluConform2dGridType >
                      , EllipticTestCase::Spe10Model1< AluConform2dGridType >
                      > AluConform2dTestCases;

std::vector< double > truncate_vector(const std::vector< double >& in, const size_t size)
{
  assert(size <= in.size());
  if (size == in.size())
    return in;
  else {
    std::vector< double > out(size);
    for (size_t ii = 0; ii < size; ++ii)
      out[ii] = in[ii];
    return out;
  }
} // ... truncate_vector(...)

template< class TestCase >
struct EllipticCGDiscretization
  : public ::testing::Test
{
  void produces_correct_results() const
  {
    const TestCase test_case;
    test_case.print_header(test_out);
    test_out << std::endl;
    EllipticCG::EocStudy< TestCase, 1 > eoc_study(test_case);
    auto errors = eoc_study.run(test_out);
    for (const auto& norm : eoc_study.provided_norms()) {
      if (!Dune::Stuff::Common::FloatCmp::lt(errors[norm],
                                             truncate_vector(eoc_study.expected_results(norm), errors[norm].size()))) {
        std::stringstream ss;
        Dune::Stuff::Common::print(errors[norm],                        "errors           (" + norm + ")", ss);
        Dune::Stuff::Common::print(eoc_study.expected_results(norm), "   expected results (" + norm + ")", ss);
        DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
      }
    }
  }
}; // EllipticCGDiscretization

//template< class TestCase >
//struct EllipticSIPDGDiscretization
//  : public ::testing::Test
//{
//  void produces_correct_results() const
//  {
//    if (std::is_same< TestCase, EllipticTestCase::Spe10Model1< Dune::ALUConformGrid< 2, 2 > > >::value) {
//      std::cerr
//          << Dune::Stuff::Common::colorStringRed("EllipticSIPDGDiscretization does not work for "
//                                                 "EllipticTestCase::Spe10Model1< Dune::ALUConformGrid< 2, 2 > >!")
//          << std::endl;
//    } else {
//      const TestCase test_case;
//      test_case.print_header(test_out);
//      test_out << std::endl;
//      EllipticSIPDG::EocStudy< TestCase, 1 > eoc_study_1(test_case);
//      auto errors_1 = eoc_study_1.run(test_out);
//      for (const auto& norm : eoc_study_1.provided_norms()) {
//        if (!Dune::Stuff::Common::FloatCmp::lt(errors_1[norm], eoc_study_1.expected_results(norm))) {
//          std::stringstream ss;
//          Dune::Stuff::Common::print(errors_1[norm],                     "errors           (" + norm + ")", ss);
//          Dune::Stuff::Common::print(eoc_study_1.expected_results(norm), "   expected results (" + norm + ")", ss);
//          DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
//        }
//      }
//      test_out << std::endl;
//      EllipticSIPDG::EocStudy< TestCase, 2 > eoc_study_2(test_case);
//      auto errors_2 = eoc_study_2.run(test_out);
//      for (const auto& norm : eoc_study_2.provided_norms())
//        if (!Dune::Stuff::Common::FloatCmp::lt(errors_2[norm], eoc_study_2.expected_results(norm))) {
//          std::stringstream ss;
//          Dune::Stuff::Common::print(errors_2[norm],                     "errors           (" + norm + ")", ss);
//          Dune::Stuff::Common::print(eoc_study_2.expected_results(norm), "   expected results (" + norm + ")", ss);
//          DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
//        }
//    }
//  }
//}; // EllipticSIPDGDiscretization

//template< class TestCase >
//struct EllipticSWIPDGDiscretization
//  : public ::testing::Test
//{
//  void produces_correct_results() const
//  {
//    const TestCase test_case;
//    test_case.print_header(test_out);
//    test_out << std::endl;
//    EllipticSWIPDG::EocStudy< TestCase, 1 > eoc_study_1(test_case);
//    auto errors_1 = eoc_study_1.run(test_out);
//    for (const auto& norm : eoc_study_1.provided_norms()) {
//      if (!Dune::Stuff::Common::FloatCmp::lt(errors_1[norm], eoc_study_1.expected_results(norm))) {
//        std::stringstream ss;
//        Dune::Stuff::Common::print(errors_1[norm],                     "errors           (" + norm + ")", ss);
//        Dune::Stuff::Common::print(eoc_study_1.expected_results(norm), "   expected results (" + norm + ")", ss);
//        DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
//      }
//    }
//    test_out << std::endl;
//    EllipticSWIPDG::EocStudy< TestCase, 2 > eoc_study_2(test_case);
//    auto errors_2 = eoc_study_2.run(test_out);
//    for (const auto& norm : eoc_study_2.provided_norms())
//      if (!Dune::Stuff::Common::FloatCmp::lt(errors_2[norm], eoc_study_2.expected_results(norm))) {
//        std::stringstream ss;
//        Dune::Stuff::Common::print(errors_2[norm],                     "errors           (" + norm + ")", ss);
//        Dune::Stuff::Common::print(eoc_study_2.expected_results(norm), "   expected results (" + norm + ")", ss);
//        DUNE_THROW_COLORFULLY(errors_are_not_as_expected, ss.str());
//      }
//  }
//};

TYPED_TEST_CASE(EllipticCGDiscretization, AluConform2dTestCases);
TYPED_TEST(EllipticCGDiscretization, produces_correct_results) {
  this->produces_correct_results();
}

//TYPED_TEST_CASE(EllipticSIPDGDiscretization, AluConform2dTestCases);
//TYPED_TEST(EllipticSIPDGDiscretization, produces_correct_results) {
//  this->produces_correct_results();
//}

//TYPED_TEST_CASE(EllipticSWIPDGDiscretization, AluConform2dTestCases);
//TYPED_TEST(EllipticSWIPDGDiscretization, produces_correct_results) {
//  this->produces_correct_results();
//}

int main(int argc, char** argv)
{
  try {
    test_init(argc, argv);
    return RUN_ALL_TESTS();
  } catch (Dune::Exception& e) {
    std::cerr << "\nDune reported error: " << e.what() << std::endl;
    std::abort();
  } catch (std::exception& e) {
    std::cerr << "\n" << e.what() << std::endl;
    std::abort();
  } catch (...) {
    std::cerr << "Unknown exception thrown!" << std::endl;
    std::abort();
  } // try
}
<|endoftext|>