/
Trace.pm
521 lines (374 loc) · 13.6 KB
/
Trace.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
# Copyright (C) 2001-2007, Parrot Foundation.
# $Id$
package Parrot::Configure::Trace;
use strict;
use warnings;
use Carp;
use Storable qw(nstore retrieve);
sub new {
my $class = shift;
my $argsref = shift || {};
croak "Constructor correctly failed due to non-hashref argument"
unless ref($argsref) eq 'HASH';
my $self = bless( [], $class );
my $sto = $argsref->{storable} || q{.configure_trace.sto};
eval { @{$self} = @{ retrieve($sto) }; };
if ($@) {
croak "Unable to retrieve storable file of configuration step data";
}
else {
return $self;
}
}
sub list_steps {
my $self = shift;
return $self->[0];
}
sub index_steps {
my $self = shift;
my @steps = @{ $self->list_steps() };
my %index = ();
for ( my $i = 0 ; $i <= $#steps ; $i++ ) {
$index{ $steps[$i] } = $i + 1;
}
return \%index;
}
sub trace_options_c {
my ( $self, $argsref ) = @_;
my @data = @{$self};
my @c = ();
for ( my $step = 1 ; $step <= $#data ; $step++ ) {
my $value = $data[$step]->{options}->{c}->{ $argsref->{attr} };
if ( $argsref->{verbose} ) {
push @c, { $self->[0]->[ $step - 1 ] => $value };
}
else {
push @c, $value;
}
}
return \@c;
}
sub trace_options_triggers {
my ( $self, $argsref ) = @_;
my @data = @{$self};
my @triggers = ();
for ( my $step = 1 ; $step <= $#data ; $step++ ) {
my $value = $data[$step]->{options}->{triggers}->{ $argsref->{trig} };
if ( $argsref->{verbose} ) {
push @triggers, { $self->[0]->[ $step - 1 ] => $value };
}
else {
push @triggers, $value;
}
}
return \@triggers;
}
sub trace_data_c {
my ( $self, $argsref ) = @_;
my @data = @{$self};
my @c = ();
for ( my $step = 1 ; $step <= $#data ; $step++ ) {
my $value = $data[$step]->{data}->{c}->{ $argsref->{attr} };
if ( $argsref->{verbose} ) {
push @c, { $self->[0]->[ $step - 1 ] => $value };
}
else {
push @c, $value;
}
}
return \@c;
}
sub diff_data_c {
my ( $self, $argsref ) = @_;
$argsref->{verbose} = 1;
my $trace_ref = $self->trace_data_c($argsref);
my @traces = @{ $trace_ref };
my @results = ();
for (my $i = 1; $i < scalar(@traces); $i++) {
my %prior = %{$traces[$i - 1]};
my %this = %{$traces[$i]};
my ($prior_key, $prior_value) = each %prior;
my ($this_key, $this_value) = each %this;
$prior_value = q{} unless defined $prior_value;
$this_value = q{} unless defined $this_value;
if ($prior_value ne $this_value) {
push @results, {
number => $i,
name => $this_key,
before => $prior_value,
after => $this_value,
};
}
}
return \@results;
}
sub trace_data_triggers {
my ( $self, $argsref ) = @_;
my @data = @{$self};
my @triggers = ();
for ( my $step = 1 ; $step <= $#data ; $step++ ) {
my $value = $data[$step]->{data}->{triggers}->{ $argsref->{trig} };
if ( $argsref->{verbose} ) {
push @triggers, { $self->[0]->[ $step - 1 ] => $value };
}
else {
push @triggers, $value;
}
}
return \@triggers;
}
sub get_state_at_step {
my $self = shift;
my $step = shift;
my $state;
if ( $step =~ /^\d+$/ ) {
croak "Must supply positive integer as step number"
unless $step > 0 and $step <= $#{ $self->[0] };
return $self->[$step];
}
else {
my $index = $self->index_steps();
croak "Must supply valid step name"
unless $index->{$step};
return $self->[ $index->{$step} ];
}
}
################### DOCUMENTATION ###################
=head1 NAME
Parrot::Configure::Trace - Trace development of Parrot::Configure object through the configuration steps
=head1 SYNOPSIS
When calling F<perl Configure.pl>:
$ perl Configure.pl --configure_trace
After configuration has completed:
use Parrot::Configure::Trace;
$obj = Parrot::Configure::Trace->new();
$steps_list = $obj->list_steps();
$steps_index = $obj->index_steps();
$attr = $obj->trace_options_c( {
attr => 'some_attr',
verbose => 1, # optional
} );
$attr = $obj->trace_options_triggers( {
trig => 'some_trig',
verbose => 1, # optional
} );
$attr = $obj->trace_data_c( {
attr => 'some_attr',
verbose => 1, # optional
} );
$list_diff_steps = $obj->diff_data_c( {
attr => 'some_attr',
} );
$attr = $obj->trace_data_triggers( {
trig => 'some_trig',
verbose => 1, # optional
} );
$state = $obj->get_state_at_step($step_no);
$state = $obj->get_state_at_step('some::step');
=head1 DESCRIPTION
This module provides ways to trace the evolution of the data structure within
the Parrot::Configure object over the various steps in the configuration
process. An understanding of this data structure's development may be useful
to Parrot developers working on the configuration process or its results.
To make use of Parrot::Configure::Trace's methods, first configure with the
C<--configure_trace> option. As configuration proceeds through what are
currently 56 individual steps, the state of the Parrot::Configuration object
is recorded in a Perl array reference. That array ref is stored on disk via
the Storable module in a file called F<.configure_trace.sto> found in the
top-level of your Parrot sandbox directory.
Once that storable file has been created, you can write programs which
retrieve its data into a Parrot::Configure::Trace object and then call methods
on that object.
=head1 METHODS
=head2 C<new()>
$obj = Parrot::Configure::Trace->new();
=over 4
=item * Purpose
Parrot::Configure::Trace constructor. Retrieve configuration data recorded on
disk over the course of the configuration steps and populate a
Parrot::Configure::Trace object with that data.
=item * Arguments
None currently required. However, to provide for future extensibility, you
may provide a reference to a hash in which various attributes are set which
will affect the Parrot::Configure::Trace object. Currently, the only such
attribute is C<storable>, whose value is the name of the Storable file holding
configuration data if that file is named something other than
F<.configure_trace.sto>.
=item * Return Value
Parrot::Configure::Trace object.
=item * Comment
The Parrot::Configure::Trace object is a blessed array reference. Element
C<0> of that array is a reference to an array holding the names of the
individual configuration steps; elements C<1> through C<$#array> hold the
state of the Parrot::Configure object at the conclusion of each step.
Since the purpose of Parrot::Configure::Trace is to track the B<evolution> of
the Parrot::Configure object through the configuration steps, there is no
point in recording information about those parts of the Parrot::Configure
object which are invariant. The C<steps> element is set in F<Configure.pl>
before the configuration steps are run and does not change during those steps.
Hence, no information about the C<steps> element is recorded and no methods
are provided herein to retrieve that information. Since the C<options> and
(especially) C<data> elements of the Parrot::Configure object do change over
the course of configuration, methods are provided to access that data.
=back
=head2 C<list_steps()>
$steps_list = $obj->list_steps();
=over 4
=item * Purpose
Provide list of the names of the configuration steps.
=item * Arguments
None.
=item * Return Value
Array reference:
[
'init::manifest',
'init::defaults',
...
'gen::config_pm'
]
=back
=head2 C<index_steps()>
$steps_index = $obj->index_steps();
=over 4
=item * Purpose
Provide lookup table showing which step number a given configuration step is.
=item * Arguments
None.
=item * Return Value
Hash reference:
{
'inter::ops' => 19,
'init::optimize' => 13,
...
'init::defaults' => 2,
}
=back
=head2 C<trace_options_c()>
=over 4
=item * Purpose
Provide a list of the values which a given attribute in the C<{options}->{c}>
part of the Parrot::Configure object takes over the course of the
configuration steps.
=item * Arguments
Hash reference. Key C<attr> is mandatory; it is the key whose value you wish
to trace over the course of the configuration steps. Key C<verbose> is
optional.
=item * Return Value
Array reference. Element C<n> of this array holds the value of the attribute
in the C<{options}->{c}> part of the Parrot::Configure object at configuration
step C<n + 1>.
If, however, C<verbose> is set, each element C<n> of the array holds a hash
reference where the hash key is the name of configuration step C<n + 1> and
the value is the value of the attribute at step C<n + 1>.
=back
=head2 C<trace_data_triggers()>
=over 4
=item * Purpose
Provide a list of the values which a given attribute in the
C<{options}->{triggers}> part of the Parrot::Configure object takes over the
course of the configuration steps.
=item * Arguments
Hash reference. Key C<attr> is mandatory; it is the key whose value you wish
to trace over the course of the configuration steps. Key C<verbose> is
optional.
=item * Return Value
Array reference. Element C<n> of this array holds the value of the attribute
in the C<{options}->{triggers}> part of the Parrot::Configure object at
configuration step C<n + 1>.
If, however, C<verbose> is set, each element C<n> of the array holds a hash
reference where the hash key is the name of configuration step C<n + 1> and
the value is the value of the attribute at step C<n + 1>.
=back
=head2 C<trace_data_c()>
=over 4
=item * Purpose
Provide a list of the values which a given attribute in the C<{data}->{c}>
part of the Parrot::Configure object takes over the course of the
configuration steps.
=item * Arguments
Hash reference. Key C<attr> is mandatory; it is the key whose value you wish
to trace over the course of the configuration steps. Key C<verbose> is
optional.
=item * Return Value
Array reference. Element C<n> of this array holds the value of the attribute
in the C<{data}->{c}> part of the Parrot::Configure object at configuration
step C<n + 1>.
If, however, C<verbose> is set, each element C<n> of the array holds a hash
reference where the hash key is the name of configuration step C<n + 1> and
the value is the value of the attribute at step C<n + 1>.
=back
=head2 C<diff_data_c()>
=over 4
=item * Purpose
Provide a list of those configuration steps where the value of a given
attribute in the C<{data}->{c}> part of the Parrot::Configure object changed
from that in effect at the conclusion of the preveious configuration step.
=item * Arguments
Hash reference. Key C<attr> is mandatory; it is the key whose changes in
value between various steps you wish to trace over the course of
configuration.
=item * Return Value
Array reference. Each element of the array is a reference to a hash holding
information about those configuration steps where the value of a given
attribute changed from the previous configuration step. The hash has the
following key-value pairs:
=over 4
=item * number
Number of the configuration step where the value of the given attribute
changed; enumeration starts at C<1>, not C<0>.
=item * name
Name of the configuration step where the value of the given attribute changed.
=item * before
For step C<n>, the value of the attribute at step C<n-1>.
=item * after
For step C<n>, the value of the attribute at step C<n>.
=back
=item * Comment
The array whose reference is the return value of this method only contains
elements for those configuration steps where the value of the given attribute
changed. Nothing is reported if nothing changed.
=back
=head2 C<trace_data_triggers()>
=over 4
=item * Purpose
Provide a list of the values which a given attribute in the
C<{data}->{triggers}> part of the Parrot::Configure object takes over the
course of the configuration steps.
=item * Arguments
Hash reference. Key C<attr> is mandatory; it is the key whose value you wish
to trace over the course of the configuration steps. Key C<verbose> is
optional.
=item * Return Value
Array reference. Element C<n> of this array holds the value of the attribute
in the C<{data}->{triggers}> part of the Parrot::Configure object at
configuration step C<n + 1>.
If, however, C<verbose> is set, each element C<n> of the array holds a hash
reference where the hash key is the name of configuration step C<n + 1> and
the value is the value of the attribute at step C<n + 1>.
=back
=head2 C<get_state_at_step()>
=over 4
=item * Purpose
Get a snapshot of the data structure in the Parrot::Configure object at the
conclusion of a given configuration step.
=item * Arguments
Either a positive integer corresponding to the step number:
$state = $obj->get_state_at_step(54);
... or the C<x::y> string corresponding to the step's name in
Parrot::Configure::Step::List.
$state = $obj->get_state_at_step('gen::makefiles');
=item * Return Value
Hash reference.
=back
=head1 AUTHOR
James E Keenan (jkeenan@cpan.org)
=head1 SEE ALSO
L<Parrot::Configure>, L<Parrot::Configure::Options>, F<Configure.pl>.
=cut
1;
# Local Variables:
# mode: cperl
# cperl-indent-level: 4
# fill-column: 100
# End:
# vim: expandtab shiftwidth=4: