<commit_before>// @(#) $Id$
// Author: Fons Rademakers  26/11/99

/**************************************************************************
 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// AliTagDB                                                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <errno.h>

#include <TSystem.h>
#include <TTimeStamp.h>

#include "AliESD.h"

#include "AliRawDB.h"
#include "AliRawEventTag.h"
#include "AliTagDB.h"
#include "AliRawEventHeaderBase.h"

ClassImp(AliTagDB)

//______________________________________________________________________________
AliTagDB::AliTagDB(AliRawEventTag *eventTag, const char* fileName) :
  fTagDB(NULL),
  fTree(NULL),
  fEventTag(eventTag),
  fMaxSize(-1),
  fFS(""),
  fDeleteFiles(kFALSE)
{
   // Create tag DB.

   if (fileName) {
      if (!Create(fileName))
         MakeZombie();
   }
}

//______________________________________________________________________________
Bool_t AliTagDB::Create(const char* fileName)
{
   // Create a new tag DB.

   const char *name = fileName;
   if (!name) name = GetFileName();
   fTagDB = new TFile(name, "RECREATE",
                      Form("ALICE tag DB (%s)", AliRawDB::GetAliRootTag()), 1);
   if (fTagDB->IsZombie()) {
      Error("Create", "error opening tag DB");
      fTagDB = 0;
      return kFALSE;
   }
   // Put wide read-write permissions
   if(gSystem->Chmod(name,438)) {
     Error("Create", "can't set permissions for tag DB file");
     fTagDB = 0;
     return kFALSE;
   }

   // Create ROOT Tree object container
   fTree = new TTree("T", Form("ALICE raw-data tag tree (%s)", AliRawDB::GetAliRootTag()));
   fTree->SetAutoSave(100000000);  // autosave when 100 Mbyte written

   Int_t bufsize = 32000;
   Int_t split   = 1;
   const char *tagname = fEventTag->GetName();
   fTree->Branch("TAG", tagname, &fEventTag, bufsize, split);

   return kTRUE;
}

//______________________________________________________________________________
void AliTagDB::Close()
{
   // Close tag DB.

   if (!fTagDB) return;

   fTagDB->cd();

   // Write the tree.
   fTree->Write();

   // Close DB, this also deletes the fTree
   fTagDB->Close();

   if (fDeleteFiles)
      gSystem->Unlink(fTagDB->GetName());

   delete fTagDB;
   fTagDB = 0;
}

//______________________________________________________________________________
Bool_t AliTagDB::NextFile(const char* fileName)
{
   // Close te current file and open a new one.
   // Returns kFALSE in case opening failed.

   Close();

   if (!Create(fileName)) return kFALSE;
   return kTRUE;
}

//______________________________________________________________________________
void AliTagDB::SetFS(const char* fs)
{
// set the file system location

  fFS = fs;
  if (fs) {
    gSystem->ResetErrno();
    gSystem->MakeDirectory(fs);
    if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
      SysError("SetFS", "mkdir %s", fs);
    }
  }
}

//______________________________________________________________________________
Float_t AliTagDB::GetCompressionFactor() const
{
   // Return compression factor.

   if (fTree->GetZipBytes() == 0.)
      return 1.0;
   else
      return fTree->GetTotBytes()/fTree->GetZipBytes();
}

//______________________________________________________________________________
const char *AliTagDB::GetFileName() const
{
   // Return filename based on hostname and date and time. This will make
   // each file unique. The tags will be stored in the /data1/tags directory.

   static char fname[1024];
   const char *fs = fFS;

   // check that fs exists (crude check fails if fs is a file)
   gSystem->MakeDirectory(fs);

   // Get the run number
   Int_t runNumber = -1;
   if (fEventTag) {
     AliRawEventHeaderBase *header = fEventTag->GetHeader();
     if (header) runNumber = header->Get("RunNb");
   }

   char hostname[1024];
   strcpy(hostname, gSystem->HostName());

   char *s;
   if ((s = strchr(hostname, '.')))
     *s = 0;

   TTimeStamp ts;

   sprintf(fname, "%s/Run%d.%s_%d_%d_%d.RAW.tag.root", fs, runNumber, hostname,
	   ts.GetDate(), ts.GetTime(), ts.GetNanoSec());

   return fname;
}
<commit_msg>Removal of the last sprintf. Using TString instead<commit_after>// @(#) $Id$
// Author: Fons Rademakers  26/11/99

/**************************************************************************
 * Copyright(c) 1998-2003, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// AliTagDB                                                             //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include <errno.h>

#include <TSystem.h>
#include <TTimeStamp.h>

#include "AliESD.h"

#include "AliRawDB.h"
#include "AliRawEventTag.h"
#include "AliTagDB.h"
#include "AliRawEventHeaderBase.h"

ClassImp(AliTagDB)

//______________________________________________________________________________
AliTagDB::AliTagDB(AliRawEventTag *eventTag, const char* fileName) :
  fTagDB(NULL),
  fTree(NULL),
  fEventTag(eventTag),
  fMaxSize(-1),
  fFS(""),
  fDeleteFiles(kFALSE)
{
   // Create tag DB.

   if (fileName) {
      if (!Create(fileName))
         MakeZombie();
   }
}

//______________________________________________________________________________
Bool_t AliTagDB::Create(const char* fileName)
{
   // Create a new tag DB.

   const char *name = fileName;
   if (!name) name = GetFileName();
   fTagDB = new TFile(name, "RECREATE",
                      Form("ALICE tag DB (%s)", AliRawDB::GetAliRootTag()), 1);
   if (fTagDB->IsZombie()) {
      Error("Create", "error opening tag DB");
      fTagDB = 0;
      return kFALSE;
   }
   // Put wide read-write permissions
   if(gSystem->Chmod(name,438)) {
     Error("Create", "can't set permissions for tag DB file");
     fTagDB = 0;
     return kFALSE;
   }

   // Create ROOT Tree object container
   fTree = new TTree("T", Form("ALICE raw-data tag tree (%s)", AliRawDB::GetAliRootTag()));
   fTree->SetAutoSave(100000000);  // autosave when 100 Mbyte written

   Int_t bufsize = 32000;
   Int_t split   = 1;
   const char *tagname = fEventTag->GetName();
   fTree->Branch("TAG", tagname, &fEventTag, bufsize, split);

   return kTRUE;
}

//______________________________________________________________________________
void AliTagDB::Close()
{
   // Close tag DB.

   if (!fTagDB) return;

   fTagDB->cd();

   // Write the tree.
   fTree->Write();

   // Close DB, this also deletes the fTree
   fTagDB->Close();

   if (fDeleteFiles)
      gSystem->Unlink(fTagDB->GetName());

   delete fTagDB;
   fTagDB = 0;
}

//______________________________________________________________________________
Bool_t AliTagDB::NextFile(const char* fileName)
{
   // Close te current file and open a new one.
   // Returns kFALSE in case opening failed.

   Close();

   if (!Create(fileName)) return kFALSE;
   return kTRUE;
}

//______________________________________________________________________________
void AliTagDB::SetFS(const char* fs)
{
// set the file system location

  fFS = fs;
  if (fs) {
    gSystem->ResetErrno();
    gSystem->MakeDirectory(fs);
    if (gSystem->GetErrno() && gSystem->GetErrno() != EEXIST) {
      SysError("SetFS", "mkdir %s", fs);
    }
  }
}

//______________________________________________________________________________
Float_t AliTagDB::GetCompressionFactor() const
{
   // Return compression factor.

   if (fTree->GetZipBytes() == 0.)
      return 1.0;
   else
      return fTree->GetTotBytes()/fTree->GetZipBytes();
}

//______________________________________________________________________________
const char *AliTagDB::GetFileName() const
{
   // Return filename based on hostname and date and time. This will make
   // each file unique. The tags will be stored in the /data1/tags directory.

   static TString fname;
   const char *fs = fFS;

   // check that fs exists (crude check fails if fs is a file)
   gSystem->MakeDirectory(fs);

   // Get the run number
   Int_t runNumber = -1;
   if (fEventTag) {
     AliRawEventHeaderBase *header = fEventTag->GetHeader();
     if (header) runNumber = header->Get("RunNb");
   }

   TString hostname;
   hostname.Form("%s",gSystem->HostName());
   hostname.Resize(hostname.First('.'));

   TTimeStamp ts;

   fname.Form("%s/Run%d.%s_%d_%d_%d.RAW.tag.root", fs, runNumber, hostname.Data(),
	      ts.GetDate(), ts.GetTime(), ts.GetNanoSec());

   return fname.Data();
}
<|endoftext|>


<commit_before>#include <windows.h>
#include <OvRender.h>
#include <sloverlay.h>
#include <overlay.h>

SlOverlayMenu* Menu;

MenuVars MenuOsd[20];
MenuVars MenuGpu[10];

WCHAR* GroupOpt[] = {L"", L""};
WCHAR* ItemOpt[] = {L"Off", L"On"};

BOOLEAN MnuInitialized;
HANDLE MenuProcessHeap;

//Add menu items to menu

VOID AddItems()
{
    Menu->AddGroup(L"OSD", GroupOpt, &MenuOsd[0].Var);

    if (MenuOsd[0].Var)
    {
        Menu->AddItem(L"GPU Core utilization",    ItemOpt, &MenuOsd[1].Var);
        Menu->AddItem(L"GPU Core temperature",    ItemOpt, &MenuOsd[2].Var);
        Menu->AddItem(L"GPU Engine Clock",        ItemOpt, &MenuOsd[3].Var);
        Menu->AddItem(L"GPU Memory Clock",        ItemOpt, &MenuOsd[4].Var);
        Menu->AddItem(L"GPU VRAM usage",          ItemOpt, &MenuOsd[5].Var);
        Menu->AddItem(L"CPU utilization",         ItemOpt, &MenuOsd[6].Var);
        Menu->AddItem(L"CPU temperature",         ItemOpt, &MenuOsd[7].Var);
        Menu->AddItem(L"RAM usage",               ItemOpt, &MenuOsd[8].Var);
        Menu->AddItem(L"Max core usage",          ItemOpt, &MenuOsd[9].Var);
        Menu->AddItem(L"Max thread usage",        ItemOpt, &MenuOsd[10].Var);
        Menu->AddItem(L"Disk read-write rate",    ItemOpt, &MenuOsd[11].Var);
        Menu->AddItem(L"Disk response time",      ItemOpt, &MenuOsd[12].Var);
        Menu->AddItem(L"Frame Buffer count",      ItemOpt, &MenuOsd[13].Var);
        Menu->AddItem(L"Show Time",               ItemOpt, &MenuOsd[14].Var);
        Menu->AddItem(L"Reset Overloads",         ItemOpt, &MenuOsd[15].Var);
    }

    Menu->AddGroup(L"GPU", GroupOpt, &MenuGpu[0].Var);

    if (MenuGpu[0].Var)
    {
        Menu->AddItem(L"Force Max Clocks", ItemOpt, &MenuGpu[1].Var);
        Menu->AddItem(L"NULL", ItemOpt, &MenuGpu[2].Var);
        Menu->AddItem(L"NULL", ItemOpt, &MenuGpu[3].Var);
        Menu->AddItem(L"NULL", ItemOpt, &MenuGpu[4].Var);
    }
}

VOID ProcessOptions()
{
    if (MenuOsd[1].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_GPU_LOAD;
    /*else
        PushSharedMemory->OSDFlags &= ~OSD_GPU_LOAD;*/
    //this needs to be fixed, if it was enable by main gui
    //checkbox then it'll get disabled. too lazy...

    if (MenuOsd[2].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_GPU_TEMP;

    if (MenuOsd[3].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_GPU_E_CLK;

    if (MenuOsd[4].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_GPU_M_CLK;

    if (MenuOsd[7].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_CPU_TEMP;

    if (MenuOsd[8].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_RAM;

    if (MenuOsd[9].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_MCU;

    if (MenuOsd[10].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_MTU;

    if (MenuOsd[11].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_DISK_RWRATE;

    if (MenuOsd[12].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_DISK_RESPONSE;

    if (MenuOsd[14].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_TIME;

    if (MenuOsd[15].Var > 0)
    {
        PushSharedMemory->Overloads = 0;
        MenuOsd[15].Var = 0;
    }

    if (MenuGpu[1].Var > 0)
    {
        HANDLE hPipe;
        DWORD dwWritten;
        WCHAR command[] = L"ForceMaxClocks";

        hPipe = CreateFile(TEXT("\\\\.\\pipe\\Push"),
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);

        if (hPipe != INVALID_HANDLE_VALUE)
        {
            WriteFile(hPipe, command, sizeof(command), &dwWritten, NULL);
            CloseHandle(hPipe);
        }

        PushSharedMemory->OSDFlags |= OSD_GPU_E_CLK;
        PushSharedMemory->OSDFlags |= OSD_GPU_M_CLK;
        PushSharedMemory->Overloads &= ~OSD_GPU_E_CLK;
        PushSharedMemory->Overloads &= ~OSD_GPU_M_CLK;
    }
}

VOID MnuRender( OvOverlay* Overlay )
{
    if (!MnuInitialized)
    {
        Menu = new SlOverlayMenu(300);
        MnuInitialized = TRUE;
    }

    if( Menu->mSet.MaxItems == 0 )
        AddItems();

    //Call drawing and navigation functions
    Menu->Render(100, 200, Overlay);
}

#define GROUP 1
#define ITEM  2
#define HEIGHT 16

DWORD LightBlue = 0xFF4DD0EB;
DWORD Green     = 0xFF33FF00;
DWORD White     = 0xFFE6E6E6;
DWORD Blue      = 0xFF00A4C5;

WNDPROC         OldWNDPROC;
SlOverlayMenu*  OvmMenu;

VOID MenuKeyboardHook( WPARAM Key )
{
    if (!OvmMenu)
        return;

    if (Key == VK_INSERT || Key == VK_UP || Key == VK_DOWN || Key == VK_LEFT || Key == VK_RIGHT)
    {
        switch (Key)
        {
        case VK_INSERT:
            OvmMenu->mSet.Show = !OvmMenu->mSet.Show;
            break;

        case VK_UP:
        {
            if (!OvmMenu->mSet.Show)
                break;

            OvmMenu->mSet.SeletedIndex--;

            if (OvmMenu->mSet.SeletedIndex < 0)
                OvmMenu->mSet.SeletedIndex = OvmMenu->mSet.MaxItems - 1;

        } break;

        case VK_DOWN:
        {
            if (!OvmMenu->mSet.Show)
                break;

            OvmMenu->mSet.SeletedIndex++;

            if (OvmMenu->mSet.SeletedIndex == OvmMenu->mSet.MaxItems)
                OvmMenu->mSet.SeletedIndex = 0;

        } break;

        case VK_LEFT:
        {
            if (!OvmMenu->mSet.Show)
                break;

            if (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var && *OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var > 0)
            {
                *OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var += -1;

                if (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Type == GROUP)
                    OvmMenu->mSet.MaxItems = 0;
            }

        } break;

        case VK_RIGHT:
        {
            if (!OvmMenu->mSet.Show)
                break;

            if (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var
                && *OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var < (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].MaxValue - 1))
            {
                *OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var += 1;

                if (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Type == GROUP)
                    OvmMenu->mSet.MaxItems = 0;
            }

        } break;
        }

        // Update osd items.
        ProcessOptions();
    }
}

SlOverlayMenu::SlOverlayMenu( int OptionsX )
{
    OpX = OptionsX;

    mSet.Show = FALSE;
    mSet.MaxItems = 0;
    mSet.SeletedIndex = 0;

    OvmMenu = this;
    MenuProcessHeap = GetProcessHeap();
}

void SlOverlayMenu::AddItemToMenu(WCHAR* Title, WCHAR** Options, int* Var, int MaxValue, int Type)
{
    Items[mSet.MaxItems].Title = Title;
    Items[mSet.MaxItems].Options= Options;
    Items[mSet.MaxItems].Var = Var;
    Items[mSet.MaxItems].MaxValue = MaxValue;
    Items[mSet.MaxItems].Type = Type;
    mSet.MaxItems++;
}

VOID
SlOverlayMenu::Render( int X, int Y, OvOverlay* Overlay )
{
    DWORD ColorOne, ColorTwo;
    int ValueOne, ValueTwo;

    if (!mSet.Show)
        return;

    for (int i = 0; i < mSet.MaxItems; i++)
    {
        ValueOne = (Items[i].Var) ? (*Items[i].Var) : 0;
        ValueTwo = (Items[i].Var) ? (*Items[i].Var) : 0;

        if (i == mSet.SeletedIndex)
        {
            ColorOne = LightBlue;
            ColorTwo = (ValueTwo) ? Green : White;
        }
        else if (Items[i].Type == GROUP)
        {
            ColorOne = Blue;
            ColorTwo = Blue;
        }
        else
        {
            ColorOne = (ValueOne) ? White : White;
            ColorTwo = (ValueTwo) ? Green : White;
        }

        if (Items[i].Type == GROUP)
            Overlay->DrawText(Items[i].Title, X, Y, ColorOne);

        if (Items[i].Type == ITEM)
            Overlay->DrawText(Items[i].Title, X + 20, Y, ColorOne);

        if (Items[i].Options)
            Overlay->DrawText(Items[i].Options[ValueTwo], OpX, Y, ColorTwo);

        Y += HEIGHT;
    }
}
<commit_msg>makes more sense than on/off<commit_after>#include <windows.h>
#include <OvRender.h>
#include <sloverlay.h>
#include <overlay.h>

SlOverlayMenu* Menu;

MenuVars MenuOsd[20];
MenuVars MenuGpu[10];

WCHAR* GroupOpt[] = {L"", L""};
WCHAR* ItemOpt[] = {L"Off", L"On"};
WCHAR* PressOpt[] = { L">>", L">>" };

BOOLEAN MnuInitialized;
HANDLE MenuProcessHeap;

//Add menu items to menu

VOID AddItems()
{
    Menu->AddGroup(L"OSD", GroupOpt, &MenuOsd[0].Var);

    if (MenuOsd[0].Var)
    {
        Menu->AddItem(L"GPU Core utilization",    ItemOpt, &MenuOsd[1].Var);
        Menu->AddItem(L"GPU Core temperature",    ItemOpt, &MenuOsd[2].Var);
        Menu->AddItem(L"GPU Engine Clock",        ItemOpt, &MenuOsd[3].Var);
        Menu->AddItem(L"GPU Memory Clock",        ItemOpt, &MenuOsd[4].Var);
        Menu->AddItem(L"GPU VRAM usage",          ItemOpt, &MenuOsd[5].Var);
        Menu->AddItem(L"CPU utilization",         ItemOpt, &MenuOsd[6].Var);
        Menu->AddItem(L"CPU temperature",         ItemOpt, &MenuOsd[7].Var);
        Menu->AddItem(L"RAM usage",               ItemOpt, &MenuOsd[8].Var);
        Menu->AddItem(L"Max core usage",          ItemOpt, &MenuOsd[9].Var);
        Menu->AddItem(L"Max thread usage",        ItemOpt, &MenuOsd[10].Var);
        Menu->AddItem(L"Disk read-write rate",    ItemOpt, &MenuOsd[11].Var);
        Menu->AddItem(L"Disk response time",      ItemOpt, &MenuOsd[12].Var);
        Menu->AddItem(L"Frame Buffer count",      ItemOpt, &MenuOsd[13].Var);
        Menu->AddItem(L"Show Time",               ItemOpt, &MenuOsd[14].Var);
        Menu->AddItem(L"Reset Overloads",         PressOpt, &MenuOsd[15].Var);
    }

    Menu->AddGroup(L"GPU", GroupOpt, &MenuGpu[0].Var);

    if (MenuGpu[0].Var)
    {
        Menu->AddItem(L"Force Max Clocks", ItemOpt, &MenuGpu[1].Var);
        Menu->AddItem(L"NULL", ItemOpt, &MenuGpu[2].Var);
        Menu->AddItem(L"NULL", ItemOpt, &MenuGpu[3].Var);
        Menu->AddItem(L"NULL", ItemOpt, &MenuGpu[4].Var);
    }
}

VOID ProcessOptions()
{
    if (MenuOsd[1].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_GPU_LOAD;
    /*else
        PushSharedMemory->OSDFlags &= ~OSD_GPU_LOAD;*/
    //this needs to be fixed, if it was enable by main gui
    //checkbox then it'll get disabled. too lazy...

    if (MenuOsd[2].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_GPU_TEMP;

    if (MenuOsd[3].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_GPU_E_CLK;

    if (MenuOsd[4].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_GPU_M_CLK;

    if (MenuOsd[7].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_CPU_TEMP;

    if (MenuOsd[8].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_RAM;

    if (MenuOsd[9].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_MCU;

    if (MenuOsd[10].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_MTU;

    if (MenuOsd[11].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_DISK_RWRATE;

    if (MenuOsd[12].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_DISK_RESPONSE;

    if (MenuOsd[14].Var > 0)
        PushSharedMemory->OSDFlags |= OSD_TIME;

    if (MenuOsd[15].Var > 0)
    {
        PushSharedMemory->Overloads = 0;
        MenuOsd[15].Var = 0;
    }

    if (MenuGpu[1].Var > 0)
    {
        HANDLE hPipe;
        DWORD dwWritten;
        WCHAR command[] = L"ForceMaxClocks";

        hPipe = CreateFile(TEXT("\\\\.\\pipe\\Push"),
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);

        if (hPipe != INVALID_HANDLE_VALUE)
        {
            WriteFile(hPipe, command, sizeof(command), &dwWritten, NULL);
            CloseHandle(hPipe);
        }

        PushSharedMemory->OSDFlags |= OSD_GPU_E_CLK;
        PushSharedMemory->OSDFlags |= OSD_GPU_M_CLK;
        PushSharedMemory->Overloads &= ~OSD_GPU_E_CLK;
        PushSharedMemory->Overloads &= ~OSD_GPU_M_CLK;
    }
}

VOID MnuRender( OvOverlay* Overlay )
{
    if (!MnuInitialized)
    {
        Menu = new SlOverlayMenu(300);
        MnuInitialized = TRUE;
    }

    if( Menu->mSet.MaxItems == 0 )
        AddItems();

    //Call drawing and navigation functions
    Menu->Render(100, 200, Overlay);
}

#define GROUP 1
#define ITEM  2
#define HEIGHT 16

DWORD LightBlue = 0xFF4DD0EB;
DWORD Green     = 0xFF33FF00;
DWORD White     = 0xFFE6E6E6;
DWORD Blue      = 0xFF00A4C5;

WNDPROC         OldWNDPROC;
SlOverlayMenu*  OvmMenu;

VOID MenuKeyboardHook( WPARAM Key )
{
    if (!OvmMenu)
        return;

    if (Key == VK_INSERT || Key == VK_UP || Key == VK_DOWN || Key == VK_LEFT || Key == VK_RIGHT)
    {
        switch (Key)
        {
        case VK_INSERT:
            OvmMenu->mSet.Show = !OvmMenu->mSet.Show;
            break;

        case VK_UP:
        {
            if (!OvmMenu->mSet.Show)
                break;

            OvmMenu->mSet.SeletedIndex--;

            if (OvmMenu->mSet.SeletedIndex < 0)
                OvmMenu->mSet.SeletedIndex = OvmMenu->mSet.MaxItems - 1;

        } break;

        case VK_DOWN:
        {
            if (!OvmMenu->mSet.Show)
                break;

            OvmMenu->mSet.SeletedIndex++;

            if (OvmMenu->mSet.SeletedIndex == OvmMenu->mSet.MaxItems)
                OvmMenu->mSet.SeletedIndex = 0;

        } break;

        case VK_LEFT:
        {
            if (!OvmMenu->mSet.Show)
                break;

            if (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var && *OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var > 0)
            {
                *OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var += -1;

                if (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Type == GROUP)
                    OvmMenu->mSet.MaxItems = 0;
            }

        } break;

        case VK_RIGHT:
        {
            if (!OvmMenu->mSet.Show)
                break;

            if (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var
                && *OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var < (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].MaxValue - 1))
            {
                *OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Var += 1;

                if (OvmMenu->Items[OvmMenu->mSet.SeletedIndex].Type == GROUP)
                    OvmMenu->mSet.MaxItems = 0;
            }

        } break;
        }

        // Update osd items.
        ProcessOptions();
    }
}

SlOverlayMenu::SlOverlayMenu( int OptionsX )
{
    OpX = OptionsX;

    mSet.Show = FALSE;
    mSet.MaxItems = 0;
    mSet.SeletedIndex = 0;

    OvmMenu = this;
    MenuProcessHeap = GetProcessHeap();
}

void SlOverlayMenu::AddItemToMenu(WCHAR* Title, WCHAR** Options, int* Var, int MaxValue, int Type)
{
    Items[mSet.MaxItems].Title = Title;
    Items[mSet.MaxItems].Options= Options;
    Items[mSet.MaxItems].Var = Var;
    Items[mSet.MaxItems].MaxValue = MaxValue;
    Items[mSet.MaxItems].Type = Type;
    mSet.MaxItems++;
}

VOID
SlOverlayMenu::Render( int X, int Y, OvOverlay* Overlay )
{
    DWORD ColorOne, ColorTwo;
    int ValueOne, ValueTwo;

    if (!mSet.Show)
        return;

    for (int i = 0; i < mSet.MaxItems; i++)
    {
        ValueOne = (Items[i].Var) ? (*Items[i].Var) : 0;
        ValueTwo = (Items[i].Var) ? (*Items[i].Var) : 0;

        if (i == mSet.SeletedIndex)
        {
            ColorOne = LightBlue;
            ColorTwo = (ValueTwo) ? Green : White;
        }
        else if (Items[i].Type == GROUP)
        {
            ColorOne = Blue;
            ColorTwo = Blue;
        }
        else
        {
            ColorOne = (ValueOne) ? White : White;
            ColorTwo = (ValueTwo) ? Green : White;
        }

        if (Items[i].Type == GROUP)
            Overlay->DrawText(Items[i].Title, X, Y, ColorOne);

        if (Items[i].Type == ITEM)
            Overlay->DrawText(Items[i].Title, X + 20, Y, ColorOne);

        if (Items[i].Options)
            Overlay->DrawText(Items[i].Options[ValueTwo], OpX, Y, ColorTwo);

        Y += HEIGHT;
    }
}
<|endoftext|>


<commit_before>#include <net/VRNetServer.h>

#include <main/VRLog.h>
#include <main/VRError.h>

using namespace std;

namespace MinVR {

#define PORT "3490"  // the port users will be connecting to

#define BACKLOG 100	 // how many pending connections queue will hold

#ifndef WIN32
void sigchld_handler(int s) {
	while (waitpid(-1, NULL, WNOHANG) > 0);
}
#endif

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
  if (sa->sa_family == AF_INET) {
    return &(((struct sockaddr_in*)sa)->sin_addr);
  }
  return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

VRNetServer::VRNetServer(const std::string &listenPort, int numExpectedClients)
{

  VRLOG_STATUS("VRNetServer starting networking.");

#ifdef WIN32  // Winsock implementation

  WSADATA wsaData;

  // listen on sock_fd, new connection on new_fd
  SOCKET sockfd = INVALID_SOCKET;
  SOCKET new_fd = INVALID_SOCKET;
  struct addrinfo hints, *servinfo, *p;
  struct sockaddr_storage their_addr; // connector's address information
  socklen_t sin_size;
  const char yes = 1;
  char saddr[INET6_ADDRSTRLEN];
  int rv;

  rv = WSAStartup(MAKEWORD(2,2), &wsaData);
  if (rv != 0) {
    stringstream s;
    s << "WSAStartup failed with error: " << rv;
    VRERROR(s, "Check for a problem with Windows networking.");    exit(1);
  }

  ZeroMemory(&hints, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;
  hints.ai_flags = AI_PASSIVE; // use my IP

  if ((rv = getaddrinfo(NULL, listenPort.c_str(), &hints, &servinfo)) != 0) {
    stringstream s;
    s << "getaddrinfo() failed with error: " << rv;
    VRERROR(s.str(), "Check for a problem with Windows networking.");
    WSACleanup();
    exit(1);
  }

  // loop through all the results and bind to the first we can
  for (p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == INVALID_SOCKET) {
      stringstream s;
      s << "socket() failed with error " << WSAGetLastError() << "; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == SOCKET_ERROR) {
      stringstream s;
      s << "setsockopt() failed with error " << WSAGetLastError() << ".";
      VRERROR(s.str(), "Check for a problem with Windows networking.");
      closesocket(sockfd);
      WSACleanup();
      exit(1);
    }

    if (bind(sockfd, p->ai_addr, (int)p->ai_addrlen) == SOCKET_ERROR) {
      closesocket(sockfd);
      sockfd = INVALID_SOCKET;
      stringstream s;
      s << "bind() failed with error " << WSAGetLastError() << "; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    break;
  }

  if (p == NULL) {
    VRERROR("VRNetServer failed to bind -- exiting.", "Check for a problem with Windows networking.");
    exit(2);
  }

  freeaddrinfo(servinfo); // all done with this structure

  if (listen(sockfd, BACKLOG) == SOCKET_ERROR) {
    stringstream s;
    s << "listen() failed with error " << WSAGetLastError() << ".";
    VRERROR(s.str(), "Check for a problem with Windows networking.");
    closesocket(sockfd);
    WSACleanup();
    exit(1);
  }

  // Should we do the "reap all dead processes" as in the linux implementation below?

  VRLOG_STATUS("VRNetServer waiting for client connection(s)...");

  int numConnected = 0;
  while (numConnected < numExpectedClients) {
    sin_size = sizeof their_addr;
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
    if (new_fd == INVALID_SOCKET) {
      stringstream s;
      s << "accept() got an INVALID_SOCKET; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    // Disable Nagle's algorithm on the client's socket
    char value = 1;
    setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));

    numConnected++;
    inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), saddr, sizeof saddr);
    stringstream s;
    s << "Received connection " << numConnected << " of " << numExpectedClients << " from " << saddr;
    VRLOG_STATUS(s.str());

    _clientSocketFDs.push_back(new_fd);
  }
  VRLOG_STATUS("Established all expected connections.");

#else  // BSD sockets implementation

  int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
  struct addrinfo hints, *servinfo, *p;
  struct sockaddr_storage their_addr; // connector's address information
  socklen_t sin_size;
  struct sigaction sa;
  int yes=1;
  char saddr[INET6_ADDRSTRLEN];
  int rv;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE; // use my IP

  if ((rv = getaddrinfo(NULL, listenPort.c_str(), &hints, &servinfo)) != 0) {
    stringstream s;
    s << "getaddrinfo() failed with error: " << gai_strerror(rv);
    VRERROR(s.str(), "Check for a problem with networking.");
    exit(1);
  }

  // loop through all the results and bind to the first we can
  for (p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
      stringstream s;
      s << "socket() failed; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
      stringstream s;
      s << "setsockopt() failed.";
      VRERROR(s.str(), "Check for a problem with networking.");
      exit(1);
    }

      if (::bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
      close(sockfd);
      stringstream s;
      s << "bind() failed; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    break;
  }

  if (p == NULL)  {
    VRERROR("VRNetServer failed to bind -- exiting.", "Check for a problem with networking.");
    exit(2);
  }

  freeaddrinfo(servinfo); // all done with this structure

  if (listen(sockfd, BACKLOG) == -1) {
    stringstream s;
    s << "listen() failed.";
    VRERROR(s.str(), "Check for a problem with networking.");
    exit(1);
  }

  sa.sa_handler = sigchld_handler; // reap all dead processes
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_RESTART;
  if (sigaction(SIGCHLD, &sa, NULL) == -1) {
    stringstream s;
    s << "sigaction() failed.";
    VRERROR(s.str(), "Check for a problem with networking.");
    exit(1);
  }

  VRLOG_STATUS("VRNetServer waiting for client connection(s)...");

  int numConnected = 0;
  while (numConnected < numExpectedClients) {
    sin_size = sizeof their_addr;
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
    if (new_fd == -1) {
      stringstream s;
      s << "accept() failed; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    // Disable Nagle's algorithm on the client's socket
    char value = 1;
    setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));

    numConnected++;
    inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), saddr, sizeof saddr);

    stringstream s;
    s << "Received connection " << numConnected << " of " << numExpectedClients << " from " << saddr;
    VRLOG_STATUS(s.str());

    _clientSocketFDs.push_back(new_fd);
  }

#endif
}

VRNetServer::~VRNetServer()
{
  VRLOG_STATUS("VRNetServer closing all sockets.");
  for (std::vector<SOCKET>::iterator i=_clientSocketFDs.begin(); i < _clientSocketFDs.end(); i++) {
	#ifdef WIN32
      closesocket(*i);
    #else
      close(*i);
    #endif
  }

#ifdef WIN32
  WSACleanup();
#endif
}

// Wait for and receive an eventData message from every client, add
// them together and send them out again.
VRDataQueue VRNetServer::syncEventDataAcrossAllNodes(VRDataQueue eventQueue) {

  // TODO: rather than a for loop, could use a select() system call
  // here (I think) to figure out which socket is ready for a read in
  // the situation where one client is ready but other(s) are not
  for (std::vector<SOCKET>::iterator itr=_clientSocketFDs.begin();
       itr < _clientSocketFDs.end(); itr++) {
    VRDataQueue::serialData eventData = waitForAndReceiveEventData(*itr);

    eventQueue.addQueue(eventData);
  }

  VRDataQueue::serialData serializedEventQueue = eventQueue.serialize();
  // 2. send new combined inputEvents array out to all clients
  for (std::vector<SOCKET>::iterator itr=_clientSocketFDs.begin();
       itr < _clientSocketFDs.end(); itr++) {
    sendEventData(*itr, serializedEventQueue);
  }

  return eventQueue;
}

void VRNetServer::syncSwapBuffersAcrossAllNodes() {
  // 1. wait for, receive, and parse a swap_buffers_request message
  // from every client

  // TODO: rather than a for loop could use a select() system call
  // here (I think) to figure out which socket is ready for a read in
  // the situation where 1 is ready but other(s) are not
  for (std::vector<SOCKET>::iterator itr=_clientSocketFDs.begin();
       itr < _clientSocketFDs.end(); itr++) {
    waitForAndReceiveSwapBuffersRequest(*itr);
  }

  // 2. send a swap_buffers_now message to every client
  for (std::vector<SOCKET>::iterator itr=_clientSocketFDs.begin();
       itr < _clientSocketFDs.end(); itr++) {
    sendSwapBuffersNow(*itr);
  }
}

} // end namespace MinVR
<commit_msg>Update VRNetServer.cpp<commit_after>#include <net/VRNetServer.h>

#include <main/VRLog.h>
#include <main/VRError.h>

using namespace std;

namespace MinVR {

#define PORT "3490"  // the port users will be connecting to

#define BACKLOG 100	 // how many pending connections queue will hold

#ifndef WIN32
void sigchld_handler(int s) {
	while (waitpid(-1, NULL, WNOHANG) > 0);
}
#endif

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa) {
  if (sa->sa_family == AF_INET) {
    return &(((struct sockaddr_in*)sa)->sin_addr);
  }
  return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

VRNetServer::VRNetServer(const std::string &listenPort, int numExpectedClients)
{

  VRLOG_STATUS("VRNetServer starting networking.");

#ifdef WIN32  // Winsock implementation

  WSADATA wsaData;

  // listen on sock_fd, new connection on new_fd
  SOCKET sockfd = INVALID_SOCKET;
  SOCKET new_fd = INVALID_SOCKET;
  struct addrinfo hints, *servinfo, *p;
  struct sockaddr_storage their_addr; // connector's address information
  socklen_t sin_size;
  const char yes = 1;
  char saddr[INET6_ADDRSTRLEN];
  int rv;

  rv = WSAStartup(MAKEWORD(2,2), &wsaData);
  if (rv != 0) {
    stringstream s;
    s << "WSAStartup failed with error: " << rv;
    VRERROR(s.str(), "Check for a problem with Windows networking.");    exit(1);
  }

  ZeroMemory(&hints, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;
  hints.ai_flags = AI_PASSIVE; // use my IP

  if ((rv = getaddrinfo(NULL, listenPort.c_str(), &hints, &servinfo)) != 0) {
    stringstream s;
    s << "getaddrinfo() failed with error: " << rv;
    VRERROR(s.str(), "Check for a problem with Windows networking.");
    WSACleanup();
    exit(1);
  }

  // loop through all the results and bind to the first we can
  for (p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == INVALID_SOCKET) {
      stringstream s;
      s << "socket() failed with error " << WSAGetLastError() << "; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == SOCKET_ERROR) {
      stringstream s;
      s << "setsockopt() failed with error " << WSAGetLastError() << ".";
      VRERROR(s.str(), "Check for a problem with Windows networking.");
      closesocket(sockfd);
      WSACleanup();
      exit(1);
    }

    if (bind(sockfd, p->ai_addr, (int)p->ai_addrlen) == SOCKET_ERROR) {
      closesocket(sockfd);
      sockfd = INVALID_SOCKET;
      stringstream s;
      s << "bind() failed with error " << WSAGetLastError() << "; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    break;
  }

  if (p == NULL) {
    VRERROR("VRNetServer failed to bind -- exiting.", "Check for a problem with Windows networking.");
    exit(2);
  }

  freeaddrinfo(servinfo); // all done with this structure

  if (listen(sockfd, BACKLOG) == SOCKET_ERROR) {
    stringstream s;
    s << "listen() failed with error " << WSAGetLastError() << ".";
    VRERROR(s.str(), "Check for a problem with Windows networking.");
    closesocket(sockfd);
    WSACleanup();
    exit(1);
  }

  // Should we do the "reap all dead processes" as in the linux implementation below?

  VRLOG_STATUS("VRNetServer waiting for client connection(s)...");

  int numConnected = 0;
  while (numConnected < numExpectedClients) {
    sin_size = sizeof their_addr;
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
    if (new_fd == INVALID_SOCKET) {
      stringstream s;
      s << "accept() got an INVALID_SOCKET; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    // Disable Nagle's algorithm on the client's socket
    char value = 1;
    setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));

    numConnected++;
    inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), saddr, sizeof saddr);
    stringstream s;
    s << "Received connection " << numConnected << " of " << numExpectedClients << " from " << saddr;
    VRLOG_STATUS(s.str());

    _clientSocketFDs.push_back(new_fd);
  }
  VRLOG_STATUS("Established all expected connections.");

#else  // BSD sockets implementation

  int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
  struct addrinfo hints, *servinfo, *p;
  struct sockaddr_storage their_addr; // connector's address information
  socklen_t sin_size;
  struct sigaction sa;
  int yes=1;
  char saddr[INET6_ADDRSTRLEN];
  int rv;

  memset(&hints, 0, sizeof hints);
  hints.ai_family = AF_UNSPEC;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_flags = AI_PASSIVE; // use my IP

  if ((rv = getaddrinfo(NULL, listenPort.c_str(), &hints, &servinfo)) != 0) {
    stringstream s;
    s << "getaddrinfo() failed with error: " << gai_strerror(rv);
    VRERROR(s.str(), "Check for a problem with networking.");
    exit(1);
  }

  // loop through all the results and bind to the first we can
  for (p = servinfo; p != NULL; p = p->ai_next) {
    if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
      stringstream s;
      s << "socket() failed; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
      stringstream s;
      s << "setsockopt() failed.";
      VRERROR(s.str(), "Check for a problem with networking.");
      exit(1);
    }

      if (::bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
      close(sockfd);
      stringstream s;
      s << "bind() failed; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    break;
  }

  if (p == NULL)  {
    VRERROR("VRNetServer failed to bind -- exiting.", "Check for a problem with networking.");
    exit(2);
  }

  freeaddrinfo(servinfo); // all done with this structure

  if (listen(sockfd, BACKLOG) == -1) {
    stringstream s;
    s << "listen() failed.";
    VRERROR(s.str(), "Check for a problem with networking.");
    exit(1);
  }

  sa.sa_handler = sigchld_handler; // reap all dead processes
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = SA_RESTART;
  if (sigaction(SIGCHLD, &sa, NULL) == -1) {
    stringstream s;
    s << "sigaction() failed.";
    VRERROR(s.str(), "Check for a problem with networking.");
    exit(1);
  }

  VRLOG_STATUS("VRNetServer waiting for client connection(s)...");

  int numConnected = 0;
  while (numConnected < numExpectedClients) {
    sin_size = sizeof their_addr;
    new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
    if (new_fd == -1) {
      stringstream s;
      s << "accept() failed; will retry.";
      VRLOG_STATUS(s.str());
      continue;
    }

    // Disable Nagle's algorithm on the client's socket
    char value = 1;
    setsockopt(new_fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value));

    numConnected++;
    inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr *)&their_addr), saddr, sizeof saddr);

    stringstream s;
    s << "Received connection " << numConnected << " of " << numExpectedClients << " from " << saddr;
    VRLOG_STATUS(s.str());

    _clientSocketFDs.push_back(new_fd);
  }

#endif
}

VRNetServer::~VRNetServer()
{
  VRLOG_STATUS("VRNetServer closing all sockets.");
  for (std::vector<SOCKET>::iterator i=_clientSocketFDs.begin(); i < _clientSocketFDs.end(); i++) {
	#ifdef WIN32
      closesocket(*i);
    #else
      close(*i);
    #endif
  }

#ifdef WIN32
  WSACleanup();
#endif
}

// Wait for and receive an eventData message from every client, add
// them together and send them out again.
VRDataQueue VRNetServer::syncEventDataAcrossAllNodes(VRDataQueue eventQueue) {

  // TODO: rather than a for loop, could use a select() system call
  // here (I think) to figure out which socket is ready for a read in
  // the situation where one client is ready but other(s) are not
  for (std::vector<SOCKET>::iterator itr=_clientSocketFDs.begin();
       itr < _clientSocketFDs.end(); itr++) {
    VRDataQueue::serialData eventData = waitForAndReceiveEventData(*itr);

    eventQueue.addQueue(eventData);
  }

  VRDataQueue::serialData serializedEventQueue = eventQueue.serialize();
  // 2. send new combined inputEvents array out to all clients
  for (std::vector<SOCKET>::iterator itr=_clientSocketFDs.begin();
       itr < _clientSocketFDs.end(); itr++) {
    sendEventData(*itr, serializedEventQueue);
  }

  return eventQueue;
}

void VRNetServer::syncSwapBuffersAcrossAllNodes() {
  // 1. wait for, receive, and parse a swap_buffers_request message
  // from every client

  // TODO: rather than a for loop could use a select() system call
  // here (I think) to figure out which socket is ready for a read in
  // the situation where 1 is ready but other(s) are not
  for (std::vector<SOCKET>::iterator itr=_clientSocketFDs.begin();
       itr < _clientSocketFDs.end(); itr++) {
    waitForAndReceiveSwapBuffersRequest(*itr);
  }

  // 2. send a swap_buffers_now message to every client
  for (std::vector<SOCKET>::iterator itr=_clientSocketFDs.begin();
       itr < _clientSocketFDs.end(); itr++) {
    sendSwapBuffersNow(*itr);
  }
}

} // end namespace MinVR
<|endoftext|>


<commit_before>/** This is a TcpServer's performance test.
  * It could be run in N different modes:
  * 1) Local throughput test:
  *     Clients and server created on the same machine and communicates through the loopback.
  *     This mode is designated to test server performance locally, on a single machine. And
  *     this mode is very limited because clients affects the server performance.
  * 2) Server mode:
  *     Application starts in server mode and accepts incomming connections. It can be termia
  *     ted using ^C signal. This mode can be used to test server performance in isolation.
  *     Also, this test mode takes network into account. Application should dump number of me
  *     ssages per second to stdout.
  * 3) Client mode:
  *     Application started in client mode can connect to server (the same application should
  *     be started on another node in server mode) and dump specified number of messages to
  *     the server.
  *
  * Parameters:
  * a) `mode` can accept three parameters - 'client', 'server' or 'local'.
  * b) `host` url or ip of the server if app was started in client mode.
  * c) `count` number of messages to send inf started in client mode.
  * d) `njobs` number of threads to use
  */
#include <iostream>
#include <thread>
#include <boost/thread/barrier.hpp>
#include <boost/program_options.hpp>

#include "tcp_server.h"
#include "perftest_tools.h"
#include <sys/time.h>

using namespace Akumuli;
namespace po = boost::program_options;

struct DbMock : DbConnection {
    typedef std::tuple<aku_ParamId, aku_TimeStamp, double> ValueT;
    aku_ParamId idsum;
    aku_TimeStamp tssum;
    double valsum;

    DbMock() {
        idsum  = 0;
        tssum  = 0;
        valsum = 0;
    }

    void write_double(aku_ParamId param, aku_TimeStamp ts, double data) {
        idsum  += param;
        tssum  += ts;
        valsum += data;
    }
};

enum Mode {
    CLIENT,
    SERVER,
    LOCAL,
};

Mode str_to_mode(std::string str) {
    if (str == "client" || str == "CLIENT") {
        return CLIENT;
    } else if (str == "server" || str == "SERVER") {
        return SERVER;
    } else if (str == "local" || str == "LOCAL") {
        return LOCAL;
    }
    throw std::runtime_error("Bad mode value");
}

struct Server {

    Mode                                mode;
    std::shared_ptr<IngestionPipeline>  pline;
    std::shared_ptr<DbMock>             dbcon;
    std::shared_ptr<TcpServer>          serv;
    boost::asio::io_service             ioA;
    std::vector<IOService*>             iovec       = { &ioA };
    boost::barrier                      barrier;

    Server(Mode mode)
        : mode(mode)
        , barrier(iovec.size() + 1)
    {
        dbcon = std::make_shared<DbMock>();
        pline = std::make_shared<IngestionPipeline>(dbcon, AKU_LINEAR_BACKOFF);
        int port = 4096;
        serv = std::make_shared<TcpServer>(iovec, port, pline);
        pline->start();
        serv->start();
    }

    //! Run IO service
    void start() {
        auto iorun = [](IOService& io, boost::barrier& bar) {
            auto fn = [&]() {
                io.run();
                bar.wait();
            };
            return fn;
        };

        for (auto io: iovec) {
            std::thread iothread(iorun(*io, barrier));
            iothread.detach();
        }
    }

    void stop() {
        serv->stop();
        std::cout << "TcpServer stopped" << std::endl;

        // No need to joint I/O threads, just wait until they completes.
        barrier.wait();
        std::cout << "I/O threads stopped" << std::endl;

        pline->stop();
        std::cout << "Pipeline stopped" << std::endl;

        for (auto io: iovec) {
            io->stop();
        }
        std::cout << "I/O service stopped" << std::endl;

        std::cout << dbcon->idsum << " messages received" << std::endl;
    }
};

struct Client {
    int nthreads;
    int count;
    boost::barrier start_barrier, stop_barrier;
    EndpointT endpoint;

    Client(EndpointT ep, int nthreads = 4, int count = 2500000)
        : nthreads(nthreads)
        , count(count)
        , start_barrier(nthreads)
        , stop_barrier(nthreads + 1)
        , endpoint(ep)
    {
    }

    void start() {
        auto self = this;
        auto push = [self]() {
            IOService io;
            TcpSocket socket(io);
            std::cout << "Connecting to server at " << self->endpoint << std::endl;
            socket.connect(self->endpoint);
            self->start_barrier.wait();

            boost::asio::streambuf stream;
            std::ostream os(&stream);
            os << ":1\r\n" ":2\r\n" "+3.14\r\n";
            for (int i = self->count; i --> 0; ) {
                boost::asio::write(socket, stream);
            }
            socket.shutdown(TcpSocket::shutdown_both);
            self->stop_barrier.wait();
            std::cout << "Push process completed" << std::endl;
        };

        for (int i = 0; i < nthreads; i++) {
            std::thread th(push);
            th.detach();
        }
    }

    void wait() {
        stop_barrier.wait();
    }
};

int main(int argc, char *argv[]) {
    std::cout << "Tcp server performance test" << std::endl;
    po::options_description desc("Allowed options");
    /*
     * Parameters:
     * a) `mode` can accept three parameters - 'client', 'server' or 'local'.
     * b) `host` url or ip of the server if app was started in client mode.
     * c) `count` number of messages to send inf started in client mode.
     * d) `njobs` number of threads to use
     */
    std::string strmode;
    std::string host;
    int num_messages;
    desc.add_options()
        ("help",                                                                "produce help message")
        ("mode",    po::value<std::string>(&strmode)->default_value("local"),   "test mode")
        ("host",    po::value<std::string>(&host)->default_value("localhost"),  "server host in client mode")
        ("count",   po::value<int>(&num_messages)->default_value(1000000),      "number of messages to send")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << desc << std::endl;
        return 0;
    }

    Mode mode = str_to_mode(strmode);

    switch(mode) {
    case LOCAL: {
        Server server(mode);
        EndpointT ep(boost::asio::ip::address_v4::loopback(), 4096);
        Client client(ep);
        server.start();
        client.start();
        client.wait();
        server.stop();
        break;
    }
    case SERVER:
        break;
    case CLIENT:
        break;
    }

    return 0;
}
<commit_msg>WIP: tcp server test suite, tcp server now can send data to graphite, individual clients now can measure throughput<commit_after>/** This is a TcpServer's performance test.
  * It could be run in N different modes:
  * 1) Local throughput test:
  *     Clients and server created on the same machine and communicates through the loopback.
  *     This mode is designated to test server performance locally, on a single machine. And
  *     this mode is very limited because clients affects the server performance.
  * 2) Server mode:
  *     Application starts in server mode and accepts incomming connections. It can be termia
  *     ted using ^C signal. This mode can be used to test server performance in isolation.
  *     Also, this test mode takes network into account. Application should dump number of me
  *     ssages per second to stdout.
  * 3) Client mode:
  *     Application started in client mode can connect to server (the same application should
  *     be started on another node in server mode) and dump specified number of messages to
  *     the server.
  *
  * Parameters:
  * a) `mode` can accept three parameters - 'client', 'server' or 'local'.
  * b) `host` url or ip of the server if app was started in client mode.
  * c) `count` number of messages to send inf started in client mode.
  * d) `njobs` number of threads to use
  */
#include <iostream>
#include <thread>
#include <boost/thread/barrier.hpp>
#include <boost/program_options.hpp>

#include "tcp_server.h"
#include "perftest_tools.h"
#include <sys/time.h>

using namespace Akumuli;
namespace po = boost::program_options;

struct DbMock : DbConnection {
    typedef std::tuple<aku_ParamId, aku_TimeStamp, double> ValueT;
    aku_ParamId idsum;
    aku_TimeStamp tssum;
    double valsum;

    DbMock() {
        idsum  = 0;
        tssum  = 0;
        valsum = 0;
    }

    void write_double(aku_ParamId param, aku_TimeStamp ts, double data) {
        idsum  += param;
        tssum  += ts;
        valsum += data;
    }
};

enum Mode {
    CLIENT,
    SERVER,
    LOCAL,
};

Mode str_to_mode(std::string str) {
    if (str == "client" || str == "CLIENT") {
        return CLIENT;
    } else if (str == "server" || str == "SERVER") {
        return SERVER;
    } else if (str == "local" || str == "LOCAL") {
        return LOCAL;
    }
    throw std::runtime_error("Bad mode value");
}

struct Server {

    Mode                                mode;
    std::shared_ptr<IngestionPipeline>  pline;
    std::shared_ptr<DbMock>             dbcon;
    std::shared_ptr<TcpServer>          serv;
    boost::asio::io_service             ioA;
    std::vector<IOService*>             iovec       = { &ioA };
    boost::barrier                      barrier;

    Server(Mode mode)
        : mode(mode)
        , barrier(iovec.size() + 1)
    {
        dbcon = std::make_shared<DbMock>();
        pline = std::make_shared<IngestionPipeline>(dbcon, AKU_LINEAR_BACKOFF);
        int port = 4096;
        serv = std::make_shared<TcpServer>(iovec, port, pline);
        pline->start();
        serv->start();
    }

    //! Run IO service
    void start() {
        auto iorun = [](IOService& io, boost::barrier& bar) {
            auto fn = [&]() {
                io.run();
                bar.wait();
            };
            return fn;
        };

        for (auto io: iovec) {
            std::thread iothread(iorun(*io, barrier));
            iothread.detach();
        }
    }

    void stop() {
        serv->stop();
        std::cout << "TcpServer stopped" << std::endl;

        // No need to joint I/O threads, just wait until they completes.
        barrier.wait();
        std::cout << "I/O threads stopped" << std::endl;

        pline->stop();
        std::cout << "Pipeline stopped" << std::endl;

        for (auto io: iovec) {
            io->stop();
        }
        std::cout << "I/O service stopped" << std::endl;

        std::cout << dbcon->idsum << " messages received" << std::endl;
    }
};

struct Client {
    int nthreads;
    int count;
    boost::barrier start_barrier, stop_barrier;
    EndpointT endpoint;
    PerfTimer *timer;

    Client(EndpointT ep, PerfTimer *timer, int nthreads = 4, int count = 2500000)
        : nthreads(nthreads)
        , count(count)
        , start_barrier(nthreads + 1)
        , stop_barrier(nthreads + 1)
        , endpoint(ep)
        , timer(timer)
    {
    }

    void start() {
        auto self = this;
        auto push = [self]() {
            std::vector<double> threshold_values;
            IOService io;
            TcpSocket socket(io);
            std::cout << "Connecting to server at " << self->endpoint << std::endl;
            socket.connect(self->endpoint);
            self->start_barrier.wait();

            boost::asio::streambuf stream;
            std::ostream os(&stream);
            size_t nsent = 0u;
            double tm = self->timer->elapsed();
            for (int i = self->count; i --> 0; ) {
                os << ":1\r\n" ":2\r\n" "+3.14\r\n";
                nsent += boost::asio::write(socket, stream);
                if (nsent >= 1024*1024) {  // +1Mb was sent
                    double newtm = self->timer->elapsed();
                    threshold_values.push_back(newtm - tm);
                    nsent = 0u;
                    tm = newtm;
                }
            }
            socket.shutdown(TcpSocket::shutdown_both);
            self->stop_barrier.wait();
            std::cout << "Push process completed" << std::endl;
            if (threshold_values.size()) {
                std::sort(threshold_values.begin(), threshold_values.end());
                double min = threshold_values.front(), max = threshold_values.back();
                double sum = 0, avg = 0, med = threshold_values[threshold_values.size() / 2];
                for (auto x: threshold_values) { sum += x; }
                avg = sum / threshold_values.size();
                auto convert = [&](double val) {
                    // Convert seconds per Mb to Mb per second
                    return 1.0/val;
                };
                std::cout << "Push process performance" << std::endl;
                std::cout << "max: " << convert(min) << " Mb/sec" << std::endl;  // min and max should be
                std::cout << "min: " << convert(max) << " Mb/sec" << std::endl;  // swapped because of conv
                std::cout << "avg: " << convert(avg) << " Mb/sec" << std::endl;
                std::cout << "med: " << convert(med) << " Mb/sec" << std::endl;
            }
        };

        for (int i = 0; i < nthreads; i++) {
            std::thread th(push);
            th.detach();
        }

        start_barrier.wait();
        timer->restart();
    }

    void wait() {
        stop_barrier.wait();
    }
};

int main(int argc, char *argv[]) {
    std::cout << "Tcp server performance test" << std::endl;
    po::options_description desc("Allowed options");
    /*
     * Parameters:
     * a) `mode` can accept three parameters - 'client', 'server' or 'local'.
     * b) `host` url or ip of the server if app was started in client mode.
     * c) `count` number of messages to send inf started in client mode.
     * d) `njobs` number of threads to use
     */
    std::string strmode;
    std::string host;
    int num_messages;
    bool graphite_enabled = false;
    desc.add_options()
        ("help",                                                                 "produce help message")
        ("mode",     po::value<std::string>(&strmode)->default_value("local"),   "test mode")
        ("host",     po::value<std::string>(&host)->default_value("localhost"),  "server host in client mode")
        ("count",    po::value<int>(&num_messages)->default_value(1000000),      "number of messages to send")
        ("graphite", po::value<bool>(&graphite_enabled)->default_value(false),   "push result to graphite")
    ;

    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

    if (vm.count("help")) {
        std::cout << desc << std::endl;
        return 0;
    }

    Mode mode = str_to_mode(strmode);

    switch(mode) {
    case LOCAL: {
        PerfTimer tm;
        Server server(mode);
        EndpointT ep(boost::asio::ip::address_v4::loopback(), 4096);
        Client client(ep, &tm, 4, 2500000);
        server.start();
        client.start();
        client.wait();
        server.stop();
        double elapsed = tm.elapsed();
        std::cout << "Local test completed in " << elapsed << " seconds" << std::endl;
        if (graphite_enabled) {
            push_metric_to_graphite("tcp_server_local", elapsed);
        }
        break;
    }
    case SERVER:
        break;
    case CLIENT:
        break;
    }

    return 0;
}
<|endoftext|>


<commit_before>#include "workerCL.hpp"

#define __CL_DEFINE_EXCEPTIONS
#include <CL/cl.hpp>

#include <vector>
#include <string>
#include <iostream>

#include "log.hpp"
#include "reads.hpp"

using namespace std;

WorkerCL::WorkerCL(size_t platform_id, size_t device_id){
	/* GPU environment preparation */

	//Get platforms (drivers) list and keep the one to be use
	vector<cl::Platform> all_platforms;
	cl::Platform::get(&all_platforms);
	if(!all_platforms.size()){
		//No platform ? Send error
		string error = "OPENCL: no platforms found.";
		throw(error);
	}
	m_platform = all_platforms[platform_id];

	//Get devices list and keep the one to use
	vector<cl::Device> devices;
	m_platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
	if(device_id >= devices.size()){
		string error = "OPENCL: no device of id "+to_string(device_id)+
			" on platform "+to_string(platform_id)+" ("+to_string(devices.size())+" devices)";
		throw(error);
	}
	m_device = devices[device_id];

	//Create context
	m_context = cl::Context({m_device});

	//initialize commands queue
	m_commandqueue = cl::CommandQueue(m_context, m_device);

	//Build kernel sources
	m_program = cl::Program(m_context, kernel_cmp_2_contigs);
	if(m_program.build({m_device}) != CL_SUCCESS){
		string error = "Error building: ";
		error += m_program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(m_device);
		throw(error);
	}

	//Make the kernel
	m_kernel = cl::Kernel(m_program, "cmp_2_contigs");

}

WorkerCL::~WorkerCL(){
}

void WorkerCL::run(const Contigs& contigs){
	/*
	Create the string containing all contigs sequences
	and store the list of contigs size (in same orders)
	to be able to retrieve contigs. Size is store in
	an uint64_t (ulong) to be sure it is 64bits as cl_ulong
	*/

	//Get list of contigs size and the total length of the
	//contigs concatenation
	uint64_t nbContigs = contigs.get_nbContigs();
	uint64_t ultraSequenceSize = 0;
	vector<uint64_t> contigs_size (nbContigs, 0);
	for(uint64_t i=0; i < nbContigs; i++){
		contigs_size[i] = contigs.get_sizeContig(i);
		ultraSequenceSize += contigs_size[i];
	}

	//Create the ultraSequence
	char* ultraSequence = new char[ultraSequenceSize];
	uint64_t i = 0;
		//Get each contigs sequence and add it in ultraSequence
	for(uint64_t c=0; c < nbContigs; c++){
		string seq = contigs.get_seqContig(c);
		for(size_t j=0; j < seq.size();j++){
			ultraSequence[i] = seq[j];
			i++;
		}
	}
	cout << "UltraSequence:" << endl;
	cout << ultraSequence << endl;

	//Prepare GPU for the run
	cl::Event ev;
		//infos buffer (64bits): nbcontigs
		//buffer only accepts non-dynamics arrays (even of size 1)
	uint64_t infos[1] = {ultraSequenceSize};
	cl::Buffer buf_infos (m_context, CL_MEM_READ_ONLY, sizeof(uint64_t));
	m_commandqueue.enqueueWriteBuffer(buf_infos, CL_TRUE, 0, sizeof(uint64_t), &infos);
		//sequences sizes (array of 64bits) buffer
	cl::Buffer buf_sizes (m_context, CL_MEM_READ_ONLY, sizeof(uint64_t)*nbContigs);
	m_commandqueue.enqueueWriteBuffer(buf_sizes, CL_TRUE, 0, sizeof(uint64_t)*nbContigs, &contigs_size[0]);

	//Update the kernel (gpu function)
	m_kernel.setArg(0, buf_infos);

	//Run the kernel and wait the end
	m_commandqueue.enqueueNDRangeKernel(m_kernel,cl::NullRange, cl::NDRange(nbContigs, nbContigs), cl::NullRange, NULL, &ev);
	ev.wait();

	//Clean the memory
	delete ultraSequence;
	ultraSequence = nullptr;
}

void WorkerCL::list_infos(Log& output){
	string txt;

	//Get platforms
	txt = "\n\t[Platforms list]";
	output.write(txt);
	vector<cl::Platform> platforms;
	cl::Platform::get(&platforms);
	if(!platforms.size()){
		txt = "No platform detected";
		output.write(txt);
		return;
	}
	txt = "platform_id\tplatform_name\tplatform_profile\tplatform_vendor\tplatform_version";
	output.write(txt);
	for(size_t i=0; i < platforms.size(); i++){
		cl::Platform& p = platforms[i];

		txt += "\t" + p.getInfo<CL_PLATFORM_NAME>();
		txt += "\t" + p.getInfo<CL_PLATFORM_PROFILE>();
		txt += "\t" + p.getInfo<CL_PLATFORM_VENDOR>();
		txt += "\t" + p.getInfo<CL_PLATFORM_VERSION>();
		//txt += "\t" + p.getInfo<CL_PLATFORM_EXTENSIONS>();
		output.write(txt);
	}

	//Get devices
	txt = "\n\t[Devices list]";
	output.write(txt);
	txt = "platform_id\tdevice_id\tdevice_name\tdevice_vendor\tdevice_profile\tdevice_version\tdriver_version\topencl_c_version";
	output.write(txt);
	for(size_t p = 0; p < platforms.size(); p++){
		vector<cl::Device> devices;
		platforms[p].getDevices(CL_DEVICE_TYPE_ALL, &devices);
		for(size_t d = 0; d < devices.size(); d++){
			cl::Device& device = devices[d];
			txt = to_string(p)+"\t"+to_string(d);
			txt += "\t" + device.getInfo<CL_DEVICE_NAME>();
			txt += "\t" + device.getInfo<CL_DEVICE_VENDOR>();
			txt += "\t" + device.getInfo<CL_DEVICE_PROFILE>();
			txt += "\t" + device.getInfo<CL_DEVICE_VERSION>();
			txt += "\t" + device.getInfo<CL_DRIVER_VERSION>();
			txt += "\t" + device.getInfo<CL_DEVICE_OPENCL_C_VERSION>();
			output.write(txt);
		}
	}
}

/*
Les balises 'R"CLCODE(' et ')CLCODE'   (du type R"NAME( ... )NAME") servent à définir un
string litéral brut. C'est utile pour avoir un string sur plusieurs ligne, comme un code,
et cela évite d'avoir à ouvrir puis fermer les guillemets à chaque ligne.
*/

string WorkerCL::kernel_cmp_2_contigs = R"CLCODE(
	kernel void cmp_2_contigs(){
		int i = 0;
	}
)CLCODE";
<commit_msg>Add global ids<commit_after>#include "workerCL.hpp"

#define __CL_DEFINE_EXCEPTIONS
#include <CL/cl.hpp>

#include <vector>
#include <string>
#include <iostream>

#include "log.hpp"
#include "reads.hpp"

using namespace std;

WorkerCL::WorkerCL(size_t platform_id, size_t device_id){
	/* GPU environment preparation */

	//Get platforms (drivers) list and keep the one to be use
	vector<cl::Platform> all_platforms;
	cl::Platform::get(&all_platforms);
	if(!all_platforms.size()){
		//No platform ? Send error
		string error = "OPENCL: no platforms found.";
		throw(error);
	}
	m_platform = all_platforms[platform_id];

	//Get devices list and keep the one to use
	vector<cl::Device> devices;
	m_platform.getDevices(CL_DEVICE_TYPE_ALL, &devices);
	if(device_id >= devices.size()){
		string error = "OPENCL: no device of id "+to_string(device_id)+
			" on platform "+to_string(platform_id)+" ("+to_string(devices.size())+" devices)";
		throw(error);
	}
	m_device = devices[device_id];

	//Create context
	m_context = cl::Context({m_device});

	//initialize commands queue
	m_commandqueue = cl::CommandQueue(m_context, m_device);

	//Build kernel sources
	m_program = cl::Program(m_context, kernel_cmp_2_contigs);
	if(m_program.build({m_device}) != CL_SUCCESS){
		string error = "Error building: ";
		error += m_program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(m_device);
		throw(error);
	}

	//Make the kernel
	m_kernel = cl::Kernel(m_program, "cmp_2_contigs");

}

WorkerCL::~WorkerCL(){
}

void WorkerCL::run(const Contigs& contigs){
	/*
	Create the string containing all contigs sequences
	and store the list of contigs size (in same orders)
	to be able to retrieve contigs. Size is store in
	an uint64_t (ulong) to be sure it is 64bits as cl_ulong
	*/

	//Get list of contigs size and the total length of the
	//contigs concatenation
	uint64_t nbContigs = contigs.get_nbContigs();
	uint64_t ultraSequenceSize = 0;
	vector<uint64_t> contigs_size (nbContigs, 0);
	for(uint64_t i=0; i < nbContigs; i++){
		contigs_size[i] = contigs.get_sizeContig(i);
		ultraSequenceSize += contigs_size[i];
	}

	//Create the ultraSequence
	char* ultraSequence = new char[ultraSequenceSize];
	uint64_t i = 0;
		//Get each contigs sequence and add it in ultraSequence
	for(uint64_t c=0; c < nbContigs; c++){
		string seq = contigs.get_seqContig(c);
		for(size_t j=0; j < seq.size();j++){
			ultraSequence[i] = seq[j];
			i++;
		}
	}
	cout << "UltraSequence:" << endl;
	cout << ultraSequence << endl;

	//Prepare GPU for the run
	cl::Event ev;
		//infos buffer (64bits): nbcontigs
		//buffer only accepts non-dynamics arrays (even of size 1)
	uint64_t infos[1] = {ultraSequenceSize};
	cl::Buffer buf_infos (m_context, CL_MEM_READ_ONLY, sizeof(uint64_t));
	m_commandqueue.enqueueWriteBuffer(buf_infos, CL_TRUE, 0, sizeof(uint64_t), &infos);
		//sequences sizes (array of 64bits) buffer
	cl::Buffer buf_sizes (m_context, CL_MEM_READ_ONLY, sizeof(uint64_t)*nbContigs);
	m_commandqueue.enqueueWriteBuffer(buf_sizes, CL_TRUE, 0, sizeof(uint64_t)*nbContigs, &contigs_size[0]);

	//Update the kernel (gpu function)
	m_kernel.setArg(0, buf_infos);

	//Run the kernel and wait the end
	m_commandqueue.enqueueNDRangeKernel(m_kernel,cl::NullRange, cl::NDRange(nbContigs, nbContigs), cl::NullRange, NULL, &ev);
	ev.wait();

	//Clean the memory
	delete ultraSequence;
	ultraSequence = nullptr;
}

void WorkerCL::list_infos(Log& output){
	string txt;

	//Get platforms
	txt = "\n\t[Platforms list]";
	output.write(txt);
	vector<cl::Platform> platforms;
	cl::Platform::get(&platforms);
	if(!platforms.size()){
		txt = "No platform detected";
		output.write(txt);
		return;
	}
	txt = "platform_id\tplatform_name\tplatform_profile\tplatform_vendor\tplatform_version";
	output.write(txt);
	for(size_t i=0; i < platforms.size(); i++){
		cl::Platform& p = platforms[i];

		txt += "\t" + p.getInfo<CL_PLATFORM_NAME>();
		txt += "\t" + p.getInfo<CL_PLATFORM_PROFILE>();
		txt += "\t" + p.getInfo<CL_PLATFORM_VENDOR>();
		txt += "\t" + p.getInfo<CL_PLATFORM_VERSION>();
		//txt += "\t" + p.getInfo<CL_PLATFORM_EXTENSIONS>();
		output.write(txt);
	}

	//Get devices
	txt = "\n\t[Devices list]";
	output.write(txt);
	txt = "platform_id\tdevice_id\tdevice_name\tdevice_vendor\tdevice_profile\tdevice_version\tdriver_version\topencl_c_version";
	output.write(txt);
	for(size_t p = 0; p < platforms.size(); p++){
		vector<cl::Device> devices;
		platforms[p].getDevices(CL_DEVICE_TYPE_ALL, &devices);
		for(size_t d = 0; d < devices.size(); d++){
			cl::Device& device = devices[d];
			txt = to_string(p)+"\t"+to_string(d);
			txt += "\t" + device.getInfo<CL_DEVICE_NAME>();
			txt += "\t" + device.getInfo<CL_DEVICE_VENDOR>();
			txt += "\t" + device.getInfo<CL_DEVICE_PROFILE>();
			txt += "\t" + device.getInfo<CL_DEVICE_VERSION>();
			txt += "\t" + device.getInfo<CL_DRIVER_VERSION>();
			txt += "\t" + device.getInfo<CL_DEVICE_OPENCL_C_VERSION>();
			output.write(txt);
		}
	}
}

/*
Les balises 'R"CLCODE(' et ')CLCODE'   (du type R"NAME( ... )NAME") servent à définir un
string litéral brut. C'est utile pour avoir un string sur plusieurs ligne, comme un code,
et cela évite d'avoir à ouvrir puis fermer les guillemets à chaque ligne.
*/

string WorkerCL::kernel_cmp_2_contigs = R"CLCODE(
	kernel void cmp_2_contigs(){
		int i = get_global_id(0);
		int j = get_global_id(1);
	}
)CLCODE";
<|endoftext|>


<commit_before>//
//  SubFunctions.hpp
//
//
//  Created by Myoung-Jong Noh on 3/30/20.
//

#ifndef SubFunctions_hpp
#define SubFunctions_hpp

#include <string.h>
#include <stdio.h>

#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>

#include <iostream>

#include "Typedefine.hpp"
#include "CoordConversion.hpp"
#include "Template.hpp"
#include "setsmgeo.hpp"
#include "grid_triangulation.hpp"
#include <sys/resource.h>
#include <sys/time.h>

#define min(a, b)  (((a) < (b)) ? (a) : (b))
#define max(a, b)  (((a) > (b)) ? (a) : (b))
#define SUB_RATIO 4.6

char* remove_ext(const char* mystr);
char* GetFileName(char file_path[]);
char* GetFileDir(char file_path[],int *size);
char* SetOutpathName(char *_path);
int Maketmpfolders(ProInfo *info);
double getSystemMemory();

bool GetRAinfo(ProInfo *proinfo, const char* RAfile, double **Imageparams);
bool GetRAinfoFromEcho(ProInfo *proinfo, const char* echofile, double **Imageparams);

bool GetsubareaImage(const int sensor_type, const FrameInfo m_frameinfo, const int ti, const TransParam transparam, const double *ImageParam, const double * const *RPCs, char *ImageFilename, CSize Imagesize, const double *subBoundary, const double *minmaxHeight, long *cols, long *rows);
bool GetImageSize(char *filename, CSize *Imagesize);

bool GetsubareaImage_GeoTiff(ProInfo proinfo, char *ImageFilename, CSize Imagesize, double *subBoundary, long *cols,long *rows);

float* GetDEMValue(char *GIMP_path,CSize seeddem_size);

bool OpenProject(char* _filename, ProInfo *info, ARGINFO args);
bool OpenDMCproject(char* project_path,ProInfo *proinfo, ARGINFO args);
void SetPySizes(CSize *data_size_lr, const CSize Lsubsetsize, const int level);
void RemoveFiles(const ProInfo *proinfo,const char *save_path, char **filename, const int py_level,const bool flag);

double Correlate(const double *L, const double *R, const int N);
double Correlate(const vector<double> &L, const vector<double> &R, const int N);

void SetTranParam_fromGeoTiff(TransParam *param, char* inputfile);
void SetTransParam_param(TransParam *param, bool Hemisphere);
void SetTransParam(double minLat, double minLon, TransParam *param);

void RPCsFree(double **rpcs);
double** OpenXMLFile(ProInfo *proinfo, int ImageID, double* gsd_r, double* gsd_c, double* gsd, BandInfo* band);
double** OpenXMLFile_Pleiades(char* _filename);
double** OpenXMLFile_Planet(char* _filename);
void OpenXMLFile_orientation(char* _filename, ImageInfo *Iinfo);

float median(int n, float* x,float min, float max);
float binmedian(int n, float *x);
double quickselect(double *arr, int n, int k);
double quickselect(vector<double> &arr, int n, int k);
bool CheckOverlap(const D2DPOINT br1_lt, const D2DPOINT br1_rb, const D2DPOINT br2_lt, const D2DPOINT br2_rb);

void Preprocessing(const ProInfo *proinfo, const char *save_path,char **Subsetfile, const uint8 py_level, const CSize * const *data_size_lr, FILE *fid);
void MakeSobelMagnitudeImage(const CSize _img_size,const uint16* _src_image, uint16* _dist_mag_image, int16* _dir);
void Orientation(const CSize imagesize,const uint16* Gmag,const int16* Gdir,const uint8 Template_size, uint8* plhs);

double InterpolatePatch(const uint16 *Image, const long int position, const CSize Imagesize, const double dx, const double dy);

struct KernelPatchArg {
    SetKernel &rkernel;

    CSize LImagesize;
    CSize RImagesize;

    const uint16 *left_image;
    const uint16 *left_mag_image;
    const uint16 *right_image;
    const uint16 *right_mag_image;
};

void SetVecKernelValue(const KernelPatchArg &kernel_patch, const int row, const int col, const D2DPOINT &pos_left, const D2DPOINT &pos_right, const int radius2, int *Count_N);

void ComputeMultiNCC(SetKernel &rsetkernel, const int Th_rho, const int *Count_N, double &count_NCC, double &sum_NCC_multi);

D2DPOINT *SetDEMGrid(const double *Boundary, const double Grid_x, const double Grid_y, CSize *Size_2D);
void SetPyramidImages(const ProInfo *proinfo, const int py_level_set, const CSize * const *data_size_lr, uint16 ***SubImages, uint16 ***SubMagImages, uint8 ***SubOriImages);
uint16 *SubsetImageFrombitsToUint16(const int image_bits, char *imagefile, long *cols, long *rows, CSize *subsize);
uint8 *SubsetImageFrombitsToUint8(const int image_bits, char *imagefile, long *cols, long *rows, CSize *subsize);

uint16* LoadPyramidImages(const char *save_path,char *subsetfile,const CSize data_size,const uint8 py_level);
uint16* LoadPyramidMagImages(const char *save_path,char *subsetfile,const CSize data_size,const uint8 py_level);
uint8* LoadPyramidOriImages(const char *save_path,char *subsetfile,const CSize data_size,const uint8 py_level);

GMA_double* GMA_double_create(uint32 size_row, uint32 size_col);
void GMA_double_destroy(GMA_double* in);
void GMA_double_inv(GMA_double *a, GMA_double *I);
void GMA_double_mul(GMA_double *a, GMA_double *b, GMA_double *out);
void GMA_double_Tran(GMA_double *a, GMA_double *out);
void GMA_double_sub(GMA_double *a, GMA_double *b, GMA_double *out);
void GMA_double_sum(GMA_double *a, GMA_double *b, GMA_double *out);
void GMA_double_printf(GMA_double *a);

FullTriangulation *TINCreate_list(D3DPOINT *ptslists, int numofpts, vector<UI3DPOINT> *trilists, double min_max[], int *count_tri, double resolution);

//void TINUpdate(D3DPOINT *ptslists, int numofpts, UI3DPOINT* trilists, double min_max[], int *count_tri, double resolution, FullTriangulation* oldTri, D3DPOINT* blunderlist, int numblunders);
void TINUpdate_list(D3DPOINT *ptslists, int numofpts, vector<UI3DPOINT> *trilists, double min_max[], int *count_tri, double resolution, FullTriangulation* oldTri, D3DPOINT* blunderlist, int numblunders);

void SetTinBoundary(LevelInfo &rlevelinfo, const D3DPOINT &TriP1, const D3DPOINT &TriP2, const D3DPOINT &TriP3, int *PixelMinXY, int *PixelMaxXY, double &Total_Min_Z, double &Total_Max_Z, double &temp_MinZ, double &temp_MaxZ);

bool IsTinInside(const D3DPOINT &CurGPXY, const D3DPOINT &TriP1, const D3DPOINT &TriP2, const D3DPOINT &TriP3, float &Z);

double SetNormalAngle(const D3DPOINT &pts0, const D3DPOINT &pts1, const D3DPOINT &pts2);
void SetAngle(double &angle);

//FullTriangulation *TINCreate_float(F3DPOINT *ptslists, long numofpts, UI3DPOINT* trilists, double min_max[], long *count_tri, double resolution);
//FullTriangulation *TINCreate(D3DPOINT *ptslists, int numofpts, UI3DPOINT* trilists, double min_max[], int *count_tri, double resolution);

CSize Envihdr_reader(char *filename);

CSize Envihdr_reader_seedDEM(TransParam _param, char *filename, double *minX, double *maxY, double *grid_size);
bool TFW_reader_LSFDEM(char *filename, double *minX, double *maxY, double *grid_size, int *zone, char *dir);
//bool TFW_reader_seedDEM(char *filename, double *minX, double *maxY, double *grid_size);
#endif /* SubFunctions_hpp */
<commit_msg>Use constexpr for min/max instead of macro<commit_after>//
//  SubFunctions.hpp
//
//
//  Created by Myoung-Jong Noh on 3/30/20.
//

#ifndef SubFunctions_hpp
#define SubFunctions_hpp

#include <string.h>
#include <stdio.h>

#include <libgen.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>

#include <iostream>

#include "Typedefine.hpp"
#include "CoordConversion.hpp"
#include "Template.hpp"
#include "setsmgeo.hpp"
#include "grid_triangulation.hpp"
#include <sys/resource.h>
#include <sys/time.h>

// Don't use macros here, they break things in the c++ stdlibrary
// see here for rationale:
// https://en.cppreference.com/w/cpp/language/template_argument_deduction
template<typename T> struct identity { typedef T type; };
template <typename T>
constexpr  const T& min(const T& a, const typename identity<T>::type& b) { return a < b ? a : b; }
template <typename T>
constexpr  const T& max(const T& a, const typename identity<T>::type& b) { return a > b ? a : b; }
#define SUB_RATIO 4.6

char* remove_ext(const char* mystr);
char* GetFileName(char file_path[]);
char* GetFileDir(char file_path[],int *size);
char* SetOutpathName(char *_path);
int Maketmpfolders(ProInfo *info);
double getSystemMemory();

bool GetRAinfo(ProInfo *proinfo, const char* RAfile, double **Imageparams);
bool GetRAinfoFromEcho(ProInfo *proinfo, const char* echofile, double **Imageparams);

bool GetsubareaImage(const int sensor_type, const FrameInfo m_frameinfo, const int ti, const TransParam transparam, const double *ImageParam, const double * const *RPCs, char *ImageFilename, CSize Imagesize, const double *subBoundary, const double *minmaxHeight, long *cols, long *rows);
bool GetImageSize(char *filename, CSize *Imagesize);

bool GetsubareaImage_GeoTiff(ProInfo proinfo, char *ImageFilename, CSize Imagesize, double *subBoundary, long *cols,long *rows);

float* GetDEMValue(char *GIMP_path,CSize seeddem_size);

bool OpenProject(char* _filename, ProInfo *info, ARGINFO args);
bool OpenDMCproject(char* project_path,ProInfo *proinfo, ARGINFO args);
void SetPySizes(CSize *data_size_lr, const CSize Lsubsetsize, const int level);
void RemoveFiles(const ProInfo *proinfo,const char *save_path, char **filename, const int py_level,const bool flag);

double Correlate(const double *L, const double *R, const int N);
double Correlate(const vector<double> &L, const vector<double> &R, const int N);

void SetTranParam_fromGeoTiff(TransParam *param, char* inputfile);
void SetTransParam_param(TransParam *param, bool Hemisphere);
void SetTransParam(double minLat, double minLon, TransParam *param);

void RPCsFree(double **rpcs);
double** OpenXMLFile(ProInfo *proinfo, int ImageID, double* gsd_r, double* gsd_c, double* gsd, BandInfo* band);
double** OpenXMLFile_Pleiades(char* _filename);
double** OpenXMLFile_Planet(char* _filename);
void OpenXMLFile_orientation(char* _filename, ImageInfo *Iinfo);

float median(int n, float* x,float min, float max);
float binmedian(int n, float *x);
double quickselect(double *arr, int n, int k);
double quickselect(vector<double> &arr, int n, int k);
bool CheckOverlap(const D2DPOINT br1_lt, const D2DPOINT br1_rb, const D2DPOINT br2_lt, const D2DPOINT br2_rb);

void Preprocessing(const ProInfo *proinfo, const char *save_path,char **Subsetfile, const uint8 py_level, const CSize * const *data_size_lr, FILE *fid);
void MakeSobelMagnitudeImage(const CSize _img_size,const uint16* _src_image, uint16* _dist_mag_image, int16* _dir);
void Orientation(const CSize imagesize,const uint16* Gmag,const int16* Gdir,const uint8 Template_size, uint8* plhs);

double InterpolatePatch(const uint16 *Image, const long int position, const CSize Imagesize, const double dx, const double dy);

struct KernelPatchArg {
    SetKernel &rkernel;

    CSize LImagesize;
    CSize RImagesize;

    const uint16 *left_image;
    const uint16 *left_mag_image;
    const uint16 *right_image;
    const uint16 *right_mag_image;
};

void SetVecKernelValue(const KernelPatchArg &kernel_patch, const int row, const int col, const D2DPOINT &pos_left, const D2DPOINT &pos_right, const int radius2, int *Count_N);

void ComputeMultiNCC(SetKernel &rsetkernel, const int Th_rho, const int *Count_N, double &count_NCC, double &sum_NCC_multi);

D2DPOINT *SetDEMGrid(const double *Boundary, const double Grid_x, const double Grid_y, CSize *Size_2D);
void SetPyramidImages(const ProInfo *proinfo, const int py_level_set, const CSize * const *data_size_lr, uint16 ***SubImages, uint16 ***SubMagImages, uint8 ***SubOriImages);
uint16 *SubsetImageFrombitsToUint16(const int image_bits, char *imagefile, long *cols, long *rows, CSize *subsize);
uint8 *SubsetImageFrombitsToUint8(const int image_bits, char *imagefile, long *cols, long *rows, CSize *subsize);

uint16* LoadPyramidImages(const char *save_path,char *subsetfile,const CSize data_size,const uint8 py_level);
uint16* LoadPyramidMagImages(const char *save_path,char *subsetfile,const CSize data_size,const uint8 py_level);
uint8* LoadPyramidOriImages(const char *save_path,char *subsetfile,const CSize data_size,const uint8 py_level);

GMA_double* GMA_double_create(uint32 size_row, uint32 size_col);
void GMA_double_destroy(GMA_double* in);
void GMA_double_inv(GMA_double *a, GMA_double *I);
void GMA_double_mul(GMA_double *a, GMA_double *b, GMA_double *out);
void GMA_double_Tran(GMA_double *a, GMA_double *out);
void GMA_double_sub(GMA_double *a, GMA_double *b, GMA_double *out);
void GMA_double_sum(GMA_double *a, GMA_double *b, GMA_double *out);
void GMA_double_printf(GMA_double *a);

FullTriangulation *TINCreate_list(D3DPOINT *ptslists, int numofpts, vector<UI3DPOINT> *trilists, double min_max[], int *count_tri, double resolution);

//void TINUpdate(D3DPOINT *ptslists, int numofpts, UI3DPOINT* trilists, double min_max[], int *count_tri, double resolution, FullTriangulation* oldTri, D3DPOINT* blunderlist, int numblunders);
void TINUpdate_list(D3DPOINT *ptslists, int numofpts, vector<UI3DPOINT> *trilists, double min_max[], int *count_tri, double resolution, FullTriangulation* oldTri, D3DPOINT* blunderlist, int numblunders);

void SetTinBoundary(LevelInfo &rlevelinfo, const D3DPOINT &TriP1, const D3DPOINT &TriP2, const D3DPOINT &TriP3, int *PixelMinXY, int *PixelMaxXY, double &Total_Min_Z, double &Total_Max_Z, double &temp_MinZ, double &temp_MaxZ);

bool IsTinInside(const D3DPOINT &CurGPXY, const D3DPOINT &TriP1, const D3DPOINT &TriP2, const D3DPOINT &TriP3, float &Z);

double SetNormalAngle(const D3DPOINT &pts0, const D3DPOINT &pts1, const D3DPOINT &pts2);
void SetAngle(double &angle);

//FullTriangulation *TINCreate_float(F3DPOINT *ptslists, long numofpts, UI3DPOINT* trilists, double min_max[], long *count_tri, double resolution);
//FullTriangulation *TINCreate(D3DPOINT *ptslists, int numofpts, UI3DPOINT* trilists, double min_max[], int *count_tri, double resolution);

CSize Envihdr_reader(char *filename);

CSize Envihdr_reader_seedDEM(TransParam _param, char *filename, double *minX, double *maxY, double *grid_size);
bool TFW_reader_LSFDEM(char *filename, double *minX, double *maxY, double *grid_size, int *zone, char *dir);
//bool TFW_reader_seedDEM(char *filename, double *minX, double *maxY, double *grid_size);
#endif /* SubFunctions_hpp */
<|endoftext|>


<commit_before>#include "bitcoinunits.h"

#include <QStringList>

BitcoinUnits::BitcoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
{
    QList<BitcoinUnits::Unit> unitlist;
    unitlist.append(DGR);
    unitlist.append(DGPaise);
    return unitlist;
}

bool BitcoinUnits::valid(int unit)
{
    switch(unit)
    {
    case NXC:
    case Nexxie:
        return true;
    default:
        return false;
    }
}

QString BitcoinUnits::name(int unit)
{
    switch(unit)
    {
    case NXC: return QString("NXC");
    case Nexxie: return QString("Nexxie");
    default: return QString("???");
    }
}

QString BitcoinUnits::description(int unit)
{
    switch(unit)
    {
    case NXC: return QString("NexxusCoins");
    case Nexxie: return QString("Nexxie (1 / 100)");
    default: return QString("???");
    }
}

qint64 BitcoinUnits::factor(int unit)
{
    switch(unit)
    {
    case NXC:  return 100;
    case Nexxie: return 100;
    default:   return 100;
    }
}

int BitcoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case NXC: return 16; // 21,000,000 (# digits, without commas)
    case Nexxie: return 16; // 21,000,000,000
    default: return 0;
    }
}

int BitcoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case NXC: return 2;
    case Nexxie: return 2;
    default: return 0;
    }
}

