1afc6c6d98a6ea44ef82a59ec1cec69af83eb082
[freeside.git] / rt / lib / RT / Migrate / Serializer / File.pm
1 # BEGIN BPS TAGGED BLOCK {{{
2 #
3 # COPYRIGHT:
4 #
5 # This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC
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::Serializer::File;
50
51 use strict;
52 use warnings;
53
54 use base 'RT::Migrate::Serializer';
55
56 sub Init {
57     my $self = shift;
58
59     my %args = (
60         Directory   => undef,
61         Force       => undef,
62         MaxFileSize => 32,
63
64         @_,
65     );
66
67     # Set up the output directory we'll be writing to
68     my ($y,$m,$d) = (localtime)[5,4,3];
69     $args{Directory} = $RT::Organization .
70         sprintf(":%d-%02d-%02d",$y+1900,$m+1,$d)
71         unless defined $args{Directory};
72     system("rm", "-rf", $args{Directory}) if $args{Force};
73     die "Output directory $args{Directory} already exists"
74         if -d $args{Directory};
75     mkdir $args{Directory}
76         or die "Can't create output directory $args{Directory}: $!\n";
77     $self->{Directory} = delete $args{Directory};
78
79     # How many megabytes each chunk should be, approximitely
80     $self->{MaxFileSize} = delete $args{MaxFileSize};
81
82     # Which file we're writing to
83     $self->{FileCount} = 1;
84
85     $self->SUPER::Init(@_);
86 }
87
88 sub Metadata {
89     my $self = shift;
90     return $self->SUPER::Metadata(
91         Files => [ $self->Files ],
92         @_,
93     )
94 }
95
96 sub Export {
97     my $self = shift;
98
99     # Set up our output file
100     $self->OpenFile;
101
102     # Write the initial metadata
103     $self->InitStream;
104
105     # Walk the objects
106     $self->Walk( @_ );
107
108     # Close everything back up
109     $self->CloseFile;
110
111     # Write the summary file
112     Storable::nstore(
113         $self->Metadata( Final => 1 ),
114         $self->Directory . "/rt-serialized"
115     );
116
117     return $self->ObjectCount;
118 }
119
120 sub Visit {
121     my $self = shift;
122
123     # Rotate if we get too big
124     my $maxsize = 1024 * 1024 * $self->{MaxFileSize};
125     $self->RotateFile if tell($self->{Filehandle}) > $maxsize;
126
127     # Serialize it
128     $self->SUPER::Visit( @_ );
129 }
130
131
132 sub Files {
133     my $self = shift;
134     return @{ $self->{Files} };
135 }
136
137 sub Filename {
138     my $self = shift;
139     return sprintf(
140         "%s/%03d.dat",
141         $self->{Directory},
142         $self->{FileCount}
143     );
144 }
145
146 sub Directory {
147     my $self = shift;
148     return $self->{Directory};
149 }
150
151 sub OpenFile {
152     my $self = shift;
153     open($self->{Filehandle}, ">", $self->Filename)
154         or die "Can't write to file @{[$self->Filename]}: $!";
155     push @{$self->{Files}}, $self->Filename;
156 }
157
158 sub CloseFile {
159     my $self = shift;
160     close($self->{Filehandle})
161         or die "Can't close @{[$self->Filename]}: $!";
162     $self->{FileCount}++;
163 }
164
165 sub RotateFile {
166     my $self = shift;
167     $self->CloseFile;
168     $self->OpenFile;
169 }
170
171 1;