<commit_before>/*
 * NotebookQueue.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionRmdNotebook.hpp"
#include "NotebookQueue.hpp"
#include "NotebookQueueUnit.hpp"
#include "NotebookExec.hpp"
#include "NotebookDocQueue.hpp"
#include "NotebookCache.hpp"
#include "NotebookAlternateEngines.hpp"

#include "../../SessionClientEventService.hpp"

#include <boost/foreach.hpp>

#include <r/RInterface.hpp>

#include <core/Exec.hpp>
#include <core/Thread.hpp>

#include <session/SessionModuleContext.hpp>
#include <session/SessionClientEvent.hpp>
#include <session/http/SessionRequest.hpp>

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace rmarkdown {
namespace notebook {
namespace {

enum ChunkExecState
{
   ChunkExecStarted   = 0,
   ChunkExecFinished  = 1,
   ChunkExecCancelled = 2
};

// represents the global queue of work
class NotebookQueue
{
public:
   NotebookQueue()
   {
      // launch a thread to process console input
      thread::safeLaunchThread(boost::bind(
               &NotebookQueue::consoleThreadMain, this), &console_);

      // register handler for chunk exec complete
      handlers_.push_back(events().onChunkExecCompleted.connect(
               boost::bind(&NotebookQueue::onChunkExecCompleted, this, _1, _2, _3)));
   }

   ~NotebookQueue()
   {
      // clean up thread
      console_.detach();

      // unregister handlers
      BOOST_FOREACH(boost::signals::connection connection, handlers_)
      {
         connection.disconnect();
      }
   }

   bool complete()
   {
      return queue_.empty();
   }

   Error process()
   {
      // if list is empty, we're done
      if (queue_.empty())
         return Success();

      // defer if R is currently executing code (we'll initiate processing when
      // the console continues)
      if (r::getGlobalContext()->nextcontext != NULL)
         return Success();

      // if we have a currently executing unit, execute it; otherwise, pop the
      // next unit off the stack
      if (execUnit_)
      {
         if (execContext_ && execContext_->hasErrors())
         {
            // when an error occurs, see what the chunk options say; if they
            // have error = TRUE we can keep going, but in all other
            // circumstances we should stop right away
            const json::Object& options = execContext_->options();
            bool error = false;
            json::readObject(options, "error", &error);
            if (!error)
            {
               clear();
               return Success();
            }
         }
         if (execUnit_->complete())
         {
            // unit has finished executing; remove it from the queue
            popUnit(execUnit_);

            // notify client
            enqueueExecStateChanged(ChunkExecFinished, execContext_->options());

            // clean up current exec unit
            execContext_->disconnect();
            execContext_.reset();
            execUnit_.reset();
         }
         else
            return executeCurrentUnit();
      }

      return executeNextUnit();
   }

   Error update(boost::shared_ptr<NotebookQueueUnit> pUnit, QueueOperation op,
      const std::string& before)
   {
      // find the document queue corresponding to this unit
      BOOST_FOREACH(const boost::shared_ptr<NotebookDocQueue> queue, queue_)
      {
         if (queue->docId() == pUnit->docId())
         {
            queue->update(pUnit, op, before);
            break;
         }
      }

      return Success();
   }

   void add(boost::shared_ptr<NotebookDocQueue> pQueue)
   {
      queue_.push_back(pQueue);
   }

   void clear()
   {
      // clean up any active execution context
      if (execContext_)
         execContext_->disconnect();

      // remove all document queues
      queue_.clear();
   }

   json::Value getDocQueue(const std::string& docId)
   {
      BOOST_FOREACH(boost::shared_ptr<NotebookDocQueue> pQueue, queue_)
      {
         if (pQueue->docId() == docId)
            return pQueue->toJson();
      }
      return json::Value();
   }

   void onConsolePrompt(const std::string& prompt)
   {
      process();
   }

private:

   void onChunkExecCompleted(const std::string& docId,
         const std::string& chunkId, const std::string& nbCtxId)
   {
      if (!execUnit_)
         return;

      // if this is the currently executing chunk but it doesn't have an R
      // execution context, it must be executing with an alternate engine;
      // this event signals that the alternate engine is finished, so move to
      // the next document in the queue
      if (execUnit_->docId() == docId && execUnit_->chunkId() == chunkId &&
          !execContext_)
      {
         // remove from the queue
         popUnit(execUnit_);

         // signal client
         enqueueExecStateChanged(ChunkExecFinished, json::Object());

         // execute the next chunk, if any
         execUnit_.reset();
         process();
      }
   }

   // execute the next line or expression in the current execution unit
   Error executeCurrentUnit()
   {
      // ensure we have a unit to execute
      if (!execUnit_)
         return Success();

      json::Array arr;
      ExecRange range(0, 0);
      arr.push_back(execUnit_->popExecRange(&range));
      arr.push_back(execUnit_->chunkId());

      // formulate request body
      json::Object rpc;
      rpc["method"] = "console_input";
      rpc["params"] = arr;
      rpc["clientId"] = clientEventService().clientId();

      // serialize RPC body and send it to helper thread for submission
      std::ostringstream oss;
      json::write(rpc, oss);
      input_.enque(oss.str());

      // let client know the range has been sent to R
      json::Object exec;
      exec["doc_id"]     = execUnit_->docId();
      exec["chunk_id"]   = execUnit_->chunkId();
      exec["exec_range"] = range.toJson();
      module_context::enqueClientEvent(
            ClientEvent(client_events::kNotebookRangeExecuted, exec));

      return Success();
   }

   Error executeNextUnit()
   {
      // no work to do if we have no documents
      if (queue_.empty())
         return Success();

      // get the next execution unit from the current queue
      boost::shared_ptr<NotebookDocQueue> docQueue = *queue_.begin();
      if (docQueue->complete())
         return Success();

      boost::shared_ptr<NotebookQueueUnit> unit = docQueue->firstUnit();

      // establish execution context for the unit
      json::Object options;
      Error error = unit->parseOptions(&options);
      if (error)
         return error;

      // in batch mode, make sure unit should be evaluated -- note that
      // eval=FALSE units generally do not get sent up in the first place, so
      // if we're here it's because the unit has eval=<expr>
      if (unit->execMode() == ExecModeBatch)
      {
         bool eval = true;
         json::readObject(options, "eval", &eval);
         if (!eval)
            return skipUnit();
      }

      // compute context
      std::string ctx = docQueue->commitMode() == ModeCommitted ?
         kSavedCtx : notebookCtxId();

      // compute engine
      std::string engine = "r";
      json::readObject(options, "engine", &engine);
      if (engine == "r")
      {
         execContext_ = boost::make_shared<ChunkExecContext>(
            unit->docId(), unit->chunkId(), ctx, unit->execScope(), options,
            docQueue->pixelWidth(), docQueue->charWidth());
         execContext_->connect();
      }
      else
      {
         // execute with alternate engine
         std::string innerCode;
         error = unit->innerCode(&innerCode);
         if (error)
         {
            LOG_ERROR(error);
         }
         else
         {
            error = executeAlternateEngineChunk(
               unit->docId(), unit->chunkId(), ctx, engine, innerCode, options);
            if (error)
               LOG_ERROR(error);
         }
      }

      // if there was an error, skip the chunk
      if (error)
         return skipUnit();

      // notify client
      execUnit_ = unit;
      enqueueExecStateChanged(ChunkExecStarted, options);

      if (engine == "r")
         executeCurrentUnit();

      return Success();
   }

   // main function for thread which receives console input
   void consoleThreadMain()
   {
      std::string input;
      while (input_.deque(&input, boost::posix_time::not_a_date_time))
      {
         // loop back console input request to session -- this allows us to treat
         // notebook console input exactly as user console input
         core::http::Response response;
         Error error = session::http::sendSessionRequest(
               "/rpc/console_input", input, &response);
         if (error)
            LOG_ERROR(error);
      }
   }

   void enqueueExecStateChanged(ChunkExecState state,
         const json::Object& options)
   {
      json::Object event;
      event["doc_id"]     = execUnit_->docId();
      event["chunk_id"]   = execUnit_->chunkId();
      event["exec_state"] = state;
      event["options"]    = options;
      module_context::enqueClientEvent(ClientEvent(
               client_events::kChunkExecStateChanged, event));
   }

   Error skipUnit()
   {
      if (queue_.empty())
         return Success();

      boost::shared_ptr<NotebookDocQueue> docQueue = *queue_.begin();
      if (docQueue->complete())
         return Success();

      boost::shared_ptr<NotebookQueueUnit> unit = docQueue->firstUnit();
      popUnit(unit);

      execUnit_ = unit;
      enqueueExecStateChanged(ChunkExecCancelled, json::Object());

      return executeNextUnit();
   }

   void popUnit(boost::shared_ptr<NotebookQueueUnit> pUnit)
   {
      if (queue_.empty())
         return;

      // remove this unit from the queue
      boost::shared_ptr<NotebookDocQueue> docQueue = *queue_.begin();
      docQueue->update(pUnit, QueueDelete, "");

      // advance if queue is complete
      if (docQueue->complete())
         queue_.pop_front();
   }

   // the documents with active queues
   std::list<boost::shared_ptr<NotebookDocQueue> > queue_;

   // the execution context for the currently executing chunk
   boost::shared_ptr<NotebookQueueUnit> execUnit_;
   boost::shared_ptr<ChunkExecContext> execContext_;

   // registered signal handlers
   std::vector<boost::signals::connection> handlers_;

   // the thread which submits console input, and the queue which feeds it
   boost::thread console_;
   core::thread::ThreadsafeQueue<std::string> input_;
};

static boost::shared_ptr<NotebookQueue> s_queue;

Error updateExecQueue(const json::JsonRpcRequest& request,
                      json::JsonRpcResponse* pResponse)
{
   json::Object unitJson;
   int op = 0;
   std::string before;
   Error error = json::readParams(request.params, &unitJson, &op, &before);
   if (error)
      return error;

   boost::shared_ptr<NotebookQueueUnit> pUnit =
      boost::make_shared<NotebookQueueUnit>();
   error = NotebookQueueUnit::fromJson(unitJson, &pUnit);
   if (error)
      return error;
   if (!s_queue)
      return Success();

   return s_queue->update(pUnit, static_cast<QueueOperation>(op), before);
}

Error executeNotebookChunks(const json::JsonRpcRequest& request,
                            json::JsonRpcResponse* pResponse)
{
   json::Object docObj;
   Error error = json::readParams(request.params, &docObj);

   boost::shared_ptr<NotebookDocQueue> pQueue =
      boost::make_shared<NotebookDocQueue>();
   error = NotebookDocQueue::fromJson(docObj, &pQueue);
   if (error)
      return error;

   // create queue if it doesn't exist
   if (!s_queue)
      s_queue = boost::make_shared<NotebookQueue>();

   // add the queue and process immediately
   s_queue->add(pQueue);
   s_queue->process();

   return Success();
}

void onConsolePrompt(const std::string& prompt)
{
   if (s_queue)
   {
      s_queue->onConsolePrompt(prompt);
   }

   // clean up queue if it's finished executing
   if (s_queue && s_queue->complete())
   {
      s_queue.reset();
   }
}

void onUserInterrupt()
{
   if (s_queue)
   {
      s_queue->clear();
      s_queue.reset();
   }
}

} // anonymous namespace

json::Value getDocQueue(const std::string& docId)
{
   if (!s_queue)
      return json::Value();

   return s_queue->getDocQueue(docId);
}

Error initQueue()
{
   using boost::bind;
   using namespace module_context;

   module_context::events().onConsolePrompt.connect(onConsolePrompt);
   module_context::events().onUserInterrupt.connect(onUserInterrupt);

   ExecBlock initBlock;
   initBlock.addFunctions()
      (bind(registerRpcMethod, "update_notebook_exec_queue", updateExecQueue))
      (bind(registerRpcMethod, "execute_notebook_chunks", executeNotebookChunks));

   return initBlock.execute();
}

} // namespace notebook
} // namespace rmarkdown
} // namespace modules
} // namespace session
} // namespace rstudio
<commit_msg>clean up console input processing thread safely<commit_after>/*
 * NotebookQueue.cpp
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionRmdNotebook.hpp"
#include "NotebookQueue.hpp"
#include "NotebookQueueUnit.hpp"
#include "NotebookExec.hpp"
#include "NotebookDocQueue.hpp"
#include "NotebookCache.hpp"
#include "NotebookAlternateEngines.hpp"

#include "../../SessionClientEventService.hpp"

#include <boost/foreach.hpp>

#include <r/RInterface.hpp>

#include <core/Exec.hpp>
#include <core/Thread.hpp>

#include <session/SessionModuleContext.hpp>
#include <session/SessionClientEvent.hpp>
#include <session/http/SessionRequest.hpp>

#define kThreadQuitCommand "thread_quit"

using namespace rstudio::core;

namespace rstudio {
namespace session {
namespace modules {
namespace rmarkdown {
namespace notebook {
namespace {

enum ChunkExecState
{
   ChunkExecStarted   = 0,
   ChunkExecFinished  = 1,
   ChunkExecCancelled = 2
};

// represents the global queue of work
class NotebookQueue
{
public:
   NotebookQueue()
   {
      // launch a thread to process console input
      pInput_ =
         boost::make_shared<core::thread::ThreadsafeQueue<std::string> >();
      thread::safeLaunchThread(boost::bind(
               &NotebookQueue::consoleThreadMain, this), &console_);

      // register handler for chunk exec complete
      handlers_.push_back(events().onChunkExecCompleted.connect(
               boost::bind(&NotebookQueue::onChunkExecCompleted, this, _1, _2, _3)));
   }

   ~NotebookQueue()
   {
      // let thread clean up asynchronously
      pInput_->enque(kThreadQuitCommand);

      // unregister handlers
      BOOST_FOREACH(boost::signals::connection connection, handlers_)
      {
         connection.disconnect();
      }
   }

   bool complete()
   {
      return queue_.empty();
   }

   Error process()
   {
      // if list is empty, we're done
      if (queue_.empty())
         return Success();

      // defer if R is currently executing code (we'll initiate processing when
      // the console continues)
      if (r::getGlobalContext()->nextcontext != NULL)
         return Success();

      // if we have a currently executing unit, execute it; otherwise, pop the
      // next unit off the stack
      if (execUnit_)
      {
         if (execContext_ && execContext_->hasErrors())
         {
            // when an error occurs, see what the chunk options say; if they
            // have error = TRUE we can keep going, but in all other
            // circumstances we should stop right away
            const json::Object& options = execContext_->options();
            bool error = false;
            json::readObject(options, "error", &error);
            if (!error)
            {
               clear();
               return Success();
            }
         }
         if (execUnit_->complete())
         {
            // unit has finished executing; remove it from the queue
            popUnit(execUnit_);

            // notify client
            enqueueExecStateChanged(ChunkExecFinished, execContext_->options());

            // clean up current exec unit
            execContext_->disconnect();
            execContext_.reset();
            execUnit_.reset();
         }
         else
            return executeCurrentUnit();
      }

      return executeNextUnit();
   }

   Error update(boost::shared_ptr<NotebookQueueUnit> pUnit, QueueOperation op,
      const std::string& before)
   {
      // find the document queue corresponding to this unit
      BOOST_FOREACH(const boost::shared_ptr<NotebookDocQueue> queue, queue_)
      {
         if (queue->docId() == pUnit->docId())
         {
            queue->update(pUnit, op, before);
            break;
         }
      }

      return Success();
   }

   void add(boost::shared_ptr<NotebookDocQueue> pQueue)
   {
      queue_.push_back(pQueue);
   }

   void clear()
   {
      // clean up any active execution context
      if (execContext_)
         execContext_->disconnect();

      // remove all document queues
      queue_.clear();
   }

   json::Value getDocQueue(const std::string& docId)
   {
      BOOST_FOREACH(boost::shared_ptr<NotebookDocQueue> pQueue, queue_)
      {
         if (pQueue->docId() == docId)
            return pQueue->toJson();
      }
      return json::Value();
   }

   void onConsolePrompt(const std::string& prompt)
   {
      process();
   }

private:

   void onChunkExecCompleted(const std::string& docId,
         const std::string& chunkId, const std::string& nbCtxId)
   {
      if (!execUnit_)
         return;

      // if this is the currently executing chunk but it doesn't have an R
      // execution context, it must be executing with an alternate engine;
      // this event signals that the alternate engine is finished, so move to
      // the next document in the queue
      if (execUnit_->docId() == docId && execUnit_->chunkId() == chunkId &&
          !execContext_)
      {
         // remove from the queue
         popUnit(execUnit_);

         // signal client
         enqueueExecStateChanged(ChunkExecFinished, json::Object());

         // execute the next chunk, if any
         execUnit_.reset();
         process();
      }
   }

   // execute the next line or expression in the current execution unit
   Error executeCurrentUnit()
   {
      // ensure we have a unit to execute
      if (!execUnit_)
         return Success();

      json::Array arr;
      ExecRange range(0, 0);
      arr.push_back(execUnit_->popExecRange(&range));
      arr.push_back(execUnit_->chunkId());

      // formulate request body
      json::Object rpc;
      rpc["method"] = "console_input";
      rpc["params"] = arr;
      rpc["clientId"] = clientEventService().clientId();

      // serialize RPC body and send it to helper thread for submission
      std::ostringstream oss;
      json::write(rpc, oss);
      pInput_->enque(oss.str());

      // let client know the range has been sent to R
      json::Object exec;
      exec["doc_id"]     = execUnit_->docId();
      exec["chunk_id"]   = execUnit_->chunkId();
      exec["exec_range"] = range.toJson();
      module_context::enqueClientEvent(
            ClientEvent(client_events::kNotebookRangeExecuted, exec));

      return Success();
   }

   Error executeNextUnit()
   {
      // no work to do if we have no documents
      if (queue_.empty())
         return Success();

      // get the next execution unit from the current queue
      boost::shared_ptr<NotebookDocQueue> docQueue = *queue_.begin();
      if (docQueue->complete())
         return Success();

      boost::shared_ptr<NotebookQueueUnit> unit = docQueue->firstUnit();

      // establish execution context for the unit
      json::Object options;
      Error error = unit->parseOptions(&options);
      if (error)
         return error;

      // in batch mode, make sure unit should be evaluated -- note that
      // eval=FALSE units generally do not get sent up in the first place, so
      // if we're here it's because the unit has eval=<expr>
      if (unit->execMode() == ExecModeBatch)
      {
         bool eval = true;
         json::readObject(options, "eval", &eval);
         if (!eval)
            return skipUnit();
      }

      // compute context
      std::string ctx = docQueue->commitMode() == ModeCommitted ?
         kSavedCtx : notebookCtxId();

      // compute engine
      std::string engine = "r";
      json::readObject(options, "engine", &engine);
      if (engine == "r")
      {
         execContext_ = boost::make_shared<ChunkExecContext>(
            unit->docId(), unit->chunkId(), ctx, unit->execScope(), options,
            docQueue->pixelWidth(), docQueue->charWidth());
         execContext_->connect();
      }
      else
      {
         // execute with alternate engine
         std::string innerCode;
         error = unit->innerCode(&innerCode);
         if (error)
         {
            LOG_ERROR(error);
         }
         else
         {
            error = executeAlternateEngineChunk(
               unit->docId(), unit->chunkId(), ctx, engine, innerCode, options);
            if (error)
               LOG_ERROR(error);
         }
      }

      // if there was an error, skip the chunk
      if (error)
         return skipUnit();

      // notify client
      execUnit_ = unit;
      enqueueExecStateChanged(ChunkExecStarted, options);

      if (engine == "r")
         executeCurrentUnit();

      return Success();
   }

   // main function for thread which receives console input
   void consoleThreadMain()
   {
      // create our own reference to the threadsafe queue (this prevents it
      // from getting cleaned up when the parent detaches)
      boost::shared_ptr<core::thread::ThreadsafeQueue<std::string> > pInput =
         pInput_;

      std::string input;
      while (pInput->deque(&input, boost::posix_time::not_a_date_time))
      {
         // if we were asked to quit, stop processing now
         if (input == kThreadQuitCommand)
            return;

         // loop back console input request to session -- this allows us to treat
         // notebook console input exactly as user console input
         core::http::Response response;
         Error error = session::http::sendSessionRequest(
               "/rpc/console_input", input, &response);
         if (error)
            LOG_ERROR(error);
      }
   }

   void enqueueExecStateChanged(ChunkExecState state,
         const json::Object& options)
   {
      json::Object event;
      event["doc_id"]     = execUnit_->docId();
      event["chunk_id"]   = execUnit_->chunkId();
      event["exec_state"] = state;
      event["options"]    = options;
      module_context::enqueClientEvent(ClientEvent(
               client_events::kChunkExecStateChanged, event));
   }

   Error skipUnit()
   {
      if (queue_.empty())
         return Success();

      boost::shared_ptr<NotebookDocQueue> docQueue = *queue_.begin();
      if (docQueue->complete())
         return Success();

      boost::shared_ptr<NotebookQueueUnit> unit = docQueue->firstUnit();
      popUnit(unit);

      execUnit_ = unit;
      enqueueExecStateChanged(ChunkExecCancelled, json::Object());

      return executeNextUnit();
   }

   void popUnit(boost::shared_ptr<NotebookQueueUnit> pUnit)
   {
      if (queue_.empty())
         return;

      // remove this unit from the queue
      boost::shared_ptr<NotebookDocQueue> docQueue = *queue_.begin();
      docQueue->update(pUnit, QueueDelete, "");

      // advance if queue is complete
      if (docQueue->complete())
         queue_.pop_front();
   }

   // the documents with active queues
   std::list<boost::shared_ptr<NotebookDocQueue> > queue_;

   // the execution context for the currently executing chunk
   boost::shared_ptr<NotebookQueueUnit> execUnit_;
   boost::shared_ptr<ChunkExecContext> execContext_;

   // registered signal handlers
   std::vector<boost::signals::connection> handlers_;

   // the thread which submits console input, and the queue which feeds it
   boost::thread console_;
   boost::shared_ptr<core::thread::ThreadsafeQueue<std::string> > pInput_;
};

static boost::shared_ptr<NotebookQueue> s_queue;

Error updateExecQueue(const json::JsonRpcRequest& request,
                      json::JsonRpcResponse* pResponse)
{
   json::Object unitJson;
   int op = 0;
   std::string before;
   Error error = json::readParams(request.params, &unitJson, &op, &before);
   if (error)
      return error;

   boost::shared_ptr<NotebookQueueUnit> pUnit =
      boost::make_shared<NotebookQueueUnit>();
   error = NotebookQueueUnit::fromJson(unitJson, &pUnit);
   if (error)
      return error;
   if (!s_queue)
      return Success();

   return s_queue->update(pUnit, static_cast<QueueOperation>(op), before);
}

Error executeNotebookChunks(const json::JsonRpcRequest& request,
                            json::JsonRpcResponse* pResponse)
{
   json::Object docObj;
   Error error = json::readParams(request.params, &docObj);

   boost::shared_ptr<NotebookDocQueue> pQueue =
      boost::make_shared<NotebookDocQueue>();
   error = NotebookDocQueue::fromJson(docObj, &pQueue);
   if (error)
      return error;

   // create queue if it doesn't exist
   if (!s_queue)
      s_queue = boost::make_shared<NotebookQueue>();

   // add the queue and process immediately
   s_queue->add(pQueue);
   s_queue->process();

   return Success();
}

void onConsolePrompt(const std::string& prompt)
{
   if (s_queue)
   {
      s_queue->onConsolePrompt(prompt);
   }

   // clean up queue if it's finished executing
   if (s_queue && s_queue->complete())
   {
      s_queue.reset();
   }
}

void onUserInterrupt()
{
   if (s_queue)
   {
      s_queue->clear();
      s_queue.reset();
   }
}

} // anonymous namespace

json::Value getDocQueue(const std::string& docId)
{
   if (!s_queue)
      return json::Value();

   return s_queue->getDocQueue(docId);
}

Error initQueue()
{
   using boost::bind;
   using namespace module_context;

   module_context::events().onConsolePrompt.connect(onConsolePrompt);
   module_context::events().onUserInterrupt.connect(onUserInterrupt);

   ExecBlock initBlock;
   initBlock.addFunctions()
      (bind(registerRpcMethod, "update_notebook_exec_queue", updateExecQueue))
      (bind(registerRpcMethod, "execute_notebook_chunks", executeNotebookChunks));

   return initBlock.execute();
}

} // namespace notebook
} // namespace rmarkdown
} // namespace modules
} // namespace session
} // namespace rstudio
<|endoftext|>


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

/* $Id:  */

