<commit_before>/*
   Bacula® - The Network Backup Solution

   Copyright (C) 2007-2010 Free Software Foundation Europe e.V.

   The main author of Bacula is Kern Sibbald, with contributions from
   many others, a complete list can be found in the file AUTHORS.
   This program is Free Software; you can redistribute it and/or
   modify it under the terms of version three of the GNU Affero General Public
   License as published by the Free Software Foundation and included
   in the file LICENSE.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301, USA.

   Bacula® is a registered trademark of Kern Sibbald.
   The licensor of Bacula is the Free Software Foundation Europe
   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
   Switzerland, email:ftf@fsfeurope.org.
*/

#include "bat.h"
#include <QAbstractEventDispatcher>
#include <QMenu>
#include <math.h>
#include "mediaview.h"
#include "mediaedit/mediaedit.h"
#include "mediainfo/mediainfo.h"
#include "joblist/joblist.h"
#include "relabel/relabel.h"
#include "run/run.h"
#include "util/fmtwidgetitem.h"

MediaView::MediaView() : Pages()
{
   setupUi(this);
   m_name = tr("Media");
   pgInitialize();
   QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
   thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/cartridge.png")));
   connect(m_pbApply, SIGNAL(pressed()), this, SLOT(applyPushed()));
   connect(m_pbEdit, SIGNAL(pressed()), this, SLOT(editPushed()));
   connect(m_pbPurge, SIGNAL(pressed()), this, SLOT(purgePushed()));
   connect(m_pbDelete, SIGNAL(pressed()), this, SLOT(deletePushed()));
   connect(m_pbPrune, SIGNAL(pressed()), this, SLOT(prunePushed()));
   connect(m_tableMedia, SIGNAL(itemDoubleClicked(QTableWidgetItem*)),
           this, SLOT(showInfoForMedia(QTableWidgetItem *)));

   /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_medialist.h */
   m_populated = false;
   m_checkcurwidget = true;
   m_closeable = false;
}

void MediaView::showInfoForMedia(QTableWidgetItem * item)
{
   QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
   int row = item->row();
   QString vol = m_tableMedia->item(row, 0)->text();
   new MediaInfo(pageSelectorTreeWidgetItem, vol);
//   connect(j, SIGNAL(destroyed()), this, SLOT(populateTree()));
}

MediaView::~MediaView()
{
}

void MediaView::applyPushed()
{
   populateTable();
}

void MediaView::editPushed()
{
   QStringList sel;
   QString cmd;
   getSelection(sel);

   for(int i=0; i<sel.count(); i++) {
      cmd = sel.at(i);
      new MediaEdit(mainWin->getFromHash(this), cmd);
   }
}

void MediaView::purgePushed()
{
   if (QMessageBox::warning(this, "Bat",
      tr("Are you sure you want to purge ??  !!!.\n"
"The Purge command will delete associated Catalog database records from Jobs and"
" Volumes without considering the retention period. Purge  works only on the"
" Catalog database and does not affect data written to Volumes. This command can"
" be dangerous because you can delete catalog records associated with current"
" backups of files, and we recommend that you do not use it unless you know what"
" you are doing.\n"
      "Press OK to proceed with the purge operation?"),
      QMessageBox::Ok | QMessageBox::Cancel)
      == QMessageBox::Cancel) { return; }

   QStringList lst;
   QString cmd;
   getSelection(lst);
   for(int i=0; i<lst.count(); i++) {
      cmd = "purge volume=" + lst.at(i);
      consoleCommand(cmd);
   }
   populateTable();
}

bool MediaView::getSelection(QStringList &list)
{
   int i, nb, nr_rows, row;
   bool *tab;
   QTableWidgetItem *it;
   QList<QTableWidgetItem*> items = m_tableMedia->selectedItems();

   /*
    * See if anything is selected.
    */
   nb = items.count();
   if (!nb) {
      return false;
   }

   /*
    * Create a nibble map for each row so we can see if its
    * selected or not.
    */
   nr_rows = m_tableMedia->rowCount();
   tab = (bool *)malloc (nr_rows * sizeof(bool));
   memset(tab, 0, sizeof(bool) * nr_rows);

   for (i = 0; i < nb; ++i) {
      row = items[i]->row();
      if (!tab[row]) {
         tab[row] = true;
         it = m_tableMedia->item(row, 0);
         list.append(it->text());
      }
   }
   free(tab);

   return list.count() > 0;
}

void MediaView::prunePushed()
{
   QStringList sel;
   QString cmd;
   getSelection(sel);

   for(int i=0; i<sel.count(); i++) {
      cmd = "prune volume=" + sel.at(i);
      consoleCommand(cmd);
   }
}

void MediaView::deletePushed()
{
   if (QMessageBox::warning(this, "Bat",
      tr("Are you sure you want to delete??  !!!.\n"
"This delete command is used to delete a Volume record and all associated catalog"
" records that were created. This command operates only on the Catalog"
" database and has no effect on the actual data written to a Volume. This"
" command can be dangerous and we strongly recommend that you do not use"
" it unless you know what you are doing.  All Jobs and all associated"
" records (File and JobMedia) will be deleted from the catalog."
      "Press OK to proceed with delete operation.?"),
      QMessageBox::Ok | QMessageBox::Cancel)
      == QMessageBox::Cancel) { return; }

   QStringList lst;
   QString cmd;
   getSelection(lst);
   for(int i=0; i<lst.count(); i++) {
      cmd = "delete volume=" + lst.at(i);
      consoleCommand(cmd);
   }
   populateTable();
}

void MediaView::populateForm()
{
   m_cbPool->clear();
   m_cbPool->addItem("");
   m_cbPool->addItems(m_console->pool_list);

   m_cbStatus->clear();
   m_cbStatus->addItem("");
   m_cbStatus->addItems(m_console->volstatus_list);

   m_cbMediaType->clear();
   m_cbMediaType->addItem("");
   m_cbMediaType->addItems(m_console->mediatype_list);

   m_cbLocation->clear();
   m_cbLocation->addItem("");
   m_cbLocation->addItems(m_console->location_list);
}

/*
 * If chkExpired button is checked, we can remove all non Expired
 * entries
 */
void MediaView::filterExipired(QStringList &list)
{
   utime_t t, now = time(NULL);
   QString resultline, stat, LastWritten;
   QStringList fieldlist;

   /* We should now in advance how many rows we will have */
   if (m_chkExpired->isChecked()) {
      for (int i=list.size() -1; i >= 0; i--) {
         fieldlist = list.at(i).split("\t");
         ASSERT(fieldlist.size() != 9);
         LastWritten = fieldlist.at(7);
         if (LastWritten == "") {
            list.removeAt(i);

         } else {
            stat = fieldlist.at(8);
            t = str_to_utime(LastWritten.toAscii().data());
            t = t + stat.toULongLong();
            if (t > now) {
               list.removeAt(i);
            }
         }
      }
   }
}

/*
 * The main meat of the class!!  The function that querries the director and
 * creates the widgets with appropriate values.
 */
void MediaView::populateTable()
{
   utime_t t;
   time_t ttime;
   QString stat, resultline, query;
   QString str_usage;
   QHash<QString, float> hash_size;
   QStringList fieldlist, results;
   char buf[256];
   float usage;
   struct tm tm;

   m_populated = true;

   Freeze frz(*m_tableMedia); /* disable updating*/
   QStringList where;
   QString cmd;
   if (m_cbPool->currentText() != "") {
      cmd = " Pool.Name = '" + m_cbPool->currentText() + "'";
      where.append(cmd);
   }

   if (m_cbStatus->currentText() != "") {
      cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
      where.append(cmd);
   }

   if (m_cbStatus->currentText() != "") {
      cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
      where.append(cmd);
   }

   if (m_cbMediaType->currentText() != "") {
      cmd = " Media.MediaType = '" + m_cbMediaType->currentText() + "'";
      where.append(cmd);
   }

   if (m_cbLocation->currentText() != "") {
      cmd = " Location.Location = '" + m_cbLocation->currentText() + "'";
      where.append(cmd);
   }

   if (m_textName->text() != "") {
      cmd = " Media.VolumeName like '%" + m_textName->text() + "%'";
      where.append(cmd);
   }

   if (where.size() > 0) {
      cmd = " WHERE " + where.join(" AND ");
   } else {
      cmd = "";
   }

   query =
      "SELECT AVG(VolBytes) AS size, COUNT(1) as nb, "
      "MediaType  FROM Media "
      "WHERE VolStatus IN ('Full', 'Used') "
      "GROUP BY MediaType";

   if (mainWin->m_sqlDebug) {
      Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
   }
   if (m_console->sql_cmd(query, results)) {
      foreach (resultline, results) {
         fieldlist = resultline.split("\t");
         if (fieldlist.at(1).toInt() >= 1) {
            //           MediaType
            hash_size[fieldlist.at(2)]
               = fieldlist.at(0).toFloat();
         }
      }
   }

   m_tableMedia->clearContents();
   query =
      "SELECT VolumeName, InChanger, "
      "Slot, MediaType, VolStatus, VolBytes, Pool.Name,  "
      "LastWritten, Media.VolRetention "
      "FROM Media JOIN Pool USING (PoolId) "
      "LEFT JOIN Location ON (Media.LocationId=Location.LocationId) "
      + cmd +
      " ORDER BY VolumeName LIMIT " + m_sbLimit->cleanText();

   m_tableMedia->sortByColumn(0, Qt::AscendingOrder);
   m_tableMedia->setSortingEnabled(false); /* Don't sort during insert */
   results.clear();
   if (mainWin->m_sqlDebug) {
      Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
   }
   if (m_console->sql_cmd(query, results)) {
      int row=0;
      filterExipired(results);
      m_tableMedia->setRowCount(results.size());

      foreach (resultline, results) { // should have only one result
         int index = 0;
         QString Slot, VolBytes, MediaType, LastWritten, VolStatus;
         fieldlist = resultline.split("\t");
         if (fieldlist.size() != 10) {
            continue;
         }
         QStringListIterator fld(fieldlist);
         TableItemFormatter mediaitem(*m_tableMedia, row);

         /* VolumeName */
         mediaitem.setTextFld(index++, fld.next());

         /* Online */
         mediaitem.setInChanger(index++, fld.next());

         Slot = fld.next();            // Slot
         mediaitem.setTextFld(index++, Slot);

         MediaType = fld.next();
         VolStatus = fld.next();

         /* Volume bytes */
         VolBytes = fld.next();
         mediaitem.setBytesFld(index++, VolBytes);

         /* Usage */
         usage = 0;
         if (hash_size.contains(MediaType) &&
             hash_size[MediaType] != 0) {
            usage = VolBytes.toLongLong() * 100 / hash_size[MediaType];
         }
         mediaitem.setPercent(index++, usage);

         /* Volstatus */
         mediaitem.setVolStatusFld(index++, VolStatus);

         /* Pool */
         mediaitem.setTextFld(index++, fld.next());

         /* MediaType */
         mediaitem.setTextFld(index++, MediaType);

         LastWritten = fld.next();
         buf[0] = 0;
         if (LastWritten != "") {
            stat = fld.next();  // VolUseDuration
            t = str_to_utime(LastWritten.toAscii().data());
            t = t + stat.toULongLong();
            ttime = t;
            localtime_r(&ttime, &tm);
            strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
         }

         /* LastWritten */
         mediaitem.setTextFld(index++, LastWritten);

         /* When expired */
         mediaitem.setTextFld(index++, buf);
         row++;
      }
   }
   m_tableMedia->resizeColumnsToContents();
   m_tableMedia->resizeRowsToContents();
   m_tableMedia->verticalHeader()->hide();
   m_tableMedia->setSortingEnabled(true);

   /* make read only */
   m_tableMedia->setEditTriggers(QAbstractItemView::NoEditTriggers);
}

/*
 * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
 * The tree has been populated.
 */
void MediaView::PgSeltreeWidgetClicked()
{
   if (!m_populated) {
      populateForm();
      populateTable();
   }
   if (!isOnceDocked()) {
      dockPage();
   }
}

/*
 * Virtual function which is called when this page is visible on the stack
 */
void MediaView::currentStackItem()
{
   if(!m_populated) {
      populateForm();
      populateTable();
   }
}

// /*
//  * Called from the signal of the context sensitive menu to relabel!
//  */
// void MediaView::relabelVolume()
// {
//    setConsoleCurrent();
//    new relabelDialog(m_console, m_currentVolumeName);
// }
//
// /*
//  * Called from the signal of the context sensitive menu to purge!
//  */
// void MediaView::allVolumesFromPool()
// {
//    QString cmd = "update volume AllFromPool=" + m_currentVolumeName;
//    consoleCommand(cmd);
//    populateTable();
// }
//
// void MediaView::allVolumes()
// {
//    QString cmd = "update volume allfrompools";
//    consoleCommand(cmd);
//    populateTable();
// }
//
//  /*
//   * Called from the signal of the context sensitive menu to purge!
//   */
//  void MediaView::volumeFromPool()
//  {
//     QTreeWidgetItem *currentItem = mp_treeWidget->currentItem();
//     QTreeWidgetItem *parent = currentItem->parent();
//     QString pool = parent->text(0);
//     QString cmd;
//     cmd = "update volume=" + m_currentVolumeName + " frompool=" + pool;
//     consoleCommand(cmd);
//     populateTable();
//  }
//
<commit_msg>Insert the slot field as a numeric field.<commit_after>/*
   Bacula® - The Network Backup Solution

   Copyright (C) 2007-2010 Free Software Foundation Europe e.V.

   The main author of Bacula is Kern Sibbald, with contributions from
   many others, a complete list can be found in the file AUTHORS.
   This program is Free Software; you can redistribute it and/or
   modify it under the terms of version three of the GNU Affero General Public
   License as published by the Free Software Foundation and included
   in the file LICENSE.

   This program is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   General Public License for more details.

   You should have received a copy of the GNU Affero General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   02110-1301, USA.

   Bacula® is a registered trademark of Kern Sibbald.
   The licensor of Bacula is the Free Software Foundation Europe
   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
   Switzerland, email:ftf@fsfeurope.org.
*/

#include "bat.h"
#include <QAbstractEventDispatcher>
#include <QMenu>
#include <math.h>
#include "mediaview.h"
#include "mediaedit/mediaedit.h"
#include "mediainfo/mediainfo.h"
#include "joblist/joblist.h"
#include "relabel/relabel.h"
#include "run/run.h"
#include "util/fmtwidgetitem.h"

MediaView::MediaView() : Pages()
{
   setupUi(this);
   m_name = tr("Media");
   pgInitialize();
   QTreeWidgetItem* thisitem = mainWin->getFromHash(this);
   thisitem->setIcon(0,QIcon(QString::fromUtf8(":images/cartridge.png")));
   connect(m_pbApply, SIGNAL(pressed()), this, SLOT(applyPushed()));
   connect(m_pbEdit, SIGNAL(pressed()), this, SLOT(editPushed()));
   connect(m_pbPurge, SIGNAL(pressed()), this, SLOT(purgePushed()));
   connect(m_pbDelete, SIGNAL(pressed()), this, SLOT(deletePushed()));
   connect(m_pbPrune, SIGNAL(pressed()), this, SLOT(prunePushed()));
   connect(m_tableMedia, SIGNAL(itemDoubleClicked(QTableWidgetItem*)),
           this, SLOT(showInfoForMedia(QTableWidgetItem *)));

   /* mp_treeWidget, Storage Tree Tree Widget inherited from ui_medialist.h */
   m_populated = false;
   m_checkcurwidget = true;
   m_closeable = false;
}

void MediaView::showInfoForMedia(QTableWidgetItem * item)
{
   QTreeWidgetItem* pageSelectorTreeWidgetItem = mainWin->getFromHash(this);
   int row = item->row();
   QString vol = m_tableMedia->item(row, 0)->text();
   new MediaInfo(pageSelectorTreeWidgetItem, vol);
//   connect(j, SIGNAL(destroyed()), this, SLOT(populateTree()));
}

MediaView::~MediaView()
{
}

void MediaView::applyPushed()
{
   populateTable();
}

void MediaView::editPushed()
{
   QStringList sel;
   QString cmd;
   getSelection(sel);

   for(int i=0; i<sel.count(); i++) {
      cmd = sel.at(i);
      new MediaEdit(mainWin->getFromHash(this), cmd);
   }
}

void MediaView::purgePushed()
{
   if (QMessageBox::warning(this, "Bat",
      tr("Are you sure you want to purge ??  !!!.\n"
"The Purge command will delete associated Catalog database records from Jobs and"
" Volumes without considering the retention period. Purge  works only on the"
" Catalog database and does not affect data written to Volumes. This command can"
" be dangerous because you can delete catalog records associated with current"
" backups of files, and we recommend that you do not use it unless you know what"
" you are doing.\n"
      "Press OK to proceed with the purge operation?"),
      QMessageBox::Ok | QMessageBox::Cancel)
      == QMessageBox::Cancel) { return; }

   QStringList lst;
   QString cmd;
   getSelection(lst);
   for(int i=0; i<lst.count(); i++) {
      cmd = "purge volume=" + lst.at(i);
      consoleCommand(cmd);
   }
   populateTable();
}

bool MediaView::getSelection(QStringList &list)
{
   int i, nb, nr_rows, row;
   bool *tab;
   QTableWidgetItem *it;
   QList<QTableWidgetItem*> items = m_tableMedia->selectedItems();

   /*
    * See if anything is selected.
    */
   nb = items.count();
   if (!nb) {
      return false;
   }

   /*
    * Create a nibble map for each row so we can see if its
    * selected or not.
    */
   nr_rows = m_tableMedia->rowCount();
   tab = (bool *)malloc (nr_rows * sizeof(bool));
   memset(tab, 0, sizeof(bool) * nr_rows);

   for (i = 0; i < nb; ++i) {
      row = items[i]->row();
      if (!tab[row]) {
         tab[row] = true;
         it = m_tableMedia->item(row, 0);
         list.append(it->text());
      }
   }
   free(tab);

   return list.count() > 0;
}

void MediaView::prunePushed()
{
   QStringList sel;
   QString cmd;
   getSelection(sel);

   for(int i=0; i<sel.count(); i++) {
      cmd = "prune volume=" + sel.at(i);
      consoleCommand(cmd);
   }
}

void MediaView::deletePushed()
{
   if (QMessageBox::warning(this, "Bat",
      tr("Are you sure you want to delete??  !!!.\n"
"This delete command is used to delete a Volume record and all associated catalog"
" records that were created. This command operates only on the Catalog"
" database and has no effect on the actual data written to a Volume. This"
" command can be dangerous and we strongly recommend that you do not use"
" it unless you know what you are doing.  All Jobs and all associated"
" records (File and JobMedia) will be deleted from the catalog."
      "Press OK to proceed with delete operation.?"),
      QMessageBox::Ok | QMessageBox::Cancel)
      == QMessageBox::Cancel) { return; }

   QStringList lst;
   QString cmd;
   getSelection(lst);
   for(int i=0; i<lst.count(); i++) {
      cmd = "delete volume=" + lst.at(i);
      consoleCommand(cmd);
   }
   populateTable();
}

void MediaView::populateForm()
{
   m_cbPool->clear();
   m_cbPool->addItem("");
   m_cbPool->addItems(m_console->pool_list);

   m_cbStatus->clear();
   m_cbStatus->addItem("");
   m_cbStatus->addItems(m_console->volstatus_list);

   m_cbMediaType->clear();
   m_cbMediaType->addItem("");
   m_cbMediaType->addItems(m_console->mediatype_list);

   m_cbLocation->clear();
   m_cbLocation->addItem("");
   m_cbLocation->addItems(m_console->location_list);
}

/*
 * If chkExpired button is checked, we can remove all non Expired
 * entries
 */
void MediaView::filterExipired(QStringList &list)
{
   utime_t t, now = time(NULL);
   QString resultline, stat, LastWritten;
   QStringList fieldlist;

   /* We should now in advance how many rows we will have */
   if (m_chkExpired->isChecked()) {
      for (int i=list.size() -1; i >= 0; i--) {
         fieldlist = list.at(i).split("\t");
         ASSERT(fieldlist.size() != 9);
         LastWritten = fieldlist.at(7);
         if (LastWritten == "") {
            list.removeAt(i);

         } else {
            stat = fieldlist.at(8);
            t = str_to_utime(LastWritten.toAscii().data());
            t = t + stat.toULongLong();
            if (t > now) {
               list.removeAt(i);
            }
         }
      }
   }
}

/*
 * The main meat of the class!!  The function that querries the director and
 * creates the widgets with appropriate values.
 */
void MediaView::populateTable()
{
   utime_t t;
   time_t ttime;
   QString stat, resultline, query;
   QString str_usage;
   QHash<QString, float> hash_size;
   QStringList fieldlist, results;
   char buf[256];
   float usage;
   struct tm tm;

   m_populated = true;

   Freeze frz(*m_tableMedia); /* disable updating*/
   QStringList where;
   QString cmd;
   if (m_cbPool->currentText() != "") {
      cmd = " Pool.Name = '" + m_cbPool->currentText() + "'";
      where.append(cmd);
   }

   if (m_cbStatus->currentText() != "") {
      cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
      where.append(cmd);
   }

   if (m_cbStatus->currentText() != "") {
      cmd = " Media.VolStatus = '" + m_cbStatus->currentText() + "'";
      where.append(cmd);
   }

   if (m_cbMediaType->currentText() != "") {
      cmd = " Media.MediaType = '" + m_cbMediaType->currentText() + "'";
      where.append(cmd);
   }

   if (m_cbLocation->currentText() != "") {
      cmd = " Location.Location = '" + m_cbLocation->currentText() + "'";
      where.append(cmd);
   }

   if (m_textName->text() != "") {
      cmd = " Media.VolumeName like '%" + m_textName->text() + "%'";
      where.append(cmd);
   }

   if (where.size() > 0) {
      cmd = " WHERE " + where.join(" AND ");
   } else {
      cmd = "";
   }

   query =
      "SELECT AVG(VolBytes) AS size, COUNT(1) as nb, "
      "MediaType  FROM Media "
      "WHERE VolStatus IN ('Full', 'Used') "
      "GROUP BY MediaType";

   if (mainWin->m_sqlDebug) {
      Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
   }
   if (m_console->sql_cmd(query, results)) {
      foreach (resultline, results) {
         fieldlist = resultline.split("\t");
         if (fieldlist.at(1).toInt() >= 1) {
            //           MediaType
            hash_size[fieldlist.at(2)]
               = fieldlist.at(0).toFloat();
         }
      }
   }

   m_tableMedia->clearContents();
   query =
      "SELECT VolumeName, InChanger, "
      "Slot, MediaType, VolStatus, VolBytes, Pool.Name,  "
      "LastWritten, Media.VolRetention "
      "FROM Media JOIN Pool USING (PoolId) "
      "LEFT JOIN Location ON (Media.LocationId=Location.LocationId) "
      + cmd +
      " ORDER BY VolumeName LIMIT " + m_sbLimit->cleanText();

   m_tableMedia->sortByColumn(0, Qt::AscendingOrder);
   m_tableMedia->setSortingEnabled(false); /* Don't sort during insert */
   results.clear();
   if (mainWin->m_sqlDebug) {
      Pmsg1(000, "MediaView query cmd : %s\n",query.toUtf8().data());
   }
   if (m_console->sql_cmd(query, results)) {
      int row=0;
      filterExipired(results);
      m_tableMedia->setRowCount(results.size());

      foreach (resultline, results) { // should have only one result
         int index = 0;
         QString Slot, VolBytes, MediaType, LastWritten, VolStatus;
         fieldlist = resultline.split("\t");
         if (fieldlist.size() != 10) {
            continue;
         }
         QStringListIterator fld(fieldlist);
         TableItemFormatter mediaitem(*m_tableMedia, row);

         /* VolumeName */
         mediaitem.setTextFld(index++, fld.next());

         /* Online */
         mediaitem.setInChanger(index++, fld.next());

         Slot = fld.next();            // Slot
         mediaitem.setNumericFld(index++, Slot);

         MediaType = fld.next();
         VolStatus = fld.next();

         /* Volume bytes */
         VolBytes = fld.next();
         mediaitem.setBytesFld(index++, VolBytes);

         /* Usage */
         usage = 0;
         if (hash_size.contains(MediaType) &&
             hash_size[MediaType] != 0) {
            usage = VolBytes.toLongLong() * 100 / hash_size[MediaType];
         }
         mediaitem.setPercent(index++, usage);

         /* Volstatus */
         mediaitem.setVolStatusFld(index++, VolStatus);

         /* Pool */
         mediaitem.setTextFld(index++, fld.next());

         /* MediaType */
         mediaitem.setTextFld(index++, MediaType);

         LastWritten = fld.next();
         buf[0] = 0;
         if (LastWritten != "") {
            stat = fld.next();  // VolUseDuration
            t = str_to_utime(LastWritten.toAscii().data());
            t = t + stat.toULongLong();
            ttime = t;
            localtime_r(&ttime, &tm);
            strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
         }

         /* LastWritten */
         mediaitem.setTextFld(index++, LastWritten);

         /* When expired */
         mediaitem.setTextFld(index++, buf);
         row++;
      }
   }
   m_tableMedia->resizeColumnsToContents();
   m_tableMedia->resizeRowsToContents();
   m_tableMedia->verticalHeader()->hide();
   m_tableMedia->setSortingEnabled(true);

   /* make read only */
   m_tableMedia->setEditTriggers(QAbstractItemView::NoEditTriggers);
}

