NCBI C++ ToolKit
project_service_test.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: project_service_test.cpp 46071 2021-01-21 19:47:46Z grichenk $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Andrey Yazhuk
27  *
28  */
29 
30 #include <ncbi_pch.hpp>
31 #include <corelib/ncbifile.hpp>
32 
35 #include <gui/core/document.hpp>
36 
41 
42 #include <objects/general/Date.hpp>
43 
45 
46 #include <corelib/ncbi_system.hpp>
47 
48 #include <serial/iterator.hpp>
49 
50 
53 
55 : CAppTask("Project Service Concurrency Test", true),
56  m_SrvLocator(srv_locator),
57  m_Service(NULL)
58 {
60 
62 }
63 
64 
66 {
67 }
68 
69 
71 {
72  LOG_POST(Info << "CProjectServiceTestTask::x_Run() - BEGIN");
73 
75 
77 
79  disp.StartJob(*job, "ThreadPool");
80 
82  disp.StartJob(*job, "ThreadPool");
83 
85  disp.StartJob(*job, "ThreadPool");
86 
88  disp.StartJob(*job, "ThreadPool");
89 
90  LOG_POST(Info << "CProjectServiceTestTask::x_Run() - BEGIN(completed)");
91  return eCompleted;
92 }
93 
94 
95 ///////////////////////////////////////////////////////////////////////////////
96 /// CProjectServiceTestJob
97 
99  EType Type, int sleep_ms)
100 : CAppJob(),
101  m_ProjectService(service),
102  m_Type(Type),
103  m_SleepMs(sleep_ms)
104 {
105  string sType;
106 
107  switch(m_Type) {
108  case eCreateItems:
109  sType = "eCreateItems";
110  break;
111 
112  case eModifyItems:
113  sType = "eModifyItems";
114  break;
115 
116  case eDeleteItems:
117  sType = "eDeleteItems";
118  break;
119 
120  case ePrintItems:
121  sType = "ePrintItems";
122  break;
123  }
124 
125  m_Descr = "Test Job - " + sType;
126 }
127 
128 
130 {
131  static const char* kLogMsg = "CProjectServiceTestJob::Run() - exception in x_Run() ";
132  static string kErrorMsg = "Unhandled exception in CProjectServiceTestJob::Run()";
133 
134  x_ResetState(); // reset state before execution
135 
136  string err_msg;
137  try {
138  while(true) {
139  if (IsCanceled())
140  break;
141 
142  LOG_POST(Info << m_Descr << " - now working ");
143 
144  switch(m_Type) {
145  case eCreateItems:
146  x_CreateItems();
147  break;
148 
149  case eModifyItems:
150  x_ModifyItems();
151  break;
152 
153  case eDeleteItems:
154  x_DeleteItems();
155  break;
156 
157  case ePrintItems:
158  x_PrintItems();
159  break;
160 
161  default:
162  _ASSERT(false); //unsupported
163  }
164 
165  LOG_POST(Info << m_Descr << " - sleeping for " << m_SleepMs << " ms");
167  }
168  } catch (CException& e) {
169  err_msg = kLogMsg + GetDescr() + ". " + e.GetMsg();
170  LOG_POST(Error << err_msg);
171  LOG_POST(Error << e.ReportAll());
172  }
173 
174  CFastMutexGuard lock(m_Mutex);
175 
176  if(err_msg.empty()) {
177  return eCompleted;
178  } else {
179  string s = kErrorMsg + err_msg;
180  m_Error.Reset(new CAppJobError(s));
181  return eFailed;
182  }
183 }
184 
185 static vector<int> s_GetProjectIds(const CWorkspaceFolder& folder)
186 {
187  vector<int> projectIds;
188  for (CTypeConstIterator<CGBProjectHandle> it(folder); it; ++it) {
189  const CGBDocument* doc = dynamic_cast<const CGBDocument*>(&*it);
190  if (doc && doc->IsLoaded()) {
191  projectIds.push_back(doc->GetId());
192  }
193  }
194  return projectIds;
195 }
196 
198 {
199  CGBProject_ver2* prj_obj = new CGBProject_ver2();
200  CRef<CGBDocument> doc(new CGBDocument(srv, CGBDocument::GetNextId(), *prj_obj));
201  doc->CreateProjectScope();
202 
203  string new_name = ws.MakeUniqueProjectTitle("New Project");
204  doc->SetDescr().SetTitle(new_name);
205  CTime now(CTime::eCurrent);
206 
207  CDate date(now);
208  doc->SetCreateDate(date);
209  doc->SetModifiedDate(date);
210 
211  ws.SetWorkspace().AddProject(*doc);
212  ws.SetDirty(true);
213 
214  srv->x_OnProjectChanged(doc->GetId());
215  srv->x_OnWorkspaceChanged(ws.GetId());
216 
217  return doc;
218 }
219 
220 
222 {
223  static int item_counter = 0;
224 
225  unique_ptr<ILocked> lock = m_ProjectService->GetWorkspaceLock();
226  lock->GetLock();
227 
228  LOG_POST(Info << m_Descr << " get Write lock for Workspace and Projects");
229 
231  if (!ws) {
232  LOG_POST(Info << m_Descr << " failed - no workspace");
233  return;
234  }
235 
236  CWorkspaceFolder& root_folder = ws->SetWorkspace();
237 
238  vector<int> projectIds = s_GetProjectIds(root_folder);
239 
240  if (projectIds.empty()) {
241  LOG_POST(Info << "Creating a new project ...");
243  s_GetProjectIds(root_folder);
244  LOG_POST(Info << "Creating a new project ... Done");
245  }
246 
247  for (size_t i = 0; i < projectIds.size(); i++) {
248  CGBDocument* doc = dynamic_cast<CGBDocument*>(ws->GetProjectFromId(projectIds[i]));
249  if (!doc) continue;
250 
251  CProjectFolder& data_folder = doc->SetData();
252 
253  static int kItemsN = 2;
254  LOG_POST(Info << "Creating " << kItemsN << " items in project " << doc->GetDescr().GetTitle());
255 
256  for( int j = 0; j < kItemsN; j++ ) {
257  CRef<objects::CSeq_id> id(new objects::CSeq_id);
258  id->Set("19568015");
259  string label = "Item # " + NStr::IntToString(++item_counter);
260 
261  CRef<CProjectItem> item(new CProjectItem());
262  item->SetLabel(doc->MakeUniqueItemLabel(label));
263  item->SetObject(*id);
264 
265  doc->AddItem(*item, data_folder);
266  doc->AttachProjectItem(item->GetId());
267  }
268  doc->SetDirty( true );
269  doc->x_OnProjectChanged(CProjectViewEvent::eNone);
270  m_ProjectService->x_OnProjectChanged(doc->GetId());
271 
272  LOG_POST(Info << "Items created");
273  }
274  LOG_POST(Info << m_Descr << "Release locks");
275 }
276 
277 
279 {
280  static int pass = 1;
281 
282  unique_ptr<ILocked> lock = m_ProjectService->GetWorkspaceLock();
283  lock->GetLock();
284 
285  LOG_POST(Info << m_Descr << " get READ lock for Workspace and Write for Projects");
286 
288  if (!ws) {
289  LOG_POST(Info << m_Descr << " failed - no workspace");
290  return;
291  }
292 
293  CWorkspaceFolder& root_folder = ws->SetWorkspace();
294 
295  vector<int> projectIds = s_GetProjectIds(root_folder);
296 
297  for (size_t i = 0; i < projectIds.size(); i++) {
298  CGBDocument* doc = dynamic_cast<CGBDocument*>(ws->GetProjectFromId(projectIds[i]));
299  if (!doc) continue;
300  LOG_POST(Info << "Renaming items " << doc->GetDescr().GetTitle());
301 
302  CProjectFolder& data_folder = doc->SetData();
303  if(data_folder.CanGetItems()) {
305  string ver = ": v " + NStr::IntToString(pass);
306 
307  string name;
308  if ((*it)->IsSetLabel())
309  name = (*it)->GetLabel();
310 
311  string::size_type pos = name.find_first_of(':');
312  if(pos != string::npos) {
313  name.resize(pos);
314  }
315  name += ver;
316  (*it)->SetLabel(doc->MakeUniqueItemLabel(name));
317  }
318  }
319 
320  doc->SetDirty( true );
321  doc->x_OnProjectChanged(CProjectViewEvent::eNone);
322  m_ProjectService->x_OnProjectChanged(doc->GetId());
323  }
324 
325  pass++;
326 
327  LOG_POST(Info << m_Descr << "Release locks");
328 }
329 
330 
332 {
333  unique_ptr<ILocked> lock = m_ProjectService->GetWorkspaceLock();
334  lock->GetLock();
335 
336  LOG_POST(Info << m_Descr << " get READ lock for Workspace and Write for Projects");
337 
339  if (!ws) {
340  LOG_POST(Info << m_Descr << " failed - no workspace");
341  return;
342  }
343 
344  CWorkspaceFolder& root_folder = ws->SetWorkspace();
345 
346  vector<int> projectIds = s_GetProjectIds(root_folder);
347 
348  for (size_t i = 0; i < projectIds.size(); i++) {
349  CGBDocument* doc = dynamic_cast<CGBDocument*>(ws->GetProjectFromId(projectIds[i]));
350  if (!doc) continue;
351  LOG_POST(Info << "Deleting items from project " << doc->GetDescr().GetTitle());
352 
353  CProjectFolder& data_folder = doc->SetData();
354  if(data_folder.CanGetItems()) {
355  vector<int> projectItems;
356  ITERATE(CProjectFolder::TItems, it, data_folder.GetItems())
357  projectItems.push_back((*it)->GetId());
358 
359  ITERATE(vector<int>, it, projectItems) {
360  CProjectItem* item = data_folder.FindProjectItemById(*it);
361  if (item) {
362  LOG_POST(Info << "Deleting item " << item->GetLabel());
363  doc->DetachProjectItem(*it);
364  doc->RemoveProjectItem(*it);
365  }
366  }
367  }
368  doc->SetDirty( true );
369  doc->x_OnProjectChanged(CProjectViewEvent::eNone);
370  m_ProjectService->x_OnProjectChanged(doc->GetId());
371  }
372 
373  LOG_POST(Info << m_Descr << "Release locks");
374 }
375 
376 
378 {
379  unique_ptr<ILocked> lock = m_ProjectService->GetWorkspaceLock();
380  lock->GetLock();
381 
382  LOG_POST(Info << m_Descr << " get Read Lock for Workspace and Projects");
383 
385  if (!ws) {
386  LOG_POST(Info << m_Descr << " failed - no workspace");
387  return;
388  }
389 
390  CWorkspaceFolder& root_folder = ws->SetWorkspace();
391 
392  vector<int> projectIds = s_GetProjectIds(root_folder);
393 
394  for (size_t i = 0; i < projectIds.size(); i++) {
395  CGBDocument* doc = dynamic_cast<CGBDocument*>(ws->GetProjectFromId(projectIds[i]));
396  if (!doc) continue;
397  LOG_POST(Info << m_Descr << " printing items in project " << doc->GetDescr().GetTitle());
398 
399  CProjectFolder& data_folder = doc->SetData();
400  if(data_folder.CanGetItems()) {
401  ITERATE(CProjectFolder::TItems, it, data_folder.GetItems()) {
402  LOG_POST(Info << "\t- " << (*it)->GetLabel());
403  }
404  }
405  }
406 
407  LOG_POST(Info << m_Descr << "Release locks");
408 }
409 
410 
412 
User-defined methods of the data storage class.
User-defined methods of the data storage class.
User-defined methods of the data storage class.
#define true
Definition: bool.h:35
CAppJobDispatcher.
CAppJobError Default implementation for IAppJobError - encapsulates a text error message.
CAppJob - default implementation of IAppJob that could be used as a base class.
CAppTask - default implementation of IAppTask, use it as a base class for custom tasks.
Definition: Date.hpp:53
CGBDocument.
Definition: document.hpp:113
void DetachProjectItem(objects::CProjectItem *item)
Definition: document.cpp:780
virtual void CreateProjectScope()
Definition: document.cpp:178
bool RemoveProjectItem(objects::CProjectItem *item)
Definition: document.cpp:736
void AttachProjectItem(objects::CProjectItem *item)
Definition: document.cpp:772
CGBWorkspace.
Definition: GBWorkspace.hpp:63
string MakeUniqueProjectTitle(const string &label) const
Create a unique label for a project.
CProjectItem * FindProjectItemById(CProjectItem::TId id)
void SetObject(CSerialObject &object)
wrapper for setting the object pointed to by this item
CProjectServiceTestJob.
CProjectServiceTestJob(CProjectService *service, EType type, int sleep_ms)
CProjectServiceTestJob.
CProjectService * m_ProjectService
virtual EJobState Run()
Function that does all the useful work, called by the Engine.
IServiceLocator * m_SrvLocator
overriding CAppTask::x_Run()
CProjectServiceTestTask(IServiceLocator *srv_locator)
virtual ETaskState x_Run()
override this function in derived classes
CProjectService - a service providing API for operations with Workspaces and Projects.
CRef< objects::CGBWorkspace > GetGBWorkspace()
CTime –.
Definition: ncbitime.hpp:296
Template class for iteration on objects of class C (non-medifiable version)
Definition: iterator.hpp:767
IServiceLocator - an abstract mechanism for locating services.
Definition: service.hpp:71
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
#define NULL
Definition: ncbistd.hpp:225
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Error(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1197
const string & GetMsg(void) const
Get message string.
Definition: ncbiexpt.cpp:461
string ReportAll(TDiagPostFlags flags=eDPF_Exception) const
Report all exceptions.
Definition: ncbiexpt.cpp:370
void Info(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1185
CIRef< T > GetServiceByType()
retrieves a typed reference to a service, the name of C++ type is used as the name of the service.
Definition: service.hpp:91
ETaskState
List of task states defining the task management FSM.
Definition: app_task.hpp:87
@ eCompleted
successfully finished
Definition: app_task.hpp:92
CRef< CAppJobError > m_Error
string m_Descr
mutex to sync our internals
static CAppJobDispatcher & GetInstance()
virtual void x_ResetState()
virtual bool IsCanceled() const override
CFastMutex m_Mutex
EJobState
Job states (describe FSM)
Definition: app_job.hpp:86
TJobID StartJob(IAppJob &job, const string &engine_name, IEngineParams *params=NULL)
Starts a Job on the specified engine in "passive mode" - no notifications or progress reports will be...
virtual string GetDescr() const override
Returns a human readable description of the Job (optional)
@ eCompleted
Definition: app_job.hpp:89
@ eFailed
Definition: app_job.hpp:90
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5083
@ eCurrent
Use current time. See also CCurrentTime.
Definition: ncbitime.hpp:300
static const char label[]
list< CRef< CProjectItem > > TItems
void SetLabel(const TLabel &value)
Assign a value to Label data member.
TId GetId(void) const
Get the Id member data.
const TLabel & GetLabel(void) const
Get the Label member data.
bool CanGetItems(void) const
Check if it is safe to call GetItems method.
const TItems & GetItems(void) const
Get the Items member data.
TItems & SetItems(void)
Assign a value to Items data member.
void SetWorkspace(TWorkspace &value)
Assign a value to Workspace data member.
int i
void SleepMilliSec(unsigned long ml_sec, EInterruptOnSignal onsignal=eRestartOnSignal)
Defines classes: CDirEntry, CFile, CDir, CSymLink, CMemoryFile, CFileUtil, CFileLock,...
USING_SCOPE(objects)
static CRef< CGBDocument > s_CreateNewProject(CProjectService *srv, CGBWorkspace &ws)
static vector< int > s_GetProjectIds(const CWorkspaceFolder &folder)
#define _ASSERT
#define Type
Modified on Sat Dec 02 09:19:36 2023 by modify_doxy.py rev. 669887