//____________________________________________________________________
//
// T0 - T0.
//
// This class is a singleton that handles various parameters of
// the T0 detectors.
// Eventually, this class will use the Conditions DB to get the
// various parameters, which code can then request from here.
//
#include "AliLog.h"
#include "AliT0Parameters.h"
#include "AliT0CalibData.h"
#include "AliT0LookUpValue.h"
#include <AliCDBManager.h>
#include <AliCDBEntry.h>
#include <AliCDBStorage.h>
#include <TMath.h>
#include <TSystem.h>
#include <Riostream.h>
#include <TGeoManager.h>
#include <TGeoPhysicalNode.h>
#include <AliGeomManager.h>

AliT0CalibData* AliT0Parameters::fgCalibData = 0;
AliT0CalibData* AliT0Parameters::fgLookUp = 0;
AliT0CalibData* AliT0Parameters::fgSlewCorr =0;
//====================================================================
ClassImp(AliT0Parameters)
#if 0
  ; // This is here to keep Emacs for indenting the next line
#endif

//____________________________________________________________________
AliT0Parameters* AliT0Parameters::fgInstance = 0;
//____________________________________________________________________
AliT0Parameters* AliT0Parameters::Instance()
{
  // Get static instance
  if (!fgInstance) {
    fgInstance = new AliT0Parameters;
  }
  return fgInstance;
}

//____________________________________________________________________
AliT0Parameters::AliT0Parameters()
  :fIsInit(kFALSE),
   fPh2Mip(0),fmV2Mip(0),
   fChannelWidth(0),fmV2Channel(0),
   fQTmin(0),fQTmax(0),
   fAmpLEDRec(0),
   fPMTeff(),
   fWalk(0),
   fTimeDelayDA(0),
   fTimeDelayCFD(0),
   fTimeDelayTVD(0),
   fMeanT0(500),
   fLookUp(0),
   fNumberOfTRMs(2),
   fCalibentry(), fLookUpentry(),fSlewCorr()

{
  // Default constructor
  for (Int_t ipmt=0; ipmt<24; ipmt++)
    {
      SetPh2Mip();
      SetmV2Mip();
      SetChannelWidth();
      SetmV2channel();
      SetQTmin();
      SetQTmax();
      SetPMTeff(ipmt);
    }
  SetTimeDelayTVD();
  SetZposition();

}

//__________________________________________________________________
void
AliT0Parameters::Init()
{
  // Initialize the parameters manager.  We need to get stuff from the
  // CDB here.
   if (fIsInit) return;

   AliCDBManager *stor =AliCDBManager::Instance();
   //time equalizing
   fCalibentry  = stor->Get("T0/Calib/TimeDelay");
   if (fCalibentry)
     fgCalibData  = (AliT0CalibData*)fCalibentry->GetObject();
   else {
         AliFatal(" ALARM !!!! No time delays in CDB ");
     fIsInit = kFALSE;
     return;
   }
 //slewing correction
  fSlewCorr  = stor->Get("T0/Calib/Slewing_Walk");
  if (fSlewCorr){
    fgSlewCorr  = (AliT0CalibData*)fSlewCorr->GetObject();
  }
  else {
      AliFatal(" ALARM !!!! No slewing correction in CDB ");
    fIsInit = kFALSE;
    return;
  }
  //lookup table
  fLookUpentry  = stor->Get("T0/Calib/LookUp_Table");
  if (fLookUpentry){
    fgLookUp  = (AliT0CalibData*)fLookUpentry->GetObject();
  }
  else {
     AliFatal(" ALARM !!!! No Lookup table  in CDB ");
    fIsInit = kFALSE;
    return;
  }
  fIsInit = kTRUE;
}

//__________________________________________________________________

void AliT0Parameters::InitIfOnline()
{
// should be used in online
// for switching to this one should write
  // AliT0RawReader myrawreader(rawReader);
//	myrawreader.SetOnlineMode(kTRUE);

  if (fIsInit) return;
   //standart configuration (used for simulation)
   //Int_t trm=0; Int_t tdc=0; Int_t chain=0; Int_t channel=0;
  // configuration for test Jun07.

  fgLookUp = new AliT0CalibData("T0");

  fNumberOfTRMs = 1;
  Int_t trm=7; Int_t tdc=0; Int_t chain=0; Int_t channel=0;
  for (Int_t ik=0; ik<105; ik++)
        {
         AliT0LookUpKey * lookkey= new AliT0LookUpKey();
         AliT0LookUpValue * lookvalue= new AliT0LookUpValue();

          lookvalue->SetTRM(trm);
          lookvalue->SetTDC(tdc);
          lookvalue->SetChain(chain);
          lookvalue->SetChannel(channel);
          lookkey->SetKey(ik);
	  if (channel<6) channel +=2;
	  else {channel = 0; tdc++;}
	  if(ik==57) { tdc=0; channel=0; chain = 1;}

	  fgLookUp->GetMapLookup()->Add((TObject*)lookvalue,(TObject*)lookkey);
       }

  fIsInit=kTRUE;
}
//__________________________________________________________________

Float_t
AliT0Parameters::GetTimeDelayDA(Int_t ipmt)
{
  // return time delay for LED channel
  //
  if (!fCalibentry) {
    fTimeDelayDA = 500;
    return  fTimeDelayDA;
  }
  return fgCalibData ->GetTimeDelayDA(ipmt);
}
//__________________________________________________________________
Float_t
AliT0Parameters::GetTimeDelayCFD(Int_t ipmt)
{
  // return time delay for CFD channel
   //
  if (!fCalibentry)
    {
      fTimeDelayCFD = 1000+ipmt*100;
      return fTimeDelayCFD;
    }

  return fgCalibData->GetTimeDelayCFD(ipmt);
}

//__________________________________________________________________
Int_t
AliT0Parameters::GetMeanT0()
{
  // return mean of T0 distrubution with vertex=0
   //
  if (!fCalibentry)
    {
      return fMeanT0;
    }

  return fgCalibData->GetMeanT0();
}
//__________________________________________________________________

TGraph *AliT0Parameters::GetAmpLEDRec(Int_t ipmt) const
{
   if (!fSlewCorr) {
     AliError("No slewing correction is available!");
     return  (TGraph*)fAmpLEDRec.At(ipmt);
  }
  return fgSlewCorr -> GetAmpLEDRec(ipmt) ;
}

//__________________________________________________________________

TGraph *AliT0Parameters::GetWalk(Int_t ipmt) const
{
  if (!fSlewCorr) {
    AliError("No walk correction is available!");
    return  (TGraph*)fWalk.At(ipmt);
  }
  return fgSlewCorr -> GetWalk(ipmt) ;
}

//__________________________________________________________________

Float_t AliT0Parameters::GetWalkVal(Int_t ipmt, Float_t mv) const
{
  if (!fSlewCorr) {
    return ((TGraph*)fWalk.At(ipmt))->Eval(mv);
  }
  return fgSlewCorr -> GetWalkVal(ipmt, mv) ;
}

//__________________________________________________________________
void
AliT0Parameters::SetPMTeff(Int_t ipmt)
{
  Float_t lambda[50];
  Float_t eff[50 ] = {0,        0,       0.23619,  0.202909, 0.177913,
		    0.175667, 0.17856, 0.190769, 0.206667, 0.230286,
		    0.252276, 0.256267,0.26,     0.27125,  0.281818,
		    0.288118, 0.294057,0.296222, 0.301622, 0.290421,
		    0.276615, 0.2666,  0.248,    0.23619,  0.227814,
		    0.219818, 0.206667,0.194087, 0.184681, 0.167917,
		    0.154367, 0.1364,  0.109412, 0.0834615,0.0725283,
		    0.0642963,0.05861, 0.0465,   0.0413333,0.032069,
		    0.0252203,0.02066, 0.016262, 0.012,    0.00590476,
		    0.003875, 0.00190, 0,        0,        0          } ;
  for (Int_t i=0; i<50; i++) lambda[i]=200+10*i;

  TGraph* gr = new TGraph(50,lambda,eff);
  fPMTeff.AddAtAndExpand(gr,ipmt);
}
//________________________________________________________________

Int_t
AliT0Parameters::GetChannel(Int_t trm,  Int_t tdc, Int_t chain, Int_t channel)
{

  if (fgLookUp) {
    AliT0LookUpValue key(trm,tdc,chain,channel);
      AliT0LookUpKey *val = (AliT0LookUpKey*) fgLookUp->GetMapLookup()->GetValue((TObject*)&key);
      // AliT0LookUpKey *val = (AliT0LookUpKey*) fLookUp.GetValue((TObject*)&key);
    if (val )
      return val->GetKey();
    else {
      AliWarning(Form("No such address (%d %d %d %d)!",trm,tdc,chain,channel));
      return -1;
    }
  }
  else {
    AliError("No look up table has been loader!");
    return -1;
  }

}
//__________________________________________________________________
TMap *AliT0Parameters::GetMapLookup()
{
  if (!fgLookUp){
    cout<<" No look up table in OCDB";
    return 0;
  }
  return   fgLookUp->GetMapLookup();
}
//__________________________________________________________________

Int_t
AliT0Parameters::GetNumberOfTRMs()
{
  // return number of trms
  //
  if (!fgLookUp) {
    //  fNumberOfTRMs = 2;
    return  fNumberOfTRMs;
  }
  return  fgLookUp ->GetNumberOfTRMs();
}
/*
//________________________________________________________________________________
Double_t AliT0Parameters::GetZPosition(const char* symname){
// Get the global z coordinate of the given T0 alignable volume
//
  Double_t *tr = AliGeomManager::GetMatrix(symname)->GetTranslation();

  return tr[2];
}
*/
//________________________________________________________________________________
Double_t AliT0Parameters::GetZPosition(const char* symname){
// Get the global z coordinate of the given T0 alignable volume
//
  Double_t *tr;

  cout<<symname<<endl;
  TGeoPNEntry *pne = gGeoManager->GetAlignableEntry(symname);
  if (!pne) return 0;

  TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
  if(pnode){
          TGeoHMatrix* hm = pnode->GetMatrix();
           tr = hm->GetTranslation();
  }else{
          const char* path = pne->GetTitle();
          if(!gGeoManager->cd(path)){
                  AliErrorClass(Form("Volume path %s not valid!",path));
                  return 0;
          }
         tr = gGeoManager->GetCurrentMatrix()->GetTranslation();
  }
  return tr[2];

}
//________________________________________________________________________________

Double_t AliT0Parameters::GetZPositionShift(const char* symname)
{
// Get the global z coordinate of the given T0 alignable volume
//
  Double_t *tr = AliGeomManager::GetMatrix(symname)->GetTranslation();

  TGeoHMatrix origmat;
  AliGeomManager::GetOrigGlobalMatrix(symname,origmat);
  Double_t *otr = origmat.GetTranslation();

  return (tr[2]-otr[2]);
}

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

/* $Id:  */

//____________________________________________________________________
//
// T0 - T0.
//
// This class is a singleton that handles various parameters of
// the T0 detectors.
// Eventually, this class will use the Conditions DB to get the
// various parameters, which code can then request from here.
//
#include "AliLog.h"
#include "AliT0Parameters.h"
#include "AliT0CalibData.h"
#include "AliT0LookUpValue.h"
#include <AliCDBManager.h>
#include <AliCDBEntry.h>
#include <AliCDBStorage.h>
#include <TMath.h>
#include <TSystem.h>
#include <Riostream.h>
#include <TGeoManager.h>
#include <TGeoPhysicalNode.h>
#include <AliGeomManager.h>

AliT0CalibData* AliT0Parameters::fgCalibData = 0;
AliT0CalibData* AliT0Parameters::fgLookUp = 0;
AliT0CalibData* AliT0Parameters::fgSlewCorr =0;
//====================================================================
ClassImp(AliT0Parameters)
#if 0
  ; // This is here to keep Emacs for indenting the next line
#endif

//____________________________________________________________________
AliT0Parameters* AliT0Parameters::fgInstance = 0;
//____________________________________________________________________
AliT0Parameters* AliT0Parameters::Instance()
{
  // Get static instance
  if (!fgInstance) {
    fgInstance = new AliT0Parameters;
  }
  return fgInstance;
}

//____________________________________________________________________
AliT0Parameters::AliT0Parameters()
  :fIsInit(kFALSE),
   fPh2Mip(0),fmV2Mip(0),
   fChannelWidth(0),fmV2Channel(0),
   fQTmin(0),fQTmax(0),
   fAmpLEDRec(0),
   fPMTeff(),
   fWalk(0),
   fTimeDelayDA(0),
   fTimeDelayCFD(0),
   fTimeDelayTVD(0),
   fMeanT0(500),
   fLookUp(0),
   fNumberOfTRMs(2),
   fCalibentry(), fLookUpentry(),fSlewCorr()

{
  // Default constructor
  for (Int_t ipmt=0; ipmt<24; ipmt++)
    {
      SetPh2Mip();
      SetmV2Mip();
      SetChannelWidth();
      SetmV2channel();
      SetQTmin();
      SetQTmax();
      SetPMTeff(ipmt);
    }
  SetTimeDelayTVD();
  SetZposition();

}

//__________________________________________________________________
void
AliT0Parameters::Init()
{
  // Initialize the parameters manager.  We need to get stuff from the
  // CDB here.
   if (fIsInit) return;

   AliCDBManager *stor =AliCDBManager::Instance();
   //time equalizing
   fCalibentry  = stor->Get("T0/Calib/TimeDelay");
   if (fCalibentry)
     fgCalibData  = (AliT0CalibData*)fCalibentry->GetObject();
   else {
         AliFatal(" ALARM !!!! No time delays in CDB ");
     fIsInit = kFALSE;
     return;
   }
 //slewing correction
  fSlewCorr  = stor->Get("T0/Calib/Slewing_Walk");
  if (fSlewCorr){
    fgSlewCorr  = (AliT0CalibData*)fSlewCorr->GetObject();
  }
  else {
      AliFatal(" ALARM !!!! No slewing correction in CDB ");
    fIsInit = kFALSE;
    return;
  }
  //lookup table
  fLookUpentry  = stor->Get("T0/Calib/LookUp_Table");
  if (fLookUpentry){
    fgLookUp  = (AliT0CalibData*)fLookUpentry->GetObject();
  }
  else {
     AliFatal(" ALARM !!!! No Lookup table  in CDB ");
    fIsInit = kFALSE;
    return;
  }
  fIsInit = kTRUE;
}

//__________________________________________________________________

void AliT0Parameters::InitIfOnline()
{
// should be used in online
// for switching to this one should write
  // AliT0RawReader myrawreader(rawReader);
//	myrawreader.SetOnlineMode(kTRUE);

  if (fIsInit) return;
   //standart configuration (used for simulation)
   //Int_t trm=0; Int_t tdc=0; Int_t chain=0; Int_t channel=0;
  // configuration for test Jun07.
   fgLookUp = new AliT0CalibData("T0");

  fNumberOfTRMs = 1;
 fgLookUp-> SetNumberOfTRMs(fNumberOfTRMs);
  Int_t trm=7; Int_t tdc=0; Int_t chain=0; Int_t channel=0;
  for (Int_t ik=0; ik<105; ik++)
        {
         AliT0LookUpKey * lookkey= new AliT0LookUpKey();
         AliT0LookUpValue * lookvalue= new AliT0LookUpValue();

          lookvalue->SetTRM(trm);
          lookvalue->SetTDC(tdc);
          lookvalue->SetChain(chain);
          lookvalue->SetChannel(channel);
          lookkey->SetKey(ik);
	  if (channel<6) channel +=2;
	  else {channel = 0; tdc++;}
	  if(ik==57) { tdc=0; channel=0; chain = 1;}

	  fgLookUp->GetMapLookup()->Add((TObject*)lookvalue,(TObject*)lookkey);
       }

  fIsInit=kTRUE;
}
//__________________________________________________________________

Float_t
AliT0Parameters::GetTimeDelayDA(Int_t ipmt)
{
  // return time delay for LED channel
  //
  if (!fCalibentry) {
    fTimeDelayDA = 500;
    return  fTimeDelayDA;
  }
  return fgCalibData ->GetTimeDelayDA(ipmt);
}
//__________________________________________________________________
Float_t
AliT0Parameters::GetTimeDelayCFD(Int_t ipmt)
{
  // return time delay for CFD channel
   //
  if (!fCalibentry)
    {
      fTimeDelayCFD = 1000+ipmt*100;
      return fTimeDelayCFD;
    }

  return fgCalibData->GetTimeDelayCFD(ipmt);
}

//__________________________________________________________________
Int_t
AliT0Parameters::GetMeanT0()
{
  // return mean of T0 distrubution with vertex=0
   //
  if (!fCalibentry)
    {
      return fMeanT0;
    }

  return fgCalibData->GetMeanT0();
}
//__________________________________________________________________

TGraph *AliT0Parameters::GetAmpLEDRec(Int_t ipmt) const
{
   if (!fSlewCorr) {
     AliError("No slewing correction is available!");
     return  (TGraph*)fAmpLEDRec.At(ipmt);
  }
  return fgSlewCorr -> GetAmpLEDRec(ipmt) ;
}

//__________________________________________________________________