/*
 * When the treeWidgetItem in the page selector tree is singleclicked, Make sure
 * The tree has been populated.
 */
void MediaView::PgSeltreeWidgetClicked()
{
   if (!m_populated) {
      populateForm();
      populateTable();
   }
   if (!isOnceDocked()) {
      dockPage();
   }
}

/*
 * Virtual function which is called when this page is visible on the stack
 */
void MediaView::currentStackItem()
{
   if(!m_populated) {
      populateForm();
      populateTable();
   }
}

// /*
//  * Called from the signal of the context sensitive menu to relabel!
//  */
// void MediaView::relabelVolume()
// {
//    setConsoleCurrent();
//    new relabelDialog(m_console, m_currentVolumeName);
// }
//
// /*
//  * Called from the signal of the context sensitive menu to purge!
//  */
// void MediaView::allVolumesFromPool()
// {
//    QString cmd = "update volume AllFromPool=" + m_currentVolumeName;
//    consoleCommand(cmd);
//    populateTable();
// }
//
// void MediaView::allVolumes()
// {
//    QString cmd = "update volume allfrompools";
//    consoleCommand(cmd);
//    populateTable();
// }
//
//  /*
//   * Called from the signal of the context sensitive menu to purge!
//   */
//  void MediaView::volumeFromPool()
//  {
//     QTreeWidgetItem *currentItem = mp_treeWidget->currentItem();
//     QTreeWidgetItem *parent = currentItem->parent();
//     QString pool = parent->text(0);
//     QString cmd;
//     cmd = "update volume=" + m_currentVolumeName + " frompool=" + pool;
//     consoleCommand(cmd);
//     populateTable();
//  }
//
<|endoftext|>


<commit_before>/**************************************************************************
  **       Title: L2Error class
  **    $RCSfile$
  **   $Revision: 1723 $$Name$
  **       $Date: 2007-06-20 15:20:54 +0000 (Wed, 20 Jun 2007) $
  **   Copyright: GPL $Author: dune community $
  ** Description: L2 error class, which computes the error between a function
  **              and a discrete function. Extracted class from
  **              Roberts poisson-example
  **
  **************************************************************************/

#ifndef DUNE_MS_MEANVALUE_HH
#define DUNE_MS_MEANVALUE_HH

// where the quadratures are defined
#include <dune/fem/quadrature/cachingquadrature.hh>
#include <dune/fem/misc/l2error.hh>

#include "misc/linear-lagrange-interpolation.hh"

namespace Dune {
/**  \class Meanvalue
   *  \brief The Meanvalue class provides a method to calculate the meanvalue of a discrete function
   *
   *  Actually only the meanvalue of discrete functions on the unit-cube can be calculated.
   *  If you want more, divide the return value of getMeanvalue() by the size of the domain.
   *  Since it's the unit cube for our purpose, the domain-size is 1 and therefore unimportant
   *  for us.
   *
 * Usage of the meanvalue class:
  * Example:
   *
   *  Meanvalue< DiscreteFunctionType > mymean;
   *  DiscreteFunctionSpaceType :: RangeType theMeanValue;
   *  theMeanValue = mymean.getMeanvalue( a_discreteFunction );
   *  std :: cout << "Meanvalue of the numerical solution: " << theMeanValue << std :: endl;
   *
   * Shift the discrete function to meanvalue zero:
   *
   * mymean.adapt<DiscreteFunctionType>( a_discreteFunction , theMeanValue );
   *
   * \TODO use stuff/fem/funtions/integrals.hh instead
   **/
template< class DiscreteFunctionType >
class Meanvalue
{
  typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType
  DiscreteFunctionSpaceType;

  typedef typename DiscreteFunctionType::RangeType
  RangeType;
  typedef typename DiscreteFunctionType::DomainType
  DomainType;

  typedef typename DiscreteFunctionSpaceType::IteratorType
  IteratorType;

  typedef typename DiscreteFunctionSpaceType::GridType
  GridType;

  typedef typename DiscreteFunctionSpaceType::DomainFieldType DomainFieldType;
  typedef DomainFieldType                                     TimeType;

  typedef typename DiscreteFunctionSpaceType::GridPartType
  GridPartType;

  typedef typename GridType::template Codim< 0 >::Entity
  EntityType;

  typedef typename GridType::template Codim< 0 >::Geometry
  EnGeometryType;

  typedef typename EntityType::ctype
  coordType;

  typedef typename DiscreteFunctionType::LocalFunctionType
  LocalFunctionType;

  enum { dimension = GridType::dimension };
  enum { spacePolOrd = DiscreteFunctionSpaceType::polynomialOrder };

  struct FunctorBase {
    virtual void evaluate(const DomainType& global_point, RangeType& y) const = 0;
  };

  RangeType getMeanvalue_common(const DiscreteFunctionSpaceType& space,
                                const FunctorBase& function) const {
    const int polOrd = (2 * spacePolOrd + 2);

    RangeType y(0.0);    // return value
    RangeType theMeanValue(0.0);

    for (const auto& entity : space)
    {
      // create quadrature for given geometry type
      const CachingQuadrature< GridPartType, 0 > quadrature(entity, polOrd);

      // get geoemetry of entity
      const EnGeometryType& geo = entity.geometry();

      // integrate
      const int quadratureNop = quadrature.nop();
      for (int quadraturePoint = 0; quadraturePoint < quadratureNop; ++quadraturePoint)
      {
        const double det = quadrature.weight(quadraturePoint)
                           * geo.integrationElement( quadrature.point(quadraturePoint) );

        y = function(geo.global( quadrature.point(quadraturePoint)));

        theMeanValue += det * y;
      }
    }
  }
public:
  RangeType getMeanvalue(const DiscreteFunctionType& discFunc) const {
    const int polOrd = (2 * spacePolOrd + 2);

    // get function space
    const DiscreteFunctionSpaceType& space = discFunc.space();
    RangeType y(0.0);    // return value
    RangeType theMeanValue(0.0);

    for (const auto& entity : space)
    {
      // create quadrature for given geometry type
      const CachingQuadrature< GridPartType, 0 > quadrature(entity, polOrd);
      const LocalFunctionType localfunc = discFunc.localFunction(entity);
      const EnGeometryType& geo = entity.geometry();

      // integrate
      const int quadratureNop = quadrature.size();
      for (int quadraturePoint = 0; quadraturePoint < quadratureNop; ++quadraturePoint)
      {
        const double det = quadrature.weight(quadraturePoint)
                           * geo.integrationElement( quadrature.point(quadraturePoint) );

        localfunc.evaluate(quadrature, quadraturePoint, y);

        theMeanValue += det * y;
      }
    }

    const auto& comm = space.gridPart().grid().comm();
    theMeanValue = comm.sum(theMeanValue);

    return theMeanValue;
  }   // end of method

  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      Functor(const FunctionType& f) : function(f) {}
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(global_point, y);
      }
    } f{function};
    return getMeanvalue_common(space, f);
  }   // end of method

  // the case the function is a vector (for instance advection)
  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function,
                         const int& i /*in case there are several components*/) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      const int i;
      Functor(const FunctionType& f, const int _i) : function(f), i(_i) {}
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(i, global_point, y);
      }
    } f{function, i};
    return getMeanvalue_common(space, f);
  }   // end of method

  // the case the function is a time-dependent vector (for instance advection). The Time t is fixed.
  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function,
                         const TimeType& t,
                         const int& i /*in case there are several components*/) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      const int i;
      const TimeType t;
      Functor(const FunctionType& f, const int _i, const TimeType _t) : function(f), i(_i), t(_t) {}
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(i, global_point,t, y);
      }
    } f{function, i, t};
    return getMeanvalue_common(space, f);
  }   // end of method

  // the case the function is a matrix (for instance diffusion)
  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function,
                         const int& i,
                         const int& j) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      const int i;
      const int j;
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(i, j, global_point, y);
      }
    } f{function, i, j};
    return getMeanvalue_common(space, f);
  }   // end of method

  // the case the function is a matrix (for instance diffusion) with Time t
  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function,
                         const TimeType& t,
                         const int& i,
                         const int& j) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      const int i;
      const int j;
      const TimeType t;
      Functor(const FunctionType& f, const int _i, const int _j, const TimeType _t) : function(f), i(_i), j(_j), t(_t) {}
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(i, j, global_point,t, y);
      }
    } f{function, i, j, t};
    return getMeanvalue_common(space, f);
  }   // end of method

  //! Subdraktion des Mittelwertes von der DiscreteFunction
  template< class FunctionType >
  static void adapt(FunctionType& discreteFunction, RangeType& meanvalue) {
    typedef typename FunctionType::DofIteratorType DofIteratorType;

    const DofIteratorType end = discreteFunction.dend();
    for (DofIteratorType it = discreteFunction.dbegin(); it != end; ++it)
      *it -= meanvalue[0];
    // Dof Iterator verwenden um Verschiebung um Mittelwert

  } // adapt
}; // end of class Meanvalue

} // end namespace DUNE

#endif // ifndef DUNE_MS_MEANVALUE_HH
<commit_msg>tools/meanvalue isn't related to the L2Error class either<commit_after>#ifndef DUNE_MS_MEANVALUE_HH
#define DUNE_MS_MEANVALUE_HH

// where the quadratures are defined
#include <dune/fem/quadrature/cachingquadrature.hh>
#include <dune/fem/misc/l2error.hh>

#include "misc/linear-lagrange-interpolation.hh"

