1function startmulticoreslave(multicoreDir)
2%STARTMULTICORESLAVE  Start multi-core processing slave process.
3%   STARTMULTICORESLAVE(DIRNAME) starts a slave process for function
4%   STARTMULTICOREMASTER. The given directory DIRNAME is checked for data
5%   files including which function to run and which parameters to use.
6%
7%   STARTMULTICORESLAVE (without input arguments) uses the directory
8%   <TEMPDIR>/multicorefiles, where <TEMPDIR> is the directory returned by
9%   function tempdir.
10%
11%		Markus Buehren
12%		Last modified 13.11.2007
13%
14%   See also STARTMULTICOREMASTER.
15
16firstWarnTime = 10;
17startWarnTime = 10*60;
18maxWarnTime   = 24*3600;
19startWaitTime = 0.5;
20maxWaitTime   = 5;
21
22lastEvalEndClock = clock;
23lastWarnClock    = clock;
24firstRun         = true;
25curWarnTime      = firstWarnTime;
26curWaitTime      = startWaitTime;
27
28% get slave file directory name
29if ~exist('multicoreDir', 'var') || isempty(multicoreDir)
30	multicoreDir = fullfile(tempdir2, 'multicorefiles');
31end
32if ~exist(multicoreDir, 'dir')
33	try
34		mkdir(multicoreDir);
35	catch
36		error('Unable to create slave file directory %s.', multicoreDir);
37	end
38end
39
40while 1
41	parameterFileList = findfiles(multicoreDir, 'parameters_*.mat');
42
43	% get last file that is not a semaphore file
44	parameterFileName = '';
45	for fileNr = length(parameterFileList):-1:1
46		if isempty(strfind(parameterFileList{fileNr}, 'semaphore'))
47			parameterFileName = parameterFileList{fileNr};
48			break
49		end
50	end
51
52	if ~isempty(parameterFileName)
53
54		% load and delete last parameter file
55		sem = setfilesemaphore(parameterFileName);
56		loadSuccessful = true;
57		if existfile(parameterFileName)
58			try
59				load(parameterFileName, 'functionHandle', 'parameters');
60				delete(parameterFileName);
61			catch
62				disp(sprintf('Error loading or deleting file %s.', parameterFileName));
63				loadSuccessful = false;
64			end
65		else
66			loadSuccessful = false;
67		end
68		removefilesemaphore(sem);
69
70		% check if variables are existing
71		if loadSuccessful && (~exist('functionHandle', 'var') || ~exist('parameters', 'var'))
72			disp(sprintf('Warning: Either variable ''%s'' or ''%s'' not existing after loading file %s.', ...
73				'functionHandle', 'parameters', parameterFileName));
74			loadSuccessful = false;
75		end
76
77		% continue if loading was not successful
78		if ~loadSuccessful
79			continue
80		end
81
82		%%%%%%%%%%%%%%%%%%%%%
83		% evaluate function %
84		%%%%%%%%%%%%%%%%%%%%%
85		if firstRun
86			disp(sprintf('First function evaluation (%s)', datestr(clock, 'mmm dd, HH:MM')));
87			firstRun = false;
88		elseif etime(clock, lastEvalEndClock) > 60
89			disp(sprintf('First function evaluation after %s (%s)', ...
90				formattime(etime(clock, lastEvalEndClock)), datestr(clock, 'mmm dd, HH:MM')));
91		end
92
93		% evaluate function
94		if iscell(parameters) %#ok
95			result = feval(functionHandle, parameters{:}); %#ok
96		else
97			result = feval(functionHandle, parameters); %#ok
98		end
99
100		% save result
101		resultFileName = strrep(parameterFileName, 'parameters', 'result');
102		sem = setfilesemaphore({parameterFileName, resultFileName});
103		save(resultFileName, 'result');
104		removefilesemaphore(sem);
105
106		% save time
107		lastEvalEndClock = clock;
108		curWarnTime = startWarnTime;
109		curWaitTime = startWaitTime;
110
111		% remove variables before next run
112		clear result functionHandle parameters
113
114	else
115		% display message if idle for long time
116		timeSinceLastEvaluation = etime(clock, lastEvalEndClock);
117		if min(timeSinceLastEvaluation, etime(clock, lastWarnClock)) > curWarnTime
118			if timeSinceLastEvaluation >= 10*60
119				% round to minutes
120				timeSinceLastEvaluation = 60 * round(timeSinceLastEvaluation / 60);
121			end
122			disp(sprintf('Warning: No slave files found in last %s (%s).', formattime(timeSinceLastEvaluation), datestr(clock, 'mmm dd, HH:MM')));
123			lastWarnClock = clock;
124			if firstRun
125				curWarnTime = startWarnTime;
126			else
127				curWarnTime = min(curWarnTime * 2, maxWarnTime);
128			end
129			curWaitTime = min(curWaitTime + 0.5, maxWaitTime);
130		end
131
132		% wait before next check
133		pause(curWaitTime);
134
135	end
136end
137
138%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139function timeString = formattime(time, mode)
140%FORMATTIME  Return formatted time string.
141%   STR = FORMATTIME(TIME) returns a formatted time string for the given
142%   time difference TIME in seconds, i.e. '1 hour and 5 minutes' for TIME =
143%   3900.
144%
145%   FORMATTIME(TIME, MODE) uses the specified display mode ('long' or
146%   'short'). Default is long display.
147%
148%   FORMATTIME (without input arguments) shows examples.
149
150if nargin == 0
151	disp(sprintf('\nExamples for strings returned by function %s.m:', mfilename));
152	time = [0 1e-4 0.1 1 1.1 2 60 61 62 120 121 122 3600 3660 3720 7200 7260 7320 ...
153		3600*24 3600*25 3600*26 3600*48 3600*49 3600*50];
154	for k=1:length(time)
155		disp(sprintf('time = %6g, timeString = ''%s''', time(k), formattime(time(k))));
156	end
157	if nargout > 0
158		timeString = '';
159	end
160	return
161end
162
163if ~exist('mode', 'var')
164	mode = 'long';
165end
166
167if time < 0
168	disp('Warning: Time must be greater or equal zero.');
169	timeString = '';
170elseif time >= 3600*24
171	days = floor(time / (3600*24));
172	if days > 1
173		dayString = 'days';
174	else
175		dayString = 'day';
176	end
177	hours = floor(mod(time, 3600*24) / 3600);
178	if hours == 0
179		timeString = sprintf('%d %s', days, dayString);
180	else
181		if hours > 1
182			hourString = 'hours';
183		else
184			hourString = 'hour';
185		end
186		timeString = sprintf('%d %s and %d %s', days, dayString, hours, hourString);
187	end
188
189elseif time >= 3600
190	hours = floor(mod(time, 3600*24) / 3600);
191	if hours > 1
192		hourString = 'hours';
193	else
194		hourString = 'hour';
195	end
196	minutes = floor(mod(time, 3600) / 60);
197	if minutes == 0
198		timeString = sprintf('%d %s', hours, hourString);
199	else
200		if minutes > 1
201			minuteString = 'minutes';
202		else
203			minuteString = 'minute';
204		end
205		timeString = sprintf('%d %s and %d %s', hours, hourString, minutes, minuteString);
206	end
207
208elseif time >= 60
209	minutes = floor(time / 60);
210	if minutes > 1
211		minuteString = 'minutes';
212	else
213		minuteString = 'minute';
214	end
215	seconds = floor(mod(time, 60));
216	if seconds == 0
217		timeString = sprintf('%d %s', minutes, minuteString);
218	else
219		if seconds > 1
220			secondString = 'seconds';
221		else
222			secondString = 'second';
223		end
224		timeString = sprintf('%d %s and %d %s', minutes, minuteString, seconds, secondString);
225	end
226
227else
228	if time > 10
229		seconds = floor(time);
230	else
231		seconds = floor(time * 100) / 100;
232	end
233	if seconds > 0
234		if seconds ~= 1
235			timeString = sprintf('%.4g seconds', seconds);
236		else
237			timeString = '1 second';
238		end
239	else
240		timeString = sprintf('%.4g seconds', time);
241	end
242end
243
244switch mode
245	case 'long'
246		% do nothing
247	case 'short'
248		timeString = strrep(timeString, ' and ', ' ');
249		timeString = strrep(timeString, ' days', 'd');
250		timeString = strrep(timeString, ' day', 'd');
251		timeString = strrep(timeString, ' hours', 'h');
252		timeString = strrep(timeString, ' hour', 'h');
253		timeString = strrep(timeString, ' minutes', 'm');
254		timeString = strrep(timeString, ' minute', 'm');
255		timeString = strrep(timeString, ' seconds', 's');
256		timeString = strrep(timeString, ' second', 's');
257	otherwise
258		error('Mode ''%s'' unknown in function %s.', mode, mfilename);
259end
260
261
262