TGraph *AliT0Parameters::GetWalk(Int_t ipmt) const
{
  if (!fSlewCorr) {
    AliError("No walk correction is available!");
    return  (TGraph*)fWalk.At(ipmt);
  }
  return fgSlewCorr -> GetWalk(ipmt) ;
}

//__________________________________________________________________

Float_t AliT0Parameters::GetWalkVal(Int_t ipmt, Float_t mv) const
{
  if (!fSlewCorr) {
    return ((TGraph*)fWalk.At(ipmt))->Eval(mv);
  }
  return fgSlewCorr -> GetWalkVal(ipmt, mv) ;
}

//__________________________________________________________________
void
AliT0Parameters::SetPMTeff(Int_t ipmt)
{
  Float_t lambda[50];
  Float_t eff[50 ] = {0,        0,       0.23619,  0.202909, 0.177913,
		    0.175667, 0.17856, 0.190769, 0.206667, 0.230286,
		    0.252276, 0.256267,0.26,     0.27125,  0.281818,
		    0.288118, 0.294057,0.296222, 0.301622, 0.290421,
		    0.276615, 0.2666,  0.248,    0.23619,  0.227814,
		    0.219818, 0.206667,0.194087, 0.184681, 0.167917,
		    0.154367, 0.1364,  0.109412, 0.0834615,0.0725283,
		    0.0642963,0.05861, 0.0465,   0.0413333,0.032069,
		    0.0252203,0.02066, 0.016262, 0.012,    0.00590476,
		    0.003875, 0.00190, 0,        0,        0          } ;
  for (Int_t i=0; i<50; i++) lambda[i]=200+10*i;

  TGraph* gr = new TGraph(50,lambda,eff);
  fPMTeff.AddAtAndExpand(gr,ipmt);
}
//________________________________________________________________

Int_t
AliT0Parameters::GetChannel(Int_t trm,  Int_t tdc, Int_t chain, Int_t channel)
{

  if (fgLookUp) {
    AliT0LookUpValue key(trm,tdc,chain,channel);
      AliT0LookUpKey *val = (AliT0LookUpKey*) fgLookUp->GetMapLookup()->GetValue((TObject*)&key);
      // AliT0LookUpKey *val = (AliT0LookUpKey*) fLookUp.GetValue((TObject*)&key);
    if (val )
      return val->GetKey();
    else {
      AliWarning(Form("No such address (%d %d %d %d)!",trm,tdc,chain,channel));
      return -1;
    }
  }
  else {
    AliError("No look up table has been loader!");
    return -1;
  }

}
//__________________________________________________________________
TMap *AliT0Parameters::GetMapLookup()
{
  if (!fgLookUp){
    cout<<" No look up table in OCDB";
    return 0;
  }
  return   fgLookUp->GetMapLookup();
}
//__________________________________________________________________

Int_t
AliT0Parameters::GetNumberOfTRMs()
{
  // return number of trms
  //
  if (!fgLookUp) {
    //  fNumberOfTRMs = 2;
    return  fNumberOfTRMs;
  }
  return  fgLookUp ->GetNumberOfTRMs();
}
/*
//________________________________________________________________________________
Double_t AliT0Parameters::GetZPosition(const char* symname){
// Get the global z coordinate of the given T0 alignable volume
//
  Double_t *tr = AliGeomManager::GetMatrix(symname)->GetTranslation();

  return tr[2];
}
*/
//________________________________________________________________________________
Double_t AliT0Parameters::GetZPosition(const char* symname){
// Get the global z coordinate of the given T0 alignable volume
//
  Double_t *tr;
  TGeoPNEntry *pne = gGeoManager->GetAlignableEntry(symname);
  if (!pne) return 0;

  TGeoPhysicalNode *pnode = pne->GetPhysicalNode();
  if(pnode){
          TGeoHMatrix* hm = pnode->GetMatrix();
           tr = hm->GetTranslation();
  }else{
          const char* path = pne->GetTitle();
          if(!gGeoManager->cd(path)){
                  AliErrorClass(Form("Volume path %s not valid!",path));
                  return 0;
          }
         tr = gGeoManager->GetCurrentMatrix()->GetTranslation();
  }
  return tr[2];

}
//________________________________________________________________________________

Double_t AliT0Parameters::GetZPositionShift(const char* symname)
{
// Get the global z coordinate of the given T0 alignable volume
//
  Double_t *tr = AliGeomManager::GetMatrix(symname)->GetTranslation();

  TGeoHMatrix origmat;
  AliGeomManager::GetOrigGlobalMatrix(symname,origmat);
  Double_t *otr = origmat.GetTranslation();

  return (tr[2]-otr[2]);
}

<|endoftext|>


<commit_before>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/common_runtime/optimization_registry.h"
#include "tensorflow/core/tpu/graph_rewrite/distributed_tpu_configuration_rewrite_pass.h"
#include "tensorflow/core/tpu/graph_rewrite/encapsulate_tpu_computations_pass.h"
#include "tensorflow/core/tpu/graph_rewrite/variable_merger_pass.h"

namespace tensorflow {
namespace {

// This pass removes the TPUEmbeddingConfiguration in ConfigureDistributedTPU.
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 20,
                      DistributedTPUConfigurationRewritePass);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 20,
                      DistributedTPUShutdownRewritePass);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 34,
                      EncapsulateTPUComputationsPass);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 39,
                      ExtractOutsideCompilationPass);

}  // namespace
}  // namespace tensorflow
<commit_msg>Restore registration for variable merger pass.<commit_after>/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.

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 "tensorflow/core/common_runtime/optimization_registry.h"
#include "tensorflow/core/tpu/graph_rewrite/distributed_tpu_configuration_rewrite_pass.h"
#include "tensorflow/core/tpu/graph_rewrite/encapsulate_tpu_computations_pass.h"
#include "tensorflow/core/tpu/graph_rewrite/variable_merger_pass.h"

namespace tensorflow {
namespace {

// This pass removes the TPUEmbeddingConfiguration in ConfigureDistributedTPU.
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 20,
                      DistributedTPUConfigurationRewritePass);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 20,
                      DistributedTPUShutdownRewritePass);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 34,
                      EncapsulateTPUComputationsPass);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::PRE_PLACEMENT, 39,
                      ExtractOutsideCompilationPass);
REGISTER_OPTIMIZATION(OptimizationPassRegistry::POST_REWRITE_FOR_EXEC, 0,
                      VariableMergerPass);

}  // namespace
}  // namespace tensorflow
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "maemopackagecreationstep.h"

#include "maemoconstants.h"
#include "maemopackagecreationwidget.h"
#include "maemopackagecontents.h"
#include "maemotoolchain.h"

#include <projectexplorer/projectexplorerconstants.h>
#include <qt4buildconfiguration.h>
#include <qt4project.h>
#include <qt4target.h>

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <QtCore/QProcessEnvironment>
#include <QtCore/QStringBuilder>
#include <QtGui/QWidget>

namespace { const QLatin1String PackagingEnabledKey("Packaging Enabled"); }

using namespace ProjectExplorer::Constants;
using ProjectExplorer::BuildConfiguration;
using ProjectExplorer::BuildStepConfigWidget;
using ProjectExplorer::Task;