namespace Dune {
/**  \class Meanvalue
   *  \brief The Meanvalue class provides a method to calculate the meanvalue of a discrete function
   *
   *  Actually only the meanvalue of discrete functions on the unit-cube can be calculated.
   *  If you want more, divide the return value of getMeanvalue() by the size of the domain.
   *  Since it's the unit cube for our purpose, the domain-size is 1 and therefore unimportant
   *  for us.
   *
 * Usage of the meanvalue class:
  * Example:
   *
   *  Meanvalue< DiscreteFunctionType > mymean;
   *  DiscreteFunctionSpaceType :: RangeType theMeanValue;
   *  theMeanValue = mymean.getMeanvalue( a_discreteFunction );
   *  std :: cout << "Meanvalue of the numerical solution: " << theMeanValue << std :: endl;
   *
   * Shift the discrete function to meanvalue zero:
   *
   * mymean.adapt<DiscreteFunctionType>( a_discreteFunction , theMeanValue );
   *
   * \TODO use stuff/fem/funtions/integrals.hh instead
   **/
template< class DiscreteFunctionType >
class Meanvalue
{
  typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType
  DiscreteFunctionSpaceType;

  typedef typename DiscreteFunctionType::RangeType
  RangeType;
  typedef typename DiscreteFunctionType::DomainType
  DomainType;

  typedef typename DiscreteFunctionSpaceType::IteratorType
  IteratorType;

  typedef typename DiscreteFunctionSpaceType::GridType
  GridType;

  typedef typename DiscreteFunctionSpaceType::DomainFieldType DomainFieldType;
  typedef DomainFieldType                                     TimeType;

  typedef typename DiscreteFunctionSpaceType::GridPartType
  GridPartType;

  typedef typename GridType::template Codim< 0 >::Entity
  EntityType;

  typedef typename GridType::template Codim< 0 >::Geometry
  EnGeometryType;

  typedef typename EntityType::ctype
  coordType;

  typedef typename DiscreteFunctionType::LocalFunctionType
  LocalFunctionType;

  enum { dimension = GridType::dimension };
  enum { spacePolOrd = DiscreteFunctionSpaceType::polynomialOrder };

  struct FunctorBase {
    virtual void evaluate(const DomainType& global_point, RangeType& y) const = 0;
  };

  RangeType getMeanvalue_common(const DiscreteFunctionSpaceType& space,
                                const FunctorBase& function) const {
    const int polOrd = (2 * spacePolOrd + 2);

    RangeType y(0.0);    // return value
    RangeType theMeanValue(0.0);

    for (const auto& entity : space)
    {
      // create quadrature for given geometry type
      const CachingQuadrature< GridPartType, 0 > quadrature(entity, polOrd);

      // get geoemetry of entity
      const EnGeometryType& geo = entity.geometry();

      // integrate
      const int quadratureNop = quadrature.nop();
      for (int quadraturePoint = 0; quadraturePoint < quadratureNop; ++quadraturePoint)
      {
        const double det = quadrature.weight(quadraturePoint)
                           * geo.integrationElement( quadrature.point(quadraturePoint) );

        y = function(geo.global( quadrature.point(quadraturePoint)));

        theMeanValue += det * y;
      }
    }
  }
public:
  RangeType getMeanvalue(const DiscreteFunctionType& discFunc) const {
    const int polOrd = (2 * spacePolOrd + 2);

    // get function space
    const DiscreteFunctionSpaceType& space = discFunc.space();
    RangeType y(0.0);    // return value
    RangeType theMeanValue(0.0);

    for (const auto& entity : space)
    {
      // create quadrature for given geometry type
      const CachingQuadrature< GridPartType, 0 > quadrature(entity, polOrd);
      const LocalFunctionType localfunc = discFunc.localFunction(entity);
      const EnGeometryType& geo = entity.geometry();

      // integrate
      const int quadratureNop = quadrature.size();
      for (int quadraturePoint = 0; quadraturePoint < quadratureNop; ++quadraturePoint)
      {
        const double det = quadrature.weight(quadraturePoint)
                           * geo.integrationElement( quadrature.point(quadraturePoint) );

        localfunc.evaluate(quadrature, quadraturePoint, y);

        theMeanValue += det * y;
      }
    }

    const auto& comm = space.gridPart().grid().comm();
    theMeanValue = comm.sum(theMeanValue);

    return theMeanValue;
  }   // end of method

  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      Functor(const FunctionType& f) : function(f) {}
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(global_point, y);
      }
    } f{function};
    return getMeanvalue_common(space, f);
  }   // end of method

  // the case the function is a vector (for instance advection)
  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function,
                         const int& i /*in case there are several components*/) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      const int i;
      Functor(const FunctionType& f, const int _i) : function(f), i(_i) {}
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(i, global_point, y);
      }
    } f{function, i};
    return getMeanvalue_common(space, f);
  }   // end of method

  // the case the function is a time-dependent vector (for instance advection). The Time t is fixed.
  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function,
                         const TimeType& t,
                         const int& i /*in case there are several components*/) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      const int i;
      const TimeType t;
      Functor(const FunctionType& f, const int _i, const TimeType _t) : function(f), i(_i), t(_t) {}
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(i, global_point,t, y);
      }
    } f{function, i, t};
    return getMeanvalue_common(space, f);
  }   // end of method

  // the case the function is a matrix (for instance diffusion)
  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function,
                         const int& i,
                         const int& j) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      const int i;
      const int j;
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(i, j, global_point, y);
      }
    } f{function, i, j};
    return getMeanvalue_common(space, f);
  }   // end of method

  // the case the function is a matrix (for instance diffusion) with Time t
  template< class FunctionType >
  RangeType getMeanvalue(const DiscreteFunctionSpaceType& space,
                         const FunctionType& function,
                         const TimeType& t,
                         const int& i,
                         const int& j) const {
    struct Functor : public FunctorBase {
      const FunctionType& function;
      const int i;
      const int j;
      const TimeType t;
      Functor(const FunctionType& f, const int _i, const int _j, const TimeType _t) : function(f), i(_i), j(_j), t(_t) {}
      virtual RangeType operator()(const DomainType& global_point, RangeType& y) const {
        function.evaluate(i, j, global_point,t, y);
      }
    } f{function, i, j, t};
    return getMeanvalue_common(space, f);
  }   // end of method

  //! Subdraktion des Mittelwertes von der DiscreteFunction
  template< class FunctionType >
  static void adapt(FunctionType& discreteFunction, RangeType& meanvalue) {
    typedef typename FunctionType::DofIteratorType DofIteratorType;

    const DofIteratorType end = discreteFunction.dend();
    for (DofIteratorType it = discreteFunction.dbegin(); it != end; ++it)
      *it -= meanvalue[0];
    // Dof Iterator verwenden um Verschiebung um Mittelwert

  } // adapt
}; // end of class Meanvalue

} // end namespace DUNE

#endif // ifndef DUNE_MS_MEANVALUE_HH
<|endoftext|>


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

#ifndef SVX_BORDERLINE_HXX
#define SVX_BORDERLINE_HXX

#include <tools/color.hxx>
#include <svl/poolitem.hxx>
#include <editeng/editengdllapi.h>
#include <svtools/ctrlbox.hxx>

// Line defaults in twips (former Writer defaults):

#define DEF_LINE_WIDTH_0        1
#define DEF_LINE_WIDTH_1        20
#define DEF_LINE_WIDTH_2        50
#define DEF_LINE_WIDTH_3        80
#define DEF_LINE_WIDTH_4        100
#define DEF_LINE_WIDTH_5        10

#define DEF_MAX_LINE_WIDHT      DEF_LINE_WIDTH_4
#define DEF_MAX_LINE_DIST       DEF_LINE_WIDTH_2

#define DEF_DOUBLE_LINE0_OUT    DEF_LINE_WIDTH_0
#define DEF_DOUBLE_LINE0_IN     DEF_LINE_WIDTH_0
#define DEF_DOUBLE_LINE0_DIST   DEF_LINE_WIDTH_1

#define DEF_DOUBLE_LINE1_OUT    DEF_LINE_WIDTH_1
#define DEF_DOUBLE_LINE1_IN     DEF_LINE_WIDTH_1
#define DEF_DOUBLE_LINE1_DIST   DEF_LINE_WIDTH_1

#define DEF_DOUBLE_LINE2_OUT    DEF_LINE_WIDTH_2
#define DEF_DOUBLE_LINE2_IN     DEF_LINE_WIDTH_2
#define DEF_DOUBLE_LINE2_DIST   DEF_LINE_WIDTH_2

#define DEF_DOUBLE_LINE3_OUT    DEF_LINE_WIDTH_2
#define DEF_DOUBLE_LINE3_IN     DEF_LINE_WIDTH_1
#define DEF_DOUBLE_LINE3_DIST   DEF_LINE_WIDTH_2

#define DEF_DOUBLE_LINE4_OUT    DEF_LINE_WIDTH_1
#define DEF_DOUBLE_LINE4_IN     DEF_LINE_WIDTH_2
#define DEF_DOUBLE_LINE4_DIST   DEF_LINE_WIDTH_1

#define DEF_DOUBLE_LINE5_OUT    DEF_LINE_WIDTH_3
#define DEF_DOUBLE_LINE5_IN     DEF_LINE_WIDTH_2
#define DEF_DOUBLE_LINE5_DIST   DEF_LINE_WIDTH_2

#define DEF_DOUBLE_LINE6_OUT    DEF_LINE_WIDTH_2
#define DEF_DOUBLE_LINE6_IN     DEF_LINE_WIDTH_3
#define DEF_DOUBLE_LINE6_DIST   DEF_LINE_WIDTH_2

#define DEF_DOUBLE_LINE7_OUT    DEF_LINE_WIDTH_0
#define DEF_DOUBLE_LINE7_IN     DEF_LINE_WIDTH_0
#define DEF_DOUBLE_LINE7_DIST   DEF_LINE_WIDTH_2

#define DEF_DOUBLE_LINE8_OUT    DEF_LINE_WIDTH_1
#define DEF_DOUBLE_LINE8_IN     DEF_LINE_WIDTH_0
#define DEF_DOUBLE_LINE8_DIST   DEF_LINE_WIDTH_2

#define DEF_DOUBLE_LINE9_OUT    DEF_LINE_WIDTH_2
#define DEF_DOUBLE_LINE9_IN     DEF_LINE_WIDTH_0
#define DEF_DOUBLE_LINE9_DIST   DEF_LINE_WIDTH_2

#define DEF_DOUBLE_LINE10_OUT   DEF_LINE_WIDTH_3
#define DEF_DOUBLE_LINE10_IN    DEF_LINE_WIDTH_0
#define DEF_DOUBLE_LINE10_DIST  DEF_LINE_WIDTH_2

// ============================================================================

enum SvxBorderStyle
{
    SOLID,
    DOTTED,
    DASHED,
    DOUBLE,
    THINTHICK_SMALLGAP,
    THINTHICK_MEDIUMGAP,
    THINTHICK_LARGEGAP,
    THICKTHIN_SMALLGAP,
    THICKTHIN_MEDIUMGAP,
    THICKTHIN_LARGEGAP,
    EMBOSSED,
    ENGRAVED,
    OUTSET,
    INSET,
    NO_STYLE = -1
};

class EDITENG_DLLPUBLIC SvxBorderLine
{
protected:
    Color  aColor;

    long m_nWidth;
    bool m_bMirrorWidths;
    BorderWidthImpl m_aWidthImpl;
    long m_nMult;
    long m_nDiv;

    SvxBorderStyle   m_nStyle;
    sal_uInt16 nOutWidth;
    sal_uInt16 nInWidth;
    sal_uInt16 nDistance;

