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 "model/config_vars.h"
31
32#include "s57chart.h"
33#include "o_senc.h"
34#include "chartbase.h"
35#include "chcanv.h"
36#include "ocpn_frame.h"
37#include "s57class_registrar.h"
38
40
41//----------------------------------------------------------------------------------
42// SENCJobTicket Implementation
43//----------------------------------------------------------------------------------
44SENCJobTicket::SENCJobTicket() {
45 m_SENCResult = SENC_BUILD_INACTIVE;
46 m_status = THREAD_INACTIVE;
47}
48
49const wxEventType wxEVT_OCPN_BUILDSENCTHREAD = wxNewEventType();
50
51//----------------------------------------------------------------------------------
52// OCPN_BUILDSENC_ThreadEvent Implementation
53//----------------------------------------------------------------------------------
54OCPN_BUILDSENC_ThreadEvent::OCPN_BUILDSENC_ThreadEvent(wxEventType commandType,
55 int id)
56 : wxEvent(id, commandType) {
57 stat = 0;
58}
59
60OCPN_BUILDSENC_ThreadEvent::~OCPN_BUILDSENC_ThreadEvent() {}
61
62wxEvent *OCPN_BUILDSENC_ThreadEvent::Clone() const {
64 newevent->stat = this->stat;
65 newevent->type = this->type;
66 newevent->m_ticket = this->m_ticket;
67
68 return newevent;
69}
70
71//----------------------------------------------------------------------------------
72// SENCThreadManager Implementation
73//----------------------------------------------------------------------------------
74SENCThreadManager::SENCThreadManager() {
75 // ideally we would use the cpu count -1, and only launch jobs
76 // when the idle load average is sufficient (greater than 1)
77 int nCPU = wxMax(1, wxThread::GetCPUCount());
78 if (g_nCPUCount > 0) nCPU = g_nCPUCount;
79
80 // obviously there's at least one CPU!
81 if (nCPU < 1) nCPU = 1;
82
83 m_max_jobs = wxMax(nCPU - 1, 1);
84 // m_max_jobs = 1;
85
86 wxLogDebug("SENC: nCPU: %d m_max_jobs :%d\n", nCPU, m_max_jobs);
87
88 // Create/connect a dynamic event handler slot for messages from the worker
89 // threads
90 Connect(
92 (wxObjectEventFunction)(wxEventFunction)&SENCThreadManager::OnEvtThread);
93
94 // m_timer.Connect(wxEVT_TIMER, wxTimerEventHandler(
95 // glTextureManager::OnTimer ), NULL, this); m_timer.Start(500);
96}
97
98SENCThreadManager::~SENCThreadManager() {
99 // ClearJobList();
100}
101
102SENCThreadStatus SENCThreadManager::ScheduleJob(SENCJobTicket *ticket) {
103 // Do not add a job if there is already a job pending for this chart, by name
104 for (size_t i = 0; i < ticket_list.size(); i++) {
105 if (ticket_list[i]->m_FullPath000 == ticket->m_FullPath000)
106 return THREAD_PENDING;
107 }
108
109 ticket->m_status = THREAD_PENDING;
110 ticket_list.push_back(ticket);
111
112 // printf("Scheduling job: %s\n", (const
113 // char*)ticket->m_FullPath000.mb_str()); printf("Job count: %d\n",
114 // ticket_list.size());
115 StartTopJob();
116 return THREAD_PENDING;
117}
118
119void SENCThreadManager::StartTopJob() {
120 SENCJobTicket *startCandidate;
121 // Get the running job count
122 int nRunning = 0;
123 for (size_t i = 0; i < ticket_list.size(); i++) {
124 if (ticket_list[i]->m_status == THREAD_STARTED) nRunning++;
125 }
126
127 // OK to start one?
128 if (nRunning < m_max_jobs) {
129 // Find the first eligible
130 startCandidate = NULL;
131 for (size_t i = 0; i < ticket_list.size(); i++) {
132 if (ticket_list[i]->m_status == THREAD_PENDING) {
133 startCandidate = ticket_list[i];
134 break;
135 }
136 }
137
138 // Found one?
139 if (startCandidate) {
140 // printf("Starting job: %s\n", (const
141 // char*)startCandidate->m_FullPath000.mb_str());
142
143 SENCBuildThread *thread = new SENCBuildThread(startCandidate, this);
144 startCandidate->m_thread = thread;
145 startCandidate->m_status = THREAD_STARTED;
146 thread->SetPriority(20);
147 thread->Run();
148 nRunning++;
149 }
150 }
151
152 if (nRunning) {
153 wxString count;
154 count.Printf(" %ld", ticket_list.size());
155 if (gFrame->GetPrimaryCanvas())
156 gFrame->GetPrimaryCanvas()->SetAlertString(_("Preparing vector chart ") +
157 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 if (gFrame->GetPrimaryCanvas())
188 gFrame->GetPrimaryCanvas()->SetAlertString(_("Preparing vector chart ") +
189 count);
190 } else {
191 if (gFrame->GetPrimaryCanvas())
192 gFrame->GetPrimaryCanvas()->SetAlertString("");
193 }
194#endif
195}
196
197int SENCThreadManager::GetJobCount() { return ticket_list.size(); }
198
199bool SENCThreadManager::IsChartInTicketlist(s57chart *chart) {
200 for (size_t i = 0; i < ticket_list.size(); i++) {
201 if (ticket_list[i]->m_chart == chart) return true;
202 }
203 return false;
204}
205
206bool SENCThreadManager::SetChartPointer(s57chart *chart, void *new_ptr) {
207 // Find the ticket
208 for (size_t i = 0; i < ticket_list.size(); i++) {
209 if (ticket_list[i]->m_chart == chart) {
210 ticket_list[i]->m_chart = (s57chart *)new_ptr;
211 return true;
212 }
213 }
214 return false;
215}
216
217#define NBAR_LENGTH 40
218
219void SENCThreadManager::OnEvtThread(OCPN_BUILDSENC_ThreadEvent &event) {
221
222 switch (event.type) {
223 case SENC_BUILD_STARTED:
224 // printf("SENC build started\n");
225 Sevent.type = SENC_BUILD_STARTED;
226 Sevent.m_ticket = event.m_ticket;
227
228 break;
229 case SENC_BUILD_DONE_NOERROR:
230 // printf("SENC build done no error\n");
231 Sevent.type = SENC_BUILD_DONE_NOERROR;
232 Sevent.m_ticket = event.m_ticket;
233 FinishJob(event.m_ticket);
234 StartTopJob();
235
236 break;
237 case SENC_BUILD_DONE_ERROR:
238 // printf("SENC build done ERROR\n");
239 Sevent.type = SENC_BUILD_DONE_ERROR;
240 Sevent.m_ticket = event.m_ticket;
241 FinishJob(event.m_ticket);
242 StartTopJob();
243
244 break;
245 default:
246 break;
247 }
248 if (gFrame) gFrame->GetEventHandler()->AddPendingEvent(Sevent);
249}
250
251//----------------------------------------------------------------------------------
252// SENCBuildThread Implementation
253//----------------------------------------------------------------------------------
254
255SENCBuildThread::SENCBuildThread(SENCJobTicket *ticket,
256 SENCThreadManager *manager) {
257 m_FullPath000 = ticket->m_FullPath000;
258 m_SENCFileName = ticket->m_SENCFileName;
259 m_manager = manager;
260 m_ticket = ticket;
261
262 Create();
263}
264
265void *SENCBuildThread::Entry() {
266 // #ifdef __MSVC__
267 // _set_se_translator(my_translate);
268
269 // On Windows, if anything in this thread produces a SEH exception (like
270 // access violation) we handle the exception locally, and simply alow the
271 // thread to exit smoothly with no results. Upstream will notice that nothing
272 // got done, and maybe try again later.
273
274 try
275 // #endif
276 {
277 // Start the SENC build
278 Osenc senc;
279
280 senc.setRegistrar(g_poRegistrar);
281 senc.setRefLocn(m_ticket->ref_lat, m_ticket->ref_lon);
282 senc.SetLODMeters(m_ticket->m_LOD_meters);
283 senc.setNoErrDialog(true);
284
285 m_ticket->m_SENCResult = SENC_BUILD_STARTED;
287 Sevent.stat = 0;
288 Sevent.type = SENC_BUILD_STARTED;
289 Sevent.m_ticket = m_ticket;
290 if (m_manager) m_manager->QueueEvent(Sevent.Clone());
291
292 int ret = senc.createSenc200(m_FullPath000, m_SENCFileName, false);
293
295 Nevent.stat = ret;
296 Nevent.m_ticket = m_ticket;
297 if (ret == ERROR_INGESTING000)
298 Nevent.type = SENC_BUILD_DONE_ERROR;
299 else
300 Nevent.type = SENC_BUILD_DONE_NOERROR;
301
302 m_ticket->m_SENCResult = Sevent.type;
303 if (m_manager) m_manager->QueueEvent(Nevent.Clone());
304
305 // if(ret == ERROR_INGESTING000)
306 // return BUILD_SENC_NOK_PERMANENT;
307 // else
308 // return ret;
309
310 return 0;
311 } // try
312
313 // #ifdef __MSVC__
314 catch (const std::exception &e /*SE_Exception e*/) {
315 const char *msg = e.what();
316 if (m_manager) {
317 // OCPN_CompressionThreadEvent
318 // Nevent(wxEVT_OCPN_COMPRESSIONTHREAD, 0);
319 // m_ticket->b_isaborted = true;
320 // Nevent.SetTicket(m_ticket);
321 // Nevent.type = 0;
322 // m_manager->QueueEvent(Nevent.Clone());
323 }
324
325 return 0;
326 }
327 // #endif
328}
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.
OpenCPN top window.
S57 Chart Object.
const wxEventType wxEVT_OCPN_BUILDSENCTHREAD
Global instance.
SENCThreadManager * g_SencThreadManager
Global instance.
const wxEventType wxEVT_OCPN_BUILDSENCTHREAD
Global instance.