namespace Qt4ProjectManager {
namespace Internal {

MaemoPackageCreationStep::MaemoPackageCreationStep(BuildConfiguration *buildConfig)
    : ProjectExplorer::BuildStep(buildConfig, CreatePackageId),
      m_packageContents(new MaemoPackageContents(this)),
      m_packagingEnabled(true)
{
}

MaemoPackageCreationStep::MaemoPackageCreationStep(BuildConfiguration *buildConfig,
    MaemoPackageCreationStep *other)
    : BuildStep(buildConfig, other),
      m_packageContents(new MaemoPackageContents(this)),
      m_packagingEnabled(other->m_packagingEnabled)

{

}

bool MaemoPackageCreationStep::init()
{
    return true;
}

QVariantMap MaemoPackageCreationStep::toMap() const
{
    QVariantMap map(ProjectExplorer::BuildStep::toMap());
    map.insert(PackagingEnabledKey, m_packagingEnabled);
    return map;
}

bool MaemoPackageCreationStep::fromMap(const QVariantMap &map)
{
    m_packagingEnabled = map.value(PackagingEnabledKey, true).toBool();
    return ProjectExplorer::BuildStep::fromMap(map);
}

void MaemoPackageCreationStep::run(QFutureInterface<bool> &fi)
{
    fi.reportResult(m_packagingEnabled ? createPackage() : true);
}

BuildStepConfigWidget *MaemoPackageCreationStep::createConfigWidget()
{
    return new MaemoPackageCreationWidget(this);
}

bool MaemoPackageCreationStep::createPackage()
{
    if (!packagingNeeded())
        return true;

    QTextCharFormat textCharFormat;
    emit addOutput(tr("Creating package file ..."), textCharFormat);
    QFile configFile(targetRoot() % QLatin1String("/config.sh"));
    if (!configFile.open(QIODevice::ReadOnly)) {
        raiseError(tr("Cannot open MADDE config file '%1'.")
                   .arg(nativePath(configFile)));
        return false;
    }

    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    const QString &path = QDir::toNativeSeparators(maddeRoot() + QLatin1Char('/'));

    const QLatin1String key("PATH");
    QString colon = QLatin1String(":");
#ifdef Q_OS_WIN
    colon = QLatin1String(";");
    env.insert(key, targetRoot() % "/bin" % colon % env.value(key));
    env.insert(key, path % QLatin1String("bin") % colon % env.value(key));
#endif
    env.insert(key, path % QLatin1String("madbin") % colon % env.value(key));
    env.insert(QLatin1String("PERL5LIB"), path % QLatin1String("madlib/perl5"));

    const QString buildDir = QFileInfo(localExecutableFilePath()).absolutePath();
    env.insert(QLatin1String("PWD"), buildDir);

    const QRegExp envPattern(QLatin1String("([^=]+)=[\"']?([^;\"']+)[\"']? ;.*"));
    QByteArray line;
    do {
        line = configFile.readLine(200);
        if (envPattern.exactMatch(line))
            env.insert(envPattern.cap(1), envPattern.cap(2));
    } while (!line.isEmpty());

    QProcess buildProc;
    buildProc.setProcessEnvironment(env);
    buildProc.setWorkingDirectory(buildDir);

    if (!QFileInfo(buildDir + QLatin1String("/debian")).exists()) {
        const QString command = QLatin1String("dh_make -s -n -p ")
            % executableFileName().toLower() % versionString();
        if (!runCommand(buildProc, command))
            return false;
        QFile rulesFile(buildDir + QLatin1String("/debian/rules"));
        if (!rulesFile.open(QIODevice::ReadWrite)) {
            raiseError(tr("Packaging Error: Cannot open file '%1'.")
                       .arg(nativePath(rulesFile)));
            return false;
        }

        QByteArray rulesContents = rulesFile.readAll();
        rulesContents.replace("DESTDIR", "INSTALL_ROOT");
        rulesFile.resize(0);
        rulesFile.write(rulesContents);
        if (rulesFile.error() != QFile::NoError) {
            raiseError(tr("Packaging Error: Cannot write file '%1'.")
                       .arg(nativePath(rulesFile)));
            return false;
        }
    }

    if (!runCommand(buildProc, QLatin1String("dh_installdirs")))
        return false;

    const QDir debianRoot = QDir(buildDir % QLatin1String("/debian/")
                                 % executableFileName().toLower());
    for (int i = 0; i < m_packageContents->rowCount(); ++i) {
        const MaemoPackageContents::Deployable &d
            = m_packageContents->deployableAt(i);
        const QString absTargetDir = debianRoot.path() + '/' + d.remoteDir;
        const QString targetFile
            = absTargetDir + '/' + QFileInfo(d.localFilePath).fileName();
        const QString relTargetDir = debianRoot.relativeFilePath(absTargetDir);
        if (!debianRoot.exists(relTargetDir)
            && !debianRoot.mkpath(relTargetDir)) {
            raiseError(tr("Packaging Error: Could not create directory '%1'.")
                       .arg(QDir::toNativeSeparators(absTargetDir)));
            return false;
        }
        if (QFile::exists(targetFile) && !QFile::remove(targetFile)) {
            raiseError(tr("Packaging Error: Could not replace file '%1'.")
                       .arg(QDir::toNativeSeparators(targetFile)));
            return false;
        }

        if (!QFile::copy(d.localFilePath, targetFile)) {
            raiseError(tr("Packaging Error: Could not copy '%1' to '%2'.")
                       .arg(QDir::toNativeSeparators(d.localFilePath))
                       .arg(QDir::toNativeSeparators(targetFile)));
            return false;
        }
    }

    const QStringList commands = QStringList() << QLatin1String("dh_link")
        << QLatin1String("dh_fixperms") << QLatin1String("dh_installdeb")
        << QLatin1String("dh_shlibdeps") << QLatin1String("dh_gencontrol")
        << QLatin1String("dh_md5sums") << QLatin1String("dh_builddeb --destdir=.");
    foreach (const QString &command, commands) {
        if (!runCommand(buildProc, command))
            return false;
    }

    emit addOutput(tr("Package created."), textCharFormat);
    m_packageContents->setUnModified();
    return true;
}

bool MaemoPackageCreationStep::runCommand(QProcess &proc, const QString &command)
{
    QTextCharFormat textCharFormat;
    emit addOutput(tr("Package Creation: Running command '%1'.").arg(command), textCharFormat);
    QString perl;
#ifdef Q_OS_WIN
    perl = maddeRoot() + QLatin1String("/bin/perl.exe ");
#endif
    proc.start(perl + maddeRoot() % QLatin1String("/madbin/") % command);
    if (!proc.waitForStarted()) {
        raiseError(tr("Packaging failed."),
            tr("Packaging error: Could not start command '%1'. Reason: %2")
            .arg(command).arg(proc.errorString()));
        return false;
    }
    proc.write("\n"); // For dh_make
    proc.waitForFinished(-1);
    if (proc.error() != QProcess::UnknownError || proc.exitCode() != 0) {
        QString mainMessage = tr("Packaging Error: Command '%1' failed.")
            .arg(command);
        if (proc.error() != QProcess::UnknownError)
            mainMessage += tr(" Reason: %1").arg(proc.errorString());
        raiseError(mainMessage, mainMessage + QLatin1Char('\n')
                   + tr("Output was: ") + proc.readAllStandardError()
                   + QLatin1Char('\n') + proc.readAllStandardOutput());
        return false;
    }
    return true;
}

const Qt4BuildConfiguration *MaemoPackageCreationStep::qt4BuildConfiguration() const
{
    return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
}

QString MaemoPackageCreationStep::localExecutableFilePath() const
{
    const TargetInformation &ti = qt4BuildConfiguration()->qt4Target()
        ->qt4Project()->rootProjectNode()->targetInformation();
    if (!ti.valid)
        return QString();
    return QDir::toNativeSeparators(QDir::cleanPath(ti.workingDir
        + QLatin1Char('/') + executableFileName()));
}

QString MaemoPackageCreationStep::executableFileName() const
{
    const Qt4Project * const project
        = qt4BuildConfiguration()->qt4Target()->qt4Project();
    const TargetInformation &ti
        = project->rootProjectNode()->targetInformation();
    if (!ti.valid)
        return QString();

    return project->rootProjectNode()->projectType() == LibraryTemplate
        ? QLatin1String("lib") + ti.target + QLatin1String(".so")
        : ti.target;
}

const MaemoToolChain *MaemoPackageCreationStep::maemoToolChain() const
{
    return static_cast<MaemoToolChain *>(qt4BuildConfiguration()->toolChain());
}

QString MaemoPackageCreationStep::maddeRoot() const
{
    return maemoToolChain()->maddeRoot();
}

QString MaemoPackageCreationStep::targetRoot() const
{
    return maemoToolChain()->targetRoot();
}

bool MaemoPackageCreationStep::packagingNeeded() const
{
    QFileInfo packageInfo(packageFilePath());
    if (!packageInfo.exists() || m_packageContents->isModified())
        return true;

    for (int i = 0; i < m_packageContents->rowCount(); ++i) {
        if (packageInfo.lastModified()
            <= QFileInfo(m_packageContents->deployableAt(i).localFilePath)
               .lastModified())
            return true;
    }

    return false;
}

QString MaemoPackageCreationStep::packageFilePath() const
{
    QFileInfo execInfo(localExecutableFilePath());
    return execInfo.path() % QDir::separator() % execInfo.fileName().toLower()
        % versionString() % QLatin1String("_armel.deb");
}

QString MaemoPackageCreationStep::versionString() const
{
    return QLatin1String("_0.1");
}

QString MaemoPackageCreationStep::nativePath(const QFile &file) const
{
    return QDir::toNativeSeparators(QFileInfo(file).filePath());
}

void MaemoPackageCreationStep::raiseError(const QString &shortMsg,
                                          const QString &detailedMsg)
{
    QTextCharFormat textCharFormat;
    emit addOutput(detailedMsg.isNull() ? shortMsg : detailedMsg, textCharFormat);
    emit addTask(Task(Task::Error, shortMsg, QString(), -1,
                      TASK_CATEGORY_BUILDSYSTEM));
}

const QLatin1String MaemoPackageCreationStep::CreatePackageId("Qt4ProjectManager.MaemoPackageCreationStep");

} // namespace Internal
} // namespace Qt4ProjectManager
<commit_msg>Maemo: Use generic package build command.<commit_after>/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of Qt Creator.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "maemopackagecreationstep.h"

#include "maemoconstants.h"
#include "maemopackagecreationwidget.h"
#include "maemopackagecontents.h"
#include "maemotoolchain.h"

#include <projectexplorer/projectexplorerconstants.h>
#include <qt4buildconfiguration.h>
#include <qt4project.h>
#include <qt4target.h>

#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QProcess>
#include <QtCore/QProcessEnvironment>
#include <QtCore/QStringBuilder>
#include <QtGui/QWidget>

namespace { const QLatin1String PackagingEnabledKey("Packaging Enabled"); }

using namespace ProjectExplorer::Constants;
using ProjectExplorer::BuildConfiguration;
using ProjectExplorer::BuildStepConfigWidget;
using ProjectExplorer::Task;