    bool             m_bUseLeftTop;
    Color            (*m_pColorOutFn)( Color );
    Color            (*m_pColorInFn)( Color );
    Color            (*m_pColorGapFn)( Color );

public:
    SvxBorderLine( const Color *pCol = 0,
            long nWidth = 0, SvxBorderStyle nStyle = SOLID,
            bool bUseLeftTop = false,
            Color (*pColorOutFn)( Color ) = &darkColor,
            Color (*pColorInFn)( Color ) = &darkColor,
            Color (*pColorGapFn)( Color ) = NULL );
    SvxBorderLine( const SvxBorderLine& r );

    SvxBorderLine& operator=( const SvxBorderLine& r );

    const Color&    GetColor() const { return aColor; }
    Color           GetColorOut( bool bLeftOrTop = true ) const;
    Color           GetColorIn( bool bLeftOrTop = true ) const;
    bool            HasGapColor() const { return m_pColorGapFn != NULL; }
    Color           GetColorGap() const;

    void            SetWidth( long nWidth = 0 ) { m_nWidth = nWidth; }
    /** Guess the style and width from the three lines widths values.

        When the value of nStyle is SvxBorderLine::DOUBLE, the style set will be guessed
        using the three values to match the best possible style among the following:
            - SvxBorderLine::DOUBLE
            - SvxBorderLine::THINTHICK_SMALLGAP
            - SvxBorderLine::THINTHICK_MEDIUMGAP
            - SvxBorderLine::THINTHICK_LARGEGAP
            - SvxBorderLine::THICKTHIN_SMALLGAP
            - SvxBorderLine::THICKTHIN_MEDIUMGAP
            - SvxBorderLine::THICKTHIN_LARGEGAP

        If no styles matches the width, then the width is set to 0.

        There is one known case that could fit several styles: \a nIn = \a nDist = 0.75 pt,
        \a nOut = 1.5 pt. This case fits SvxBorderLine::THINTHICK_SMALLGAP and
        SvxBorderLine::THINTHICK_MEDIUMGAP with a 1.5 pt width and
        SvxBorderLine::THINTHICK_LARGEGAP with a 0.75 pt width. The same case happens
        also for thick-thin styles.

        \param nStyle the border style used to guess the width.
        \param nIn the width of the inner line in 1th pt
        \param nOut the width of the outer line in 1th pt
        \param nDist the width of the gap between the lines in 1th pt
     */
    void            GuessLinesWidths( SvxBorderStyle nStyle, sal_uInt16 nOut, sal_uInt16 nIn = 0, sal_uInt16 nDist = 0 );

    // TODO Hacky method to mirror lines in only a few cases
    void            SetMirrorWidths( bool bMirror = true ) { m_bMirrorWidths = bMirror; }
    long            GetWidth( ) const { return m_nWidth; }
    sal_uInt16      GetOutWidth() const;
    sal_uInt16      GetInWidth() const;
    sal_uInt16      GetDistance() const;

    SvxBorderStyle  GetStyle() const { return m_nStyle; }

    void            SetColor( const Color &rColor ) { aColor = rColor; }
    void            SetColorOutFn( Color (*pColorOutFn)( Color ) ) { m_pColorOutFn = pColorOutFn; }
    void            SetColorInFn( Color (*pColorInFn)( Color ) ) { m_pColorInFn = pColorInFn; }
    void            SetColorGapFn( Color (*pColorGapFn)( Color ) ) { m_pColorGapFn = pColorGapFn; }
    void            SetUseLeftTop( bool bUseLeftTop ) { m_bUseLeftTop = bUseLeftTop; }
    void            SetStyle( SvxBorderStyle nNew );
    void            ScaleMetrics( long nMult, long nDiv );

    sal_Bool            operator==( const SvxBorderLine &rCmp ) const;

    String          GetValueString( SfxMapUnit eSrcUnit, SfxMapUnit eDestUnit,
                                    const IntlWrapper* pIntl,
                                    sal_Bool bMetricStr = sal_False ) const;

    bool            HasPriority( const SvxBorderLine& rOtherLine ) const;

    bool isEmpty() const { return m_aWidthImpl.IsEmpty( ) || m_nStyle == NO_STYLE || m_nWidth == 0; }
    bool isDouble() const { return m_aWidthImpl.IsDouble(); }
    sal_uInt16 GetScaledWidth() const { return GetOutWidth() + GetInWidth() + GetDistance(); }

    static Color darkColor( Color aMain );
    static Color lightColor( Color aMain );

    static Color threeDLightColor( Color aMain );
    static Color threeDMediumColor( Color aMain );
    static Color threeDDarkColor( Color aMain );

    static BorderWidthImpl getWidthImpl( SvxBorderStyle nStyle );
};

// ============================================================================

#endif

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

#ifndef SVX_BORDERLINE_HXX
#define SVX_BORDERLINE_HXX

#include <tools/color.hxx>
#include <svl/poolitem.hxx>
#include <editeng/editengdllapi.h>
#include <svtools/ctrlbox.hxx>

// Line defaults in twips (former Writer defaults):

#define DEF_LINE_WIDTH_0        1
#define DEF_LINE_WIDTH_1        20
#define DEF_LINE_WIDTH_2        50
#define DEF_LINE_WIDTH_3        80
#define DEF_LINE_WIDTH_4        100
#define DEF_LINE_WIDTH_5        10

// ============================================================================

enum SvxBorderStyle
{
    SOLID,
    DOTTED,
    DASHED,
    DOUBLE,
    THINTHICK_SMALLGAP,
    THINTHICK_MEDIUMGAP,
    THINTHICK_LARGEGAP,
    THICKTHIN_SMALLGAP,
    THICKTHIN_MEDIUMGAP,
    THICKTHIN_LARGEGAP,
    EMBOSSED,
    ENGRAVED,
    OUTSET,
    INSET,
    NO_STYLE = -1
};

class EDITENG_DLLPUBLIC SvxBorderLine
{
protected:
    Color  aColor;

    long m_nWidth;
    bool m_bMirrorWidths;
    BorderWidthImpl m_aWidthImpl;
    long m_nMult;
    long m_nDiv;

    SvxBorderStyle   m_nStyle;
    sal_uInt16 nOutWidth;
    sal_uInt16 nInWidth;
    sal_uInt16 nDistance;

    bool             m_bUseLeftTop;
    Color            (*m_pColorOutFn)( Color );
    Color            (*m_pColorInFn)( Color );
    Color            (*m_pColorGapFn)( Color );

public:
    SvxBorderLine( const Color *pCol = 0,
            long nWidth = 0, SvxBorderStyle nStyle = SOLID,
            bool bUseLeftTop = false,
            Color (*pColorOutFn)( Color ) = &darkColor,
            Color (*pColorInFn)( Color ) = &darkColor,
            Color (*pColorGapFn)( Color ) = NULL );
    SvxBorderLine( const SvxBorderLine& r );

    SvxBorderLine& operator=( const SvxBorderLine& r );

    const Color&    GetColor() const { return aColor; }
    Color           GetColorOut( bool bLeftOrTop = true ) const;
    Color           GetColorIn( bool bLeftOrTop = true ) const;
    bool            HasGapColor() const { return m_pColorGapFn != NULL; }
    Color           GetColorGap() const;

    void            SetWidth( long nWidth = 0 ) { m_nWidth = nWidth; }
    /** Guess the style and width from the three lines widths values.

        When the value of nStyle is SvxBorderLine::DOUBLE, the style set will be guessed
        using the three values to match the best possible style among the following:
            - SvxBorderLine::DOUBLE
            - SvxBorderLine::THINTHICK_SMALLGAP
            - SvxBorderLine::THINTHICK_MEDIUMGAP
            - SvxBorderLine::THINTHICK_LARGEGAP
            - SvxBorderLine::THICKTHIN_SMALLGAP
            - SvxBorderLine::THICKTHIN_MEDIUMGAP
            - SvxBorderLine::THICKTHIN_LARGEGAP

        If no styles matches the width, then the width is set to 0.

        There is one known case that could fit several styles: \a nIn = \a nDist = 0.75 pt,
        \a nOut = 1.5 pt. This case fits SvxBorderLine::THINTHICK_SMALLGAP and
        SvxBorderLine::THINTHICK_MEDIUMGAP with a 1.5 pt width and
        SvxBorderLine::THINTHICK_LARGEGAP with a 0.75 pt width. The same case happens
        also for thick-thin styles.

        \param nStyle the border style used to guess the width.
        \param nIn the width of the inner line in 1th pt
        \param nOut the width of the outer line in 1th pt
        \param nDist the width of the gap between the lines in 1th pt
     */
    void            GuessLinesWidths( SvxBorderStyle nStyle, sal_uInt16 nOut, sal_uInt16 nIn = 0, sal_uInt16 nDist = 0 );

    // TODO Hacky method to mirror lines in only a few cases
    void            SetMirrorWidths( bool bMirror = true ) { m_bMirrorWidths = bMirror; }
    long            GetWidth( ) const { return m_nWidth; }
    sal_uInt16      GetOutWidth() const;
    sal_uInt16      GetInWidth() const;
    sal_uInt16      GetDistance() const;

    SvxBorderStyle  GetStyle() const { return m_nStyle; }

    void            SetColor( const Color &rColor ) { aColor = rColor; }
    void            SetColorOutFn( Color (*pColorOutFn)( Color ) ) { m_pColorOutFn = pColorOutFn; }
    void            SetColorInFn( Color (*pColorInFn)( Color ) ) { m_pColorInFn = pColorInFn; }
    void            SetColorGapFn( Color (*pColorGapFn)( Color ) ) { m_pColorGapFn = pColorGapFn; }
    void            SetUseLeftTop( bool bUseLeftTop ) { m_bUseLeftTop = bUseLeftTop; }
    void            SetStyle( SvxBorderStyle nNew );
    void            ScaleMetrics( long nMult, long nDiv );

    sal_Bool            operator==( const SvxBorderLine &rCmp ) const;

    String          GetValueString( SfxMapUnit eSrcUnit, SfxMapUnit eDestUnit,
                                    const IntlWrapper* pIntl,
                                    sal_Bool bMetricStr = sal_False ) const;

    bool            HasPriority( const SvxBorderLine& rOtherLine ) const;

    bool isEmpty() const { return m_aWidthImpl.IsEmpty( ) || m_nStyle == NO_STYLE || m_nWidth == 0; }
    bool isDouble() const { return m_aWidthImpl.IsDouble(); }
    sal_uInt16 GetScaledWidth() const { return GetOutWidth() + GetInWidth() + GetDistance(); }

    static Color darkColor( Color aMain );
    static Color lightColor( Color aMain );

    static Color threeDLightColor( Color aMain );
    static Color threeDMediumColor( Color aMain );
    static Color threeDDarkColor( Color aMain );

    static BorderWidthImpl getWidthImpl( SvxBorderStyle nStyle );
};

// ============================================================================

#endif

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


<commit_before>// Copyright 2016-2020 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <type_traits>
#include <utility>

#include <mp++/complex.hpp>
#include <mp++/real.hpp>

#include "catch.hpp"

// NOLINTNEXTLINE(google-build-using-namespace)
using namespace mppp;

