]>
Commit | Line | Data |
---|---|---|
af59614d MKG |
1 | # BEGIN BPS TAGGED BLOCK {{{ |
2 | # | |
3 | # COPYRIGHT: | |
4 | # | |
320f0092 | 5 | # This software is Copyright (c) 1996-2014 Best Practical Solutions, LLC |
af59614d MKG |
6 | # <sales@bestpractical.com> |
7 | # | |
8 | # (Except where explicitly superseded by other copyright notices) | |
9 | # | |
10 | # | |
11 | # LICENSE: | |
12 | # | |
13 | # This work is made available to you under the terms of Version 2 of | |
14 | # the GNU General Public License. A copy of that license should have | |
15 | # been provided with this software, but in any event can be snarfed | |
16 | # from www.gnu.org. | |
17 | # | |
18 | # This work is distributed in the hope that it will be useful, but | |
19 | # WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
21 | # General Public License for more details. | |
22 | # | |
23 | # You should have received a copy of the GNU General Public License | |
24 | # along with this program; if not, write to the Free Software | |
25 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
26 | # 02110-1301 or visit their web page on the internet at | |
27 | # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. | |
28 | # | |
29 | # | |
30 | # CONTRIBUTION SUBMISSION POLICY: | |
31 | # | |
32 | # (The following paragraph is not intended to limit the rights granted | |
33 | # to you to modify and distribute this software under the terms of | |
34 | # the GNU General Public License and is only of importance to you if | |
35 | # you choose to contribute your changes and enhancements to the | |
36 | # community by submitting them to Best Practical Solutions, LLC.) | |
37 | # | |
38 | # By intentionally submitting any modifications, corrections or | |
39 | # derivatives to this work, or any other work intended for use with | |
40 | # Request Tracker, to Best Practical Solutions, LLC, you confirm that | |
41 | # you are the copyright holder for those contributions and you grant | |
42 | # Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable, | |
43 | # royalty-free, perpetual, license to use, copy, create derivative | |
44 | # works based on those contributions, and sublicense and distribute | |
45 | # those contributions and any derivatives thereof. | |
46 | # | |
47 | # END BPS TAGGED BLOCK }}} | |
48 | ||
49 | package RT::Migrate; | |
50 | ||
51 | use strict; | |
52 | use warnings; | |
53 | ||
54 | use Time::HiRes qw//; | |
55 | ||
56 | sub format_time { | |
57 | my $time = shift; | |
58 | my $s = ""; | |
59 | ||
60 | $s .= int($time/60/60)."hr " | |
61 | if $time > 60*60; | |
62 | $s .= int(($time % (60*60))/60)."min " | |
63 | if $time > 60; | |
64 | $s .= int($time % 60)."s" | |
65 | if $time < 60*60; | |
66 | ||
67 | return $s; | |
68 | } | |
69 | ||
70 | sub progress_bar { | |
71 | my %args = ( | |
72 | label => "", | |
73 | now => 0, | |
74 | max => 1, | |
75 | cols => 80, | |
76 | char => "=", | |
77 | @_, | |
78 | ); | |
79 | $args{now} ||= 0; | |
80 | ||
81 | my $fraction = $args{max} ? $args{now} / $args{max} : 0; | |
82 | ||
83 | my $max_width = $args{cols} - 30; | |
84 | my $bar_width = int($max_width * $fraction); | |
85 | ||
86 | return sprintf "%20s |%-" . $max_width . "s| %3d%%\n", | |
87 | $args{label}, $args{char} x $bar_width, $fraction*100; | |
88 | } | |
89 | ||
90 | sub progress { | |
91 | my %args = ( | |
92 | top => sub { print "\n\n" }, | |
93 | bottom => sub {}, | |
94 | every => 3, | |
95 | bars => [qw/Ticket Transaction Attachment User Group/], | |
96 | counts => sub {}, | |
97 | max => {}, | |
98 | @_, | |
99 | ); | |
100 | ||
101 | my $max_objects = 0; | |
102 | $max_objects += $_ for values %{ $args{max} }; | |
103 | ||
104 | my $last_time; | |
105 | my $start; | |
106 | my $left; | |
107 | my $offset; | |
108 | return sub { | |
109 | my $obj = shift; | |
110 | my $force = shift; | |
111 | my $now = Time::HiRes::time(); | |
112 | return if defined $last_time and $now - $last_time <= $args{every} and not $force; | |
113 | ||
114 | $start = $now unless $start; | |
115 | $last_time = $now; | |
116 | ||
117 | my $elapsed = $now - $start; | |
118 | ||
119 | # Determine terminal size | |
120 | print `clear`; | |
121 | my ($cols, $rows) = (80, 25); | |
122 | eval { | |
123 | require Term::ReadKey; | |
124 | ($cols, $rows) = Term::ReadKey::GetTerminalSize(); | |
125 | }; | |
126 | $cols -= 1; | |
127 | ||
128 | $args{top}->($elapsed, $rows, $cols); | |
129 | ||
130 | my %counts = $args{counts}->(); | |
131 | for my $class (map {"RT::$_"} @{$args{bars}}) { | |
132 | my $display = $class; | |
133 | $display =~ s/^RT::(.*)/@{[$1]}s:/; | |
134 | print progress_bar( | |
135 | label => $display, | |
136 | now => $counts{$class}, | |
137 | max => $args{max}{$class}, | |
138 | cols => $cols, | |
139 | ); | |
140 | } | |
141 | ||
142 | my $total = 0; | |
143 | $total += $_ for map {$counts{$_}} grep {exists $args{max}{$_}} keys %counts; | |
144 | $offset = $total unless defined $offset; | |
145 | print "\n", progress_bar( | |
146 | label => "Total", | |
147 | now => $total, | |
148 | max => $max_objects, | |
149 | cols => $cols, | |
150 | char => "#", | |
151 | ); | |
152 | ||
153 | # Time estimates | |
154 | my $fraction = $max_objects | |
155 | ? ($total - $offset)/($max_objects - $offset) | |
156 | : 0; | |
157 | if ($fraction > 0.03) { | |
158 | if (defined $left) { | |
159 | $left = 0.75 * $left | |
160 | + 0.25 * ($elapsed / $fraction - $elapsed); | |
161 | } else { | |
162 | $left = ($elapsed / $fraction - $elapsed); | |
163 | } | |
164 | } | |
165 | print "\n"; | |
166 | printf "%20s %s\n", "Elapsed time:", | |
167 | format_time($elapsed); | |
168 | printf "%20s %s\n", "Estimated left:", | |
169 | (defined $left) ? format_time($left) : "-"; | |
170 | ||
171 | $args{bottom}->($elapsed, $rows, $cols); | |
172 | } | |
173 | ||
174 | } | |
175 | ||
176 | sub setup_logging { | |
177 | my ($dir, $file) = @_; | |
178 | ||
320f0092 MKG |
179 | |
180 | RT->Config->Set(LogToSTDERR => 'warning'); | |
181 | RT->Config->Set(LogToFile => 'warning'); | |
182 | RT->Config->Set(LogDir => $dir); | |
183 | RT->Config->Set(LogToFileNamed => $file); | |
184 | RT->Config->Set(LogStackTraces => 'error'); | |
af59614d MKG |
185 | |
186 | undef $RT::Logger; | |
187 | RT->InitLogging(); | |
188 | ||
189 | my $logger = $RT::Logger->output('file') || $RT::Logger->output("rtlog"); | |
190 | return $logger ? $logger->{filename} : undef; | |
191 | } | |
192 | ||
193 | 1; |