File Coverage

blib/lib/Data/Edit/Conversion.pm
Criterion Covered Total %
statement 208 218 95.4
branch 48 86 55.8
condition 7 19 36.8
subroutine 35 37 94.5
pod 13 14 92.8
total 311 374 83.1


line stmt bran cond sub pod time code
1             #!/usr/bin/perl
2             #-------------------------------------------------------------------------------
3             # Data::Edit::Conversion - Perform a restartable series of steps in parallel.
4             # Philip R Brenan at gmail dot com, Appa Apps Ltd Inc., 2018
5             #-------------------------------------------------------------------------------
6             package Data::Edit::Conversion;
7             our $VERSION = "20180610";
8             require v5.16;
9 49     49   25823 use warnings FATAL => qw(all);
  49         343  
  49         1421  
10 49     49   196 use strict;
  49         98  
  49         1225  
11 49     49   196 use Carp qw(confess cluck);
  49         98  
  49         3920  
12 49     49   22883 use Data::Dump qw(dump);
  49         307083  
  49         2646  
13 49     49   42630 use Data::Table::Text qw(:all);
  49         2637719  
  49         22638  
14 49     49   29204 use Storable;
  49         131369  
  49         2401  
15 49     49   343 use Time::HiRes qw(time);
  49         98  
  49         294  
16 49     49   3920 use utf8;
  49         98  
  49         294  
