summaryrefslogtreecommitdiff
path: root/mscp/mscp.py
blob: e1d2bc8858c9431d1fcff5a57299b4a1b96a1220 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

import pymscp

_STATE_INIT      = 0
_STATE_CONNECTED = 1
_STATE_PREPARED  = 2
_STATE_RUNNING   = 3
_STATE_STOPPED   = 4
_STATE_JOINED    = 5
_STATE_CLEANED   = 6
_STATE_RELEASED  = 7

_state_str = {
    _STATE_INIT:      "init",
    _STATE_CONNECTED: "connected",
    _STATE_PREPARED:  "prepared",
    _STATE_RUNNING:   "running",
    _STATE_STOPPED:   "stopped",
    _STATE_JOINED:    "joined",
    _STATE_CLEANED:   "cleaned",
    _STATE_RELEASED:  "released",
}


class mscp:
    def __init__(self, remote: str, direction: int, **kwargs):
        """
        See src/pymscp.c:wrap_mscp_init() to determine keyword arguments.
        """
        kwargs["remote"] = remote
        kwargs["direction"] = direction
        self.m = pymscp.mscp_init(**kwargs)

        self.src_paths = []
        self.dst_path = None
        self.state = _STATE_INIT

    def __del__(self):

        if not hasattr(self, "state"):
            return # this instance failed on mscp_init

        if self.state == _STATE_RUNNING:
            self.stop()
        if self.state == _STATE_STOPPED:
            self.join()
        if self.state == _STATE_JOINED:
            self.cleanup()
        if self.state == _STATE_CLEANED:
            self.free()

    def _state2str(self):
        return _state_str[self.state]


    def connect(self):
        if not (self.state == _STATE_INIT or state.state == _STATE_CLEANED):
            raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
        pymscp.mscp_connect(m = self.m)
        self.state = _STATE_CONNECTED

    def add_src_path(self, src_path: str):
        self.src_paths.append(src_path)
        pymscp.mscp_add_src_path(m = self.m, src_path = src_path)

    def set_dst_path(self, dst_path: str):
        self.dst_path = dst_path
        pymscp.mscp_set_dst_path(m = self.m, dst_path = dst_path);

    def prepare(self):
        if self.state != _STATE_CONNECTED:
            raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
        if not self.src_paths:
            raise RuntimeError("src path list is empty")
        if not self.dst_path:
            raise RuntimeError("dst path is not set")

        pymscp.mscp_prepare(m = self.m)
        self.state = _STATE_PREPARED

    def start(self):
        if self.state != _STATE_PREPARED:
            raise RuntimeError("invalid mscp state: {}".format(self._state2str()))

        pymscp.mscp_start(m = self.m)
        self.state = _STATE_RUNNING

    def stop(self):
        if self.state != _STATE_RUNNING:
            raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
        pymscp.mscp_stop(m = self.m)
        self.state = _STATE_STOPPED

    def join(self):
        if not (self.state == _STATE_RUNNING or self.state == _STATE_STOPPED):
            raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
        pymscp.mscp_join(m = self.m)
        self.state = _STATE_JOINED

    def stats(self):
        return pymscp.mscp_get_stats(m = self.m)

    def cleanup(self):
        if self.state != _STATE_JOINED:
            raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
        pymscp.mscp_cleanup(m = self.m)
        self.state = _STATE_CLEANED

    def free(self):
        if self.state != _STATE_CLEANED:
            raise RuntimeError("invalid mscp state: {}".format(self._state2str()))
        pymscp.mscp_free(m = self.m)


    # Simple interface: mscp.copy(src, dst)
    def copy(self, src, dst, nonblock = False):
        if self.state < _STATE_CONNECTED:
            self.connect()

        if type(src) == list:
            for path in src:
                self.add_src_path(path)
        elif type(src) == str:
            self.add_src_path(src)
        else:
            raise ValueError("src must be str of list: '{}'".format(src))

        self.set_dst_path(dst)
        
        self.prepare()
        self.start()
        if nonblock:
            return

        self.join()
        self.cleanup()