2 * Copyright 2017, Andrew Lindesay <apl@lindesay.co.nz>.
3 * All rights reserved. Distributed under the terms of the MIT License.
5 #include "BulkLoadStateMachine.h"
8 #include <NetworkInterface.h>
9 #include <NetworkRoster.h>
12 #include "PkgDataUpdateProcess.h"
13 #include "RepositoryDataUpdateProcess.h"
14 #include "ServerIconExportUpdateProcess.h"
15 #include "ServerSettings.h"
18 BulkLoadStateMachine::BulkLoadStateMachine(Model
* model
)
20 fBulkLoadContext(NULL
),
26 BulkLoadStateMachine::~BulkLoadStateMachine()
33 BulkLoadStateMachine::IsRunning()
35 BAutolock
locker(&fLock
);
36 return fBulkLoadContext
!= NULL
;
40 /*! This gets invoked when one of the background processes has exited. */
43 BulkLoadStateMachine::ServerProcessExited()
49 static const char* bulk_load_state_name(bulk_load_state state
) {
51 case BULK_LOAD_INITIAL
:
52 return "BULK_LOAD_INITIAL";
53 case BULK_LOAD_REPOSITORY_AND_REFERENCE
:
54 return "BULK_LOAD_REPOSITORY_AND_REFERENCE";
55 case BULK_LOAD_PKGS_AND_ICONS
:
56 return "BULK_LOAD_PKGS_AND_ICONS";
57 case BULK_LOAD_COMPLETE
:
58 return "BULK_LOAD_COMPLETE";
66 BulkLoadStateMachine::SetContextState(bulk_load_state state
)
68 if (Logger::IsDebugEnabled()) {
69 printf("bulk load - transition to state [%s]\n",
70 bulk_load_state_name(state
));
73 fBulkLoadContext
->SetState(state
);
77 /*! Bulk loading data into the model can be considered to be a state
78 machine. This method is invoked each time that an event state
83 BulkLoadStateMachine::ContextPoll()
85 BAutolock
locker(&fLock
);
87 if (Logger::IsDebugEnabled())
88 printf("bulk load - context poll\n");
90 if (CanTransitionTo(BULK_LOAD_REPOSITORY_AND_REFERENCE
)) {
91 SetContextState(BULK_LOAD_REPOSITORY_AND_REFERENCE
);
92 InitiateBulkPopulateIcons();
93 if (InitiateBulkRepositories() != B_OK
)
98 if (CanTransitionTo(BULK_LOAD_PKGS_AND_ICONS
)) {
99 fModel
->LogDepotsWithNoWebAppRepositoryCode();
100 SetContextState(BULK_LOAD_PKGS_AND_ICONS
);
101 InitiateBulkPopulatePackagesForAllDepots();
105 if (CanTransitionTo(BULK_LOAD_COMPLETE
)) {
106 SetContextState(BULK_LOAD_COMPLETE
);
107 delete fBulkLoadContext
;
108 fBulkLoadContext
= NULL
;
115 BulkLoadStateMachine::CanTransitionTo(bulk_load_state targetState
)
117 if (fBulkLoadContext
!= NULL
) {
118 bulk_load_state existingState
= fBulkLoadContext
->State();
120 switch (targetState
) {
121 case BULK_LOAD_INITIAL
:
123 case BULK_LOAD_REPOSITORY_AND_REFERENCE
:
124 return existingState
== BULK_LOAD_INITIAL
;
125 case BULK_LOAD_PKGS_AND_ICONS
:
126 return (existingState
== BULK_LOAD_REPOSITORY_AND_REFERENCE
)
127 && ((fBulkLoadContext
->RepositoryProcess() == NULL
)
128 || !fBulkLoadContext
->RepositoryProcess()->IsRunning());
129 case BULK_LOAD_COMPLETE
:
130 if ((existingState
== BULK_LOAD_PKGS_AND_ICONS
)
131 && ((fBulkLoadContext
->IconProcess() == NULL
)
132 || !fBulkLoadContext
->IconProcess()->IsRunning())) {
135 for (i
= 0; i
< fBulkLoadContext
->CountPkgProcesses(); i
++) {
136 AbstractServerProcess
* process
=
137 fBulkLoadContext
->PkgProcessAt(i
);
138 if (process
->IsRunning())
153 BulkLoadStateMachine::StopAllProcesses()
155 BAutolock
locker(&fLock
);
157 if (fBulkLoadContext
!= NULL
) {
158 if (NULL
!= fBulkLoadContext
->IconProcess())
159 fBulkLoadContext
->IconProcess()->Stop();
161 if (NULL
!= fBulkLoadContext
->RepositoryProcess())
162 fBulkLoadContext
->RepositoryProcess()->Stop();
166 for(i
= 0; i
< fBulkLoadContext
->CountPkgProcesses(); i
++) {
167 AbstractServerProcess
* serverProcess
=
168 fBulkLoadContext
->PkgProcessAt(i
);
169 serverProcess
->Stop();
176 BulkLoadStateMachine::Start()
178 if (Logger::IsInfoEnabled())
179 printf("bulk load - start\n");
184 BAutolock
locker(&fLock
);
187 fBulkLoadContext
= new BulkLoadContext();
189 if (ServerSettings::ForceNoNetwork() || !HasNetwork())
190 fBulkLoadContext
->AddProcessOption(
191 SERVER_PROCESS_NO_NETWORKING
);
193 if (ServerSettings::PreferCache())
194 fBulkLoadContext
->AddProcessOption(SERVER_PROCESS_PREFER_CACHE
);
196 if (ServerSettings::DropCache())
197 fBulkLoadContext
->AddProcessOption(SERVER_PROCESS_DROP_CACHE
);
206 BulkLoadStateMachine::Stop()
210 // spin lock to wait for the bulk-load processes to complete.
217 /*! This method is the initial function that is invoked on starting a new
218 thread. It will start a server process that is part of the bulk-load.
222 BulkLoadStateMachine::StartProcess(void* cookie
)
224 AbstractServerProcess
* process
=
225 static_cast<AbstractServerProcess
*>(cookie
);
227 if (Logger::IsInfoEnabled()) {
228 printf("bulk load - starting process [%s]\n",
238 BulkLoadStateMachine::InitiateServerProcess(AbstractServerProcess
* process
)
240 if (Logger::IsInfoEnabled())
241 printf("bulk load - initiating [%s]\n", process
->Name());
243 thread_id tid
= spawn_thread(&StartProcess
,
244 process
->Name(), B_NORMAL_PRIORITY
, process
);
256 BulkLoadStateMachine::InitiateBulkRepositories()
258 status_t result
= B_OK
;
261 fBulkLoadContext
->SetRepositoryProcess(NULL
);
262 result
= fModel
->DumpExportRepositoryDataPath(dataPath
);
264 if (result
!= B_OK
) {
265 BAutolock
locker(&fLock
);
266 printf("unable to obtain the path for storing the repository data\n");
271 fBulkLoadContext
->SetRepositoryProcess(
272 new RepositoryDataUpdateProcess(this, dataPath
, fModel
,
273 fBulkLoadContext
->ProcessOptions()));
274 return InitiateServerProcess(fBulkLoadContext
->RepositoryProcess());
279 BulkLoadStateMachine::InitiateBulkPopulateIcons()
283 if (fModel
->IconStoragePath(path
) != B_OK
) {
284 BAutolock
locker(&fLock
);
285 printf("unable to obtain the path for storing icons\n");
290 AbstractServerProcess
*process
= new ServerIconExportUpdateProcess(
291 this, path
, fModel
, fBulkLoadContext
->ProcessOptions());
292 fBulkLoadContext
->SetIconProcess(process
);
293 return InitiateServerProcess(process
);
298 BulkLoadStateMachine::InitiateBulkPopulatePackagesForDepot(
299 const DepotInfo
& depotInfo
)
301 BString repositorySourceCode
= depotInfo
.WebAppRepositorySourceCode();
303 if (repositorySourceCode
.Length() == 0) {
304 printf("the depot [%s] has no repository source code\n",
305 depotInfo
.Name().String());
309 BPath repositorySourcePkgDataPath
;
311 if (fModel
->DumpExportPkgDataPath(repositorySourcePkgDataPath
,
312 repositorySourceCode
) != B_OK
) {
313 BAutolock
locker(&fLock
);
314 printf("unable to obtain the path for storing data for [%s]\n",
315 repositorySourceCode
.String());
320 AbstractServerProcess
*process
= new PkgDataUpdateProcess(
321 this, repositorySourcePkgDataPath
, fModel
->PreferredLanguage(),
322 repositorySourceCode
, depotInfo
.Name(), fModel
,
323 fBulkLoadContext
->ProcessOptions());
324 fBulkLoadContext
->AddPkgProcess(process
);
326 return InitiateServerProcess(process
);
332 BulkLoadStateMachine::InitiatePopulatePackagesForDepotCallback(
333 const DepotInfo
& depotInfo
, void* context
)
335 BulkLoadStateMachine
* stateMachine
=
336 static_cast<BulkLoadStateMachine
*>(context
);
337 stateMachine
->InitiateBulkPopulatePackagesForDepot(depotInfo
);
342 BulkLoadStateMachine::InitiateBulkPopulatePackagesForAllDepots()
344 fModel
->ForAllDepots(&InitiatePopulatePackagesForDepotCallback
, this);
346 printf("did initiate populate package data for %" B_PRId32
" depots\n",
347 fBulkLoadContext
->CountPkgProcesses());
349 if (0 == fBulkLoadContext
->CountPkgProcesses())
355 BulkLoadStateMachine::HasNetwork()
357 BNetworkRoster
& roster
= BNetworkRoster::Default();
358 BNetworkInterface interface
;
360 while (roster
.GetNextInterface(&cookie
, interface
) == B_OK
) {
361 uint32 flags
= interface
.Flags();
362 if ((flags
& IFF_LOOPBACK
) == 0
363 && (flags
& (IFF_UP
| IFF_LINK
)) == (IFF_UP
| IFF_LINK
)) {