translator.py 6.23 KB
Newer Older
1
2
3
import llfuse
import os
import sqlfuse
4
import threading
5
import logging
Gerion Entrup's avatar
Gerion Entrup committed
6

7
8
from model import Recording
from mbdata.models import Release, ReleaseGroup, Track, Artist, ArtistCredit, ArtistCreditName, Medium
9
from sqlalchemy import distinct
10
11
from sqlalchemy.sql import select, join
from sqlfuse import QPath, FPath, Where, Functions
Gerion Entrup's avatar
Gerion Entrup committed
12

13
class Translator(threading.Thread):
14
15
16
    """
    Manages the mapping between filesystem and database.
    """
17
18
    def __init__(self, session_fac, mountpoint):
        super().__init__(target=self)
19
        self.logger = logging.getLogger('translator')
20
        self._session = session_fac()
21
22
        self._filesystem = sqlfuse.init(self._session, self._create_fs())
        self._mountpoint = mountpoint
Gerion Entrup's avatar
Gerion Entrup committed
23

24
    def _create_fs(self):
25
26
27
28
29
30
31
32
33
        fs = [QPath("/Recordings/<recording>",
                    select([Recording.name, Recording.gid, Recording.ftype, Recording.path, ArtistCredit.name]).select_from(join(Recording, ArtistCredit)),
                    Functions(ArtistCredit.name, ' - ', Recording.name, '.', Recording.ftype)),
              #FPath("/Recordings/<and>", Translator._and, is_dir=True),
              #FPath("/Recordings/<or>", Translator._or, is_dir=True),
              QPath("/Artists/<artist>", select([Artist.name, Artist.gid]), Functions(Artist.name)),
              QPath("/Artists/<artist>/Recordings/<recording>",
                    select([Recording.name, Recording.gid, Recording.ftype, Recording.path]).select_from(join(join(join(Recording, ArtistCredit), ArtistCreditName), Artist)),
                    Functions(Recording.name, '.', Recording.ftype),
34
                    where=[Where(Artist.gid.__eq__, "<artist>", "artist_gid")]),
35
36
              #("/Artists/<artist>/Recordings/<and>", _and),
              #("/Artists/<artist>/Recordings/<or>", _or),
37
38
39
40
41
42
43
44
45
46
47
              QPath("/Artists/<artist>/<releasegroup>",
                    select([ReleaseGroup.name, ReleaseGroup.id]).select_from(join(join(join(ReleaseGroup, ArtistCredit), ArtistCreditName), Artist)),
                    Functions(ReleaseGroup.name),
                    where=[Where(Artist.gid.__eq__, "<artist>", "artist_gid")]),
              QPath("/Artists/<artist>/<releasegroup>/<release>",
                    select([Release.name, Release.gid, Release.release_group_id]),
                    Functions(Release.name, '.', Release.gid),
                    where=[Where(Release.release_group_id.__eq__, '<releasegroup>', 'release_group_id')]),
              QPath("/Artists/<artist>/<releasegroup>/<release>/<track>",
                    select([Track.name, Track.number, Recording.gid, Recording.path, Recording.ftype]).select_from(join(join(join(Track, Recording), Medium), Release)),
                    Functions(Track.number, ' ', Track.name, '.', Recording.ftype),
48
                    where=[Where(Release.gid.__eq__, '<release>', 'release_gid')]),
49
50
              #("/Artists/<artist>/<releasegroup>/<release>/<and>", _and),
              #("/Artists/<artist>/<releasegroup>/<release>/<or>", _or),
51
              #QPath("/Artists/<artist>/Works/<work>"
52
53
54
              #("/Artists/<artist>/Works/<work>/<recording>"
              #("/Artists/<artist>/Works/<work>/<and>", _and),
              #("/Artists/<artist>/Works/<work>/<or>", _or),
55
56
57
58
59
60
61
62
63
64
65
              QPath("/Releases/<releasegroup>",
                    select([ReleaseGroup.name, ReleaseGroup.id]),
                    Functions(ReleaseGroup.name)),
              QPath("/Releases/<releasegroup>/<release>",
                    select([Release.name, Release.gid, Release.release_group_id]),
                    Functions(Release.name, '.', Release.gid),
                    where=[Where(Release.release_group_id.__eq__, '<releasegroup>', 'release_group_id')]),
              QPath("/Releases/<releasegroup>/<release>/<track>",
                    select([Track.name, Track.number, Recording.gid, Recording.path, Recording.ftype]).select_from(join(join(join(Track, Recording), Medium), Release)),
                    Functions(Track.number, ' ', Track.name, '.', Recording.ftype),
                    where=[Where(Release.gid.__eq__, '<release>', 'release_gid')])]
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
              #("/Releases/<releasegroup>/<release>/<and>", _and),
              #("/Releases/<releasegroup>/<release>/<or>", _or),
              #("/Works"
              #("/Works/<work>"
              #("/Works/<work>/<recording>"
              #("/Works/<work>/<and>", _and),
              #("/Works/<work>/<or>", _or),
              #("/Year/"
              #("/Year/After/"
              #("/Year/After/<year>"
              #("/Year/After/<year>/<recording>"
              #("/Year/After/<year>/<and>", _and),
              #("/Year/After/<year>/<or>", _or),
              #("/Year/Before/"
              #("/Year/Before/<year>"
              #("/Year/Before/<year>/<recording>"
              #("/Year/Before/<year>/<and>", _and),
              #("/Year/Before/<year>/<or>", _or),
              #("/Year/Between/"
              #("/Year/Between/<year> and"
              #("/Year/Between/<year> and/<year>"
              #("/Year/Between/<year> and/<year>/<recording>"
              #("/Year/Between/<year> and/<year>/<and>", _and),
              #("/Year/Between/<year> and/<year>/<or>", _or),
              #("/Year/<year>"
              #("/Playlists/<name>"
              #("/Playlists/<name>/<recording>"
              #("/Playlists/<name>/<and>", _and),
              #("/Playlists/<name>/<or>", _or),
              #("/RecordingsAsLink/<recording>", _recording_link),
              #("/settings.txt", _settings),
97
              #FPath("/log.txt", Translator._log, is_dir=False)]
98
99
        return fs

100
101
102
    def run(self):
        self.mount(self._mountpoint)

Gerion Entrup's avatar
Gerion Entrup committed
103
    def mount(self, mountpoint):
104
105
106
107
108
109
        # from utils import debug_breakpoint
        # debug_breakpoint()
        fuse_options = set(llfuse.default_options)
        fuse_options.add('fsname=brainzfs')
        llfuse.init(self._filesystem, self._mountpoint, fuse_options)
        try:
110
            self.logger.info("starting llfuse main loop")
111
112
            llfuse.main(workers=1)
        except:
113
            self.logger.error("llfuse main loop closed unexpected")
114
115
116
117
            llfuse.close(unmount=False)
            raise

        llfuse.close()
118
        self.logger.info("llfuse main loop closed")
119
        # TODO fix
120
121
        self._session.commit()
        self._session.close()
Gerion Entrup's avatar
Gerion Entrup committed
122