namespace Qt4ProjectManager {
namespace Internal {

MaemoPackageCreationStep::MaemoPackageCreationStep(BuildConfiguration *buildConfig)
    : ProjectExplorer::BuildStep(buildConfig, CreatePackageId),
      m_packageContents(new MaemoPackageContents(this)),
      m_packagingEnabled(true)
{
}

MaemoPackageCreationStep::MaemoPackageCreationStep(BuildConfiguration *buildConfig,
    MaemoPackageCreationStep *other)
    : BuildStep(buildConfig, other),
      m_packageContents(new MaemoPackageContents(this)),
      m_packagingEnabled(other->m_packagingEnabled)

{

}

bool MaemoPackageCreationStep::init()
{
    return true;
}

QVariantMap MaemoPackageCreationStep::toMap() const
{
    QVariantMap map(ProjectExplorer::BuildStep::toMap());
    map.insert(PackagingEnabledKey, m_packagingEnabled);
    return map;
}

bool MaemoPackageCreationStep::fromMap(const QVariantMap &map)
{
    m_packagingEnabled = map.value(PackagingEnabledKey, true).toBool();
    return ProjectExplorer::BuildStep::fromMap(map);
}

void MaemoPackageCreationStep::run(QFutureInterface<bool> &fi)
{
    fi.reportResult(m_packagingEnabled ? createPackage() : true);
}

BuildStepConfigWidget *MaemoPackageCreationStep::createConfigWidget()
{
    return new MaemoPackageCreationWidget(this);
}

bool MaemoPackageCreationStep::createPackage()
{
    if (!packagingNeeded())
        return true;

    QTextCharFormat textCharFormat;
    emit addOutput(tr("Creating package file ..."), textCharFormat);
    QFile configFile(targetRoot() % QLatin1String("/config.sh"));
    if (!configFile.open(QIODevice::ReadOnly)) {
        raiseError(tr("Cannot open MADDE config file '%1'.")
                   .arg(nativePath(configFile)));
        return false;
    }

    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
    const QString &path = QDir::toNativeSeparators(maddeRoot() + QLatin1Char('/'));

    const QLatin1String key("PATH");
    QString colon = QLatin1String(":");
#ifdef Q_OS_WIN
    colon = QLatin1String(";");
    env.insert(key, path % QLatin1String("bin") % colon % env.value(key));
#endif
    env.insert(key, targetRoot() % "/bin" % colon % env.value(key));
    env.insert(key, path % QLatin1String("madbin") % colon % env.value(key));
    env.insert(QLatin1String("PERL5LIB"), path % QLatin1String("madlib/perl5"));

    const QString buildDir = QFileInfo(localExecutableFilePath()).absolutePath();
    env.insert(QLatin1String("PWD"), buildDir);

    const QRegExp envPattern(QLatin1String("([^=]+)=[\"']?([^;\"']+)[\"']? ;.*"));
    QByteArray line;
    do {
        line = configFile.readLine(200);
        if (envPattern.exactMatch(line))
            env.insert(envPattern.cap(1), envPattern.cap(2));
    } while (!line.isEmpty());

    QProcess buildProc;
    buildProc.setProcessEnvironment(env);
    buildProc.setWorkingDirectory(buildDir);
    buildProc.start("cd " + buildDir);
    buildProc.waitForFinished();

    if (!QFileInfo(buildDir + QLatin1String("/debian")).exists()) {
        const QString command = QLatin1String("dh_make -s -n -p ")
            % executableFileName().toLower() % versionString();
        if (!runCommand(buildProc, command))
            return false;
        QFile rulesFile(buildDir + QLatin1String("/debian/rules"));
        if (!rulesFile.open(QIODevice::ReadWrite)) {
            raiseError(tr("Packaging Error: Cannot open file '%1'.")
                       .arg(nativePath(rulesFile)));
            return false;
        }

        QByteArray rulesContents = rulesFile.readAll();
        rulesContents.replace("DESTDIR", "INSTALL_ROOT");

        // Would be the right solution, but does not work (on Windows),
        // because dpkg-genchanges doesn't know about it (and can't be told).
        // rulesContents.replace("dh_builddeb", "dh_builddeb --destdir=.");

        rulesFile.resize(0);
        rulesFile.write(rulesContents);
        if (rulesFile.error() != QFile::NoError) {
            raiseError(tr("Packaging Error: Cannot write file '%1'.")
                       .arg(nativePath(rulesFile)));
            return false;
        }
    }

    if (!runCommand(buildProc, "dpkg-buildpackage -nc -uc -us"))
        return false;

    // Workaround for non-working dh_builddeb --destdir=.
    if (!QDir(buildDir).isRoot()) {
        const QString packageFileName = QFileInfo(packageFilePath()).fileName();
        const QString changesFileName = QFileInfo(packageFileName)
            .completeBaseName() + QLatin1String(".changes");
        const QString packageSourceDir = buildDir + QLatin1String("/../");
        const QString packageSourceFilePath
            = packageSourceDir + packageFileName;
        const QString changesSourceFilePath
            = packageSourceDir + changesFileName;
        const QString changesTargetFilePath
            = buildDir + QLatin1Char('/') + changesFileName;
        QFile::remove(packageFilePath());
        QFile::remove(changesTargetFilePath);
        if (!QFile::rename(packageSourceFilePath, packageFilePath())
            || !QFile::rename(changesSourceFilePath, changesTargetFilePath)) {
            raiseError(tr("Packaging failed."),
                tr("Could not move package files from %1 to %2.")
                .arg(packageSourceDir, buildDir));
            return false;
        }
    }

    emit addOutput(tr("Package created."), textCharFormat);
    m_packageContents->setUnModified();
    return true;
}

bool MaemoPackageCreationStep::runCommand(QProcess &proc, const QString &command)
{
    QTextCharFormat textCharFormat;
    emit addOutput(tr("Package Creation: Running command '%1'.").arg(command), textCharFormat);
    QString perl;
#ifdef Q_OS_WIN
    perl = maddeRoot() + QLatin1String("/bin/perl.exe ");
#endif
    proc.start(perl + maddeRoot() % QLatin1String("/madbin/") % command);
    if (!proc.waitForStarted()) {
        raiseError(tr("Packaging failed."),
            tr("Packaging error: Could not start command '%1'. Reason: %2")
            .arg(command).arg(proc.errorString()));
        return false;
    }
    proc.write("\n"); // For dh_make
    proc.waitForFinished(-1);
    if (proc.error() != QProcess::UnknownError || proc.exitCode() != 0) {
        QString mainMessage = tr("Packaging Error: Command '%1' failed.")
            .arg(command);
        if (proc.error() != QProcess::UnknownError)
            mainMessage += tr(" Reason: %1").arg(proc.errorString());
        else
            mainMessage += tr("Exit code: %1").arg(proc.exitCode());
        raiseError(mainMessage, mainMessage + QLatin1Char('\n')
                   + tr("Output was: ") + proc.readAllStandardError()
                   + QLatin1Char('\n') + proc.readAllStandardOutput());
        return false;
    }
    return true;
}

const Qt4BuildConfiguration *MaemoPackageCreationStep::qt4BuildConfiguration() const
{
    return static_cast<Qt4BuildConfiguration *>(buildConfiguration());
}

QString MaemoPackageCreationStep::localExecutableFilePath() const
{
    const TargetInformation &ti = qt4BuildConfiguration()->qt4Target()
        ->qt4Project()->rootProjectNode()->targetInformation();
    if (!ti.valid)
        return QString();
    return QDir::toNativeSeparators(QDir::cleanPath(ti.workingDir
        + QLatin1Char('/') + executableFileName()));
}

QString MaemoPackageCreationStep::executableFileName() const
{
    const Qt4Project * const project
        = qt4BuildConfiguration()->qt4Target()->qt4Project();
    const TargetInformation &ti
        = project->rootProjectNode()->targetInformation();
    if (!ti.valid)
        return QString();

    return project->rootProjectNode()->projectType() == LibraryTemplate
        ? QLatin1String("lib") + ti.target + QLatin1String(".so")
        : ti.target;
}

const MaemoToolChain *MaemoPackageCreationStep::maemoToolChain() const
{
    return static_cast<MaemoToolChain *>(qt4BuildConfiguration()->toolChain());
}

QString MaemoPackageCreationStep::maddeRoot() const
{
    return maemoToolChain()->maddeRoot();
}

QString MaemoPackageCreationStep::targetRoot() const
{
    return maemoToolChain()->targetRoot();
}

bool MaemoPackageCreationStep::packagingNeeded() const
{
    QFileInfo packageInfo(packageFilePath());
    if (!packageInfo.exists() || m_packageContents->isModified())
        return true;

    for (int i = 0; i < m_packageContents->rowCount(); ++i) {
        if (packageInfo.lastModified()
            <= QFileInfo(m_packageContents->deployableAt(i).localFilePath)
               .lastModified())
            return true;
    }

    return false;
}

QString MaemoPackageCreationStep::packageFilePath() const
{
    QFileInfo execInfo(localExecutableFilePath());
    return execInfo.path() % QDir::separator() % execInfo.fileName().toLower()
        % versionString() % QLatin1String("_armel.deb");
}

QString MaemoPackageCreationStep::versionString() const
{
    return QLatin1String("_0.1");
}

QString MaemoPackageCreationStep::nativePath(const QFile &file) const
{
    return QDir::toNativeSeparators(QFileInfo(file).filePath());
}

void MaemoPackageCreationStep::raiseError(const QString &shortMsg,
                                          const QString &detailedMsg)
{
    QTextCharFormat textCharFormat;
    emit addOutput(detailedMsg.isNull() ? shortMsg : detailedMsg, textCharFormat);
    emit addTask(Task(Task::Error, shortMsg, QString(), -1,
                      TASK_CATEGORY_BUILDSYSTEM));
}

const QLatin1String MaemoPackageCreationStep::CreatePackageId("Qt4ProjectManager.MaemoPackageCreationStep");

} // namespace Internal
} // namespace Qt4ProjectManager
<|endoftext|>


<commit_before>//=============================================================================================================
/**
* @file     test_mne_forward_solution.cpp
* @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     December, 2016
*
* @section  LICENSE
*
* Copyright (C) 2016, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    The forward solution test implementation
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <fwd/computeFwd/compute_fwd_settings.h>
#include <fwd/computeFwd/compute_fwd.h>
#include <mne/mne.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FWDLIB;
using namespace MNELIB;

//=============================================================================================================
/**
* DECLARE CLASS TestMneForwardSolution
*
* @brief The TestMneForwardSolution class provides dipole fit tests
*
*/
class TestMneForwardSolution : public QObject
{
    Q_OBJECT

public:
    TestMneForwardSolution();

private slots:
    void initTestCase();
    void computeForward();
    void compareForward();
    void cleanupTestCase();

private:
    double epsilon;

    QSharedPointer<MNEForwardSolution> m_pFwdMEGEEGRead;
    QSharedPointer<MNEForwardSolution> m_pFwdMEGEEGRef;

};

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

TestMneForwardSolution::TestMneForwardSolution()
: epsilon(0.0001)
{
}

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

void TestMneForwardSolution::initTestCase()
{

}

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