17              
18             #1 Methods # Specify and run the restartable conversion of zero or more files in parallel
19              
20             sub defaultMaximumNumberOfProcesses #P Default maximum number of processes to use during the conversion
21 0     0 1 0 {8}
22              
23             sub defaultOutFileLimit #P Default maximum number of files to clear art a time.
24 0     0 1 0 {32}
25              
26             sub new(@) #S Create a conversion specification for zero or more files represented by projects.
27 49     49 1 686 {my (@attributes) = @_; # L describing the launch
28 49         931 my $launch = bless {@attributes};
29 49 50 33     1666 ref($launch->projects) &&
30             ref($launch->projects) =~ m(\AData::Edit::Conversion::Projects\Z) or # Convert zero or more projects
31             confess "projects=>Data::Edit::Conversion::Projects required";
32              
33 49 50       4165 ref($launch->convert) or confess "convert=>specification required";
34 49   50     1127 $launch->save //= q(save); # Default save folder
35              
36 49 50       1666 if (my $r = ref $launch->convert) # Conversion specification
37 49 50       637 {if ($r =~ m(ARRAY))
38 49         147 {my @convert = @{$launch->convert};
  49         1372  
39 49         441 for my $stage(@convert)
40 196 50 33     1176 {if (ref($stage) and ref($stage) =~ m(ARRAY))
41 196 50       441 {@$stage >= 2 or
42             confess "name=>sub required for stage, got: ".dump($stage);
43 196         441 my ($name, $sub) = @$stage;
44 196 50       441 ref($name) and
45             confess "Scalar required for stage name, got: ". dump($name);
46 196 50 33     1470 ref($sub) && ref($sub) =~ m(\ACODE\Z) or
47             confess "Code required for stage $name, got: ". dump($sub);
48             }
49             else
50 0         0 {confess "[conversion stage name => conversion sub] required, got: ".
51             dump($stage);
52             }
53             }
54              
55 49         343 for my $convert(@convert) # Each conversion step
56 196         1519 {my ($stepName, $sub) = @$convert; # Step name, processing sub
57              
58 196 50       3479 $launch->stepNumberByName->{$stepName} and # Check each step has a unique name
59             confess "Duplicate step name: $stepName";
60 196         1372 $launch->stepNumberByName->{$stepName} = @{$launch->stepsByNumber}; # Step number from name
  196         2793  
61              
62 196         2793 push @{$launch->stepsByNumber}, sub # Conversion steps
63 130     130   1075 {my ($launch, $projectName) = @_;
64 130 50       881 ref($launch) =~ m(Data::Edit::Conversion)s or confess;
65 130 50       332 !ref($projectName) or confess;
66 130         1193 my $S = time(); # Start time
67 130         2757 my $R = $sub->($launch->projects->{$projectName}, $stepName);
68 130         375526 $launch->projects->{$projectName}->stepTimes->{$stepName} = # Step processed in float seconds
69             time() - $S;
70 130         7955 $launch->saveProject($projectName, $stepName);
71 130         124121 $R # Return result of convertion
72 196         4606 };
73             }
74             }
75             else # Syntax
76 0         0 {confess "Convert=>[[conversion stage name => conversion sub], ...]".
77             " required, got: ".dump($launch->convert);
78             }
79             }
80              
81 49         1568 return $launch; # Launch specification
82             }
83              
84             sub launch($;$$) # Launch the conversion of several files, each represented by a project, in parallel processes, saving the project state after each step of the conversion so that subsequent conversions can be restarted at later steps to speed up development by bypassing initial processing steps unless they are really needed. The L and L are transferred back from each project's sub process to the main calling process so that the main process can further process their results.
85 174     174 1 811 {my ($launch, $title, $restart) = @_; # Launch specification, optional title, optional name of latest step to restart at.
86 174         2849 my $projects = $launch->projects;
87 174   33     4196 my $mp = $launch->maximumNumberOfProcesses // # Maximum number of simultaneous processes
88             defaultMaximumNumberOfProcesses;
89              
90 174 50       4490 if (my $out = $launch->out) # Clear the output area if present
91 0   0     0 {my $limit = $launch->outFileLimit // defaultOutFileLimit;
92 0         0 clearFolder($out, $limit);
93             }
94              
95 174         4255 $_->stepTimes = {} for values %$projects; # Reset step times
96              
97 174 50       18029 if ($mp == 1) # Process sequentially
98 0         0 {for my $projectName(sort keys %$projects) # Convert matching projects
99 0         0 {$launch->launchProject($projectName, $restart);
100             }
101             }
102             else # Process in parallel
103 174         199 {my $count = 0;
104 174         992 for my $projectName(sort keys %$projects) # Convert matching projects
105 1224 50       4596 {wait if ++$count > $mp; # Wait for processes to finish
106 1224 100       882621 $launch->launchProject($projectName, $restart), exit unless fork; # Convert in parallel
107             }
108 126 100       5940 for(;;) {last if wait == -1} # Wait for conversions to complete
  1134         48995019  
109              
110 126         539 if (1) # Reload last good step to retrieve fully processed data
111 126         806 {my @steps = reverse @{$launch->convert}; # Steps
  126         17529  
112 126         4286 for my $projectName(sort keys %$projects) # Projects
113 1008         2081 {for my $step(@steps) # Find latest save file
114 1008         2075 {my ($stepName) = @$step;
115 1008         2279 my $file = $launch->stepSaveFile($projectName, $stepName);
116 1008 50       59817 if (-e $file) # Retrive file
117 1008         4349 {my $d = retrieve $file;
118 1008         91753 $projects->{$projectName}->data = $d->data; # Transfer data back so a good idea to put something meaningful here especially in the last step
119 1008         17639 $projects->{$projectName}->stepTimes = $d->stepTimes; # Transfer list of steps processed
120 1008         14729 last; # Ignore earlier steps
121             }
122             }
123             }
124             }
125             }
126             }
127              
128             sub restart($$;$) # Launch the conversion of several files represented by projects in parallel, starting at the specified step: the L from the previous step will be restored unless it does not exist in which case the conversion will be run from the latest step available prior to this step or right from the start.
129 125     125 1 885 {my ($launch, $restart, $title) = @_; # Launch specification, step to restart at, optional title
130              
131             defined($restart) or confess "No such step: $restart, choose from: ". # No such restart step
132 125 50       467 dump([sort keys %{$launch->stepNumberByName}]);
  0         0  
133              
134 125   100     1565 $launch->launch($title // "Restart", $restart); # Launch with restart
135             }
136              
137             #1 Launch Attributes # Use these attributes to configure a launch.
138              
139             genLValueScalarMethods(q(convert)); #I [[step name => sub]...] A list of steps and their associated subs to process that step. At the end of each step the data stored on L is saved to allow for a later restart at the next step.
140             genLValueScalarMethods(q(maximumNumberOfProcesses)); #I Maximum number of processes to run in parallel
141             genLValueScalarMethods(q(out)); #I Optional file output area. This area will be cleared at the start of each launch.
142             genLValueScalarMethods(q(outFileLimit)); #I Limit on the number of files to be cleared from the L folder at the start of each launch.
143             genLValueScalarMethods(q(projects)); #I A reference to a hash of Data::Edit::Conversion::Project definitions. This can be most easily created by using L.
144             genLValueScalarMethods(q(save)); #I Temporary files will be stored in this folder
145             genLValueScalarMethods(q(stepNumberByName)); #O Get the number of a step from its name
146             genLValueArrayMethods (q(stepsByNumber)); #O Array of steps to be performed. The subs in this array call the user supplied subs after approriate set up and then do the required set down after the execution of each step.
147              
148             sub stepSaveFile($$$) #P Save file for a project and a step
149 1362     1362 1 2702 {my ($launch, $projectName, $step) = @_; # Launch specification, project, step name
150 1362 50       5002 ref($launch) =~ m(Data::Edit::Conversion)s or confess;
151 1362 50       2236 !ref($projectName) or confess;
152 1362         21311 fpe($launch->save, $projectName, $step, q(data))
153             }
154              
155             sub deleteProject($$$) #P Delete results before executing a particular step
156 130     130 1 294 {my ($launch, $projectName, $step) = @_; # Launch specification, project, step
157 130 50       970 ref($launch) =~ m(Data::Edit::Conversion)s or confess;
158 130 50       559 !ref($projectName) or confess;
159 130         1615 my $file = $launch->stepSaveFile($projectName, $step);
160 130         20906 unlink $file;
161             }
162              
163             sub saveProject($$$) #P Save project at a particular step
164 130     130 1 377 {my ($launch, $projectName, $step) = @_; # Launch specification, project, step
165 130 50       875 ref($launch) =~ m(Data::Edit::Conversion)s or confess;
166 130 50       451 !ref($projectName) or confess;
167 130         696 my $file = $launch->stepSaveFile($projectName, $step);
168 130         32475 makePath $file;
169 130         45881 my $project = $launch->projects->{$projectName};
170 130         1686 store $project, $file;
171             }
172              
173             sub loadProject($$$) #P Load a project at a particular step
174 31     31 1 207 {my ($launch, $projectName, $stepNumber) = @_; # Launch specification, project, step to reload
175 31 50       407 ref($launch) =~ m(Data::Edit::Conversion)s or confess;
176 31 50       108 !ref($projectName) or confess;
177 31         881 my $step = $launch->convert->[$stepNumber][0]; # Step anme from step number
178 31         278 my $file = $launch->stepSaveFile($projectName, $step);
179 31 50       2320 -e $file or confess "No such file:\n$file";
180 31         753 my $p = retrieve $file;
181 31 50       7922 $p or confess "Unable to retrieve project save file:\n$file";
182 31         732 $launch->projects->{$projectName} = $p;
183             }
184              
185             sub launchProject($$;$) #P Convert a single project in a seperate process
186 48     48 1 3208 {my ($launch, $projectName, $restart) = @_; # Launch specification, project to be processed, optional latest step to restart at
187 48 50       3429 ref($launch) =~ m(Data::Edit::Conversion)s or confess;
188 48 50       755 !ref($projectName) or confess;
189 48         11964 my $projects = $launch->projects; # Projects
190 48         1383 my $project = $projects->{$projectName}; # Project
191 48 50       702 $project or confess "No such project: $projectName";
192 48         2753 my $source = $project->source;
193 48         671 my $count = 0;
194 48         2030 my $steps = $launch->convert; # Conversion steps
195 48         712 my @steps = @$steps; # All the steps for a complete project
196              
197 48 100       700 if ($restart) # Remove steps we can skip in a restart because we have a restart file for that step
198 40         1333 {my $requested = $launch->stepNumberByName->{$restart}; # Requested restart step number
199             defined($requested) or confess "No such step: $restart, choose from: ". # Missing step
200 40 50       826 dump([sort keys %{$launch->stepNumberByName}]);
  0         0  
201 40         95 my $actual; # Actual restart step number
202 40         721 for my $step(1..$requested) # Each possible restart step
203 63         1547 {my $stepName = $launch->convert->[$step-1][0]; # Step name from step number
204 63         981 my $save = $launch->stepSaveFile($projectName, $stepName); # Save file
205 63 50       9142 last unless -e $save; # Have to start at the preceeding step if the required start file is missing for this step
206 63 100   1   1726 last if fileOutOfDate sub{1}, $save, $source; # Have to start at the preceeding step if the source file is newer than the start file
  1         140  
207 62         5563 $actual = $step-1; # Step we are going to restart at
208 62         175 shift @steps; # Consider step as done
209             }
210 40 100       561 if (defined $actual) # Overlay saved project
211 31         425 {$launch->loadProject($projectName, $actual);
212 31         694 $launch->projects->{$projectName}->stepTimes = {}; # Steps processed
213             }
214             }
215              
216 48         1232 for my $step(@steps) # Remove subsequent save files
217 130         1111 {my ($stepName) = @$step;
218 130         744 $launch->deleteProject($projectName, $stepName);
219             }
220              
221 48         299 for my $step(@steps) # Each step in the conversion
222 130         633 {my ($stepName, $code) = @$step;
223 130         3455 my $stepNumber = $launch->stepNumberByName->{$stepName};
224 130         3477 $launch->stepsByNumber->[$stepNumber]->($launch, $projectName);
225             }
226             } # launchProject
227              
228             sub loadProjectsFromFolder($@) #S Create a project for file in and below the specified folder and return the projects created
229 49     49 1 196 {my ($dir, @extensions) = @_; # Folder to search, list of file extensions to search for
230 49         294 my @f = searchDirectoryTreesForMatchingFiles($dir, @extensions);
231 49         190316 my $p = {}; # Project hash
232 49         539 for my $file(@f)
233 392         1911 {my (undef, $name, undef) = parseFileName($file); # Project name from file name
234 392         7693 $p->{$name} = # Create project definition
235             Data::Edit::Conversion::Project::new(name=>$name, source=>$file);
236             }
237 49         3724 bless $p, "Data::Edit::Conversion::Projects"; # Return hash of projects
238             }
239              
240             sub projectData($$) # Get L for a project after a launch has completed
241 1008     1008 1 254906 {my ($launch, $projectName) = @_; # Launch specification, project
242 1008         13028 $launch->projects->{$projectName}->data;
243             }
244              
245             sub projectSteps($$) # Get the L showing the executed time in seconds for each step in a project after a launch has completed. If a step name is not present in this hash then the step was not run.
246 1002     1002 1 2021 {my ($launch, $projectName) = @_; # Launch specification, project
247 1002         13507 $launch->projects->{$projectName}->stepTimes;
248             }
249              
250             package Data::Edit::Conversion::Project;
251 49     49   89719 use Carp qw(confess cluck);
  49         147  
  49         3087  
252 49     49   343 use Data::Dump qw(dump);
  49         98  
  49         2009  
253 49     49   294 use Data::Table::Text qw(:all);
  49         49  
  49         18424  
254 49     49   294 use Storable;
  49         147  
  49         1568  
255 49     49   196 use utf8;
  49         98  
  49         196  
256              
257             my %projects; # Prevent duplicate namea and number projects
258              
259             #1 Project # A project is one input file to be converted in one more restartable steps.
260              
261             #2 Construction # Methods used to construct projects
262              
263             sub new #S Create a project to describe the conversion of a source file containing xml representing documentation into one or more L topics.
264 392     392   1862 {my $p = bless{@_};
265 392         10731 $p->number = keys %projects;
266 392         8428 my $n = $p->name;
267 392         6615 my $s = $p->source;
268              
269 392 50       2352 confess "No name for project\n" unless $n;
270 392 50       1029 confess "Duplicate project: $n\n" if $projects{$n};
271 392 50       735 confess "No source file for project: $n\n" unless $s;
272 392 50       4704 confess "Source file does not exist: $s\n" unless -e $s;
273              
274 392         2597 $projects{$n} = $p;
275             }
276              
277             #2 Attributes # Attributes of a project
278             genLValueScalarMethods(q(name)); # Name of project.
279             genLValueScalarMethods(q(number)); # Number of the project.
280             genLValueScalarMethods(q(source)); # Input file containing the source xml.
281             genLValueScalarMethods(q(data)); # Per project data being converted
282             genLValueScalarMethods(q(stepTimes)); # Hash of steps processed during a launch
283             genLValueScalarMethods(q(test)) ; # Whether this is a test project or not
284             genLValueScalarMethods(q(title)); # Title of the project.
285             genLValueScalarMethods(q(numberOfFileNamesRequested)); # Number of files names requested by this project
286              
287             #2 Methods # Methods applicable to a project
288              
289             my $stringToFileName; # Number of files created
290              
291             sub stringToFileName($$$) # Create a unique file name from a specified string.
292 4     4   48 {my ($project, $title, $ext) = @_; # Project, string, desired extension - defaults to .dita
293 4         75 my $N = $project->number; # Project number
294 4         64 my $n = $project->numberOfFileNamesRequested++; # File number
295 4         26 my $t = lc $title; # Edit out constructs that would produce annoying file names
296 4         7 $t =~ s/\s+//gs;
297 4         11 $t =~ s/<.+?>//gs;
298 4         7 $t =~ s/<.+?>//gs;
299 4         6 $t =~ s/[^a-zA-Z]//gs; # Readable ascii
300 4         20 fpe(qq($t$N).qq(_$n), $ext); # Project numnber makes each file unique despite use of separate processes to run conversions
301             }
302              
303             package Data::Edit::Conversion;
304              
305             #-------------------------------------------------------------------------------
306             # Export
307             #-------------------------------------------------------------------------------
308              
309 49     49   16709 use Exporter qw(import);
  49         98  
  49         1568  
310              
311 49     49   294 use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
  49         98  
  49         11417  
312              
313             @ISA = qw(Exporter);
314             @EXPORT_OK = qw(
315             );
316             %EXPORT_TAGS = (all=>[@EXPORT, @EXPORT_OK]);
317              
318             # podDocumentation
319              
320             =pod
321              
322             =encoding utf-8
323              
324             =head1 Name
325              
326             Data::Edit::Conversion - Perform a restartable series of steps in parallel.
327              
328             =head1 Synopsis
329              
330             Launch the conversion of several files, each represented by a project, in
331             parallel processes, saving the project state after each step of the conversion
332             so that subsequent conversions can be restarted at later steps to speed up
333             development by bypassing initial processing steps unless they are really
334             needed. The L and L are transferred back
335             from each project's sub process to the main calling process so that the main
336             process can further process their results.
337              
338             use warnings FATAL=>qw(all);
339             use strict;
340             use Test::More tests=>90;
341             use File::Touch;
342             use Data::Edit::Conversion;
343              
344             my $N = 8; # Number of test files == projects per launch
345              
346             makePath(my $inDir = q(in)); clearFolder($inDir, 20); # Create and clear folders
347              
348             my $tAge = File::Touch->new(mtime=>int time - 100); # Age file
349             $tAge->touch(writeFile(fpe($inDir, $_, q(xml)), <
350             $_
351             END
352              
353             my $convert = sub {my ($p) = @_; $p->data = $p->data =~ s(\s) ()gsr x 2}; # Convert one project
354              
355             my $l = Data::Edit::Conversion::new # Convert $N projects in parallel
356             (projects => Data::Edit::Conversion::loadProjectsFromFolder($inDir,qw(xml)),
357             convert =>
358             [[load => sub {my ($p) = @_; $p->data = readFile($p->source)}], # Load a project
359             [c1 => $convert],
360             [c2 => $convert],
361             [c3 => $convert],
362             ],
363             maximumNumberOfProcesses => $N,
364             );
365              
366             my $verify = sub # Verify launch results
367             {my (@stepsExecuted) = @_; # Steps that should have been executed
368             ok $l->projectData($_) eq $_ x 8 for 1..$N; # Check result of each conversion
369             is_deeply [sort keys %{$l->projectSteps($_)}], [@stepsExecuted] for 1..$N; # Check expected steps have been executed
370             };
371              
372             $l->launch; &$verify(qw(c1 c2 c3 load)); # Full run
373             $l->restart(q(load)); &$verify(qw(c1 c2 c3 load)); # Restart the launch at various points
374             $l->restart(q(c1)); &$verify(qw(c1 c2 c3));
375             $l->restart(q(c2)); &$verify(qw(c2 c3));
376             $l->restart(q(c3)); &$verify(qw(c3));
377              
378             File::Touch->new(mtime=>int time + 100)->touch(qq($inDir/1.xml)); # Renew source file to force all the steps to be redone despite requesting a restart
379             $l->restart(q(c2), "After touch");
380             ok $l->projectData($_) eq $_ x 8 for 1..$N;
381             is_deeply [sort keys %{$l->projectSteps(1)}], [qw(c1 c2 c3 load)];
382             is_deeply [sort keys %{$l->projectSteps(2)}], [qw(c2 c3)];
383              
384             =head1 Description
385              
386              
387             The following sections describe the methods in each functional area of this
388             module. For an alphabetic listing of all methods by name see L.
389              
390              
391              
392             =head1 Methods
393              
394             Specify and run the restartable conversion of zero or more files in parallel
395              
396             =head2 new(@)
397              
398             Create a conversion specification for zero or more files represented by projects.
399              
400             Parameter Description
401             1 @attributes L describing the launch
402              
403             This is a static method and so should be invoked as:
404              
405             Data::Edit::Conversion::new
406              
407              
408             =head2 launch($$$)
409              
410             Launch the conversion of several files represented by projects in parallel
411              
412             Parameter Description
413             1 $launch Launch specification
414             2 $title Optional title
415             3 $restart Optional name of latest step to restart at.
416              
417             =head2 restart($$$)
418              
419             Launch the conversion of several files represented by projects in parallel, starting at the specified step: the L from the previous step will be restored unless it does not exist in which case the conversion will be run from the latest step available prior to this step or right from the start.
420              
421             Parameter Description
422             1 $launch Launch specification
423             2 $restart Step to restart at
424             3 $title Optional title
425              
426             =head1 Launch Attributes
427              
428             Use these attributes to configure a launch.
429              
430             =head2 convert :lvalue
431              
432             I [[step name => sub]...] A list of steps and their associated subs to process that step. At the end of each step the data stored on L is saved to allow for a later restart at the next step.
433              
434              
435             =head2 maximumNumberOfProcesses :lvalue
436              
437             I Maximum number of processes to run in parallel
438              
439              
440             =head2 out :lvalue
441              
442             I Optional file output area. This area will be cleared at the start of each launch.
443              
444              
445             =head2 outFileLimit :lvalue
446              
447             I Limit on the number of files to be cleared from the L folder at the start of each launch.
448              
449              
450             =head2 projects :lvalue
451              
452             I A reference to a hash of Data::Edit::Conversion::Project definitions. This can be most easily created by using L.
453              
454              
455             =head2 save :lvalue
456              
457             I Temporary files will be stored in this folder
458              
459              
460             =head2 stepNumberByName :lvalue
461              
462             O Get the number of a step from its name
463              
464              
465             =head2 stepsByNumber :lvalue
466              
467             O Array of steps to be performed. The subs in this array call the user supplied subs after approriate set up and then do the required set down after the execution of each step.
468              
469              
470             =head2 loadProjectsFromFolder($@)
471              
472             Create a project for file in and below the specified folder and return the projects created
473              
474             Parameter Description
475             1 $dir Folder to search
476             2 @extensions List of file extensions to search for
477              
478             This is a static method and so should be invoked as:
479              
480             Data::Edit::Conversion::loadProjectsFromFolder
481              
482              
483             =head2 projectData($$)
484              
485             Get L for a project after a launch has completed
486              
487             Parameter Description
488             1 $launch Launch specification
489             2 $projectName Project
490              
491             =head2 projectSteps($$)
492              
493             Get the L showing the executed time in seconds for each step in a project after a launch has completed. If a step name is not present in this hash then the step was not run.
494              
495             Parameter Description
496             1 $launch Launch specification
497             2 $projectName Project
498              
499             =head1 Project
500              
501             A project is one input file to be converted in one more restartable steps.
502              
503             =head2 new()
504              
505             Create a project to describe the conversion of a source file containing xml representing documentation into one or more L topics.
506              
507              
508             This is a static method and so should be invoked as:
509              
510             Data::Edit::Conversion::new
511              
512              
513             =head2 name :lvalue
514              
515             I Name of project.
516              
517              
518             =head2 number :lvalue
519              
520             I Number of the project.
521              
522              
523             =head2 source :lvalue
524              
525             I Input file containing the source xml.
526              
527              
528             =head2 data :lvalue
529              
530             O Per project data being converted
531              
532              
533             =head2 stepTimes :lvalue
534              
535             O Hash of steps processed during a launch
536              
537              
538             =head2 title :lvalue
539              
540             I Title of the project.
541              
542              
543              
544             =head1 Private Methods
545              
546             =head2 defaultMaximumNumberOfProcesses()
547              
548             Default maximum number of processes to use during the conversion
549              
550              
551             =head2 defaultOutFileLimit()
552              
553             Default maximum number of files to clear art a time.
554              
555              
556             =head2 stepSaveFile($$$)
557              
558             Save file for a project and a step
559              
560             Parameter Description
561             1 $launch Launch specification
562             2 $projectName Project
563             3 $step Step name
564              
565             =head2 deleteProject($$$)
566              
567             Delete results before executing a particular step
568              
569             Parameter Description
570             1 $launch Launch specification
571             2 $projectName Project
572             3 $step Step
573              
574             =head2 saveProject($$$)
575              
576             Save project at a particular step
577              
578             Parameter Description
579             1 $launch Launch specification
580             2 $projectName Project
581             3 $step Step
582              
583             =head2 loadProject($$$)
584              
585             Load a project at a particular step
586              
587             Parameter Description
588             1 $launch Launch specification
589             2 $projectName Project
590             3 $stepNumber Step to reload
591              
592             =head2 launchProject($$$)
593              
594             Convert a single project in a seperate process
595              
596             Parameter Description
597             1 $launch Launch specification
598             2 $projectName Project to be processed
599             3 $restart Optional latest step to restart at
600              
601              
602             =head1 Index
603              
604              
605             1 L
606              
607             2 L
608              
609             3 L
610              
611             4 L
612              
613             5 L
614              
615             6 L
616              
617             7 L
618              
619             8 L
620              
621             9 L
622              
623             10 L
624              
625             11 L
626              
627             12 L
628              
629             13 L
630              
631             14 L
632              
633             15 L
634              
635             16 L
636              
637             17 L
638              
639             18 L
640              
641             19 L
642              
643             20 L
644              
645             21 L
646              
647             22 L
648              
649             23 L
650              
651             24 L
652              
653             25 L
654              
655             26 L
656              
657             27 L
658              
659             =head1 Installation
660              
661             This module is written in 100% Pure Perl and, thus, it is easy to read,
662             comprehend, use, modify and install via B:
663              
664             sudo cpan install Data::Edit::Conversion
665              
666             =head1 Author
667              
668             L
669              
670             L
671              
672             =head1 Copyright
673              
674             Copyright (c) 2016-2018 Philip R Brenan.
675              
676             This module is free software. It may be used, redistributed and/or modified
677             under the same terms as Perl itself.
678              
679             =cut
680              
681              
682              
683             # Tests and documentation
684              
685             sub test
686 49     49 0 490 {my $p = __PACKAGE__;
687 49         441 binmode($_, ":utf8") for *STDOUT, *STDERR;
688 49 50       2548 return if eval "eof(${p}::DATA)";
689 49         2842 my $s = eval "join('', <${p}::DATA>)";
690 49 50       294 $@ and die $@;
691 49     49   245 eval $s;
  49     49   98  
  49     49   1519  
  49     49   196  
  49         98  
  49         1960  
  49         27195  
  49         2982434  
  49         833  
  49         135044  
  49         748818  
  49         43855  
  49         3381  
692 1 50       626 $@ and die $@;
693             }
694              
695             test unless caller;
696              
697             1;
698             # podDocumentation
699             __DATA__