diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:35:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:35:32 +0000 |
commit | 5ea77a75dd2d2158401331879f3c8f47940a732c (patch) | |
tree | d89dc06e9f4850a900f161e25f84e922c4f86cc8 /contrib/slapd-tools | |
parent | Initial commit. (diff) | |
download | openldap-upstream.tar.xz openldap-upstream.zip |
Adding upstream version 2.5.13+dfsg.upstream/2.5.13+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'contrib/slapd-tools')
-rw-r--r-- | contrib/slapd-tools/README | 23 | ||||
-rwxr-xr-x | contrib/slapd-tools/statslog | 171 | ||||
-rwxr-xr-x | contrib/slapd-tools/wrap_slap_ops | 162 |
3 files changed, 356 insertions, 0 deletions
diff --git a/contrib/slapd-tools/README b/contrib/slapd-tools/README new file mode 100644 index 0000000..9098a20 --- /dev/null +++ b/contrib/slapd-tools/README @@ -0,0 +1,23 @@ +Directory contents: + +statslog + Program to output selected parts of slapd's statslog output + (LDAP request/response log), grouping log lines by LDAP + connection. Useful to search and inspect the server log. + +wrap_slap_ops + Update source code to use the wrapper macros SLAP_OP() & co + for LDAP-operation backend calls. They can help debug the + SlapReply. They compile like the old code by default. + +--- +Copyright 2004-2022 The OpenLDAP Foundation. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted only as authorized by the OpenLDAP +Public License. + +A copy of this license is available in the file LICENSE in the +top-level directory of the distribution or, alternatively, at +<http://www.OpenLDAP.org/license.html>. + diff --git a/contrib/slapd-tools/statslog b/contrib/slapd-tools/statslog new file mode 100755 index 0000000..840bd4e --- /dev/null +++ b/contrib/slapd-tools/statslog @@ -0,0 +1,171 @@ +#!/usr/bin/perl -w +# statslog - Rearrange and output selected parts of slapd's statslog output. +# $OpenLDAP$ +# This work is part of OpenLDAP Software <http://www.openldap.org/>. +# +# Copyright 1998-2022 The OpenLDAP Foundation. +# Portions Copyright 2004 Hallvard B. Furuseth. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted only as authorized by the OpenLDAP +# Public License. +# +# A copy of this license is available in the file LICENSE in the +# top-level directory of the distribution or, alternatively, at +# <http://www.OpenLDAP.org/license.html>. + +sub usage { + die join("", @_, <<'EOM'); +Usage: statslog [options] [logfiles; may be .gz or .bz2 files] + + Output selected parts of slapd's statslog output (LDAP request/response + log to syslog or stderr; loglevel 256), grouping log lines by LDAP + connection. Lines with no connection are excluded by default. + +Options: + --brief -b Brief output (omit time, host/process name/ID). + --exclude=RE -e RE Exclude connections whose output matches REgexp. + --include=RE -i RE Only include connections matching REgexp. + --EXCLUDE=RE -E RE Case-sensitive '--exclude'. + --INCLUDE=RE -I RE Case-sensitive '--include'. + --loose -l Include "loose" lines (lines with no connection). + --no-loose -L RE Only exclude the "loose" lines that match RE. + --join -j Join the inputs as if they were one big log file. + Each file must start where the previous left off. + --no-join -J Do not --join. (Can be useful with --sort.) + --sort -s Sort input files by age. Implies --join. + --trace -t Print file names when read. Implies --no-join. +All --exclude/include options are applied. Note: --exclude/include are +unreliable without --join/sort for connections spanning several log files. +EOM +} + +######################################################################## + +use bytes; +use strict; +use Getopt::Long; + +# Globals +my %conns; # Hash (connection number -> output) +my @loose; # Collected output with no connection number + +# Command line options +my($brief, @filters, @conditions, $no_loose); +my($join_files, $sort_files, $trace, $getopt_ok); + +# Handle --include/INCLUDE/exclude/EXCLUDE options +sub filter_opt { + my($opt, $regexp) = @_; + push(@conditions, sprintf('$lines %s /$filters[%d]/om%s', + (lc($opt) eq 'include' ? "=~" : "!~"), + scalar(@filters), + ($opt eq lc($opt) ? "i" : ""))); + push(@filters, $regexp); +} + +# Parse options at compile time so some can become constants to optimize away +BEGIN { + &Getopt::Long::Configure(qw(bundling no_ignore_case)); + $getopt_ok = GetOptions("brief|b" => \$brief, + "include|i=s" => \&filter_opt, + "exclude|e=s" => \&filter_opt, + "INCLUDE|I=s" => \&filter_opt, + "EXCLUDE|E=s" => \&filter_opt, + "join|j" => \$join_files, + "no-join|J" => sub { $join_files = 0; }, + "sort|s" => \$sort_files, + "loose|l" => sub { $no_loose = ".^"; }, + "no-loose|L=s" => \$no_loose, + "trace|t" => \$trace); +} +usage() unless $getopt_ok; +usage("--trace is incompatible with --join.\n") if $trace && $join_files; + +$join_files = 1 if !defined($join_files) && $sort_files && !$trace; +use constant BRIEF => !!$brief; +use constant LOOSE => defined($no_loose) && ($no_loose eq ".^" ? 2 : 1); + +# Build sub out(header, connection number) to output one connection's data +my $out_body = (LOOSE + ? ' if (@loose) { print "\n", @loose; @loose = (); } ' + : ''); +$out_body .= ' print "\n", $_[0], $lines; '; +$out_body = " if (" . join("\n && ", @conditions) . ") {\n$out_body\n}" + if @conditions; +eval <<EOM; +sub out { + my \$lines = delete(\$conns{\$_[1]}); + $out_body +} +1; +EOM +die $@ if $@; + +# Read and output log lines from one file +sub do_file { + local(@ARGV) = @_; + my($conn, $line, $act); + while (<>) { + if (BRIEF + ? (($conn, $line, $act) = /\bconn=(\d+) (\S+ (\S+).*\n)/) + : (($conn, $act) = /\bconn=(\d+) \S+ (\S+)/ )) { + $conns{$conn} .= (BRIEF ? $line : $_); + out("", $conn) if $act eq 'closed'; + } elsif (LOOSE && (LOOSE > 1 || !/$no_loose/omi)) { + s/^\w{3} [ \d]+:\d\d:\d\d [^:]*: // if BRIEF; + push(@loose, $_); + } + } + final() unless $join_files; +} + +# Output log lines for unfinished connections +sub final { + if (%conns) { + for my $conn (sort keys %conns) { + out("UNFINISHED:\n", $conn); + } + die if %conns; + } + if (LOOSE && @loose) { print "\n", @loose; @loose = (); } +} + +# Main program +if (!@ARGV) { + # Read from stdin + do_file(); +} else { + if ($sort_files && @ARGV > 1) { + # Sort files by last modified time; oldest first + my @fileinfo; + for my $file (@ARGV) { + my $age = -M $file; + if (defined($age)) { + push(@fileinfo, [$age, $file]); + } else { + print STDERR "File not found: $file\n"; + } + } + exit(1) unless @fileinfo; + @ARGV = map { $_->[1] } sort { $b->[0] <=> $a->[0] } @fileinfo; + } + + # Prepare to pipe .gz, .bz2 and .bz files through gunzip or bunzip2 + my %type2prog = ("gz" => "gunzip", "bz2" => "bunzip2", "bz" => "bunzip2"); + for (@ARGV) { + if (/\.(gz|bz2?)$/) { + my $type = $1; + die "Bad filename: $_\n" if /^[+-]|[^\w\/.,:%=+-]|^$/; + $_ = "$type2prog{$type} -c $_ |"; + } + } + + # Process the files + for my $file (@ARGV) { + print "\n$file:\n" if $trace; + do_file($file); + } +} +final(); diff --git a/contrib/slapd-tools/wrap_slap_ops b/contrib/slapd-tools/wrap_slap_ops new file mode 100755 index 0000000..16b0461 --- /dev/null +++ b/contrib/slapd-tools/wrap_slap_ops @@ -0,0 +1,162 @@ +#!/usr/bin/perl -wn0777 +# wrap_slap_ops - Help update code to use SLAP_OP() & co. +# +# This work is part of OpenLDAP Software <http://www.openldap.org/>. +# +# Copyright 2011-2022 The OpenLDAP Foundation. +# Portions Copyright 2011-2013 Hallvard B. Furuseth. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted only as authorized by the OpenLDAP +# Public License. +# +# A copy of this license is available in the file LICENSE in the +# top-level directory of the distribution or, alternatively, at +# <http://www.OpenLDAP.org/license.html>. + +use strict; + +sub usage() { + warn "Usage: $0 {-l | -u | -U<num>} {file | dir}... + +Update slapd source code to wrap LDAP operation calls in the debug +macros SLAP_OP() & co. They compile like the old code by default. +Define USE_RS_ASSERT to enable asserts which verify the SlapReply. +See servers/slapd/result.c. + +Options: + -u, -U<n> Output unidiffs with n lines of context (-u = default for diff). + -l List files which would change. Show remaining cases on stderr.\n"; + exit(1); +} + +#### File/option handling. Skips symlinks, handles filenames =~ /\.[ch]+p*$/i. + +sub ls_R { + map { -l $_ ? () : -d _ ? ls_R(<$_/*>) : /\.[ch]+p*$/i ? $_ : () } @_; +} + +use constant Mode => shift(@ARGV) || ""; +use vars qw($ccnt $rcnt); +INIT { + usage() unless Mode =~ /^-(l|[uU]\d*)$/ && ($ARGV[0]||"") =~ /^[^\-]/; + exit(0) unless @ARGV = ls_R(@ARGV); # Expand ARGV, exit if no files + $| = 1; + $ccnt = $rcnt = 0; +} + +sub file_result( $$ ) { + my($contents, $changed) = @_; + $ccnt++ if $changed; + $rcnt += scalar( my @rest = remaining($contents) ); + if (Mode eq "-l") { + print "$ARGV\n" if $changed; + print STDERR "$ARGV:\t$_\n" foreach @rest; + } elsif ($changed) { + (my $file = "$ARGV") =~ s%^-%./-%; + print "Index: $file\n"; + (open(D, "|-", "diff", Mode, $file, "-") + && (print D $contents) + && (close(D) || $! == 0)) or die "$0: diff failed: $!\n"; + } +} + +END { + print STDERR <<EOMSG if defined $ccnt; +$ccnt files to change. $rcnt suspicious lines remain. (Expect three in slapd). +EOMSG +} + +#### Edit the contents of a file + +use vars qw($obj_re %addr %func2op $func_re $todo_re); +INIT { + $obj_re = qr/(?:\w+ (?:\s* (?:->|\.) \s* \w+)*?)/x; + %addr = ("." => "&", "->" => ""); # x.y => (&x)->y, x->y => x->y + %func2op = map { /(\w+) \s+ (?= .*?=>\s* (\w+))/gx } <DATA>; + $func_re = '\b(?=b[ei]_)(?:' . join("|", keys %func2op) . ')\b'; + my %both = (%func2op, reverse %func2op); + $todo_re = '\b(?=[bo][eip]_)(?:' . join("|", keys %both) . ')\b'; +} +next if !/$todo_re/; +my $orig = "$_"; + +# x->func(op, rs) ==> slap_bi_op( x, <enum op_func>, op, rs) +# x. func(op, rs) ==> slap_bi_op(&x, <enum op_func>, op, rs) +s%( # 1: entire match: "<delim><function>(" + ((?: [\)!=\;{}\\] | \*/ | \b if\s*\( | \b return \b ) \s*) # 2: delim + (\(\s* (?:\* \s*)?)? # 3: optional "(*" or "(" in (*f)() + ($obj_re) \s* (->|\.) \s* # 4: object, 5: "->" or "." + (?=(b[ie]_))($func_re) \s* # 6: "bi_" or "be_", 7: function + (\)\s*)? # 8: optional ")" in (*f), + (\(\s*) # 9: "(" + whitespace +)% (!$3) == (!$8) ? "$2slap_$6op$9$addr{$5}$4, $func2op{$7}, " : $1 %egox; + +# (&x->bi_op_bind)[which](op, rs) ==> slap_bi_op(x, which, op, rs) +# (&x->be_bind)[which](op, rs) ==> slap_be_op(x, which, op, rs) +s/\(&(\w+(?:(?:->|\.)\w+)*)->b(?=([ei]))(?:e|i_op)_bind\)\[\s* (\w+) \s*\] \((\s*) ([^()]*)\) + /slap_b$2_op($4$1, $3, $5)/gox; + +# slap_bi_op(x->bd_info, which, op, rs) ==> slap_be_op( x, which, op, rs) +# slap_bi_op(x. bd_info, which, op, rs) ==> slap_be_op(&x, which, op, rs) +s/\b slap_bi_op (\(\s*) ($obj_re) \s* (->|\.) \s* bd_info \s*, + /slap_be_op$1$addr{$3}$2,/gox; + +# slap_be_op(op->o_bd, which, &op, rs) ==> SLAP_OP(which, op, rs) +# slap_be_op(op. o_bd, which, &op, rs) ==> SLAP_OP(which, &op, rs) +s/\b(slap_be_op (\(\s*) ($obj_re) \s*(->|\.)\s* o_bd, \s (\w+, \s (&?)\3,)) + / $addr{$4} eq $6 ? "SLAP_OP$2$5" : die "$ARGV: Bad syntax: $1\n" /egox; + +my $changed = $_ ne $orig; + +# When changing a file, do some whitespace cleanup too +if ($changed) { + s/\b ((SLAP_OP|slap_b[ei](func)?_op) \b .*?) [\ \t]+$ /$1/gmx; + s/\A\s*\n//; + s/\s*\z/\n/; +} + +file_result($_, $changed); + +#### + +# Return remaining lines that contain operation method names +sub remaining { + my($contents) = @_; + return $contents !~ /$func_re/o ? () : grep { + !/^\# [ \t]* define \s+ ($func_re|slap_bi_op\b) /x && + # Skip "if ( (&bi->bi_op_bind)[ which ] )" and variants + !/^(\} \s* else \s*)? if \s* \( \s* + \(& (\w+ | \(\s*\w+\s*=\s*$obj_re\s*\)) -> bi_op_bind\) + \s* \[ \s* \w+ \s* \] + \s* [&|\)]/ox; + } $contents =~ m% ^[\ \t]* (?=\S) ( + # The line contains a member opfunction + .*? (?:->|\.) \s* $func_re + + # Skip if the member function is assigned, compared, + # 'and/or'ed, followed by a word (this is a comment), or by + # ') {' or ') word' (function is the boolean in an if/while). + (?! \s* (?: [!=&|\w] | \)\s*[\{\w] )) + + .*? + ) \s*?$ %gmox; +} + +# %func2op: Member functions => slap_operation_t +__DATA__ +be_bind bi_op_bind => op_bind +be_unbind bi_op_unbind => op_unbind +be_search bi_op_search => op_search +be_compare bi_op_compare => op_compare +be_modify bi_op_modify => op_modify +be_modrdn bi_op_modrdn => op_modrdn +be_add bi_op_add => op_add +be_delete bi_op_delete => op_delete +be_abandon bi_op_abandon => op_abandon +be_extended bi_extended => op_extended +be_cancel bi_op_cancel => op_cancel +be_operational bi_operational => op_aux_operational +be_chk_referrals bi_chk_referrals => op_aux_chk_referrals +be_chk_controls bi_chk_controls => op_aux_chk_controls |