]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/IMAPTracker.pm
102a74ce66b8ec0c1ba52be5200ee37d38dd08de
[public-inbox.git] / lib / PublicInbox / IMAPTracker.pm
1 # Copyright (C) 2018-2020 all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3 package PublicInbox::IMAPTracker;
4 use strict;
5 use parent qw(PublicInbox::Lock);
6 use DBI;
7 use DBD::SQLite;
8 use PublicInbox::Config;
9
10 sub create_tables ($) {
11         my ($dbh) = @_;
12
13         $dbh->do(<<'');
14 CREATE TABLE IF NOT EXISTS imap_last (
15         url VARCHAR PRIMARY KEY NOT NULL,
16         uid_validity INTEGER NOT NULL,
17         uid INTEGER NOT NULL,
18         UNIQUE (url)
19 )
20
21 }
22
23 sub dbh_new ($) {
24         my ($dbname) = @_;
25         my $dbh = DBI->connect("dbi:SQLite:dbname=$dbname", '', '', {
26                 AutoCommit => 1,
27                 RaiseError => 1,
28                 PrintError => 0,
29                 sqlite_use_immediate_transaction => 1,
30         });
31         $dbh->{sqlite_unicode} = 1;
32         $dbh->do('PRAGMA journal_mode = TRUNCATE');
33         create_tables($dbh);
34         $dbh;
35 }
36
37 sub get_last ($) {
38         my ($self) = @_;
39         my $sth = $self->{dbh}->prepare_cached(<<'', undef, 1);
40 SELECT uid_validity, uid FROM imap_last WHERE url = ?
41
42         $sth->execute($self->{url});
43         $sth->fetchrow_array;
44 }
45
46 sub update_last ($$$) {
47         my ($self, $validity, $last) = @_;
48         my $sth = $self->{dbh}->prepare_cached(<<'');
49 INSERT OR REPLACE INTO imap_last (url, uid_validity, uid)
50 VALUES (?, ?, ?)
51
52         $self->lock_acquire;
53         my $rv = $sth->execute($self->{url}, $validity, $last);
54         $self->lock_release;
55         $rv;
56 }
57
58 sub new {
59         my ($class, $url) = @_;
60
61         # original name for compatibility with old setups:
62         my $dbname = PublicInbox::Config->config_dir() . "/imap.sqlite3";
63
64         # use the new XDG-compliant name for new setups:
65         if (!-f $dbname) {
66                 $dbname = ($ENV{XDG_DATA_HOME} //
67                         (($ENV{HOME} // '/nonexistent').'/.local/share')) .
68                         '/public-inbox/imap.sqlite3';
69         }
70         if (!-f $dbname) {
71                 require File::Path;
72                 require File::Basename;
73                 File::Path::mkpath(File::Basename::dirname($dbname));
74         }
75         my $self = bless { lock_path => "$dbname.lock", url => $url }, $class;
76         $self->lock_acquire;
77         $self->{dbh} = dbh_new($dbname);
78         $self->lock_release;
79         $self;
80 }
81
82 1;