]>
git.ipfire.org Git - thirdparty/squid.git/blob - scripts/trace-entry.pl
3 # Reads cache.log and displays lines that correspond to a given store entry.
5 # Store entry can be identified by its key or an anchor slot ID in a rock-style
8 # Currently, the script reads and remembers many irrelevant lines because it
9 # does not know which one should be tracked in advance.
16 my @InterestingEntries = @ARGV;
17 #die("usage: $0 [entry number|key value|pointer address] ...\n");
21 my %EntriesByPartId = ();
23 my %CurrentEntries = ();
32 #$DEB = 1 if /16:53:44.632/;
34 ($Kid) = (/(kid\d+)[|]/);
35 $Kid = 'kid0' unless defined $Kid;
37 &enterBlock
($., $_) if
38 (/[|:] entering\b/ && !/Port::noteRead/) ||
39 (/Port::noteRead/ && /handling/);
41 next unless $Inside{$Kid};
43 while ($line =~ s@
\b(entry
) (\d
+) .*?
(\S
*_map
)@ @
) {
44 &processEntryPartId
("$3.$1", $2);
47 while ($line =~ s@
\b(slice
|slot
) (\d
+)@ @
) {
48 &processEntryPartId
($1, $2);
51 #while ($line =~ s@\b(page) (\w+)@ @) {
52 # &processEntryPartId($1, $2);
55 while ($line =~ s@
\b(key
) '?(\w+)@ @) {
56 &processEntryPartId($1, $2);
59 while ($line =~ s@\b([A-Z0-9]{32})\b@ @) {
60 &processEntryPartId('key
', $1);
63 while ($line =~ s@\be:\S*?/(0x\w+)@ @ || $line =~ s@\bStoreEntry\s+(0x\w+)@ @) {
64 &processEntryPartId('pointer
', $1);
67 if ($line ne $_ || /[|:] leaving\b/) {
68 if (my $entry = $CurrentEntries{$Kid}) {
69 &updateEntry($entry, $Entering{$Kid}) if exists $Entering{$Kid};
70 delete $Entering{$Kid};
71 &updateEntry($entry, &historyLine($., $_));
76 (/[|:] leaving\b/ && !/Port::noteRead/) ||
77 (/Port::noteRead/ && /handled/);
82 my %cleanEntries = ();
83 foreach my $id (sort { $a <=> $b } keys %Entries) {
84 my $entry = $Entries{$id};
86 next unless &mergeAllLinkedEntries($entry);
88 $entry->{id} = 1 + scalar keys %cleanEntries;
89 $cleanEntries{$entry->{id}} = $entry;
91 %Entries = %cleanEntries;
93 printf("Saw %d entries\n", scalar keys %Entries);
95 if (!@InterestingEntries) { # print all entries
96 foreach my $id (sort { $a <=> $b } keys %Entries) {
97 my $entry = $Entries{$id};
98 reportEntry($entry, 1);
101 foreach my $description (@InterestingEntries) {
102 my ($part, $id) = ($description =~ /(\w+)\s+(\w+)/);
103 my $entry = &getExistingEntry($part, $id);
104 reportEntry($entry, 1);
111 my ($lineNo, $lineText) = @_;
113 $Entering{$Kid} = &historyLine($., $_);
114 die("double entrance, stopped") if $Inside{$Kid};
119 $CurrentEntries{$Kid} = undef();
120 delete $Entering{$Kid};
124 sub processEntryPartId {
125 my ($part, $id) = @_;
127 #warn("XXX1: $Kid| part.id: $part.$id\n") if $DEB;
130 my $curEntry = $CurrentEntries{$Kid};
131 my $oldEntry = &getExistingEntry($part, $id);
132 if ($curEntry && $oldEntry && $curEntry->{id} != $oldEntry->{id}) {
133 &linkEntries($curEntry, $oldEntry, "$part.$id");
136 $entry = $curEntry ? $curEntry : $oldEntry;
138 $entry = &getEntry($part, $id) unless defined $entry;
139 $CurrentEntries{$Kid} = $entry;
141 $entry->{parts}->{$part} = {} unless exists $entry->{parts}->{$part};
142 $entry->{parts}->{$part}->{$id} = $_ unless exists $entry->{parts}->{$part}->{$id};
146 my ($lineCount, $line) = @_;
147 return sprintf("#%06d %s", $lineCount, $line);
151 my ($entry, $historyLine) = @_;
153 $entry->{history} .= $historyLine;
157 my ($e1, $e2, $ctx) = @_;
159 $e1->{sameAs}->{$e2->{id}} = 1;
160 $e2->{sameAs}->{$e1->{id}} = 1;
163 sub mergeAllLinkedEntries {
166 #warn(sprintf("merging %d <-- * %s\n", $entry->{id}, $entry->{merged} ? "skipped" : ""));
168 return 0 if $entry->{merged};
169 $entry->{merged} = 1;
171 foreach my $otherId (keys %{$entry->{sameAs}}) {
172 my $otherE = $Entries{$otherId};
173 die("missing internal entry$otherId, stopped") unless $otherE;
174 next if $otherE->{merged};
175 &mergeAllLinkedEntries($otherE);
176 &mergeOneEntry($entry, $otherE);
177 $otherE->{merged} = 1;
184 my ($entry, $otherE) = @_;
186 #warn(sprintf("merging %d <-- %d\n", $entry->{id}, $otherE->{id}));
188 foreach my $part (keys %{$otherE->{parts}}) {
189 foreach my $id (keys %{$otherE->{parts}->{$part}}) {
190 $entry->{parts}->{$part}->{$id} = $otherE->{parts}->{$part}->{$id};
194 $entry->{history} .= $otherE->{history};
197 sub getExistingEntry {
198 my ($part, $id) = @_;
200 return $EntriesByPartId{$part}->{$id} if exists $EntriesByPartId{$part};
205 my ($part, $id) = @_;
207 $EntriesByPartId{$part} = {} unless exists $EntriesByPartId{$part};
208 my $entry = $EntriesByPartId{$part}->{$id};
209 return $entry if $entry;
212 id => ++$LastEntryId,
221 $entry->{parts}->{$part} = {};
222 $EntriesByPartId{$part}->{$id} = $entry;
223 $Entries{$LastEntryId} = $entry;
229 my ($entry, $recursive) = @_;
231 return if $entry->{reported};
232 $entry->{reported} = 1;
234 printf("entry%d:\n", $entry->{id});
236 foreach my $part (keys %{$entry->{parts}}) {
237 printf("\t%s(s):", $part);
238 foreach my $id (keys %{$entry->{parts}->{$part}}) {
244 &reportEntryHistory($entry);
247 sub reportEntryParam {
248 my ($entry, $name, $value) = @_;
250 $value = $entry->{$name} if @_ < 3;
251 $value = '?
' unless defined $value;
252 $value = "\n$value" if $value =~ /\n/m;
253 printf("\t%s: %s\n", $name, $value);
256 sub reportEntryHistory {
259 my $history = $entry->{history};
260 my @lines = split(/\n/, $history);
261 &reportEntryParam($entry, 'history
', (scalar @lines) . " lines");
264 foreach my $line (sort @lines) {
265 my ($kid) = ($line =~ /(kid\d+)[|]/);
266 $kid = 'kid0
' unless defined $kid;
268 print "\n" if $lastKid ne $kid;
272 print "\n" if @lines;