1. 06 Aug, 2015 1 commit
    • Kirill Smelkov's avatar
      bigfile/virtmem: Block/restore SIGSEGV in non-pagefault-handling function · cb7a7055
      Kirill Smelkov authored
      Non on-pagefault code should not access any not-mmapped memory.
      
      Here we just refactor the code we already had to block/restore
      SIGSEGV from fileh_dirty_writeout() and use it in all functions called
      from non-pagefaulting context, as promised.
      
      This way, if there is an error in virtmem implementation which
      incorrectly accesses prepared for BigFile maps memory, we'll just die
      with coredump instead of trying to incorrectly handle the pagefault.
      cb7a7055
  2. 27 Jul, 2015 1 commit
    • Kirill Smelkov's avatar
      bigarray: In-place .append() · 1245acc9
      Kirill Smelkov authored
      ca064f75 (bigarray: Support resizing in-place) added O(1) in-place
      BigArray.resize() which makes possible for users to append data to BigArray in
      O(δ) time.
      
      But it is easy for people to make off-by-one mistakes when calculating
      indices for append.
      
      So provide a convenient BigArray.append() which simplifies the following
      
          A                               # ZBigArray e.g. of shape       (N, 3)
          values                          # ndarray to append of shape    (δ, 3)
          n, δ = len(A), len(values)      # length of A's major index  =N
          A.resize((n+δ, A.shape[1:]))    # add δ new entries ; now len(A) =N+δ
          A[-δ:] = values                 # set data for last new δ entries
      
      into
      
          A.append(values)
      
      /cc @klaus
      1245acc9
  3. 24 Jul, 2015 1 commit
  4. 26 Jun, 2015 4 commits
  5. 25 Jun, 2015 4 commits
  6. 12 Jun, 2015 1 commit
  7. 02 Jun, 2015 9 commits
    • Kirill Smelkov's avatar
      bigfile/py: We cannot use memoryview for py2 even on 2.7.10 · a5511edf
      Kirill Smelkov authored
      Because numpy.ndarray does not accept it as buffer= argument
      
          https://github.com/numpy/numpy/issues/5935
      
      and our memcpy crashes.
      
      NOTE if we'll need to use memoryview, we can adapt our memcpy to use
      array() directly which works with memoryview, as outlined in the above
      numpy issue.
      a5511edf
    • Kirill Smelkov's avatar
      bigarray: Teach it how to automatically convert to ndarray (if enough address space is available) · 00db08d6
      Kirill Smelkov authored
      BigArrays can be big - up to 2^64 bytes, and thus in general it is not
      possible to represent whole BigArray as ndarray view, because address
      space is usually smaller on 64bit architectures.
      
      However users often try to pass BigArrays to numpy functions as-is, and
      numpy finds a way to convert, or start converting, BigArray to ndarray -
      via detecting it as a sequence, and extracting elements one-by-one.
      Which is slooooow.
      
      Because of the above, we provide users a well-defined service:
      - if virtual address space is available - we succeed at creating ndarray
        view for whole BigArray, without delay and copying.
      - if not - we report properly the error and give hint how BigArrays have
        to be processed in chunks.
      
      Verifying that big BigArrays cannot be converted to ndarray also tests
      for behaviour and issues fixed in last 5 patches.
      
      /cc @Tyagov
      /cc @klaus
      00db08d6
    • Kirill Smelkov's avatar
      *: It is not safe to use multiply.reduce() - it overflows · 73926487
      Kirill Smelkov authored
      e.g.
      
          In [1]: multiply.reduce((1<<30, 1<<30, 1<<30))
          Out[1]: 0
      
      instead of
      
          In [2]: (1<<30) * (1<<30) * (1<<30)
          Out[2]: 1237940039285380274899124224
      
          In [3]: 1<<90
          Out[3]: 1237940039285380274899124224
      
      also multiply.reduce returns int64, instead of python int:
      
          In [4]: type( multiply.reduce([1,2,3]) )
          Out[4]: numpy.int64
      
      which also leads to overflow-related problems if we further compute with
      this value and other integers and results exceeds int64 - it becomes
      float:
      
          In [5]: idx0_stop = 18446744073709551615
      
          In [6]: stride0   = numpy.int64(1)
      
          In [7]: byte0_stop = idx0_stop * stride0
      
          In [8]: byte0_stop
          Out[8]: 1.8446744073709552e+19
      
      and then it becomes a real problem for BigArray.__getitem__()
      
          wendelin.core/bigarray/__init__.py:326: RuntimeWarning: overflow encountered in long_scalars
            page0_min  = min(byte0_start, byte0_stop+byte0_stride) // pagesize # TODO -> fileh.pagesize
      
      and then
      
          >           vma0 = self._fileh.mmap(page0_min, page0_max-page0_min+1)
          E           TypeError: integer argument expected, got float
      
      ~~~~
      
      So just avoid multiple.reduce() and do our own mul() properly the same
      way sum() is builtin into python, and we avoid overflow-related
      problems.
      73926487
    • Kirill Smelkov's avatar
      3rdparty/ccan: Update for bitmap_alloc0() segfault fix · d59b15a3
      Kirill Smelkov authored
      We need this commit:
      
          http://git.ozlabs.org/?p=ccan;a=commitdiff;h=c38e11b508e52fb2921e67d1123b05d9bef90fd2
      
      or else we segfault on really big arrays allocation instead of getting
      ENOMEM and reporting it as MemoryError to python.
      d59b15a3
    • Kirill Smelkov's avatar
      bigfile/py: Fix crash in {pyvma,pyfileh}_dealloc() if deallocated object was not fully constructed · 7e6829c7
      Kirill Smelkov authored
      Consider e.g. this for pyvma:
      
          1. in pyfileh_mmap() pyvma is created
      
          2. next fileh_mmap(pyvma, pyfileh, ...) fails
      
          3. we need to deallocate pyvma which was not mapped
      
          4. in pyvma_dealloc() we unmap pyvma unconditionally -> boom.
      
      The same story goes for pyfileh dealloc vs not fully constructing it in
      pyfileh_open().
      7e6829c7
    • Kirill Smelkov's avatar
      bigarray: Translate OverflowError when computing slice indices to MemoryError · fcbb26e6
      Kirill Smelkov authored
      OverflowError when computing slice indices practically means we'll
      cannot allocate so much address space at next step:
      
          In [1]: s = slice(None)
      
          In [2]: s.indices(1<<62)
          Out[2]: (0, 4611686018427387904, 1)
      
          In [3]: s.indices(1<<63)
          ---------------------------------------------------------------------------
          OverflowError                             Traceback (most recent call last)
          <ipython-input-4-5aa549641bc6> in <module>()
          ----> 1 s.indices(1<<63)
      
          OverflowError: cannot fit 'long' into an index-sized integer
      
      So translate this OverflowError into MemoryError (preserving message
      details), because we'll need such "no so much address space" cases to
      show up as MemoryError in a sooner patch.
      fcbb26e6
    • Kirill Smelkov's avatar
      bigfile/py: Raise MemoryError for ENOMEM errno · 2cf9073f
      Kirill Smelkov authored
      Currently we always raise RuntimeError for problems, which is
      more-or-less ok for humans, but soon we'll need to distinguish "no
      memory" errors from other error conditions in upper layers in code.
      
      Introduce helper function for choosing appropriate exception type for an
      error - MemoryError for when errno=ENOMEM and RuntimeError otherwise,
      and use it where appropriate.
      
      ( Unfortunately Python does not provide such a helper... )
      2cf9073f
    • Kirill Smelkov's avatar
      setup: file_finders entry-point group registration is not a workaround · 6fdde936
      Kirill Smelkov authored
      As discussion in https://bitbucket.org/pypa/setuptools/issue/313
      unveiled, setuptools do not have to carry setuptools.file_finders
      entrypoint with it in order to support _other_ projects to use
      .file_finders entry point.
      
      In our case it means that is is normal that we have to make sure that
      the group we are going to register entry-point into, exists.
      
      Remove erroneous comments introduced in 11d130d1 (setup: Ensure
      setuptools.file_finders entry-point group is registered).
      6fdde936
    • Kirill Smelkov's avatar
      setup: Fix for py3 · 25dbf467
      Kirill Smelkov authored
      py2-only syntax introduced in acf7e91d (setup/runcmd: Properly report
      errors, if running command is missing):
      
            File "setup.py", line 168
              except Exception, e:
                              ^
          SyntaxError: invalid syntax
      25dbf467
  8. 01 Jun, 2015 4 commits
  9. 28 May, 2015 4 commits
    • Kirill Smelkov's avatar
      setup: Ensure setuptools.file_finders entry-point group is registered · 11d130d1
      Kirill Smelkov authored
      If setuptools.file_finders group is not registered,
      dist.get_entry_map('setuptools.file_finders') returns just {} not
      connected to entry map, and further modifications of this dict go
      nowhere (and thus, our git_lsfiles() is not hooked -> sdist fails to
      produce correct source archive).
      
      This is a workaround for setuptools 9.0 dropping
      `setuptools.file_finders` entrypoint group registration:
      
          https://bitbucket.org/pypa/setuptools/commits/f191c8a1225bd58a5fb5aa9abb31b06dc710f0b9#Lsetup.pyF175
          https://bitbucket.org/pypa/setuptools/issue/313
      
      issue reported back:
      
          https://bitbucket.org/pypa/setuptools/issue/313#comment-18430008
      11d130d1
    • Kirill Smelkov's avatar
      bigarray: Test that asarray(BigArray(...)) does not hang · 0e25b01c
      Kirill Smelkov authored
      It was hanging with NumPy-1.9 before 425dc5d1 (bigarray: Raise
      IndexError for out-of-bound element access), because of the following
      correct NumPy commit:
      
          https://github.com/numpy/numpy/commit/d36f8227
      
      and in particular
      
          https://github.com/numpy/numpy/commit/d36f8227#diff-6d326badc0872de91e025cbfb0be1aafR522
      
      That PySequence_Fast(obj)    (with obj being BigArray)
      
      creates iterator on top of obj and before our previous IndexError fix in
      425dc5d1, this was looping forever.
      
      Test explicitly with both NumPy 1.8 and NumPy 1.9, that this construct
      does not hang.
      
      /cc @Tyagov
      0e25b01c
    • Kirill Smelkov's avatar
      bigarray: Raise IndexError for out-of-bound element access · 425dc5d1
      Kirill Smelkov authored
      The way BigArray.__getitem__ works for element access is that for e.g.
      
          A[i]
      
      it translates the request to
      
          A[i:i+1]
      
      and remembers to lower the dimensionality at scalar index
      
          dim_adjust = (0,)
      
      so, in full, A[i] is computed this way:
      
          A[i] -> A[i:i+1](0,)
      
      ( it is done this way to unify code for scalar / slice access in
        __getitem__ - see 0c826d5c "BigArray: An ndarray-like on top of
        BigFile memory mappings" )
      
      The code for slice access also has a shortcut - if it sees that slice
      results in empty array (e.g. for out-of-bound slice), we can avoid
      spending time to create a file vma mapping only to create empty view on
      top of it.
      
      In 0c826d5c, that optimization, however forgot to apply the "lower the
      dimensionality" step on top of resulting empty view, and that turned out
      for not raising IndexError for out-of-bounds scalar access:
      
          A = BigArray((10,), uint8)
          In [1]: A[0]
          Out[1]: 0
      
          In [2]: A[1]
          Out[2]: 0
      
          In [3]: A[2]
          Out[3]: 0
      
          In [4]: A[9]
          Out[4]: 0
      
          In [5]: A[10]
          Out[5]: array([], dtype=uint8)
      
      NOTE that A[10] returns empty array instead of raising IndexError.
      
      So do not forget to apply the "reduce dimensionality" step for empty
      views, and this way we get proper IndexError (because for empty view,
      scalar access results in IndexError).
      
      NOTE:
      
      this bug was also preventing for e.g.
      
          list(A)
      
      to work, because list(A) internally works this way:
      
          l = []
          i = iter(A)
          for _ in i:
              l.append(_)
      
      but iterating would not stop after 10 elements - after array end, _ will
      be always array([], dtype=uint8), and thus the loop never finished and
      memory usage grow to infinity.
      
      /cc @Tyagov
      425dc5d1
    • Kirill Smelkov's avatar
      bigarray: Be explicit about not-supporting advanced indexing · 4680c0cd
      Kirill Smelkov authored
      In NumPy speak advanced indexing is picking up arbitrarily requested
      elemtnts, e.g.
      
          a = arange(10)
          a[[0,3,2]]  -> array([0, 3, 2])
      
      The way this indexing schem works is - it creates a new array with
      len = len(key), and picks up requested elements sequentially into new
      area.
      
      So it is very not the same as creating _view_ to original array data by
      using basic indexing [1]
      
      BigArray does not support advanced indexing, because its main job is to
      organize an ndarray _view_ backed up by BigFile data and give that view
      to clients, and then it is up to clients how to use that view with full
      numpy api available with it.
      
      So be explicit, and reject advanced indexing in __getitem__ right at the
      beginning.
      
      [1] http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
      4680c0cd
  10. 25 May, 2015 3 commits
    • Kirill Smelkov's avatar
    • Kirill Smelkov's avatar
      wendelin.core v0.2 · c877184f
      Kirill Smelkov authored
      c877184f
    • Kirill Smelkov's avatar
      tests: Don't forget to depend on ccan's config.h · dcdb0302
      Kirill Smelkov authored
      Else, in a clean repo the tests do not build from scratch:
      
          $ make test
          x86_64-linux-gnu-gcc -pthread -g -Wall -D_GNU_SOURCE -std=gnu99 -fplan9-extensions -Wno-declaration-after-statement -Wno-error=declaration-after-statement  -Iinclude -I3rdparty/ccan -I3rdparty/include   bigfile/tests/test_virtmem.c lib/bug.c lib/utils.c 3rdparty/ccan/ccan/tap/tap.c  -o bigfile/tests/test_virtmem.t
          In file included from include/wendelin/list.h:11:0,
                           from include/wendelin/bigfile/virtmem.h:33,
                           from bigfile/tests/../virtmem.c:23,
                           from bigfile/tests/test_virtmem.c:21:
          3rdparty/ccan/ccan/array_size/array_size.h:4:20: fatal error: config.h: No such file or directory
           #include "config.h"
                              ^
          compilation terminated.
          3rdparty/ccan/ccan/tap/tap.c:26:20: fatal error: config.h: No such file or directory
           #include "config.h"
                              ^
          compilation terminated.
          Makefile:99: recipe for target 'bigfile/tests/test_virtmem.t' failed
          make: *** [bigfile/tests/test_virtmem.t] Error 1
      dcdb0302
  11. 20 May, 2015 4 commits
    • Kirill Smelkov's avatar
      bigarray: Support resizing in-place · ca064f75
      Kirill Smelkov authored
      In NumPy, ndarray has .resize() but actually it does a whole array
      copy into newly allocated larger segment which makes e.g. appending O(n).
      
      For BigArray, we don't have that internal constraint NumPy has - to
      keep the array itself contiguously _stored_ (compare to contiguously
      _presented_ in memory). So we can have O(1) resize for big arrays.
      
      NOTE having O(1) resize, here is how O(δ) append can be done:
      
          A                               # ZBigArray e.g. of shape   (N, 3)
          n = len(A)                      # lengh of A's major index  =N
          A.resize((n+δ, A.shape[1:]))    # add δ new entries ; now len(A) =N+δ
          A[-δ:] = <new-data>             # set data for last new δ entries
      
      /cc @klaus
      ca064f75
    • Kirill Smelkov's avatar
      bigarray/tests: Factor-out generic BigFile connected to numpy array · 929922fa
      Kirill Smelkov authored
      test_bigarray_indexing_Nd() contains useful class to have a BigFile
      connected to ndarray storage. Factor it out so that all tests could use
      it.
      
      BigFile_Data.storeblk() is newly introduced and is currently unused, but
      will be convenient to have later.
      929922fa
    • Kirill Smelkov's avatar
    • Kirill Smelkov's avatar
      bigarray: Fix typos · 3c7abddb
      Kirill Smelkov authored
      3c7abddb
  12. 14 May, 2015 1 commit
    • Kirill Smelkov's avatar
      Fix build with non-std "python" · a280b53d
      Kirill Smelkov authored
      In 5755a6b3 (Basic setup.py / Makefile to build/install/sdist stuff +
      bigfile.so skeleton) we overlooked one thing:
      
          when tailing from setup.py to make level, we forgot to setup the
          PYTHON env variable properly, and that leads to changing building
          with std python.
      
      Look e.g.
      
          $ python3 setup.py build_ext -i
          running build_ext
          python setup.py ll_build_ext --inplace
          ^^^
      
      which is obviously not correct.
      
      Fix it.
      
      The tox setup we have setup for testing with multiple interpreters
      (7af2b2d7 "Tox setup to test things with py27 & py34 and several
      versions of ZODB") did not caught this, because for every python and
      environment versions tox initializes separate virtualenv, in which
      .../bin/python is a link to chosen python, and this way both python and
      my-selected-for-build-python are the same.
      
      Cc: @Tyagov
      a280b53d
  13. 29 Apr, 2015 2 commits
    • Kirill Smelkov's avatar
    • Kirill Smelkov's avatar
      bigfile/ram_shmfs: Try to support compiling on older systems · 48defba0
      Kirill Smelkov authored
      For example on Debian 7 Wheezy the kernel (linux 3.2) supports holepunching,
      because holepunching was added in linux 2.6.38:
      
          http://git.kernel.org/linus/79124f18b335172e1916075c633745e12dae1dac
      
      but glibc does not provide fallocate mode constants, and compilation fails:
      
          gcc -pthread -fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -D_GNU_SOURCE -I./include -I./3rdparty/ccan -I./3rdparty/include -I/opt/slapgrid/f2a5f59d0d2b521681b9333ee76a2859/parts/python2.7/include/python2.7 -c bigfile/ram_shmfs.c -o build/temp.linux-x86_64-2.7/bigfile/ram_shmfs.o -std=gnu99 -fplan9-extensions -fvisibility=hidden -Wno-declaration-after-statement -Wno-error=declaration-after-statement
          bigfile/ram_shmfs.c: In function ‘shmfs_drop_memory’:
          bigfile/ram_shmfs.c:135:31: error: ‘FALLOC_FL_PUNCH_HOLE’ undeclared (first use in this function)
          bigfile/ram_shmfs.c:135:31: note: each undeclared identifier is reported only once for each function it appears in
          bigfile/ram_shmfs.c:135:54: error: ‘FALLOC_FL_KEEP_SIZE’ undeclared (first use in this function)
          error: command 'gcc' failed with exit status 1
      
      Try to fix it via fallbacking to provide the needed defines on older systems ourselves.
      
      Cc: Klaus Wölfel <klaus@nexedi.com>
      Cc: Ivan Tyagov <ivan@tyagov.com>
      48defba0
  14. 15 Apr, 2015 1 commit
    • Kirill Smelkov's avatar
      Fix build with Python that enables -Werror=declaration-after-statement · e0b25398
      Kirill Smelkov authored
      In C99 declaration after statement is ok, and we explicitly compile with -std=gnu99.
      
      Python >= 3.4 however adds -Werror=declaration-after-statement even for extension
      modules irregardless of their compilation flags:
      
        https://bugs.python.org/issue21121
      
      and the build fails this way:
      
          building 'wendelin.bigfile._bigfile' extension
          creating build/temp.linux-x86_64-3.4
          creating build/temp.linux-x86_64-3.4/bigfile
          creating build/temp.linux-x86_64-3.4/lib
          gcc -pthread -Wno-unused-result -Werror=declaration-after-statement -DNDEBUG -fmessage-length=0 -grecord-gcc-switches -O2 -Wall
      -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g -DOPENSSL_LOAD_CONF -fPIC -D_GNU_SOURCE
      -I./include -I./3rdparty/ccan -I./3rdparty/include -I/usr/include/python3.4m -c bigfile/_bigfile.c -o build/temp.linux-x86_64-3.4/bigfile/_bigfile.o
      -std=gnu99 -fplan9-extensions -fvisibility=hidden
          bigfile/_bigfile.c: In function ‘pyfile_new’:
          bigfile/_bigfile.c:679:5: error: ISO C90 forbids mixed declarations and code [-Werror=declaration-after-statement]
               static char *kw_list[] = {"blksize", NULL};
               ^
          cc1: some warnings being treated as errors
          error: command 'gcc' failed with exit status 1
      
      Ensure we turn off this warning and error because we already rely on compiling in C99 mode.
      Reported-and-tested-by: 's avatarIvan Tyagov <ivan@tyagov.com>
      e0b25398