void TestMneForwardSolution::computeForward()
{
    // Compute and Write Forward Solution
    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Compute/Write/Read MEG/EEG Forward Solution >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    // Read reference forward solution
    QString fwdMEGEEGFileRef("./mne-cpp-test-data/Result/ref-sample_audvis-meg-eeg-oct-6-fwd.fif");
    QFile fileFwdMEGEEGRef(fwdMEGEEGFileRef);
    m_pFwdMEGEEGRef = QSharedPointer<MNEForwardSolution>(new MNEForwardSolution(fileFwdMEGEEGRef));

    //Following is equivalent to:
    //mne_forward_solution
    // --meg
    // --eeg
    // --accurate
    // --src ./mne-cpp-test-data/subjects/sample/bem/sample-oct-6-src.fif
    // --meas ./mne-cpp-test-data/MEG/sample/sample_audvis_raw_short.fif
    // --mri ./mne-cpp-test-data/MEG/sample/all-trans.fif
    // --bem ./mne-cpp-test-data/subjects/sample/bem/sample-1280-1280-1280-bem.fif
    // --mindist 5
    // --fwd ./mne-cpp-test-data/Result/sample_audvis-meg-eeg-oct-6-fwd.fif

    ComputeFwdSettings settingsMEGEEG;

    settingsMEGEEG.include_meg = true;
    settingsMEGEEG.include_eeg = true;
    settingsMEGEEG.accurate = true;
    settingsMEGEEG.srcname = "./mne-cpp-test-data/subjects/sample/bem/sample-oct-6-src.fif";
    settingsMEGEEG.measname = "./mne-cpp-test-data/MEG/sample/sample_audvis_raw_short.fif";
    settingsMEGEEG.mriname = "./mne-cpp-test-data/MEG/sample/all-trans.fif";
    settingsMEGEEG.transname.clear();
    settingsMEGEEG.bemname = "./mne-cpp-test-data/subjects/sample/bem/sample-1280-1280-1280-bem.fif";
    settingsMEGEEG.mindist = 5.0f/1000.0f;
    settingsMEGEEG.solname = "./mne-cpp-test-data/Result/sample_audvis-meg-eeg-oct-6-fwd.fif";

    settingsMEGEEG.checkIntegrity();

    QSharedPointer<ComputeFwd> pFwdMEGEEGComputed = QSharedPointer<ComputeFwd>(new ComputeFwd(&settingsMEGEEG));
    pFwdMEGEEGComputed->calculateFwd();

    // Read newly created fwd
    QFile fileFwdMEGEEGRead(settingsMEGEEG.solname);
    m_pFwdMEGEEGRead = QSharedPointer<MNEForwardSolution>(new MNEForwardSolution(fileFwdMEGEEGRead));

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Compute/Write/Read MEG/EEG Forward Solution Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

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

void TestMneForwardSolution::compareForward()
{
    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Compare MEG/EEG Forward Solution >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    // Sum up the solution matrix elements to compare them with the reference
    double sumComputed = 0;
    for(int i = 0; i < m_pFwdMEGEEGRead->sol->nrow; ++i) {
        for(int j = 0; j < m_pFwdMEGEEGRead->sol->ncol; ++j) {
            sumComputed += m_pFwdMEGEEGRead->sol->data(i,j);
        }
    }

    double sumRef = 0;
    for(int i = 0; i < m_pFwdMEGEEGRef->sol->nrow; ++i) {
        for(int j = 0; j < m_pFwdMEGEEGRef->sol->ncol; ++j) {
            sumRef += m_pFwdMEGEEGRef->sol->data(i,j);
        }
    }

    qDebug() << "sumComputed" << sumComputed;
    qDebug() << "sumRef" << sumRef;
    qDebug() << "sumComputed-sumRef" << sumComputed-sumRef;
    qDebug() << "";

    // Please note that the solution matrix is transposed once it is read from the data file
    QVERIFY(m_pFwdMEGEEGRead->sol->ncol == m_pFwdMEGEEGRef->sol->ncol);
    QVERIFY(m_pFwdMEGEEGRead->sol->nrow == m_pFwdMEGEEGRef->sol->nrow);

    //Compare the actual fwd solution matrix results
    QVERIFY(sumComputed-sumRef <= epsilon);
    QVERIFY(m_pFwdMEGEEGRead->sol->data.isApprox(m_pFwdMEGEEGRef->sol->data, epsilon));

    // This is rather hard to test since we need to combien the two forward solutions.
    // This is normally done when reading the combined fwd solutions. Wait until everything is refactored.
    //QVERIFY(*m_pFwdMEGEEGRead == *m_pFwdMEGEEGRef);

    QVERIFY(m_pFwdMEGEEGRead->info == m_pFwdMEGEEGRef->info);
    QVERIFY(m_pFwdMEGEEGRead->source_ori == m_pFwdMEGEEGRef->source_ori);
    QVERIFY(m_pFwdMEGEEGRead->surf_ori == m_pFwdMEGEEGRef->surf_ori);
    QVERIFY(m_pFwdMEGEEGRead->coord_frame == m_pFwdMEGEEGRef->coord_frame);
    QVERIFY(m_pFwdMEGEEGRead->nsource == m_pFwdMEGEEGRef->nsource);
    QVERIFY(m_pFwdMEGEEGRead->nchan == m_pFwdMEGEEGRef->nchan);
    QVERIFY(*m_pFwdMEGEEGRead->sol == *m_pFwdMEGEEGRef->sol);
//    QVERIFY(*m_pFwdMEGEEGRead->sol_grad == *m_pFwdMEGEEGRef->sol_grad);
//    QVERIFY(m_pFwdMEGEEGRead->mri_head_t == m_pFwdMEGEEGRef->mri_head_t);
    //m_pFwdMEGEEGRead->src == m_pFwdMEGEEGRef->src);
    QVERIFY(m_pFwdMEGEEGRead->source_rr == m_pFwdMEGEEGRef->source_rr);
    QVERIFY(m_pFwdMEGEEGRead->source_nn == m_pFwdMEGEEGRef->source_nn);

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Compare MEG/EEG Forward Solution Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

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

void TestMneForwardSolution::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestMneForwardSolution)
#include "test_mne_forward_solution.moc"
<commit_msg>Make use of equality operator in test_mne_forward_solution<commit_after>//=============================================================================================================
/**
* @file     test_mne_forward_solution.cpp
* @author   Christoph Dinh <chdinh@nmr.mgh.harvard.edu>;
*           Matti Hamalainen <msh@nmr.mgh.harvard.edu>
* @version  1.0
* @date     December, 2016
*
* @section  LICENSE
*
* Copyright (C) 2016, Christoph Dinh and Matti Hamalainen. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that
* the following conditions are met:
*     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
*       following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
*       the following disclaimer in the documentation and/or other materials provided with the distribution.
*     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
*       to endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
* @brief    The forward solution test implementation
*
*/

//*************************************************************************************************************
//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include <fwd/computeFwd/compute_fwd_settings.h>
#include <fwd/computeFwd/compute_fwd.h>
#include <mne/mne.h>

//*************************************************************************************************************
//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QtTest>

//*************************************************************************************************************
//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace FWDLIB;
using namespace MNELIB;

//=============================================================================================================
/**
* DECLARE CLASS TestMneForwardSolution
*
* @brief The TestMneForwardSolution class provides dipole fit tests
*
*/
class TestMneForwardSolution : public QObject
{
    Q_OBJECT

public:
    TestMneForwardSolution();

private slots:
    void initTestCase();
    void computeForward();
    void compareForward();
    void cleanupTestCase();

private:
    double epsilon;

    QSharedPointer<MNEForwardSolution> m_pFwdMEGEEGRead;
    QSharedPointer<MNEForwardSolution> m_pFwdMEGEEGRef;

};

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

TestMneForwardSolution::TestMneForwardSolution()
: epsilon(0.0001)
{
}

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

void TestMneForwardSolution::initTestCase()
{

}

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

void TestMneForwardSolution::computeForward()
{
    // Compute and Write Forward Solution
    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Compute/Write/Read MEG/EEG Forward Solution >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    // Read reference forward solution
    QString fwdMEGEEGFileRef("./mne-cpp-test-data/Result/ref-sample_audvis-meg-eeg-oct-6-fwd.fif");
    QFile fileFwdMEGEEGRef(fwdMEGEEGFileRef);
    m_pFwdMEGEEGRef = QSharedPointer<MNEForwardSolution>(new MNEForwardSolution(fileFwdMEGEEGRef));

    //Following is equivalent to:
    //mne_forward_solution
    // --meg
    // --eeg
    // --accurate
    // --src ./mne-cpp-test-data/subjects/sample/bem/sample-oct-6-src.fif
    // --meas ./mne-cpp-test-data/MEG/sample/sample_audvis_raw_short.fif
    // --mri ./mne-cpp-test-data/MEG/sample/all-trans.fif
    // --bem ./mne-cpp-test-data/subjects/sample/bem/sample-1280-1280-1280-bem.fif
    // --mindist 5
    // --fwd ./mne-cpp-test-data/Result/sample_audvis-meg-eeg-oct-6-fwd.fif

    ComputeFwdSettings settingsMEGEEG;

    settingsMEGEEG.include_meg = true;
    settingsMEGEEG.include_eeg = true;
    settingsMEGEEG.accurate = true;
    settingsMEGEEG.srcname = "./mne-cpp-test-data/subjects/sample/bem/sample-oct-6-src.fif";
    settingsMEGEEG.measname = "./mne-cpp-test-data/MEG/sample/sample_audvis_raw_short.fif";
    settingsMEGEEG.mriname = "./mne-cpp-test-data/MEG/sample/all-trans.fif";
    settingsMEGEEG.transname.clear();
    settingsMEGEEG.bemname = "./mne-cpp-test-data/subjects/sample/bem/sample-1280-1280-1280-bem.fif";
    settingsMEGEEG.mindist = 5.0f/1000.0f;
    settingsMEGEEG.solname = "./mne-cpp-test-data/Result/sample_audvis-meg-eeg-oct-6-fwd.fif";

    settingsMEGEEG.checkIntegrity();

    QSharedPointer<ComputeFwd> pFwdMEGEEGComputed = QSharedPointer<ComputeFwd>(new ComputeFwd(&settingsMEGEEG));
    pFwdMEGEEGComputed->calculateFwd();

    // Read newly created fwd
    QFile fileFwdMEGEEGRead(settingsMEGEEG.solname);
    m_pFwdMEGEEGRead = QSharedPointer<MNEForwardSolution>(new MNEForwardSolution(fileFwdMEGEEGRead));

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Compute/Write/Read MEG/EEG Forward Solution Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

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

void TestMneForwardSolution::compareForward()
{
    printf(">>>>>>>>>>>>>>>>>>>>>>>>> Compare MEG/EEG Forward Solution >>>>>>>>>>>>>>>>>>>>>>>>>\n");

    // The following is equal to QVERIFY(*m_pFwdMEGEEGRead == *m_pFwdMEGEEGRef);
    // This just gives more inforamtion on what might be wrong if failing
    QVERIFY(m_pFwdMEGEEGRead->info == m_pFwdMEGEEGRef->info);
    QVERIFY(m_pFwdMEGEEGRead->source_ori == m_pFwdMEGEEGRef->source_ori);
    QVERIFY(m_pFwdMEGEEGRead->surf_ori == m_pFwdMEGEEGRef->surf_ori);
    QVERIFY(m_pFwdMEGEEGRead->coord_frame == m_pFwdMEGEEGRef->coord_frame);
    QVERIFY(m_pFwdMEGEEGRead->nsource == m_pFwdMEGEEGRef->nsource);
    QVERIFY(m_pFwdMEGEEGRead->nchan == m_pFwdMEGEEGRef->nchan);
    QVERIFY(*m_pFwdMEGEEGRead->sol == *m_pFwdMEGEEGRef->sol);
    QVERIFY(*m_pFwdMEGEEGRead->sol_grad == *m_pFwdMEGEEGRef->sol_grad);
    QVERIFY(m_pFwdMEGEEGRead->mri_head_t == m_pFwdMEGEEGRef->mri_head_t);
    //m_pFwdMEGEEGRead->src == m_pFwdMEGEEGRef->src);
    QVERIFY(m_pFwdMEGEEGRead->source_rr == m_pFwdMEGEEGRef->source_rr);
    QVERIFY(m_pFwdMEGEEGRead->source_nn == m_pFwdMEGEEGRef->source_nn);

    printf("<<<<<<<<<<<<<<<<<<<<<<<<< Compare MEG/EEG Forward Solution Finished <<<<<<<<<<<<<<<<<<<<<<<<<\n");
}

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

void TestMneForwardSolution::cleanupTestCase()
{
}

//*************************************************************************************************************
//=============================================================================================================
// MAIN
//=============================================================================================================

QTEST_APPLESS_MAIN(TestMneForwardSolution)
#include "test_mne_forward_solution.moc"
<|endoftext|>