int BitcoinUnits::step(int unit)
{
    switch(unit)
    {
    case NXC: return 100;
    case Nexxie: return 1;
    default: return 100;
    }
}

QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Right-trim excess zeros after the decimal point
    int nTrim = 0;
    for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
        ++nTrim;
    remainder_str.chop(nTrim);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');
    return quotient_str + QString(".") + remainder_str;
}

QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);
    QStringList parts = value.split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    qint64 retvalue = str.toLongLong(&ok);
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

int BitcoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<commit_msg>Update bitcoinunits.cpp<commit_after>#include "bitcoinunits.h"

#include <QStringList>

BitcoinUnits::BitcoinUnits(QObject *parent):
        QAbstractListModel(parent),
        unitlist(availableUnits())
{
}

QList<BitcoinUnits::Unit> BitcoinUnits::availableUnits()
{
    QList<BitcoinUnits::Unit> unitlist;
    unitlist.append(DGR);
    unitlist.append(DGPaise);
    return unitlist;
}

bool BitcoinUnits::valid(int unit)
{
    switch(unit)
    {
    case NXC:
    case Nexxi:
        return true;
    default:
        return false;
    }
}

QString BitcoinUnits::name(int unit)
{
    switch(unit)
    {
    case NXC: return QString("NXC");
    case Nexxie: return QString("Nexxie");
    default: return QString("???");
    }
}

