-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathdecodecsn
executable file
·145 lines (105 loc) · 3.49 KB
/
decodecsn
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
#!/usr/bin/perl -w
use strict;
use warnings;
use bignum qw(hex);
sub usage() {
print STDERR "Usage: $0 [-z timezone] csn [...]\n";
exit 1;
}
usage unless $#ARGV >= 0;
my $zone;
if ($ARGV[0] eq "-z") {
shift @ARGV;
$zone = shift @ARGV;
usage unless defined $zone;
}
if (eval{require DateTime}) {
$zone = DateTime::TimeZone->new(name => defined($zone) ? $zone : 'local');
} elsif (eval{require POSIX}) {
$zone = undef;
} else {
die "Cannot convert times due to missing modules (DateTime is preferred)\n"
}
sub ts2timestr($) {
my $ts_dec = shift;
if (defined $zone) {
my $time = DateTime->from_epoch( epoch => $ts_dec / 1000 ); # UTC
$time->set_time_zone($zone);
return $time->strftime("%a %b %e %Y %H:%M:%S.%3N %Z");
}
my $ms = sprintf "%03d", $ts_dec % 1000;
return POSIX::strftime("%a %b %e %Y %H:%M:%S.$ms %z", localtime($ts_dec / 1000));
}
foreach (@ARGV) {
my ($ts,$id,$no,$id_len);
if (($ts,$id,$no) = m{^0000(............)(....)(........)$}) {
# CSNs pre 6.5.0
my $ts_dec = hex($ts); # Value is 64-bits hence using bignum
my $id_dec = hex($id);
my $no_dec = hex($no);
my $ts_str = ts2timestr $ts_dec;
print "CSNv1 $_\n ts=$ts ($ts_dec) $ts_str\n id=$id ($id_dec)\n no=$no ($no_dec)\n";
} elsif (($id_len,$ts,$no,$id) = m{^01(..)(............)(........)(.*)}) {
# CSNs from 6.5.0 onwards
if (length($id) != hex($id_len)) {
warn "Not a CSN: $_\n";
next;
}
my $ts_dec = hex($ts); # Value is 64-bits hence using bignum
my $no_dec = hex($no);
my $ts_str = ts2timestr $ts_dec;
print "CSNv2 $_\n ts=$ts ($ts_dec) $ts_str\n id=$id\n no=$no ($no_dec)\n";
} else {
warn "Not a CSN: $_\n";
}
}
exit 0;
__END__
=head1 NAME
decodecsn - decode OpenDJ change sequence numbers
=head1 SYNOPSIS
decodecsn [-z timezone] csn [...]
=head1 DESCRIPTION
OpenDJ uses change sequence numbers to record information about replicated
changes. The CSN format is structured and can sometimes be usefully analyzed.
This tool decodes CSNs.
=head1 OPTIONS
=over
=item B<-z> use the following timezone name or offset instead of localtime to
display the date and time in the CSN. This uses the perl DateTime module. If
that module isn't installed this flag will be ignored and localtime will be
used.
=item B<csn> a change sequence number encoded in hex.
=back
=head1 EXAMPLES
$ decodecsn 0000014bcd10fe1562cd0083a482
CSNv1 0000014bcd10fe1562cd0083a482
ts=014bcd10fe15 (1425074617877) Fri Feb 27 2015 22:03:37.877 GMT
id=62cd (25293)
no=0083a482 (8627330)
$ decodecsn -z America/Los_Angeles 0000014bcd10fe1562cd0083a482
CSNv1 0000014bcd10fe1562cd0083a482
ts=014bcd10fe15 (1425074617877) Fri Feb 27 2015 14:03:37.877 PST
id=62cd (25293)
no=0083a482 (8627330)
$ decodecsn -z -0500 0000014bcd10fe1562cd0083a482
CSNv1 0000014bcd10fe1562cd0083a482
ts=014bcd10fe15 (1425074617877) Fri Feb 27 2015 17:03:37.877 -0500
id=62cd (25293)
no=0083a482 (8627330)
$ decodecsn 01050166b043d5fe000000c416407
CSNv2 01050166b043d5fe000000c416407
ts=0166b043d5fe (1540555527678) Fri Oct 26 2018 13:05:27.678 BST
id=16407
no=000000c4 (196)
=head1 WARNING
The format of the CSN is undocumented and subject to change. This tool has been
tested with CSNv1 (OpenDJ 2.4 to DS 6.0.0), and CSNv2 (DS 6.5.0 and up).
=head1 SEE ALSO
L<http://opendj.forgerock.org>
=head1 AUTHOR
Chris Ridd E<lt>chris.ridd@forgerock.comE<gt>
=head1 COPYRIGHT
Copyright (c) 2012-2018 Chris Ridd. All rights reserved. This tool is free
software; you can redistribute it and/or modify it under the same terms as Perl
itself.