|
Luc Didry |
d909b8 |
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
|
Luc Didry |
d909b8 |
package Lufi::DB::Slice;
|
|
Luc Didry |
d909b8 |
use Mojo::Base -base;
|
|
Luc Didry |
8d6f10 |
use Encode 'encode';
|
|
Luc Didry |
8d6f10 |
use File::Spec::Functions;
|
|
Luc Didry |
164698 |
use Mojo::Collection 'c';
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
has 'short';
|
|
Luc Didry |
d909b8 |
has 'j';
|
|
Luc Didry |
164698 |
has 'record' => 0;
|
|
Luc Didry |
d909b8 |
has 'app';
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
8d6f10 |
=encoding utf8
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
d909b8 |
=head1 NAME
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
Lufi::DB::Slice - DB abstraction layer for Lufi file
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=head1 Contributing
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
When creating a new database accessor, make sure that it provides the following subroutines.
|
|
Luc Didry |
d909b8 |
After that, modify this file and modify the C<new> subroutine to allow to use your accessor.
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
Have a look at Lufi::DB::Slice::SQLite's code: it's simple and may be more understandable that this doc.
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=head1 Attributes
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=over 1
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<short> : string
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<j> : integer
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<app> : A mojolicious object
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=back
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=head1 Sub routines
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=head2 new
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=over 1
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Usage> : C<$c = Lufi::DB::Slice-E<gt>new(app =E<gt> $self);>
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Arguments> : any of the attribute above
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Purpose> : construct a new db accessor object. If the C<short> attribute is provided, it have to load the informations from the database.
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Returns> : the db accessor object
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Info> : the app argument is used by Lufi::DB::Slice to choose which db accessor will be used, you don't need to use it in new(), but you can use it to access helpers or configuration settings in the other subroutines
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=back
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=cut
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
sub new {
|
|
Luc Didry |
d909b8 |
my $c = shift;
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
$c = $c->SUPER::new(@_);
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
if (ref($c) eq 'Lufi::DB::Slice') {
|
|
Luc Didry |
d909b8 |
my $dbtype = $c->app->config('dbtype');
|
|
Luc Didry |
d909b8 |
if ($dbtype eq 'sqlite') {
|
|
Luc Didry |
d909b8 |
use Lufi::DB::Slice::SQLite;
|
|
Luc Didry |
d909b8 |
$c = Lufi::DB::Slice::SQLite->new(@_);
|
|
Luc Didry |
18499a |
} elsif ($dbtype eq 'postgresql') {
|
|
Luc Didry |
18499a |
use Lufi::DB::Slice::Pg;
|
|
Luc Didry |
18499a |
$c = Lufi::DB::Slice::Pg->new(@_);
|
|
Luc Didry |
44507c |
} elsif ($dbtype eq 'mysql') {
|
|
Luc Didry |
44507c |
use Lufi::DB::Slice::Mysql;
|
|
Luc Didry |
44507c |
$c = Lufi::DB::Slice::Mysql->new(@_);
|
|
Luc Didry |
d909b8 |
}
|
|
Luc Didry |
d909b8 |
}
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
return $c;
|
|
Luc Didry |
d909b8 |
}
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=head2 write
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=over 1
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Usage> : C<$c-E<gt>write>
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Arguments> : none
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Purpose> : create or update a record in the database, with the values of the object's attributes
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Returns> : the db accessor object
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=back
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
164698 |
=cut
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
sub write {
|
|
Luc Didry |
164698 |
my $c = shift;
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
if ($c->record) {
|
|
Luc Didry |
8d6f10 |
$c->app->dbi->db->query('UPDATE slices SET short = ?, j = ? WHERE short = ? AND j = ?', $c->short, $c->j, $c->short, $c->j);
|
|
Luc Didry |
164698 |
} else {
|
|
Luc Didry |
8d6f10 |
$c->app->dbi->db->query('INSERT INTO slices (short, j) VALUES (?, ?)', $c->short, $c->j);
|
|
Luc Didry |
164698 |
$c->record(1);
|
|
Luc Didry |
164698 |
}
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
return $c;
|
|
Luc Didry |
164698 |
}
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
8d6f10 |
=head2 store
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=over 1
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Usage> : C<$c-E<gt>store($text)>
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Arguments> : a scalar value
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Purpose> : will store the content to the object's path, either on filesystem or on Swift object storage
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Returns> : the db accessor object
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=back
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=cut
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
sub store {
|
|
Luc Didry |
8d6f10 |
my $c = shift;
|
|
Luc Didry |
8d6f10 |
my $text = shift;
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
if ($c->app->config('swift')) {
|
|
Luc Didry |
8d6f10 |
$c->app->swift->put_object(
|
|
Luc Didry |
8d6f10 |
container_name => $c->app->config('swift')->{container},
|
|
Luc Didry |
8d6f10 |
object_name => $c->get_path(),
|
|
Luc Didry |
8d6f10 |
content_length => length(Encode::encode_utf8($text)),
|
|
Luc Didry |
ed302d |
content => Encode::encode_utf8($text)
|
|
Luc Didry |
8d6f10 |
);
|
|
Luc Didry |
8d6f10 |
} else {
|
|
Luc Didry |
8d6f10 |
# Create directory
|
|
Luc Didry |
8d6f10 |
my $dir = catfile($c->app->config('upload_dir'), $c->short);
|
|
Luc Didry |
8d6f10 |
mkdir($dir, 0700) unless (-d $dir);
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
# Write file
|
|
Luc Didry |
8d6f10 |
my $file = catfile($c->app->config('upload_dir'), $c->get_path());
|
|
Luc Didry |
8d6f10 |
Mojo::File->new($file)->spurt($text);
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
return $c;
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=head2 retrieve
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=over 1
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Usage> : C<$c-E<gt>retrieve>
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Arguments> : none
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Purpose> : get file from storage, either filesystem or Swift object storage
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Returns> : the data from the file
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=back
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=cut
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
sub retrieve {
|
|
Luc Didry |
8d6f10 |
my $c = shift;
|
|
Luc Didry |
8d6f10 |
my $upload = shift;
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
if ($c->app->config('swift')) {
|
|
Luc Didry |
8d6f10 |
my $file;
|
|
Luc Didry |
8d6f10 |
$c->app->swift->get_object(
|
|
Luc Didry |
8d6f10 |
container_name => $c->app->config('swift')->{container},
|
|
Luc Didry |
8d6f10 |
object_name => $c->get_path(),
|
|
Luc Didry |
8d6f10 |
write_code => sub {
|
|
Luc Didry |
8d6f10 |
my ($status, $message, $headers, $chunk) = @_;
|
|
Luc Didry |
8d6f10 |
$file .= $chunk;
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
8d6f10 |
);
|
|
Luc Didry |
ed302d |
return Encode::decode_utf8($file);
|
|
Luc Didry |
8d6f10 |
} else {
|
|
Luc Didry |
8d6f10 |
my $file = catfile($c->app->config('upload_dir'), $c->get_path());
|
|
Luc Didry |
8d6f10 |
return Mojo::File->new($file)->slurp;
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
8d6f10 |
=head2 delete_file
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=over 1
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Usage> : C<$c-E<gt>delete_file()>
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Arguments> : none
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Purpose> : delete the file on filesystem or Swift object storage
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Returns> : the db accessor object
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=back
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=cut
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
sub delete_file {
|
|
Luc Didry |
8d6f10 |
my $c = shift;
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
if ($c->app->config('swift')) {
|
|
Luc Didry |
8d6f10 |
$c->app->swift->delete_object({
|
|
Luc Didry |
8d6f10 |
container_name => $c->app->config('swift')->{container},
|
|
Luc Didry |
8d6f10 |
object_name => $c->get_path()
|
|
Luc Didry |
8d6f10 |
});
|
|
Luc Didry |
8d6f10 |
} else {
|
|
Luc Didry |
8d6f10 |
my $file = catfile($c->app->config('upload_dir'), $c->get_path());
|
|
Luc Didry |
8d6f10 |
unlink $file or warn sprintf('Could not unlink %s: %s', $file, $!);
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
8d6f10 |
return $c;
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
d909b8 |
=head2 get_slices_of_file
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=over 1
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Usage> : C<$c-E<gt>get_slices_of_file($short)>
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Arguments> : string
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Purpose> : get all Lufi::DB::Slice objects related to a file
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=item B<Returns> : a Mojo::Collection of Lufi::DB::Slice objects
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=back
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
d909b8 |
=cut
|
|
Luc Didry |
d909b8 |
|
|
Luc Didry |
164698 |
sub get_slices_of_file {
|
|
Luc Didry |
164698 |
my $c = shift;
|
|
Luc Didry |
164698 |
my $short = shift;
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
my @slices;
|
|
Luc Didry |
164698 |
my $records = $c->app->dbi->db->query('SELECT * FROM slices WHERE short = ? ORDER BY j ASC', $short)->hashes;
|
|
Luc Didry |
164698 |
$records->each(
|
|
Luc Didry |
164698 |
sub {
|
|
Luc Didry |
164698 |
my ($e, $num) = @_;
|
|
Luc Didry |
164698 |
my $i = Lufi::DB::Slice->new(app => $c->app);
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
push @slices, $i->_slurp($e);
|
|
Luc Didry |
164698 |
}
|
|
Luc Didry |
164698 |
);
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
return c(@slices);
|
|
Luc Didry |
164698 |
}
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
e41b08 |
=head2 delete_all
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
e41b08 |
=over 1
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
e41b08 |
=item B<Usage> : C<$c-E<gt>delete_all()>
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
e41b08 |
=item B<Arguments> : none
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
8d6f10 |
=item B<Purpose> : delete all slices records from database unconditionnally
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
e41b08 |
=item B<Returns> : nothing
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
e41b08 |
=back
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
e41b08 |
=cut
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
e41b08 |
sub delete_all {
|
|
Luc Didry |
e41b08 |
my $c = shift;
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
e41b08 |
$c->app->dbi->db->delete('slices');
|
|
Luc Didry |
e41b08 |
}
|
|
Luc Didry |
e41b08 |
|
|
Luc Didry |
8d6f10 |
=head2 path
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=over 1
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Usage> : C<$c-E<gt>path()>
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Arguments> : non
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Purpose> : format the path of the file, relative to the directory of the Swift object storage
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Returns> : the path of the file
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=back
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=cut
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
sub get_path {
|
|
Luc Didry |
8d6f10 |
my $c = shift;
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
return catfile($c->short, sprintf('%d.part', $c->j));
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=head2 count
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=over 1
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Usage> : C<$c-E<gt>count()>
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Arguments> : none
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Purpose> : get count of slices records from database
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=item B<Returns> : integer
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=back
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
=cut
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
sub count {
|
|
Luc Didry |
8d6f10 |
my $c = shift;
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
8d6f10 |
return $c->app->dbi->db->query('SELECT count(*) AS count FROM slices')->hashes->first->{count};
|
|
Luc Didry |
8d6f10 |
}
|
|
Luc Didry |
8d6f10 |
|
|
Luc Didry |
164698 |
=head2 _slurp
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
=over 1
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
=item B<Usage> : C<$c-E<gt>_slurp>
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
=item B<Arguments> : none
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
=item B<Purpose> : put a database record's columns into the Lufi::DB::Slice object's attributes
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
=item B<Returns> : the Lufi::DB::Slice object
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
=back
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
=cut
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
sub _slurp {
|
|
Luc Didry |
164698 |
my $c = shift;
|
|
Luc Didry |
164698 |
my $r = shift;
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
my $slice;
|
|
Luc Didry |
164698 |
if (defined $r) {
|
|
Luc Didry |
164698 |
$slice = $r;
|
|
Luc Didry |
164698 |
} else {
|
|
Luc Didry |
164698 |
my $slices = $c->app->dbi->db->query('SELECT * FROM slices WHERE short = ? AND j = ?', $c->short, $c->j)->hashes;
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
if ($slices->size) {
|
|
Luc Didry |
164698 |
$slice = $slices->first;
|
|
Luc Didry |
164698 |
}
|
|
Luc Didry |
164698 |
}
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
if ($slice) {
|
|
Luc Didry |
164698 |
$c->short($slice->{short});
|
|
Luc Didry |
164698 |
$c->j($slice->{j});
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
$c->record(1);
|
|
Luc Didry |
164698 |
}
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
164698 |
return $c;
|
|
Luc Didry |
164698 |
}
|
|
Luc Didry |
164698 |
|
|
Luc Didry |
d909b8 |
1;
|