TEST_CASE("sqrt")
{
    complex r0{0};
    r0.sqrt();
    REQUIRE(std::is_same<complex &, decltype(r0.sqrt())>::value);
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0.zero_p());
    complex rop;
    REQUIRE(sqrt(rop, r0).zero_p());
    REQUIRE(std::is_same<complex &, decltype(sqrt(rop, r0))>::value);
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(sqrt(r0).zero_p());
    REQUIRE(std::is_same<complex, decltype(sqrt(r0))>::value);
    REQUIRE(sqrt(std::move(r0)).zero_p());
    // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
    REQUIRE(!r0.is_valid());
    // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
    r0 = complex{16, 17, complex_prec_t(128)};
    REQUIRE(abs(sqrt(r0)
                - (4.4353824558800734853070281844863776932288_r128 + 1.9164074540474820480048239757004444314933_icr128))
            < pow(2_r128, -120));
    REQUIRE(sqrt(r0).get_prec() == 128);
    rop = real{12, 40};
    sqrt(rop, r0);
    REQUIRE(
        abs(rop - (4.4353824558800734853070281844863776932288_r128 + 1.9164074540474820480048239757004444314933_icr128))
        < pow(2_r128, -120));
    REQUIRE(rop.get_prec() == 128);
    r0.sqrt();
    REQUIRE(
        abs(r0 - (4.4353824558800734853070281844863776932288_r128 + 1.9164074540474820480048239757004444314933_icr128))
        < pow(2_r128, -120));
    REQUIRE(r0.get_prec() == 128);
}

TEST_CASE("rec_sqrt")
{
    const auto cmp1
        = 0.52984103253104949318719835021445625746079_r128 + 0.33391728095862217076724902471316862541707_icr128;
    {
        // Member function.
        auto c = 1.1_r128 - 2.3_icr128;
        c.rec_sqrt();
        REQUIRE(abs(c - cmp1) < pow(2_r128, -126));
        REQUIRE(c.get_prec() == 128);
    }
    {
        // rop overload.
        complex c1, c2 = 1.1_r128 - 2.3_icr128;
        const auto p = c2.get_prec();
        REQUIRE(&rec_sqrt(c1, c2) == &c1);
        REQUIRE(std::is_same<decltype(rec_sqrt(c1, c2)), complex &>::value);
        REQUIRE(abs(c1 - cmp1) < pow(2_r128, -126));
        REQUIRE(c1.get_prec() == p);

        // Move, but won't steal because rop
        // has higher precision.
        c1 = complex{0, complex_prec_t(c2.get_prec() + 1)};
        rec_sqrt(c1, std::move(c2));
        REQUIRE(abs(c1 - cmp1) < pow(2_r128, -126));
        REQUIRE(c1.get_prec() == p);
        // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
        REQUIRE(c2 == 1.1_r128 - 2.3_icr128);

        // Move, will steal.
        c1 = complex{};
        rec_sqrt(c1, std::move(c2));
        REQUIRE(abs(c1 - cmp1) < pow(2_r128, -126));
        REQUIRE(c1.get_prec() == p);
        // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
        REQUIRE(c2 == complex{});
    }
    {
        // return overload.
        REQUIRE(abs(rec_sqrt(1.1_r128 - 2.3_icr128) - cmp1) < pow(2_r128, -126));
        REQUIRE(std::is_same<decltype(rec_sqrt(complex{1, 2})), complex>::value);

        // move, will steal.
        complex c1 = 1.1_r128 - 2.3_icr128;
        const auto p = c1.get_prec();
        auto c2 = rec_sqrt(std::move(c1));
        REQUIRE(abs(c2 - cmp1) < pow(2_r128, -126));
        REQUIRE(c2.get_prec() == p);
        // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
        REQUIRE(!c1.is_valid());
    }

    // Test the special cases.
    {
        complex c{0, complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().inf_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{0, complex_prec_t(128)}).inf_p());
    }
    {
        complex c{"(inf, 0)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(inf, 0)", complex_prec_t(128)}).zero_p());
    }
    {
        complex c{"(inf, nan)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(inf, nan)", complex_prec_t(128)}).zero_p());
    }
    {
        complex c{"(0, inf)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(0, inf)", complex_prec_t(128)}).zero_p());
    }
    {
        complex c{"(nan, inf)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(nan, inf)", complex_prec_t(128)}).zero_p());
    }
    {
        complex c{"(inf, inf)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(inf, inf)", complex_prec_t(128)}).zero_p());
    }
}
<commit_msg>Forgot MPPP_WITH_ARB bracketing.<commit_after>// Copyright 2016-2020 Francesco Biscani (bluescarni@gmail.com)
//
// This file is part of the mp++ library.
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include <type_traits>
#include <utility>

#include <mp++/complex.hpp>
#include <mp++/config.hpp>
#include <mp++/real.hpp>

#include "catch.hpp"

// NOLINTNEXTLINE(google-build-using-namespace)
using namespace mppp;

TEST_CASE("sqrt")
{
    complex r0{0};
    r0.sqrt();
    REQUIRE(std::is_same<complex &, decltype(r0.sqrt())>::value);
    REQUIRE(r0.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(r0.zero_p());
    complex rop;
    REQUIRE(sqrt(rop, r0).zero_p());
    REQUIRE(std::is_same<complex &, decltype(sqrt(rop, r0))>::value);
    REQUIRE(rop.get_prec() == detail::real_deduce_precision(0));
    REQUIRE(sqrt(r0).zero_p());
    REQUIRE(std::is_same<complex, decltype(sqrt(r0))>::value);
    REQUIRE(sqrt(std::move(r0)).zero_p());
    // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
    REQUIRE(!r0.is_valid());
    // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
    r0 = complex{16, 17, complex_prec_t(128)};
    REQUIRE(abs(sqrt(r0)
                - (4.4353824558800734853070281844863776932288_r128 + 1.9164074540474820480048239757004444314933_icr128))
            < pow(2_r128, -120));
    REQUIRE(sqrt(r0).get_prec() == 128);
    rop = real{12, 40};
    sqrt(rop, r0);
    REQUIRE(
        abs(rop - (4.4353824558800734853070281844863776932288_r128 + 1.9164074540474820480048239757004444314933_icr128))
        < pow(2_r128, -120));
    REQUIRE(rop.get_prec() == 128);
    r0.sqrt();
    REQUIRE(
        abs(r0 - (4.4353824558800734853070281844863776932288_r128 + 1.9164074540474820480048239757004444314933_icr128))
        < pow(2_r128, -120));
    REQUIRE(r0.get_prec() == 128);
}

#if defined(MPPP_WITH_ARB)

TEST_CASE("rec_sqrt")
{
    const auto cmp1
        = 0.52984103253104949318719835021445625746079_r128 + 0.33391728095862217076724902471316862541707_icr128;
    {
        // Member function.
        auto c = 1.1_r128 - 2.3_icr128;
        c.rec_sqrt();
        REQUIRE(abs(c - cmp1) < pow(2_r128, -126));
        REQUIRE(c.get_prec() == 128);
    }
    {
        // rop overload.
        complex c1, c2 = 1.1_r128 - 2.3_icr128;
        const auto p = c2.get_prec();
        REQUIRE(&rec_sqrt(c1, c2) == &c1);
        REQUIRE(std::is_same<decltype(rec_sqrt(c1, c2)), complex &>::value);
        REQUIRE(abs(c1 - cmp1) < pow(2_r128, -126));
        REQUIRE(c1.get_prec() == p);

        // Move, but won't steal because rop
        // has higher precision.
        c1 = complex{0, complex_prec_t(c2.get_prec() + 1)};
        rec_sqrt(c1, std::move(c2));
        REQUIRE(abs(c1 - cmp1) < pow(2_r128, -126));
        REQUIRE(c1.get_prec() == p);
        // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
        REQUIRE(c2 == 1.1_r128 - 2.3_icr128);

        // Move, will steal.
        c1 = complex{};
        rec_sqrt(c1, std::move(c2));
        REQUIRE(abs(c1 - cmp1) < pow(2_r128, -126));
        REQUIRE(c1.get_prec() == p);
        // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
        REQUIRE(c2 == complex{});
    }
    {
        // return overload.
        REQUIRE(abs(rec_sqrt(1.1_r128 - 2.3_icr128) - cmp1) < pow(2_r128, -126));
        REQUIRE(std::is_same<decltype(rec_sqrt(complex{1, 2})), complex>::value);

        // move, will steal.
        complex c1 = 1.1_r128 - 2.3_icr128;
        const auto p = c1.get_prec();
        auto c2 = rec_sqrt(std::move(c1));
        REQUIRE(abs(c2 - cmp1) < pow(2_r128, -126));
        REQUIRE(c2.get_prec() == p);
        // NOLINTNEXTLINE(bugprone-use-after-move, clang-analyzer-cplusplus.Move, hicpp-invalid-access-moved)
        REQUIRE(!c1.is_valid());
    }

    // Test the special cases.
    {
        complex c{0, complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().inf_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{0, complex_prec_t(128)}).inf_p());
    }
    {
        complex c{"(inf, 0)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(inf, 0)", complex_prec_t(128)}).zero_p());
    }
    {
        complex c{"(inf, nan)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(inf, nan)", complex_prec_t(128)}).zero_p());
    }
    {
        complex c{"(0, inf)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(0, inf)", complex_prec_t(128)}).zero_p());
    }
    {
        complex c{"(nan, inf)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(nan, inf)", complex_prec_t(128)}).zero_p());
    }
    {
        complex c{"(inf, inf)", complex_prec_t(128)};
        REQUIRE(c.rec_sqrt().zero_p());
        REQUIRE(c.get_prec() == 128);
        REQUIRE(rec_sqrt(complex{"(inf, inf)", complex_prec_t(128)}).zero_p());
    }
}

#endif
<|endoftext|>


<commit_before>#include "gtest/gtest.h"

#include "ROOTUnitTestSupport.h"

#include "TString.h"

TEST(TString, Basics)
{
   TString *s = nullptr;
   ROOT_EXPECT_ERROR(s = new TString("Test", -5), "TString::TString", "Negative length!");
   EXPECT_STREQ("", s);
   TString p("Test", 1);
   EXPECT_STREQ("T", p);
   TString a = "test";
   a.Append("s", -5);
   EXPECT_STREQ("test", a);
   ROOT_EXPECT_ERROR(a.Append("s", -5), "TString::Append", "Negative length!");
}
<commit_msg>Update core/base/test/TStringTest.cxx<commit_after>#include "gtest/gtest.h"

#include "ROOTUnitTestSupport.h"

#include "TString.h"

TEST(TString, Basics)
{
   TString *s = nullptr;
   ROOT_EXPECT_ERROR(s = new TString("Test", -5), "TString::TString", "Negative length!");
   delete s;
   TString p("Test", 1);
   EXPECT_STREQ("T", p);
   TString a = "test";
   a.Append("s", -5);
   EXPECT_STREQ("test", a);
   ROOT_EXPECT_ERROR(a.Append("s", -5), "TString::Append", "Negative length!");
}
<|endoftext|>


<commit_before>#include <iostream>
#include <vector>
#include <cybozu/test.hpp>
#include "../src/low_func.hpp"

CYBOZU_TEST_AUTO(cpu)
{
	mcl::bint::initBint();
}

#define PUT(x) std::cout << #x "=" << (x) << std::endl;

using namespace mcl::bint;
typedef mcl::Unit Unit;

template<class RG>
void setRand(Unit *x, size_t n, RG& rg)
{
	for (size_t i = 0; i < n; i++) {
		x[i] = (Unit)rg.get64();
	}
}

struct Montgomery {
	mpz_class p_;
	mpz_class R_; // (1 << (pn_ * 64)) % p
	mpz_class RR_; // (R * R) % p
	Unit rp_; // rp * p = -1 mod M = 1 << 64
	size_t pn_;
	std::vector<Unit> v_;
	const Unit *rpp_;
	Montgomery() {}
	void put() const
	{
		PUT(p_);
		PUT(R_);
		PUT(RR_);
		PUT(rp_);
	}
	explicit Montgomery(const mpz_class& p)
	{
		p_ = p;
		rp_ = mcl::fp::getMontgomeryCoeff(mcl::gmp::getUnit(p, 0));
		pn_ = mcl::gmp::getUnitSize(p);
		R_ = 1;
		R_ = (R_ << (pn_ * 64)) % p_;
		RR_ = (R_ * R_) % p_;
		v_.resize(pn_ + 1);
		mcl::gmp::getArray(&v_[1], pn_, p);
		v_[0] = rp_;
		rpp_ = v_.data() + 1;
	}

