OpenCPN Partial API docs
Loading...
Searching...
No Matches
senc_manager.cpp
Go to the documentation of this file.
1/**************************************************************************
2 * Copyright (C) 2010 by David S. Register *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, see <https://www.gnu.org/licenses/>. *
16 **************************************************************************/
17
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26#ifndef WX_PRECOMP
27#include "wx/wx.h"
28#endif
29
30#include "senc_manager.h"
31
32#include "model/config_vars.h"
33
34#include "s57chart.h"
35#include "o_senc.h"
36#include "chartbase.h"
37#include "chcanv.h"
38#include "s57class_registrar.h"
39#include "top_frame.h"
40
42
43//----------------------------------------------------------------------------------
44// SENCJobTicket Implementation
45//----------------------------------------------------------------------------------
46SENCJobTicket::SENCJobTicket() {
47 m_SENCResult = SENC_BUILD_INACTIVE;
48 m_status = THREAD_INACTIVE;
49}
50
51const wxEventType wxEVT_OCPN_BUILDSENCTHREAD = wxNewEventType();
52
53//----------------------------------------------------------------------------------
54// OCPN_BUILDSENC_ThreadEvent Implementation
55//----------------------------------------------------------------------------------
56OCPN_BUILDSENC_ThreadEvent::OCPN_BUILDSENC_ThreadEvent(wxEventType commandType,
57 int id)
58 : wxEvent(id, commandType) {
59 stat = 0;
60}
61
62OCPN_BUILDSENC_ThreadEvent::~OCPN_BUILDSENC_ThreadEvent() {}
63
64wxEvent *OCPN_BUILDSENC_ThreadEvent::Clone() const {
66 newevent->stat = this->stat;
67 newevent->type = this->type;
68 newevent->m_ticket = this->m_ticket;
69
70 return newevent;
71}
72
73//----------------------------------------------------------------------------------
74// SENCThreadManager Implementation
75//----------------------------------------------------------------------------------
76SENCThreadManager::SENCThreadManager() {
77 // ideally we would use the cpu count -1, and only launch jobs
78 // when the idle load average is sufficient (greater than 1)
79 int nCPU = wxMax(1, wxThread::GetCPUCount());
80 if (g_nCPUCount > 0) nCPU = g_nCPUCount;
81
82 // obviously there's at least one CPU!
83 if (nCPU < 1) nCPU = 1;
84
85 m_max_jobs = wxMax(nCPU - 1, 1);
86 // m_max_jobs = 1;
87
88 wxLogDebug("SENC: nCPU: %d m_max_jobs :%d\n", nCPU, m_max_jobs);
89
90 // Create/connect a dynamic event handler slot for messages from the worker
91 // threads
92 Connect(
94 (wxObjectEventFunction)(wxEventFunction)&SENCThreadManager::OnEvtThread);
95
96 // m_timer.Connect(wxEVT_TIMER, wxTimerEventHandler(
97 // glTextureManager::OnTimer ), NULL, this); m_timer.Start(500);
98}
99
100SENCThreadManager::~SENCThreadManager() {
101 // ClearJobList();
102}
103
104SENCThreadStatus SENCThreadManager::ScheduleJob(SENCJobTicket *ticket) {
105 // Do not add a job if there is already a job pending for this chart, by name
106 for (size_t i = 0; i < ticket_list.size(); i++) {
107 if (ticket_list[i]->m_FullPath000 == ticket->m_FullPath000)
108 return THREAD_PENDING;
109 }
110
111 ticket->m_status = THREAD_PENDING;
112 ticket_list.push_back(ticket);
113
114 // printf("Scheduling job: %s\n", (const
115 // char*)ticket->m_FullPath000.mb_str()); printf("Job count: %d\n",
116 // ticket_list.size());
117 StartTopJob();
118 return THREAD_PENDING;
119}
120
121void SENCThreadManager::StartTopJob() {
122 SENCJobTicket *startCandidate;
123 // Get the running job count
124 int nRunning = 0;
125 for (size_t i = 0; i < ticket_list.size(); i++) {
126 if (ticket_list[i]->m_status == THREAD_STARTED) nRunning++;
127 }
128
129 // OK to start one?
130 if (nRunning < m_max_jobs) {
131 // Find the first eligible
132 startCandidate = NULL;
133 for (size_t i = 0; i < ticket_list.size(); i++) {
134 if (ticket_list[i]->m_status == THREAD_PENDING) {
135 startCandidate = ticket_list[i];
136 break;
137 }
138 }
139
140 // Found one?
141 if (startCandidate) {
142 // printf("Starting job: %s\n", (const
143 // char*)startCandidate->m_FullPath000.mb_str());
144
145 SENCBuildThread *thread = new SENCBuildThread(startCandidate, this);
146 startCandidate->m_thread = thread;
147 startCandidate->m_status = THREAD_STARTED;
148 thread->SetPriority(20);
149 thread->Run();
150 nRunning++;
151 }
152 }
153
154 if (nRunning) {
155 wxString count;
156 count.Printf(" %ld", ticket_list.size());
157 top_frame::Get()->SetAlertString(_("Preparing vector chart ") + count);
158 }
159}
160
161void SENCThreadManager::FinishJob(SENCJobTicket *ticket) {
162 // printf("Finishing job: %s\n", (const
163 // char*)ticket->m_FullPath000.mb_str());
164
165 // Find and remove the ticket from the list
166 for (size_t i = 0; i < ticket_list.size(); i++) {
167 if (ticket_list[i] == ticket) {
168 // printf(" Removing job: %s\n", (const
169 // char*)ticket->m_FullPath000.mb_str());
170
171 ticket_list.erase(ticket_list.begin() + i);
172 // printf("Job count: %d\n", ticket_list.size());
173
174 break;
175 }
176 }
177
178#if 1
179 int nRunning = 0;
180 for (size_t i = 0; i < ticket_list.size(); i++) {
181 if (ticket_list[i]->m_status == THREAD_STARTED) nRunning++;
182 }
183
184 if (nRunning) {
185 wxString count;
186 count.Printf(" %ld", ticket_list.size());
187 top_frame::Get()->SetAlertString(_("Preparing vector chart ") + count);
188 } else {
189 top_frame::Get()->SetAlertString("");
190 }
191#endif
192}
193
194int SENCThreadManager::GetJobCount() { return ticket_list.size(); }
195
196bool SENCThreadManager::IsChartInTicketlist(s57chart *chart) {
197 for (size_t i = 0; i < ticket_list.size(); i++) {
198 if (ticket_list[i]->m_chart == chart) return true;
199 }
200 return false;
201}
202
203bool SENCThreadManager::SetChartPointer(s57chart *chart, void *new_ptr) {
204 // Find the ticket
205 for (size_t i = 0; i < ticket_list.size(); i++) {
206 if (ticket_list[i]->m_chart == chart) {
207 ticket_list[i]->m_chart = (s57chart *)new_ptr;
208 return true;
209 }
210 }
211 return false;
212}
213
214#define NBAR_LENGTH 40
215
216void SENCThreadManager::OnEvtThread(OCPN_BUILDSENC_ThreadEvent &event) {
218
219 switch (event.type) {
220 case SENC_BUILD_STARTED:
221 // printf("SENC build started\n");
222 Sevent.type = SENC_BUILD_STARTED;
223 Sevent.m_ticket = event.m_ticket;
224
225 break;
226 case SENC_BUILD_DONE_NOERROR:
227 // printf("SENC build done no error\n");
228 Sevent.type = SENC_BUILD_DONE_NOERROR;
229 Sevent.m_ticket = event.m_ticket;
230 FinishJob(event.m_ticket);
231 StartTopJob();
232
233 break;
234 case SENC_BUILD_DONE_ERROR:
235 // printf("SENC build done ERROR\n");
236 Sevent.type = SENC_BUILD_DONE_ERROR;
237 Sevent.m_ticket = event.m_ticket;
238 FinishJob(event.m_ticket);
239 StartTopJob();
240
241 break;
242 default:
243 break;
244 }
245 if (top_frame::Get())
246 top_frame::Get()->GetEventHandler()->AddPendingEvent(Sevent);
247}
248
249//----------------------------------------------------------------------------------
250// SENCBuildThread Implementation
251//----------------------------------------------------------------------------------
252
253SENCBuildThread::SENCBuildThread(SENCJobTicket *ticket,
254 SENCThreadManager *manager) {
255 m_FullPath000 = ticket->m_FullPath000;
256 m_SENCFileName = ticket->m_SENCFileName;
257 m_manager = manager;
258 m_ticket = ticket;
259
260 Create();
261}
262
263void *SENCBuildThread::Entry() {
264 // #ifdef __MSVC__
265 // _set_se_translator(my_translate);
266
267 // On Windows, if anything in this thread produces a SEH exception (like
268 // access violation) we handle the exception locally, and simply alow the
269 // thread to exit smoothly with no results. Upstream will notice that nothing
270 // got done, and maybe try again later.
271
272 try
273 // #endif
274 {
275 // Start the SENC build
276 Osenc senc;
277
278 senc.setRegistrar(g_poRegistrar);
279 senc.setRefLocn(m_ticket->ref_lat, m_ticket->ref_lon);
280 senc.SetLODMeters(m_ticket->m_LOD_meters);
281 senc.setNoErrDialog(true);
282
283 m_ticket->m_SENCResult = SENC_BUILD_STARTED;
285 Sevent.stat = 0;
286 Sevent.type = SENC_BUILD_STARTED;
287 Sevent.m_ticket = m_ticket;
288 if (m_manager) m_manager->QueueEvent(Sevent.Clone());
289
290 int ret = senc.createSenc200(m_FullPath000, m_SENCFileName, false);
291
293 Nevent.stat = ret;
294 Nevent.m_ticket = m_ticket;
295 if (ret == ERROR_INGESTING000)
296 Nevent.type = SENC_BUILD_DONE_ERROR;
297 else
298 Nevent.type = SENC_BUILD_DONE_NOERROR;
299
300 m_ticket->m_SENCResult = Sevent.type;
301 if (m_manager) m_manager->QueueEvent(Nevent.Clone());
302
303 // if(ret == ERROR_INGESTING000)
304 // return BUILD_SENC_NOK_PERMANENT;
305 // else
306 // return ret;
307
308 return 0;
309 } // try
310
311 // #ifdef __MSVC__
312 catch (const std::exception &e /*SE_Exception e*/) {
313 const char *msg = e.what();
314 if (m_manager) {
315 // OCPN_CompressionThreadEvent
316 // Nevent(wxEVT_OCPN_COMPRESSIONTHREAD, 0);
317 // m_ticket->b_isaborted = true;
318 // Nevent.SetTicket(m_ticket);
319 // Nevent.type = 0;
320 // m_manager->QueueEvent(Nevent.Clone());
321 }
322
323 return 0;
324 }
325 // #endif
326}
General chart base definitions.
Generic Chart canvas base.
Manager for S57 chart SENC creation threads.
Represents an S57 format electronic navigational chart in OpenCPN.
Definition s57chart.h:90
Global variables stored in configuration file.
S57 SENC File Object.
S57 Chart Object.
const wxEventType wxEVT_OCPN_BUILDSENCTHREAD
Global instance.
SENCThreadManager * g_SencThreadManager
Global instance.
S57 Chart Object.
const wxEventType wxEVT_OCPN_BUILDSENCTHREAD
Global instance.
Abstract gFrame/MyFrame interface.