changeset 80:f40a78cc7070 wasm

Oracle
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 24 May 2017 22:33:20 +0200
parents 4e21f6b3aa0d
children 8677d95753f8
files Framework/Toolbox/IWebService.h Framework/Toolbox/OrthancAsynchronousWebService.h Framework/Toolbox/OrthancSynchronousWebService.h Platforms/Generic/IOracleCommand.h Platforms/Generic/Oracle.cpp Platforms/Generic/Oracle.h Platforms/Generic/OracleWebService.h Platforms/Generic/WebServiceGetCommand.cpp Platforms/Generic/WebServiceGetCommand.h Platforms/Generic/WebServicePostCommand.cpp Platforms/Generic/WebServicePostCommand.h Resources/CMake/OrthancStone.cmake UnitTestsSources/UnitTestsMain.cpp
diffstat 13 files changed, 612 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/Framework/Toolbox/IWebService.h	Wed May 24 21:23:29 2017 +0200
+++ b/Framework/Toolbox/IWebService.h	Wed May 24 22:33:20 2017 +0200
@@ -58,9 +58,5 @@
                                      const std::string& uri,
                                      const std::string& body,
                                      Orthanc::IDynamicObject* payload) = 0;
-
-    virtual void Start() = 0;
-    
-    virtual void Stop() = 0;
   };
 }
--- a/Framework/Toolbox/OrthancAsynchronousWebService.h	Wed May 24 21:23:29 2017 +0200
+++ b/Framework/Toolbox/OrthancAsynchronousWebService.h	Wed May 24 22:33:20 2017 +0200
@@ -50,8 +50,8 @@
                                      const std::string& body,
                                      Orthanc::IDynamicObject* payload);
 
-    virtual void Start();
+    void Start();
 
-    virtual void Stop();
+    void Stop();
   };
 }
--- a/Framework/Toolbox/OrthancSynchronousWebService.h	Wed May 24 21:23:29 2017 +0200
+++ b/Framework/Toolbox/OrthancSynchronousWebService.h	Wed May 24 22:33:20 2017 +0200
@@ -54,13 +54,5 @@
                                      const std::string& uri,
                                      const std::string& body,
                                      Orthanc::IDynamicObject* payload);