	void toMont(mpz_class& x) const { mul(x, x, RR_); }
	void fromMont(mpz_class& x) const { mul(x, x, 1); }

	void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const
	{
		z = x * y;
		for (size_t i = 0; i < pn_; i++) {
			Unit q = mcl::gmp::getUnit(z, 0) * rp_;
			z += p_ * q;
			z >>= sizeof(Unit) * 8;
		}
		if (z >= p_) {
			z -= p_;
		}
	}
	void mod(mpz_class& z, const mpz_class& xy) const
	{
		z = xy;
		for (size_t i = 0; i < pn_; i++) {
			Unit q = mcl::gmp::getUnit(z, 0) * rp_;
			mpz_class t;
			mcl::gmp::set(t, q);
			z += p_ * t;
			z >>= sizeof(Unit) * 8;
		}
		if (z >= p_) {
			z -= p_;
		}
	}
};

template<size_t N>
void testEdge(const mpz_class& p)
{
	Montgomery mont(p);
	CYBOZU_TEST_EQUAL(mont.pn_, N);
	mpz_class tbl[] = { 0, 1, 2, 0x1234568, p-1, p-2, p-3 };
	std::vector<Unit> x1Buf(N);
	std::vector<Unit> x2Buf(N);
	std::vector<Unit> yBuf(N);
	std::vector<Unit> zBuf(N);
	const size_t n = CYBOZU_NUM_OF_ARRAY(tbl);
	for (size_t i = 0; i < n; i++) {
		mpz_class x1 = tbl[i];
		mont.toMont(x1);
		mcl::gmp::getArray(x1Buf.data(), N, x1);
		for (size_t j = i; j < n; j++) {
			mpz_class x2 = tbl[j];
			mont.toMont(x2);
			mcl::gmp::getArray(x2Buf.data(), N, x2);
			mcl::fp::mulMontT<N>(zBuf.data(), x1Buf.data(), x2Buf.data(), mont.rpp_);
			mpz_class z1, z2;
			mcl::gmp::setArray(z1, zBuf.data(), N);
//			mont.mod(z, x1 * x2);
			mont.mul(z2, x1, x2);
			CYBOZU_TEST_EQUAL(z1, z2);
			mont.fromMont(z1);
			CYBOZU_TEST_EQUAL(z1, (tbl[i] * tbl[j]) % p);
		}
	}
}

CYBOZU_TEST_AUTO(limit)
{
	std::cout << std::hex;
	const size_t N = 4;
	mpz_class p = (mpz_class(1) << (sizeof(Unit) * 8 * N)) - 1;
	testEdge<N>(p);
}

<commit_msg>add modRedT test<commit_after>#include <iostream>
#include <vector>
#include <cybozu/test.hpp>
#include "../src/low_func.hpp"

CYBOZU_TEST_AUTO(cpu)
{
	mcl::bint::initBint();
}

#define PUT(x) std::cout << #x "=" << (x) << std::endl;

using namespace mcl::bint;
typedef mcl::Unit Unit;

template<class RG>
void setRand(Unit *x, size_t n, RG& rg)
{
	for (size_t i = 0; i < n; i++) {
		x[i] = (Unit)rg.get64();
	}
}

struct Montgomery {
	mpz_class p_;
	mpz_class R_; // (1 << (pn_ * 64)) % p
	mpz_class RR_; // (R * R) % p
	Unit rp_; // rp * p = -1 mod M = 1 << 64
	size_t pn_;
	std::vector<Unit> v_;
	const Unit *rpp_;
	Montgomery() {}
	void put() const
	{
		PUT(p_);
		PUT(R_);
		PUT(RR_);
		PUT(rp_);
	}
	explicit Montgomery(const mpz_class& p)
	{
		p_ = p;
		rp_ = mcl::fp::getMontgomeryCoeff(mcl::gmp::getUnit(p, 0));
		pn_ = mcl::gmp::getUnitSize(p);
		R_ = 1;
		R_ = (R_ << (pn_ * 64)) % p_;
		RR_ = (R_ * R_) % p_;
		v_.resize(pn_ + 1);
		mcl::gmp::getArray(&v_[1], pn_, p);
		v_[0] = rp_;
		rpp_ = v_.data() + 1;
	}

	void toMont(mpz_class& x) const { mul(x, x, RR_); }
	void fromMont(mpz_class& x) const { mul(x, x, 1); }

	void mul(mpz_class& z, const mpz_class& x, const mpz_class& y) const
	{
		z = x * y;
		for (size_t i = 0; i < pn_; i++) {
			Unit q = mcl::gmp::getUnit(z, 0) * rp_;
			z += p_ * q;
			z >>= sizeof(Unit) * 8;
		}
		if (z >= p_) {
			z -= p_;
		}
	}
	void mod(mpz_class& z, const mpz_class& xy) const
	{
		z = xy;
		for (size_t i = 0; i < pn_; i++) {
			Unit q = mcl::gmp::getUnit(z, 0) * rp_;
			mpz_class t;
			mcl::gmp::set(t, q);
			z += p_ * t;
			z >>= sizeof(Unit) * 8;
		}
		if (z >= p_) {
			z -= p_;
		}
	}
};

template<size_t N>
void testEdge(const mpz_class& p)
{
	Montgomery mont(p);
	CYBOZU_TEST_EQUAL(mont.pn_, N);
	mpz_class tbl[] = { 0, 1, 2, 0x1234568, p-1, p-2, p-3 };
	Unit x1Buf[N], x2Buf[N], z1Buf[N], z2Buf[N], xyBuf[N * 2];
	const size_t n = CYBOZU_NUM_OF_ARRAY(tbl);
	for (size_t i = 0; i < n; i++) {
		mpz_class x1 = tbl[i];
		mont.toMont(x1);
		mcl::gmp::getArray(x1Buf, N, x1);
		for (size_t j = i; j < n; j++) {
			mpz_class x2 = tbl[j];
			mpz_class xy = tbl[i] * tbl[j] % p;
			mont.toMont(x2);
			mcl::gmp::getArray(x2Buf, N, x2);
			mcl::fp::mulMontT<N>(z1Buf, x1Buf, x2Buf, mont.rpp_);
			mpz_class z1, z2;
			mcl::gmp::setArray(z1, z1Buf, N);
			mont.mul(z2, x1, x2);
			CYBOZU_TEST_EQUAL(z1, z2);
			mont.fromMont(z1);
			CYBOZU_TEST_EQUAL(z1, xy);
			mont.toMont(xy);
			mcl::gmp::getArray(xyBuf, N * 2, xy);
			mcl::fp::modRedT<N>(z2Buf, xyBuf, mont.rpp_);
			CYBOZU_TEST_EQUAL_ARRAY(z1Buf, z2Buf, N);
		}
	}
}

CYBOZU_TEST_AUTO(limit)
{
	std::cout << std::hex;
	const size_t N = 4;
	mpz_class p = (mpz_class(1) << (sizeof(Unit) * 8 * N)) - 1;
	testEdge<N>(p);
}

<|endoftext|>


<commit_before>#include <SimpleAmqpClient/SimpleAmqpClient.h>

#include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/exception/all.hpp>
#include <iostream>
#include <stdlib.h>
#include <amqp.h>

#include "messages.h"

using namespace AmqpClient;
using namespace akkapatterns::daemon;

std::string process(BasicMessage::ptr_t request) {
  const amqp_bytes_t& bytes = request->getAmqpBody();
  if (bytes.len < sizeof(message_header_t)) throw MessageError() << errinfo_message("message too small");
  const message_header_t* header = static_cast<message_header_t*>(bytes.bytes);
  if (header->signature != message_signature) throw MessageError() << errinfo_message("bad signature");

  // we're good.
  size_t totalSize = sizeof(message_header_t) + header->size1 + header->size2;
  if (bytes.len != totalSize) throw MessageError() << errinfo_message("bad message size");

  // do the processing
  return "{\"success\":true}";
}

int main() {
  try {
    Channel::ptr_t channel = Channel::Create();

    //channel->DeclareQueue("faceverify");
    channel->BindQueue("akkapatterns", "amq.direct", "demo.key");

    std::string tag;
    tag = channel->BasicConsume("akkapatterns", "", true, true, false, 1);

    while (true) {
      // consume the message
      Envelope::ptr_t env = channel->BasicConsumeMessage(tag);
      BasicMessage::ptr_t request = env->Message();
      try {
        // process it
        std::string body = process(request);
        // then reply to this message
        BasicMessage::ptr_t response = BasicMessage::Create();
        response->CorrelationId(request->CorrelationId());
        response->Body(body);
        channel->BasicPublish("", request->ReplyTo(), response);
      } catch (MessageError &e) {
        const std::string* msg = boost::get_error_info<errinfo_message>(e);
        std::cerr << (*msg) << std::endl;
      }
    }
  } catch (std::runtime_error &e) {
    std::cout << "Error " << e.what() << std::endl;
  }

}
<commit_msg>tidy up<commit_after>#include <SimpleAmqpClient/SimpleAmqpClient.h>

#include <boost/lexical_cast.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/exception/all.hpp>
#include <iostream>
#include <stdlib.h>
#include <amqp.h>

#include "messages.h"

using namespace AmqpClient;
using namespace akkapatterns::daemon;

std::string process(BasicMessage::ptr_t request) {
  const amqp_bytes_t& bytes = request->getAmqpBody();
  if (bytes.len < sizeof(message_header_t)) throw MessageError() << errinfo_message("message too small");
  const message_header_t* header = static_cast<message_header_t*>(bytes.bytes);
  if (header->signature != message_signature) throw MessageError() << errinfo_message("bad signature");

  // we're good.
  size_t totalSize = sizeof(message_header_t) + header->size1 + header->size2;
  if (bytes.len != totalSize) throw MessageError() << errinfo_message("bad message size");

  // do the processing
  return "{\"success\":true}";
}

int main() {
  try {
    Channel::ptr_t channel = Channel::Create();

    channel->BindQueue("akkapatterns", "amq.direct", "demo.key");

    std::string tag;
    tag = channel->BasicConsume("akkapatterns", "", true, true, false, 1);

    while (true) {
      // consume the message
      Envelope::ptr_t env = channel->BasicConsumeMessage(tag);
      BasicMessage::ptr_t request = env->Message();
      try {
        // process it
        std::string body = process(request);
        // then reply to this message
        BasicMessage::ptr_t response = BasicMessage::Create();
        response->CorrelationId(request->CorrelationId());
        response->Body(body);
        channel->BasicPublish("", request->ReplyTo(), response);
      } catch (MessageError &e) {
        const std::string* msg = boost::get_error_info<errinfo_message>(e);
        std::cerr << (*msg) << std::endl;
      }
    }
  } catch (std::runtime_error &e) {
    std::cout << "Error " << e.what() << std::endl;
  }

}
<|endoftext|>


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

#include <memory>
#include <thread>

#include <folly/Function.h>
#include <folly/SharedMutex.h>
#include <folly/Singleton.h>
#include <folly/detail/AsyncTrace.h>
#include <folly/executors/CPUThreadPoolExecutor.h>
#include <folly/executors/GlobalExecutor.h>
#include <folly/executors/IOExecutor.h>
#include <folly/executors/IOThreadPoolExecutor.h>
#include <folly/system/HardwareConcurrency.h>

using namespace folly;

