globals.py 3.07 KB
Newer Older
Matt Traudt's avatar
Matt Traudt committed
1
import os
2
import time
3
import logging
4
from filelock import FileLock
Matt Traudt's avatar
Matt Traudt committed
5

6
log = logging.getLogger(__name__)
Matt Traudt's avatar
Matt Traudt committed
7
8
9

G_PKG_DIR = os.path.abspath(os.path.dirname(__file__))

10
11
12
# Minimum and maximum number of bytes a client is allowed to request from a
# server. If these are changed, a WIRE_PROTO_VER bump is required, which also
# happens to require an sbws major version bump.
13
14
15
16
17
18
19
20
#
# Note for smart people and people who pull out Wireshark: Even if the client
# requests 1 byte, that request and the 1 byte response will each be carried
# over the Internet in 514 byte Tor cells. Theoretically we could bump the
# minimum request size up to ~498 bytes, but I see no reason why we should.
# Trying to hit the maximum cell size just makes sbws server send more, us read
# more, and it runs the risk of standards changing underneath us and sbws
# suddenly creating more than one cell.
21
MIN_REQ_BYTES = 1
22
MAX_REQ_BYTES = 1 * 1024 * 1024 * 1024  # 1 GiB
23
SOCKET_TIMEOUT = 60  # seconds
24

Matt Traudt's avatar
Matt Traudt committed
25
26

def is_initted(d):
27
    if not os.path.isdir(d):
Matt Traudt's avatar
Matt Traudt committed
28
        return False
Matt Traudt's avatar
Matt Traudt committed
29
30
31
32
33
    conf_fnames = [os.path.join(d, 'config.ini'),
                   os.path.join(d, 'config.log.ini')]
    for fname in conf_fnames:
        if not os.path.exists(fname):
            return False
Matt Traudt's avatar
Matt Traudt committed
34
    return True
35
36


37
def fail_hard(*a, **kw):
38
39
    ''' Optionally log something to stdout ... and then exit as fast as
    possible '''
Matt Traudt's avatar
Matt Traudt committed
40
    log.critical(*a, **kw)
41
    exit(1)
Matt Traudt's avatar
Matt Traudt committed
42
43


44
45
46
47
48
49
50
51
52
53
def time_now():
    '''
    Return the current time in seconds since 1970. This function exists to
    make testing easier

    :returns: Unix timestamp as a float
    '''
    return time.time()


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
def _log_level_string_to_int(s):
    if s == 'debug':
        return 4
    elif s == 'info':
        return 3
    elif s == 'notice':
        return 2
    elif s == 'warn':
        return 1
    elif s == 'error':
        return 0
    fail_hard('Unknown log level:', s)


def _log_level_int_to_string(i):
    if i >= 4:
        return 'debug'
    elif i == 3:
        return 'info'
    elif i == 2:
        return 'notice'
    elif i == 1:
        return 'warn'
    else:
        return 'error'

Matt Traudt's avatar
Matt Traudt committed
80

81
82
83
84
85
86
87
88
89
90
91
92
93
94
def lock_directory(dname):
    '''
    Holds a lock on a file in **dname** so that other sbws processes/threads
    won't try to read/write while we are reading/writing in this directory.

    >>> with lock_directory(dname):
    >>>     # do things while you have the lock
    >>> # no longer have lock

    :param str dname: Name of directory we want to obtain a lock for
    :retrurns: the FileLock context manager for you to use in a with statement
    '''
    assert os.path.isdir(dname)
    return FileLock(os.path.join(dname, 'lockfile'))
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109


def touch_file(fname, times=None):
    '''
    If **fname** exists, update its last access and modified times to now. If
    **fname** does not exist, create it. If **times** are specified, pass them
    to os.utime for use.

    :param str fname: Name of file to update or create
    :param tuple times: 2-tuple of floats for access time and modified time
        respectively
    '''
    log.debug('Touching %s', fname)
    with open(fname, 'a') as fd:
        os.utime(fd.fileno(), times=times)