-
-    virtual void Start()
-    {
-    }
-
-    virtual void Stop()
-    {
-    }
   };
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/IOracleCommand.h	Wed May 24 22:33:20 2017 +0200
@@ -0,0 +1,42 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017 Osimis, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "../../Resources/Orthanc/Core/IDynamicObject.h"
+
+namespace OrthancStone
+{
+  class IOracleCommand : public Orthanc::IDynamicObject
+  {
+  public:
+    virtual ~IOracleCommand()
+    {
+    }
+
+    // This part of the command can be invoked simultaneously, and
+    // must not modify the Stone context
+    virtual void Execute() = 0;
+
+    // This part of the command must be invoked in mutual exclusion
+    virtual void Commit() = 0;
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/Oracle.cpp	Wed May 24 22:33:20 2017 +0200
@@ -0,0 +1,208 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017 Osimis, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "Oracle.h"
+
+#include "../../Resources/Orthanc/Core/Logging.h"
+#include "../../Resources/Orthanc/Core/MultiThreading/SharedMessageQueue.h"
+#include "../../Resources/Orthanc/Core/OrthancException.h"
+
+#include <vector>
+
+namespace OrthancStone
+{
+  class Oracle::PImpl
+  {
+  private:
+    enum State
+    {
+      State_Init,
+      State_Started,
+      State_Stopped
+    };
+
+    boost::mutex*                  globalMutex_;
+    boost::mutex                   oracleMutex_;
+    State                          state_;
+    std::vector<boost::thread*>    threads_;
+    Orthanc::SharedMessageQueue    queue_;
+
+    static void Worker(PImpl* that)
+    {
+      for (;;)
+      {
+        State state;
+        
+        {
+          boost::mutex::scoped_lock lock(that->oracleMutex_);
+          state = that->state_;
+        }
+
+        if (state == State_Stopped)
+        {
+          break;
+        }
+
+        std::auto_ptr<Orthanc::IDynamicObject> item(that->queue_.Dequeue(100));
+        if (item.get() != NULL)
+        {
+          IOracleCommand& command = dynamic_cast<IOracleCommand&>(*item);
+          command.Execute();
+
+          if (that->globalMutex_ != NULL)
+          {
+            boost::mutex::scoped_lock lock(*that->globalMutex_);
+            command.Commit();
+          }
+          else
+          {
+            command.Commit();
+          }
+        }
+      }
+    }
+    
+  public:
+    PImpl(boost::mutex* globalMutex,
+          unsigned int threadCount) :
+      globalMutex_(globalMutex),
+      state_(State_Init),
+      threads_(threadCount)
+    {
+    }
+
+    ~PImpl()
+    {
+      if (state_ == State_Started)
+      {
+        LOG(ERROR) << "You should have manually called Oracle::Stop()";
+        Stop();
+      }
+    }
+
+    void Submit(IOracleCommand* command)
+    {
+      std::auto_ptr<IOracleCommand> protection(command);
+
+      if (command == NULL)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_NullPointer);
+      }
+      
+      boost::mutex::scoped_lock lock(oracleMutex_);
+
+      switch (state_)
+      {
+        case State_Init:
+          LOG(ERROR) << "You must call Oracle::Start()";
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+
+        case State_Started:
+          queue_.Enqueue(protection.release());
+          break;
+
+        case State_Stopped:
+          LOG(ERROR) << "Cannot schedule a request to the Oracle after having "
+                     << "called Oracle::Stop()";
+          break;
+
+        default:
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_InternalError);
+      }
+      
+    }
+
+    void Start()
+    {
+      boost::mutex::scoped_lock lock(oracleMutex_);
+
+      if (state_ != State_Init)
+      {
+        throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+      }
+      
+      for (size_t i = 0; i < threads_.size(); i++)
+      {
+        threads_[i] = new boost::thread(Worker, this);
+      }
+
+      state_ = State_Started;
+    }
+
+    void Stop()
+    {
+      {
+        boost::mutex::scoped_lock lock(oracleMutex_);
+
+        if (state_ != State_Started)
+        {
+          throw Orthanc::OrthancException(Orthanc::ErrorCode_BadSequenceOfCalls);
+        }
+
+        state_ = State_Stopped;
+      }
+      
+      for (size_t i = 0; i < threads_.size(); i++)
+      {
+        if (threads_[i] != NULL)
+        {
+          if (threads_[i]->joinable())
+          {
+            threads_[i]->join();
+          }
+
+          delete threads_[i];
+        }
+      }
+    }
+  };
+  
+
+  Oracle::Oracle(boost::mutex& globalMutex,
+                 unsigned int threadCount) :
+    pimpl_(new PImpl(&globalMutex, threadCount))
+  {
+  }
+
+
+  Oracle::Oracle(unsigned int threadCount) :
+    pimpl_(new PImpl(NULL, threadCount))
+  {
+  }
+
+
+  void Oracle::Start()
+  {
+    pimpl_->Start();
+  }
+
+
+  void Oracle::Submit(IOracleCommand* command)
+  {
+    pimpl_->Submit(command);
+  }
+     
+   
+  void Oracle::Stop()
+  {
+    pimpl_->Stop();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/Oracle.h	Wed May 24 22:33:20 2017 +0200
@@ -0,0 +1,50 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017 Osimis, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IOracleCommand.h"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/mutex.hpp>
+
+namespace OrthancStone
+{
+  class Oracle : public boost::noncopyable
+  {
+  private:
+    class PImpl;
+  
+    boost::shared_ptr<PImpl>  pimpl_;
+
+  public:
+    Oracle(boost::mutex& globalMutex,
+           unsigned int threadCount);
+
+    Oracle(unsigned int threadCount);
+
+    void Start();
+
+    void Submit(IOracleCommand* command);
+        
+    void Stop();
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/OracleWebService.h	Wed May 24 22:33:20 2017 +0200
@@ -0,0 +1,60 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017 Osimis, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "../../Framework/Toolbox/IWebService.h"
+#include "Oracle.h"
+#include "WebServiceGetCommand.h"
+#include "WebServicePostCommand.h"
+
+namespace OrthancStone
+{
+  class OracleWebService : public IWebService
+  {
+  private:
+    Oracle&                        oracle_;
+    Orthanc::WebServiceParameters  parameters_;
+
+  public:
+    OracleWebService(Oracle& oracle,
+                     const Orthanc::WebServiceParameters& parameters) : 
+      oracle_(oracle),
+      parameters_(parameters)
+    {
+    }
+
+    virtual void ScheduleGetRequest(ICallback& callback,
+                                    const std::string& uri,
+                                    Orthanc::IDynamicObject* payload)
+    {
+      oracle_.Submit(new WebServiceGetCommand(callback, parameters_, uri, payload));
+    }
+
+    virtual void SchedulePostRequest(ICallback& callback,
+                                     const std::string& uri,
+                                     const std::string& body,
+                                     Orthanc::IDynamicObject* payload)
+    {
+      oracle_.Submit(new WebServicePostCommand(callback, parameters_, uri, body, payload));
+    }
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/WebServiceGetCommand.cpp	Wed May 24 22:33:20 2017 +0200
@@ -0,0 +1,59 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017 Osimis, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "WebServiceGetCommand.h"
+
+#include "../../Resources/Orthanc/Core/HttpClient.h"
+
+namespace OrthancStone
+{
+  WebServiceGetCommand::WebServiceGetCommand(IWebService::ICallback& callback,
+                                             const Orthanc::WebServiceParameters& parameters,
+                                             const std::string& uri,
+                                             Orthanc::IDynamicObject* payload /* takes ownership */) :
+    callback_(callback),
+    parameters_(parameters),
+    uri_(uri),
+    payload_(payload)
+  {
+  }
+
+
+  void WebServiceGetCommand::Execute()
+  {
+    Orthanc::HttpClient client(parameters_, uri_);
+    client.SetMethod(Orthanc::HttpMethod_Get);
+    success_ = client.Apply(answer_);
+  }
+
+
+  void WebServiceGetCommand::Commit()
+  {
+    if (success_)
+    {
+      callback_.NotifySuccess(uri_, answer_.c_str(), answer_.size(), payload_.release());
+    }
+    else
+    {
+      callback_.NotifyError(uri_, payload_.release());
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/WebServiceGetCommand.h	Wed May 24 22:33:20 2017 +0200
@@ -0,0 +1,53 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017 Osimis, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IOracleCommand.h"
+
+#include "../../Framework/Toolbox/IWebService.h"
+#include "../../Resources/Orthanc/Core/WebServiceParameters.h"
+
+#include <memory>
+
+namespace OrthancStone
+{
+  class WebServiceGetCommand : public IOracleCommand
+  {
+  private:
+    IWebService::ICallback&                 callback_;
+    Orthanc::WebServiceParameters           parameters_;
+    std::string                             uri_;
+    std::auto_ptr<Orthanc::IDynamicObject>  payload_;
+    bool                                    success_;
+    std::string                             answer_;
+
+  public:
+    WebServiceGetCommand(IWebService::ICallback& callback,
+                         const Orthanc::WebServiceParameters& parameters,
+                         const std::string& uri,
+                         Orthanc::IDynamicObject* payload /* takes ownership */);
+
+    virtual void Execute();
+
+    virtual void Commit();
+  };
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/WebServicePostCommand.cpp	Wed May 24 22:33:20 2017 +0200
@@ -0,0 +1,60 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017 Osimis, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#include "WebServicePostCommand.h"
+
+#include "../../Resources/Orthanc/Core/HttpClient.h"
+
+namespace OrthancStone
+{
+  WebServicePostCommand::WebServicePostCommand(IWebService::ICallback& callback,
+                                               const Orthanc::WebServiceParameters& parameters,
+                                               const std::string& uri,
+                                               const std::string& body,
+                                               Orthanc::IDynamicObject* payload /* takes ownership */) :
+    callback_(callback),
+    parameters_(parameters),
+    uri_(uri),
+    body_(body),
+    payload_(payload)
+  {
+  }
+
+  void WebServicePostCommand::Execute()
+  {
+    Orthanc::HttpClient client(parameters_, uri_);
+    client.SetMethod(Orthanc::HttpMethod_Post);
+    client.GetBody().swap(body_);
+    success_ = client.Apply(answer_);
+  }
+
+  void WebServicePostCommand::Commit()
+  {
+    if (success_)
+    {
+      callback_.NotifySuccess(uri_, answer_.c_str(), answer_.size(), payload_.release());
+    }
+    else
+    {
+      callback_.NotifyError(uri_, payload_.release());
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Platforms/Generic/WebServicePostCommand.h	Wed May 24 22:33:20 2017 +0200
@@ -0,0 +1,55 @@
+/**
+ * Stone of Orthanc
+ * Copyright (C) 2012-2016 Sebastien Jodogne, Medical Physics
+ * Department, University Hospital of Liege, Belgium
+ * Copyright (C) 2017 Osimis, Belgium
+ *
+ * This program is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU Affero General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Affero General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ **/
+
+
+#pragma once
+
+#include "IOracleCommand.h"
+
+#include "../../Framework/Toolbox/IWebService.h"
+#include "../../Resources/Orthanc/Core/WebServiceParameters.h"
+
+#include <memory>
+
+namespace OrthancStone
+{
+  class WebServicePostCommand : public IOracleCommand
+  {
+  private:
+    IWebService::ICallback&                 callback_;
+    Orthanc::WebServiceParameters           parameters_;
+    std::string                             uri_;
+    std::string                             body_;
+    std::auto_ptr<Orthanc::IDynamicObject>  payload_;
+    bool                                    success_;
+    std::string                             answer_;
+
+  public:
+    WebServicePostCommand(IWebService::ICallback& callback,
+                          const Orthanc::WebServiceParameters& parameters,
+                          const std::string& uri,
+                          const std::string& body,
+                          Orthanc::IDynamicObject* payload /* takes ownership */);
+
+    virtual void Execute();
+
+    virtual void Commit();
+  };
+}
--- a/Resources/CMake/OrthancStone.cmake	Wed May 24 21:23:29 2017 +0200
+++ b/Resources/CMake/OrthancStone.cmake	Wed May 24 22:33:20 2017 +0200
@@ -175,6 +175,12 @@
 ## All the source files required to build Stone of Orthanc
 #####################################################################
 
+set(PLATFORM_SOURCES
+  ${ORTHANC_STONE_DIR}/Platforms/Generic/WebServiceGetCommand.cpp
+  ${ORTHANC_STONE_DIR}/Platforms/Generic/WebServicePostCommand.cpp
+  ${ORTHANC_STONE_DIR}/Platforms/Generic/Oracle.cpp
+  )
+
 list(APPEND ORTHANC_STONE_SOURCES
   ${ORTHANC_STONE_DIR}/Applications/BasicApplicationContext.cpp
   ${ORTHANC_STONE_DIR}/Applications/IBasicApplication.cpp
@@ -229,6 +235,8 @@
   ${ORTHANC_STONE_DIR}/Framework/Widgets/LayerWidget.cpp
   ${ORTHANC_STONE_DIR}/Framework/Widgets/WorldSceneWidget.cpp
 
+  ${PLATFORM_SOURCES}
+
   ${ORTHANC_ROOT}/Core/ChunkedBuffer.cpp
   ${ORTHANC_ROOT}/Core/Compression/DeflateBaseCompressor.cpp
   ${ORTHANC_ROOT}/Core/Compression/GzipCompressor.cpp
--- a/UnitTestsSources/UnitTestsMain.cpp	Wed May 24 21:23:29 2017 +0200
+++ b/UnitTestsSources/UnitTestsMain.cpp	Wed May 24 22:33:20 2017 +0200
@@ -21,9 +21,13 @@
 
 #include "gtest/gtest.h"
 
+#include "../Platforms/Generic/OracleWebService.h"
 #include "../Framework/Toolbox/OrthancAsynchronousWebService.h"
 #include "../Framework/Toolbox/OrthancSlicesLoader.h"
+#include "../Resources/Orthanc/Core/HttpClient.h"
 #include "../Resources/Orthanc/Core/Logging.h"
+#include "../Resources/Orthanc/Core/MultiThreading/SharedMessageQueue.h"
+#include "../Resources/Orthanc/Core/OrthancException.h"
 
 #include <boost/lexical_cast.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
@@ -36,7 +40,7 @@
   public:
     virtual void NotifyGeometryReady(const OrthancSlicesLoader& loader)
     {
-      printf(">> %d\n", loader.GetSliceCount());
+      printf(">> %d\n", (int) loader.GetSliceCount());
 
       for (size_t i = 0; i < loader.GetSliceCount(); i++)
       {
@@ -70,23 +74,28 @@
 
 TEST(Toto, Tutu)
 {
+  OrthancStone::Oracle oracle(4);
+  oracle.Start();
+
   Orthanc::WebServiceParameters web;
-  OrthancStone::OrthancAsynchronousWebService orthanc(web, 4);
-  orthanc.Start();
+  //OrthancStone::OrthancAsynchronousWebService orthanc(web, 4);
+  OrthancStone::OracleWebService orthanc(oracle, web);
+  //orthanc.Start();
 
   OrthancStone::Tata tata;
   OrthancStone::OrthancSlicesLoader loader(tata, orthanc);
-  //loader.ScheduleLoadSeries("c1c4cb95-05e3bd11-8da9f5bb-87278f71-0b2b43f5");
+  loader.ScheduleLoadSeries("c1c4cb95-05e3bd11-8da9f5bb-87278f71-0b2b43f5");
   //loader.ScheduleLoadSeries("67f1b334-02c16752-45026e40-a5b60b6b-030ecab5");
 
-  loader.ScheduleLoadInstance("19816330-cb02e1cf-df3a8fe8-bf510623-ccefe9f5", 0);
+  //loader.ScheduleLoadInstance("19816330-cb02e1cf-df3a8fe8-bf510623-ccefe9f5", 0);
 
   /*printf(">> %d\n", loader.GetSliceCount());
     loader.ScheduleLoadSliceImage(31);*/
 
   boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
 
-  orthanc.Stop();
+  //orthanc.Stop();
+  oracle.Stop();
 }