namespace {

class GlobalTag {};

// aka InlineExecutor
class DefaultCPUExecutor : public Executor {
 public:
  FOLLY_NOINLINE void add(Func f) override {
    f();
  }
};

Singleton<std::shared_ptr<DefaultCPUExecutor>> gDefaultGlobalCPUExecutor([] {
  return new std::shared_ptr<DefaultCPUExecutor>(new DefaultCPUExecutor{});
});

Singleton<std::shared_ptr<CPUThreadPoolExecutor>, GlobalTag>
    gImmutableGlobalCPUExecutor([] {
      return new std::shared_ptr<CPUThreadPoolExecutor>(
          new CPUThreadPoolExecutor(
              folly::hardware_concurrency(),
              std::make_shared<NamedThreadFactory>("GlobalCPUThreadPool")));
    });

Singleton<std::shared_ptr<IOThreadPoolExecutor>, GlobalTag>
    gImmutableGlobalIOExecutor([] {
      return new std::shared_ptr<IOThreadPoolExecutor>(new IOThreadPoolExecutor(
          folly::hardware_concurrency(),
          std::make_shared<NamedThreadFactory>("GlobalIOThreadPool")));
    });

template <class ExecutorBase>
std::shared_ptr<ExecutorBase> getImmutable();

template <>
std::shared_ptr<Executor> getImmutable() {
  if (auto executorPtrPtr = gImmutableGlobalCPUExecutor.try_get()) {
    return *executorPtrPtr;
  }
  return nullptr;
}

template <>
std::shared_ptr<IOExecutor> getImmutable() {
  if (auto executorPtrPtr = gImmutableGlobalIOExecutor.try_get()) {
    return *executorPtrPtr;
  }
  return nullptr;
}

template <class ExecutorBase>
class GlobalExecutor {
 public:
  explicit GlobalExecutor(
      Function<std::shared_ptr<ExecutorBase>()> constructDefault)
      : getDefault_(std::move(constructDefault)) {}

  std::shared_ptr<ExecutorBase> get() {
    SharedMutex::ReadHolder guard(mutex_);
    if (auto executor = executor_.lock()) {
      return executor; // Fast path.
    }

    return getDefault_();
  }

  void set(std::weak_ptr<ExecutorBase> executor) {
    SharedMutex::WriteHolder guard(mutex_);
    executor_.swap(executor);
  }

  // Replace the constructDefault function to use the immutable singleton
  // rather than the default singleton
  void setFromImmutable() {
    SharedMutex::WriteHolder guard(mutex_);

    getDefault_ = [] { return getImmutable<ExecutorBase>(); };
    executor_ = std::weak_ptr<ExecutorBase>{};
  }

 private:
  SharedMutex mutex_;
  std::weak_ptr<ExecutorBase> executor_;
  Function<std::shared_ptr<ExecutorBase>()> getDefault_;
};

LeakySingleton<GlobalExecutor<Executor>> gGlobalCPUExecutor([] {
  return new GlobalExecutor<Executor>(
      // Default global CPU executor is an InlineExecutor.
      [] {
        if (auto executorPtrPtr = gDefaultGlobalCPUExecutor.try_get()) {
          return *executorPtrPtr;
        }
        return std::shared_ptr<DefaultCPUExecutor>{};
      });
});

LeakySingleton<GlobalExecutor<IOExecutor>> gGlobalIOExecutor([] {
  return new GlobalExecutor<IOExecutor>(
      // Default global IO executor is an IOThreadPoolExecutor.
      [] { return getImmutable<IOExecutor>(); });
});

} // namespace

namespace folly {

Executor::KeepAlive<> getGlobalCPUExecutor() {
  auto executorPtr = getImmutable<Executor>();
  if (!executorPtr) {
    throw std::runtime_error("Requested global CPU executor during shutdown.");
  }
  async_tracing::logGetImmutableCPUExecutor(executorPtr.get());
  return folly::getKeepAliveToken(executorPtr.get());
}

Executor::KeepAlive<> getGlobalIOExecutor() {
  auto executorPtr = getImmutable<IOExecutor>();
  if (!executorPtr) {
    throw std::runtime_error("Requested global IO executor during shutdown.");
  }
  async_tracing::logGetImmutableIOExecutor(executorPtr.get());
  return folly::getKeepAliveToken(executorPtr.get());
}

std::shared_ptr<Executor> getCPUExecutor() {
  auto& singleton = gGlobalCPUExecutor.get();
  auto executor = singleton.get();
  async_tracing::logGetGlobalCPUExecutor(executor.get());
  return executor;
}

void setCPUExecutorToGlobalCPUExecutor() {
  async_tracing::logSetGlobalCPUExecutorToImmutable();
  gGlobalCPUExecutor.get().setFromImmutable();
}

void setCPUExecutor(std::weak_ptr<Executor> executor) {
  async_tracing::logSetGlobalCPUExecutor(executor.lock().get());
  gGlobalCPUExecutor.get().set(std::move(executor));
}

std::shared_ptr<IOExecutor> getIOExecutor() {
  auto& singleton = gGlobalIOExecutor.get();
  auto executor = singleton.get();
  async_tracing::logGetGlobalIOExecutor(executor.get());
  return executor;
}

void setIOExecutor(std::weak_ptr<IOExecutor> executor) {
  async_tracing::logSetGlobalIOExecutor(executor.lock().get());
  gGlobalIOExecutor.get().set(std::move(executor));
}

EventBase* getEventBase() {
  auto executor = getIOExecutor();
  if (FOLLY_LIKELY(!!executor)) {
    return executor->getEventBase();
  }

  return nullptr;
}

} // namespace folly
<commit_msg>Make sure global CPU executor is never joined on an application thread<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <memory>
#include <thread>

#include <folly/Function.h>
#include <folly/SharedMutex.h>
#include <folly/Singleton.h>
#include <folly/detail/AsyncTrace.h>
#include <folly/executors/CPUThreadPoolExecutor.h>
#include <folly/executors/GlobalExecutor.h>
#include <folly/executors/IOExecutor.h>
#include <folly/executors/IOThreadPoolExecutor.h>
#include <folly/system/HardwareConcurrency.h>

using namespace folly;

namespace {

class GlobalTag {};

// aka InlineExecutor
class DefaultCPUExecutor : public Executor {
 public:
  FOLLY_NOINLINE void add(Func f) override {
    f();
  }
};

Singleton<std::shared_ptr<DefaultCPUExecutor>> gDefaultGlobalCPUExecutor([] {
  return new std::shared_ptr<DefaultCPUExecutor>(new DefaultCPUExecutor{});
});

Singleton<std::shared_ptr<Executor>, GlobalTag> gImmutableGlobalCPUExecutor([] {
  return new std::shared_ptr<Executor>(new CPUThreadPoolExecutor(
      folly::hardware_concurrency(),
      std::make_shared<NamedThreadFactory>("GlobalCPUThreadPool")));
});

Singleton<std::shared_ptr<IOExecutor>, GlobalTag> gImmutableGlobalIOExecutor(
    [] {
      return new std::shared_ptr<IOExecutor>(new IOThreadPoolExecutor(
          folly::hardware_concurrency(),
          std::make_shared<NamedThreadFactory>("GlobalIOThreadPool")));
    });

template <class ExecutorBase>
std::shared_ptr<std::shared_ptr<ExecutorBase>> getImmutablePtrPtr();

template <class ExecutorBase>
std::shared_ptr<ExecutorBase> getImmutable() {
  if (auto executorPtrPtr = getImmutablePtrPtr<ExecutorBase>()) {
    return *executorPtrPtr;
  }
  return nullptr;
}

template <>
std::shared_ptr<std::shared_ptr<Executor>> getImmutablePtrPtr() {
  return gImmutableGlobalCPUExecutor.try_get();
}

template <>
std::shared_ptr<std::shared_ptr<IOExecutor>> getImmutablePtrPtr() {
  return gImmutableGlobalIOExecutor.try_get();
}

template <class ExecutorBase>
class GlobalExecutor {
 public:
  explicit GlobalExecutor(
      Function<std::shared_ptr<ExecutorBase>()> constructDefault)
      : getDefault_(std::move(constructDefault)) {}

  std::shared_ptr<ExecutorBase> get() {
    SharedMutex::ReadHolder guard(mutex_);
    if (auto executor = executor_.lock()) {
      return executor; // Fast path.
    }

    return getDefault_();
  }

  void set(std::weak_ptr<ExecutorBase> executor) {
    SharedMutex::WriteHolder guard(mutex_);
    executor_.swap(executor);
  }

  // Replace the constructDefault function to use the immutable singleton
  // rather than the default singleton
  void setFromImmutable() {
    SharedMutex::WriteHolder guard(mutex_);

    getDefault_ = [] { return getImmutable<ExecutorBase>(); };
    executor_ = std::weak_ptr<ExecutorBase>{};
  }

 private:
  SharedMutex mutex_;
  std::weak_ptr<ExecutorBase> executor_;
  Function<std::shared_ptr<ExecutorBase>()> getDefault_;
};

LeakySingleton<GlobalExecutor<Executor>> gGlobalCPUExecutor([] {
  return new GlobalExecutor<Executor>(
      // Default global CPU executor is an InlineExecutor.
      [] {
        if (auto executorPtrPtr = gDefaultGlobalCPUExecutor.try_get()) {
          return *executorPtrPtr;
        }
        return std::shared_ptr<DefaultCPUExecutor>{};
      });
});

LeakySingleton<GlobalExecutor<IOExecutor>> gGlobalIOExecutor([] {
  return new GlobalExecutor<IOExecutor>(
      // Default global IO executor is an IOThreadPoolExecutor.
      [] { return getImmutable<IOExecutor>(); });
});

} // namespace

namespace folly {

Executor::KeepAlive<> getGlobalCPUExecutor() {
  auto executorPtrPtr = getImmutablePtrPtr<Executor>();
  if (!executorPtrPtr) {
    throw std::runtime_error("Requested global CPU executor during shutdown.");
  }
  async_tracing::logGetImmutableCPUExecutor(executorPtrPtr->get());
  return folly::getKeepAliveToken(executorPtrPtr->get());
}

Executor::KeepAlive<> getGlobalIOExecutor() {
  auto executorPtrPtr = getImmutablePtrPtr<IOExecutor>();
  if (!executorPtrPtr) {
    throw std::runtime_error("Requested global IO executor during shutdown.");
  }
  async_tracing::logGetImmutableIOExecutor(executorPtrPtr->get());
  return folly::getKeepAliveToken(executorPtrPtr->get());
}

std::shared_ptr<Executor> getCPUExecutor() {
  auto& singleton = gGlobalCPUExecutor.get();
  auto executor = singleton.get();
  async_tracing::logGetGlobalCPUExecutor(executor.get());
  return executor;
}

void setCPUExecutorToGlobalCPUExecutor() {
  async_tracing::logSetGlobalCPUExecutorToImmutable();
  gGlobalCPUExecutor.get().setFromImmutable();
}

void setCPUExecutor(std::weak_ptr<Executor> executor) {
  async_tracing::logSetGlobalCPUExecutor(executor.lock().get());
  gGlobalCPUExecutor.get().set(std::move(executor));
}

std::shared_ptr<IOExecutor> getIOExecutor() {
  auto& singleton = gGlobalIOExecutor.get();
  auto executor = singleton.get();
  async_tracing::logGetGlobalIOExecutor(executor.get());
  return executor;
}

void setIOExecutor(std::weak_ptr<IOExecutor> executor) {
  async_tracing::logSetGlobalIOExecutor(executor.lock().get());
  gGlobalIOExecutor.get().set(std::move(executor));
}

EventBase* getEventBase() {
  auto executor = getIOExecutor();
  if (FOLLY_LIKELY(!!executor)) {
    return executor->getEventBase();
  }

  return nullptr;
}

} // namespace folly
<|endoftext|>


<commit_before><commit_msg>net: update DNSSEC chain embedded extension OID.<commit_after><|endoftext|>