QString BitcoinUnits::description(int unit)
{
    switch(unit)
    {
    case NXC: return QString("NexxusCoins");
    case Nexxie: return QString("Nexxie (1 / 100)");
    default: return QString("???");
    }
}

qint64 BitcoinUnits::factor(int unit)
{
    switch(unit)
    {
    case NXC:  return 100;
    case Nexxie: return 100;
    default:   return 100;
    }
}

int BitcoinUnits::amountDigits(int unit)
{
    switch(unit)
    {
    case NXC: return 16; // 21,000,000 (# digits, without commas)
    case Nexxie: return 16; // 21,000,000,000
    default: return 0;
    }
}

int BitcoinUnits::decimals(int unit)
{
    switch(unit)
    {
    case NXC: return 2;
    case Nexxie: return 2;
    default: return 0;
    }
}

int BitcoinUnits::step(int unit)
{
    switch(unit)
    {
    case NXC: return 100;
    case Nexxie: return 1;
    default: return 100;
    }
}

QString BitcoinUnits::format(int unit, qint64 n, bool fPlus)
{
    // Note: not using straight sprintf here because we do NOT want
    // localized number formatting.
    if(!valid(unit))
        return QString(); // Refuse to format invalid unit
    qint64 coin = factor(unit);
    int num_decimals = decimals(unit);
    qint64 n_abs = (n > 0 ? n : -n);
    qint64 quotient = n_abs / coin;
    qint64 remainder = n_abs % coin;
    QString quotient_str = QString::number(quotient);
    QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');

    // Right-trim excess zeros after the decimal point
    int nTrim = 0;
    for (int i = remainder_str.size()-1; i>=2 && (remainder_str.at(i) == '0'); --i)
        ++nTrim;
    remainder_str.chop(nTrim);

    if (n < 0)
        quotient_str.insert(0, '-');
    else if (fPlus && n > 0)
        quotient_str.insert(0, '+');
    return quotient_str + QString(".") + remainder_str;
}

