OpenCPN Partial API docs
Loading...
Searching...
No Matches
SencManager.cpp
1/***************************************************************************
2 *
3 * Project: OpenCPN
4 * Purpose: S57 Chart Object
5 * Author: David Register
6 *
7 ***************************************************************************
8 * Copyright (C) 2010 by David S. Register *
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the *
22 * Free Software Foundation, Inc., *
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
24 **************************************************************************/
25
26// For compilers that support precompilation, includes "wx.h".
27#include "wx/wxprec.h"
28
29#ifndef WX_PRECOMP
30#include "wx/wx.h"
31#endif // precompiled headers
32
33#include "s57chart.h"
34#include "Osenc.h"
35#include "chcanv.h"
36#include "ocpn_frame.h"
37
38extern MyFrame *gFrame;
39extern int g_nCPUCount;
40extern S57ClassRegistrar *g_poRegistrar;
41
42//----------------------------------------------------------------------------------
43// SENCJobTicket Implementation
44//----------------------------------------------------------------------------------
45SENCJobTicket::SENCJobTicket() {
46 m_SENCResult = SENC_BUILD_INACTIVE;
47 m_status = THREAD_INACTIVE;
48}
49
50const wxEventType wxEVT_OCPN_BUILDSENCTHREAD = wxNewEventType();
51
52//----------------------------------------------------------------------------------
53// OCPN_BUILDSENC_ThreadEvent Implementation
54//----------------------------------------------------------------------------------
55OCPN_BUILDSENC_ThreadEvent::OCPN_BUILDSENC_ThreadEvent(wxEventType commandType,
56 int id)
57 : wxEvent(id, commandType) {
58 stat = 0;
59}
60
61OCPN_BUILDSENC_ThreadEvent::~OCPN_BUILDSENC_ThreadEvent() {}
62
63wxEvent *OCPN_BUILDSENC_ThreadEvent::Clone() const {
65 newevent->stat = this->stat;
66 newevent->type = this->type;
67 newevent->m_ticket = this->m_ticket;
68
69 return newevent;
70}
71
72//----------------------------------------------------------------------------------
73// SENCThreadManager Implementation
74//----------------------------------------------------------------------------------
75SENCThreadManager::SENCThreadManager() {
76 // ideally we would use the cpu count -1, and only launch jobs
77 // when the idle load average is sufficient (greater than 1)
78 int nCPU = wxMax(1, wxThread::GetCPUCount());
79 if (g_nCPUCount > 0) nCPU = g_nCPUCount;
80
81 // obviously there's at least one CPU!
82 if (nCPU < 1) nCPU = 1;
83
84 m_max_jobs = wxMax(nCPU - 1, 1);
85 // m_max_jobs = 1;
86
87 // if(bthread_debug)
88 printf(" 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(
93 wxEVT_OCPN_BUILDSENCTHREAD,
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(_T(" %ld"), ticket_list.size());
157 if (gFrame->GetPrimaryCanvas())
158 gFrame->GetPrimaryCanvas()->SetAlertString(_("Preparing vector chart ") +
159 count);
160 }
161}
162
163void SENCThreadManager::FinishJob(SENCJobTicket *ticket) {
164 // printf("Finishing job: %s\n", (const
165 // char*)ticket->m_FullPath000.mb_str());
166
167 // Find and remove the ticket from the list
168 for (size_t i = 0; i < ticket_list.size(); i++) {
169 if (ticket_list[i] == ticket) {
170 // printf(" Removing job: %s\n", (const
171 // char*)ticket->m_FullPath000.mb_str());
172
173 ticket_list.erase(ticket_list.begin() + i);
174 // printf("Job count: %d\n", ticket_list.size());
175
176 break;
177 }
178 }
179
180#if 1
181 int nRunning = 0;
182 for (size_t i = 0; i < ticket_list.size(); i++) {
183 if (ticket_list[i]->m_status == THREAD_STARTED) nRunning++;
184 }
185
186 if (nRunning) {
187 wxString count;
188 count.Printf(_T(" %ld"), ticket_list.size());
189 if (gFrame->GetPrimaryCanvas())
190 gFrame->GetPrimaryCanvas()->SetAlertString(_("Preparing vector chart ") +
191 count);
192 } else {
193 if (gFrame->GetPrimaryCanvas())
194 gFrame->GetPrimaryCanvas()->SetAlertString(_T(""));
195 }
196#endif
197}
198
199int SENCThreadManager::GetJobCount() { return ticket_list.size(); }
200
201bool SENCThreadManager::IsChartInTicketlist(s57chart *chart) {
202 for (size_t i = 0; i < ticket_list.size(); i++) {
203 if (ticket_list[i]->m_chart == chart) return true;
204 }
205 return false;
206}
207
208bool SENCThreadManager::SetChartPointer(s57chart *chart, void *new_ptr) {
209 // Find the ticket
210 for (size_t i = 0; i < ticket_list.size(); i++) {
211 if (ticket_list[i]->m_chart == chart) {
212 ticket_list[i]->m_chart = (s57chart *)new_ptr;
213 return true;
214 }
215 }
216 return false;
217}
218
219#define NBAR_LENGTH 40
220
221void SENCThreadManager::OnEvtThread(OCPN_BUILDSENC_ThreadEvent &event) {
222 OCPN_BUILDSENC_ThreadEvent Sevent(wxEVT_OCPN_BUILDSENCTHREAD, 0);
223
224 switch (event.type) {
225 case SENC_BUILD_STARTED:
226 // printf("SENC build started\n");
227 Sevent.type = SENC_BUILD_STARTED;
228 Sevent.m_ticket = event.m_ticket;
229
230 break;
231 case SENC_BUILD_DONE_NOERROR:
232 // printf("SENC build done no error\n");
233 Sevent.type = SENC_BUILD_DONE_NOERROR;
234 Sevent.m_ticket = event.m_ticket;
235 FinishJob(event.m_ticket);
236 StartTopJob();
237
238 break;
239 case SENC_BUILD_DONE_ERROR:
240 // printf("SENC build done ERROR\n");
241 Sevent.type = SENC_BUILD_DONE_ERROR;
242 Sevent.m_ticket = event.m_ticket;
243 FinishJob(event.m_ticket);
244 StartTopJob();
245
246 break;
247 default:
248 break;
249 }
250 if (gFrame) gFrame->GetEventHandler()->AddPendingEvent(Sevent);
251}
252
253//----------------------------------------------------------------------------------
254// SENCBuildThread Implementation
255//----------------------------------------------------------------------------------
256
257SENCBuildThread::SENCBuildThread(SENCJobTicket *ticket,
258 SENCThreadManager *manager) {
259 m_FullPath000 = ticket->m_FullPath000;
260 m_SENCFileName = ticket->m_SENCFileName;
261 m_manager = manager;
262 m_ticket = ticket;
263
264 Create();
265}
266
267void *SENCBuildThread::Entry() {
268 //#ifdef __MSVC__
269 // _set_se_translator(my_translate);
270
271 // On Windows, if anything in this thread produces a SEH exception (like
272 // access violation) we handle the exception locally, and simply alow the
273 // thread to exit smoothly with no results. Upstream will notice that nothing
274 // got done, and maybe try again later.
275
276 try
277 //#endif
278 {
279 // Start the SENC build
280 Osenc senc;
281
282 senc.setRegistrar(g_poRegistrar);
283 senc.setRefLocn(m_ticket->ref_lat, m_ticket->ref_lon);
284 senc.SetLODMeters(m_ticket->m_LOD_meters);
285 senc.setNoErrDialog(true);
286
287 m_ticket->m_SENCResult = SENC_BUILD_STARTED;
288 OCPN_BUILDSENC_ThreadEvent Sevent(wxEVT_OCPN_BUILDSENCTHREAD, 0);
289 Sevent.stat = 0;
290 Sevent.type = SENC_BUILD_STARTED;
291 Sevent.m_ticket = m_ticket;
292 if (m_manager) m_manager->QueueEvent(Sevent.Clone());
293
294 int ret = senc.createSenc200(m_FullPath000, m_SENCFileName, false);
295
296 OCPN_BUILDSENC_ThreadEvent Nevent(wxEVT_OCPN_BUILDSENCTHREAD, 0);
297 Nevent.stat = ret;
298 Nevent.m_ticket = m_ticket;
299 if (ret == ERROR_INGESTING000)
300 Nevent.type = SENC_BUILD_DONE_ERROR;
301 else
302 Nevent.type = SENC_BUILD_DONE_NOERROR;
303
304 m_ticket->m_SENCResult = Sevent.type;
305 if (m_manager) m_manager->QueueEvent(Nevent.Clone());
306
307 // if(ret == ERROR_INGESTING000)
308 // return BUILD_SENC_NOK_PERMANENT;
309 // else
310 // return ret;
311
312 return 0;
313 } // try
314
315 //#ifdef __MSVC__
316 catch (const std::exception &e /*SE_Exception e*/) {
317 const char *msg = e.what();
318 if (m_manager) {
319 // OCPN_CompressionThreadEvent
320 // Nevent(wxEVT_OCPN_COMPRESSIONTHREAD, 0);
321 // m_ticket->b_isaborted = true;
322 // Nevent.SetTicket(m_ticket);
323 // Nevent.type = 0;
324 // m_manager->QueueEvent(Nevent.Clone());
325 }
326
327 return 0;
328 }
329 //#endif
330}
Definition: Osenc.h:401