utils.py 4.18 KB
Newer Older
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Copyright (C) 2015 GRNET S.A.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

16
17
18
import os
import hashlib
import datetime
19
import threading
20
import watchdog.utils
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
21
22
import sys
import logging
23
import platform
24
import time
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
25
26

logger = logging.getLogger(__name__)
27

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
28
29
from agkyra.syncer.common import OBJECT_DIRSEP

30
ENCODING = sys.getfilesystemencoding() or 'UTF-8'
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
31
PLATFORM = sys.platform
32
NODE = platform.node()
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
33

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
34
35
36
37
38
39
40
def iswin():
    return PLATFORM.startswith("win")


def islinux():
    return PLATFORM.startswith("linux")

41

Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
42
43
44
45
def isosx():
    return PLATFORM.startswith("darwin")


Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
46
47
48
49
50
51
52
53
def to_local_sep(filename):
    return filename.replace(OBJECT_DIRSEP, os.path.sep)


def to_standard_sep(filename):
    return filename.replace(os.path.sep, OBJECT_DIRSEP)


54
def join_path(dirpath, filename):
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
55
56
57
58
59
60
61
    return os.path.join(dirpath, to_local_sep(filename))


def join_objname(prefix, filename):
    if prefix != "":
        prefix = prefix.rstrip(OBJECT_DIRSEP) + OBJECT_DIRSEP
    return prefix + filename
62
63


Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
64
65
66
67
68
69
70
71
def normalize_standard_suffix(path):
    return path.rstrip(OBJECT_DIRSEP) + OBJECT_DIRSEP


def normalize_local_suffix(path):
    return path.rstrip(os.path.sep) + os.path.sep


Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def from_unicode(s):
    if type(s) is unicode:
        return s.encode(ENCODING)
    return s


def to_unicode(s):
    if type(s) is unicode:
        return s
    try:
        return unicode(s, ENCODING)
    except UnicodeDecodeError as e:
        logger.warning("Failed to decode %s" % s.__repr__())
        raise


88
def hash_string(s):
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
89
    s = from_unicode(s)
90
91
92
93
    return hashlib.sha256(s).hexdigest()


def time_stamp():
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
94
95
96
97
98
    return datetime.datetime.now()


def str_time_stamp():
    return time_stamp().isoformat().replace(':', '.')
99
100
101
102


def younger_than(tstamp, seconds):
    now = datetime.datetime.now()
Giorgos Korfiatis's avatar
Giorgos Korfiatis committed
103
    delta = now - tstamp
104
    return delta < datetime.timedelta(seconds=seconds)
105
106


107
108
def reg_name(settings, objname):
    if settings.case_insensitive:
109
110
111
112
        return objname.lower()
    return objname


113
114
115
116
BaseStoppableThread = watchdog.utils.BaseThread


class StoppableThread(BaseStoppableThread):
117
118
119
120
    period = 0
    step = 0

    def run_body(self, period):
121
122
123
        raise NotImplementedError()

    def run(self):
124
        remaining = 0
125
126
127
        while True:
            if not self.should_keep_running():
                return
128
129
130
131
132
133
134
135
136
137
138
139
            if remaining <= 0:
                remaining = self.period
                self.run_body()
            time.sleep(self.step)
            remaining -= self.step

    def __init__(self, period, target=None, step=0.1):
        BaseStoppableThread.__init__(self)
        self.period = period
        self.step = step
        if target:
            self.run_body = target
140
141


142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def _remaining(timeout, total_elapsed):
    return max(0, timeout - total_elapsed) if timeout is not None else None


def wait_joins(threads, timeout=None):
    total_elapsed = 0
    for thread in threads:
        tbefore = datetime.datetime.now()
        remaining_timeout = _remaining(timeout, total_elapsed)
        thread.join(timeout=remaining_timeout)
        tafter = datetime.datetime.now()
        elapsed = (tafter - tbefore).total_seconds()
        total_elapsed += elapsed
    return _remaining(timeout, total_elapsed)


158
159
160
161
162
163
164
165
166
167
168
169
170
171
class ThreadSafeDict(object):
    def __init__(self, *args, **kwargs):
        self._DICT = {}
        self._LOCK = threading.Lock()

    def lock(self):
        class Lock(object):
            def __enter__(this):
                self._LOCK.acquire()
                return self._DICT

            def __exit__(this, exctype, value, traceback):
                self._LOCK.release()
                if value is not None:
172
                    return False  # re-raise
173
        return Lock()