QString BitcoinUnits::formatWithUnit(int unit, qint64 amount, bool plussign)
{
    return format(unit, amount, plussign) + QString(" ") + name(unit);
}

bool BitcoinUnits::parse(int unit, const QString &value, qint64 *val_out)
{
    if(!valid(unit) || value.isEmpty())
        return false; // Refuse to parse invalid unit or empty string
    int num_decimals = decimals(unit);
    QStringList parts = value.split(".");

    if(parts.size() > 2)
    {
        return false; // More than one dot
    }
    QString whole = parts[0];
    QString decimals;

    if(parts.size() > 1)
    {
        decimals = parts[1];
    }
    if(decimals.size() > num_decimals)
    {
        return false; // Exceeds max precision
    }
    bool ok = false;
    QString str = whole + decimals.leftJustified(num_decimals, '0');

    if(str.size() > 18)
    {
        return false; // Longer numbers will exceed 63 bits
    }
    qint64 retvalue = str.toLongLong(&ok);
    if(val_out)
    {
        *val_out = retvalue;
    }
    return ok;
}

int BitcoinUnits::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return unitlist.size();
}

QVariant BitcoinUnits::data(const QModelIndex &index, int role) const
{
    int row = index.row();
    if(row >= 0 && row < unitlist.size())
    {
        Unit unit = unitlist.at(row);
        switch(role)
        {
        case Qt::EditRole:
        case Qt::DisplayRole:
            return QVariant(name(unit));
        case Qt::ToolTipRole:
            return QVariant(description(unit));
        case UnitRole:
            return QVariant(static_cast<int>(unit));
        }
    }
    return QVariant();
}
<|endoftext|>