Revision 6915fe26

b/Makefile.am
724 724
	test/ganeti.tools.ensure_dirs_unittest.py \
725 725
	test/ganeti.uidpool_unittest.py \
726 726
	test/ganeti.utils.algo_unittest.py \
727
	test/ganeti.utils.cfunc_unittest.py \
727
	test/ganeti.utils.cfunc.mlockall_unittest.py \
728 728
	test/ganeti.utils.filelock_unittest.py \
729 729
	test/ganeti.utils.hash_unittest.py \
730 730
	test/ganeti.utils.io_unittest.py \
b/lib/utils/cfunc.py
34 34
  ctypes = None
35 35

  
36 36

  
37
# Flags for mlockall() (from bits/mman.h)
37
# Flags for mlockall(2) (from bits/mman.h)
38 38
_MCL_CURRENT = 1
39 39
_MCL_FUTURE = 2
40 40

  
41 41

  
42
class _FuncWrapper:
43
  def __init__(self, ct):
44
    """Initializes this class.
45

  
46
    """
47
    # Make use of a dlopen(3) feature whereby giving a NULL handle returns the
48
    # main program. Functions from all previously loaded libraries can then be
49
    # used.
50
    mainprog = ct.CDLL(None)
51

  
52
    # The ctypes module before Python 2.6 does not have built-in functionality
53
    # to access the global errno global (which, depending on the libc and build
54
    # options, is per-thread), where function error codes are stored. Use GNU
55
    # libc's way to retrieve errno(3) instead.
56
    try:
57
      errno_loc = getattr(mainprog, "__errno_location")
58
    except AttributeError, err:
59
      logging.debug("Unable to find errno location: %s", err)
60
      errno_fn = None
61
    else:
62
      errno_loc.restype = ct.POINTER(ct.c_int)
63
      errno_fn = lambda: errno_loc().contents.value
64

  
65
    self.errno_fn = errno_fn
66

  
67
    # Try to get mlockall(2)
68
    self.mlockall_fn = getattr(mainprog, "mlockall", None)
69

  
70

  
42 71
def Mlockall(_ctypes=ctypes):
43 72
  """Lock current process' virtual address space into RAM.
44 73

  
45
  This is equivalent to the C call mlockall(MCL_CURRENT|MCL_FUTURE),
46
  see mlock(2) for more details. This function requires ctypes module.
74
  This is equivalent to the C call C{mlockall(MCL_CURRENT | MCL_FUTURE)}. See
75
  mlockall(2) for more details. This function requires the C{ctypes} module.
47 76

  
48
  @raises errors.NoCtypesError: if ctypes module is not found
77
  @raises errors.NoCtypesError: If the C{ctypes} module is not found
49 78

  
50 79
  """
51 80
  if _ctypes is None:
52 81
    raise errors.NoCtypesError()
53 82

  
54
  try:
55
    libc = _ctypes.cdll.LoadLibrary("libc.so.6")
56
  except EnvironmentError, err:
57
    logging.error("Failure trying to load libc: %s", err)
58
    libc = None
59
  if libc is None:
60
    logging.error("Cannot set memory lock, ctypes cannot load libc")
61
    return
62

  
63
  # Some older version of the ctypes module don't have built-in functionality
64
  # to access the errno global variable, where function error codes are stored.
65
  # By declaring this variable as a pointer to an integer we can then access
66
  # its value correctly, should the mlockall call fail, in order to see what
67
  # the actual error code was.
68
  # pylint: disable=W0212
69
  libc.__errno_location.restype = _ctypes.POINTER(_ctypes.c_int)
70

  
71
  if libc.mlockall(_MCL_CURRENT | _MCL_FUTURE):
72
    # pylint: disable=W0212
73
    logging.error("Cannot set memory lock: %s",
74
                  os.strerror(libc.__errno_location().contents.value))
75
    return
76

  
77
  logging.debug("Memory lock set")
83
  funcs = _FuncWrapper(_ctypes)
84

  
85
  if funcs.mlockall_fn is None:
86
    logging.debug("libc doesn't support mlockall(2)")
87
  else:
88
    if funcs.mlockall_fn(_MCL_CURRENT | _MCL_FUTURE) == 0:
89
      logging.debug("Memory lock set")
90
      return True
91

  
92
    logging.error("Cannot set memory lock: %s", os.strerror(funcs.errno_fn()))
93

  
94
  return False
b/test/ganeti.utils.cfunc.mlockall_unittest.py
1
#!/usr/bin/python
2
#
3

  
4
# Copyright (C) 2010, 2011 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

  
21

  
22
"""Script for testing utils.Mlockall
23

  
24
This test is run in a separate process because it changes memory behaviour.
25

  
26
"""
27

  
28
import unittest
29

  
30
from ganeti import utils
31
from ganeti import errors
32

  
33
import testutils
34

  
35

  
36
# WARNING: The following tests modify the memory behaviour at runtime. Don't
37
# add unrelated tests here.
38

  
39

  
40
class TestMlockallWithCtypes(unittest.TestCase):
41
  """Whether Mlockall() works if ctypes is present.
42

  
43
  """
44
  def test(self):
45
    if utils.ctypes:
46
      self.assertTrue(utils.Mlockall())
47

  
48

  
49
class TestMlockallWithNoCtypes(unittest.TestCase):
50
  """Whether Mlockall() raises an error if ctypes is not present.
51

  
52
  """
53
  def test(self):
54
    self.assertRaises(errors.NoCtypesError, utils.Mlockall, _ctypes=None)
55

  
56

  
57
if __name__ == "__main__":
58
  testutils.GanetiTestProgram()
/dev/null
1
#!/usr/bin/python
2
#
3

  
4
# Copyright (C) 2010, 2011 Google Inc.
5
#
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; either version 2 of the License, or
9
# (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful, but
12
# WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
# General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
# 02110-1301, USA.
20

  
21

  
22
"""Script for testing utils.Mlockall
23

  
24
This test is run in a separate process because it changes memory behaviour.
25

  
26
"""
27

  
28
import unittest
29

  
30
from ganeti import utils
31
from ganeti import errors
32

  
33
import testutils
34

  
35

  
36
# WARNING: The following tests modify the memory behaviour at runtime. Don't
37
# add unrelated tests here.
38

  
39

  
40
class TestMlockallWithCtypes(unittest.TestCase):
41
  """Whether Mlockall() works if ctypes is present.
42

  
43
  """
44

  
45
  def test(self):
46
    if utils.ctypes:
47
      utils.Mlockall()
48

  
49

  
50
class TestMlockallWithNoCtypes(unittest.TestCase):
51
  """Whether Mlockall() raises an error if ctypes is not present.
52

  
53
  """
54

  
55
  def test(self):
56
    self.assertRaises(errors.NoCtypesError, utils.Mlockall, _ctypes=None)
57

  
58

  
59
if __name__ == "__main__":
60
  testutils.GanetiTestProgram()

Also available in: Unified diff