Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
W
wendelin.core
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Joshua
wendelin.core
Commits
a4d63fbb
Commit
a4d63fbb
authored
Feb 22, 2019
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
bc041be8
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
109 additions
and
19 deletions
+109
-19
bigfile/file_zodb.py
bigfile/file_zodb.py
+41
-8
bigfile/virtmem.c
bigfile/virtmem.c
+1
-1
tox.ini
tox.ini
+4
-1
wcfs/__init__.py
wcfs/__init__.py
+58
-4
wcfs/wcfs_test.py
wcfs/wcfs_test.py
+5
-5
No files found.
bigfile/file_zodb.py
View file @
a4d63fbb
# -*- coding: utf-8 -*-
# Wendelin.bigfile | BigFile ZODB backend
# Copyright (C) 2014-201
5
Nexedi SA and Contributors.
# Copyright (C) 2014-201
9
Nexedi SA and Contributors.
# Kirill Smelkov <kirr@nexedi.com>
#
# This program is free software: you can Use, Study, Modify and Redistribute
...
...
@@ -79,6 +79,7 @@ natural to also use "2" here.
"""
from
wendelin.bigfile
import
BigFile
,
WRITEOUT_STORE
,
WRITEOUT_MARKSTORED
from
wendelin
import
wcfs
# XXX -> wendelin.bigfile.wcfs ?
from
wendelin.lib.mem
import
bzero
,
memcpy
from
wendelin.lib.zodb
import
deactivate_btree
...
...
@@ -489,6 +490,7 @@ class ZBigFile(LivePersistent):
# load data ZODB obj -> page
def
loadblk
(
self
,
blk
,
buf
):
# XXX overlay: BUG if called (XXX here, in ZBigFile?)
zblk
=
self
.
blktab
.
get
(
blk
)
# no data written yet - "hole" reads as all zeros
if
zblk
is
None
:
...
...
@@ -538,12 +540,36 @@ class ZBigFile(LivePersistent):
# bigfile-like
def
fileh_open
(
self
):
fileh
=
_ZBigFileH
(
self
)
#
# _use_wcfs is internal option and controls whether to use wcfs to access
# ZBigFile data:
#
# - True -> use wcfs
# - False -> don't use wcfs
# - not set -> behave according to global default
def
fileh_open
(
self
,
_use_wcfs
=
None
):
if
_use_wcfs
is
None
:
_use_wcfs
=
self
.
_default_use_wcfs
()
wcfileh
=
None
if
_use_wcfs
:
zstor
=
self
.
_p_jar
.
db
().
storage
zurl
=
wcfs
.
zstor_2zurl
(
zstor
)
wc
=
wcfs
.
join
(
zurl
,
shared
=
True
)
wcfileh
=
wc
.
open
(
self
)
fileh
=
_ZBigFileH
(
self
,
wcfileh
)
self
.
_v_filehset
.
add
(
fileh
)
return
fileh
# _default_use_wcfs returns whether default virtmem setting is to use wcfs or not.
@
staticmethod
def
_default_use_wcfs
():
virtmem
=
os
.
environ
.
get
(
"WENDELIN_CORE_VIRTMEM"
,
"rw:uvmm"
)
# unset -> !wcfs
virtmem
=
virtmem
.
lower
()
return
{
"r:wcfs+w:uvmm"
:
True
,
"rw:uvmm"
:
True
}[
virtmem
]
# patch for ZODB.Connection to support callback on .open()
...
...
@@ -616,11 +642,18 @@ Connection.open = Connection_open
@
implementer
(
ISynchronizer
)
class
_ZBigFileH
(
object
):
# .zfile ZBigFile we were opened for
# .zfileh handle for ^^^
def
__init__
(
self
,
zfile
):
self
.
zfile
=
zfile
self
.
zfileh
=
zfile
.
_v_file
.
fileh_open
()
# .wcfileh handle for ZBigFile in wcfs | None
# .zfileh handle for ZBigFile (overlayed over .wcfileh if .wcfile != ø)
def
__init__
(
self
,
zfile
,
wcfileh
):
self
.
zfile
=
zfile
self
.
wcfileh
=
wcfileh
# FIXME for now we use only wcfs handle
# TODO setup overlaying
if
wcfileh
is
not
None
:
self
.
zfileh
=
wcfileh
else
:
self
.
zfileh
=
zfile
.
_v_file
.
fileh_open
()
# FIXME zfile._p_jar could be None (ex. ZBigFile is newly created
# before first commit)
...
...
bigfile/virtmem.c
View file @
a4d63fbb
...
...
@@ -742,7 +742,7 @@ VMFaultResult vma_on_pagefault(VMA *vma, uintptr_t addr, int write)
return
VM_RETRY
;
}
inject_page:
//
inject_page:
/* (6) page data ready. Mmap it atomically into vma address space, or mprotect
* appropriately if it was already mmaped. */
int
prot
=
PROT_READ
;
...
...
tox.ini
View file @
a4d63fbb
# wendelin.core | tox setup
[tox]
envlist
=
py27-{ZODB3,ZODB4,ZODB5}-{zblk0,zblk1}-{fs,zeo,neo}-{numpy113,numpy114}
, {py35,py36}-{ZODB4,ZODB5}-{zblk0,zblk1}-{fs,zeo}-{numpy113,numpy114
}
envlist
=
py27-{ZODB3,ZODB4,ZODB5}-{zblk0,zblk1}-{fs,zeo,neo}-{numpy113,numpy114}
-{!wcfs,wcfs}, {py35,py36}-{ZODB4,ZODB5}-{zblk0,zblk1}-{fs,zeo}-{numpy113,numpy114}-{!wcfs,wcfs
}
# (NOTE ZODB3 does not work on python3)
# (NOTE NEO does not work on python3 at all)
# (XXX ZODB5-*-neo are currently failing)
...
...
@@ -44,6 +44,9 @@ setenv =
zblk0:
WENDELIN_CORE_ZBLK_FMT
=
ZBlk0
zblk1:
WENDELIN_CORE_ZBLK_FMT
=
ZBlk1
!wcfs:
WENDELIN_CORE_VIRTMEM
=
rw:uvmm
wcfs:
WENDELIN_CORE_VIRTMEM
=
r:wcfs+w:uvmm
commands
=
{envpython} setup.py test
# XXX setenv = TMPDIR = ... ? (so that /tmp is not on tmpfs and we don't run out of memory on bench)
# + {envpython} setup.py bench (?)
wcfs/__init__.py
View file @
a4d63fbb
...
...
@@ -26,6 +26,7 @@ It will also be automatically started by default unless
$WENDELIN_CORE_WCFS_AUTOSTART=no is specified in environment.
Conn represents connection to wcfs server obtained by join.
FileH ... XXX
XXX
"""
...
...
@@ -38,6 +39,8 @@ from golang import go, chan, select, default
from
golang.gcompat
import
qq
from
ZODB.FileStorage
import
FileStorage
from
ZODB.utils
import
u64
,
p64
from
zodbtools.util
import
ashex
# Conn represents connection to wcfs server.
...
...
@@ -52,6 +55,51 @@ class Conn(object):
def
close
(
self
):
self
.
_fwcfs
.
close
()
# open creates wcfs file handle, which can be mmaped to give data of ZBigFile.
#
# XXX more text
#
# All mmapings of one FileH share changes.
# There can be several different FileH for the same (at, oid), and those
# FileH do not share changes.
def
open
(
self
,
zfile
):
# -> FileH
#assert isinstance(zfile, ZBigFile) # XXX import cycle
zconn
=
zfile
.
_p_jar
# XXX ._start is probably ZODB5 only -> check ZODB4 and ZODB3
zat
=
p64
(
u64
(
zconn
.
_start
)
-
1
)
# before -> at
# XXX pinned to @revX/... for now -> TODO /head/bigfile/...
path
=
'%s/@%s/bigfile/%s'
%
(
self
.
mountpoint
,
ashex
(
zat
),
ashex
(
self
.
_p_oid
))
fd
=
os
.
open
(
path
)
return
FileH
(
fd
)
# FileH is handle to opened bigfile/X.
#
# XXX it mimics BigFileH and should be integrated into virtmem (see fileh_open_overlay)
#
# XXX it should implement wcfs invalidation protocol and remmap head/... parts
# to pinned as requested.
import
mmap
from
bigarray.array_ram
import
_VMA
,
pagesize
# XXX hack
class
FileH
(
object
):
# .fd
def
__init__
(
self
,
fd
):
self
.
fd
def
__del__
(
self
):
os
.
close
(
self
.
fd
)
def
mmap
(
self
,
pgoffset
,
pglen
):
return
_VMA
(
self
.
fd
,
pgoffset
,
pglen
,
pagesize
,
mmap
.
PROT_READ
)
# ---- join/run wcfs ----
# serve starts and runs wcfs server for ZODB @ zurl.
#
...
...
@@ -103,8 +151,13 @@ def _default_autostart():
# If wcfs for that zurl was already started, join connects to it.
# Otherwise it starts wcfs for zurl if autostart is True.
#
# If shared is True - a shared connection is returned - one that will be also
# returned for following join(shared=True) requests with the same zurl.
#
# join(zurl) -> Conn.
def
join
(
zurl
,
autostart
=
_default_autostart
()):
def
join
(
zurl
,
autostart
=
_default_autostart
(),
shared
=
False
):
# XXX implement shared
mntpt
=
_mntpt_4zurl
(
zurl
)
# try opening .wcfs - if we succeed - it is already mounted.
...
...
@@ -255,7 +308,7 @@ def _wcfs_exe():
# it also makes sure the mountpoint exists.
def
_mntpt_4zurl
(
zurl
):
# XXX what if zurl is zconfig://... ? -> then we have to look inside?
# ->
_
zstor_2zurl extracts zurl in canonical form and zconfig:// is not possible there.
# -> zstor_2zurl extracts zurl in canonical form and zconfig:// is not possible there.
m
=
hashlib
.
sha1
()
m
.
update
(
zurl
)
mntpt
=
"%s/wcfs/%s"
%
(
tempfile
.
gettempdir
(),
m
.
hexdigest
())
...
...
@@ -263,8 +316,9 @@ def _mntpt_4zurl(zurl):
return
mntpt
# _zstor_2zurl converts a ZODB storage to URL to access it.
def
_zstor_2zurl
(
zstor
):
# zstor_2zurl converts a ZODB storage to URL to access it.
# XXX -> unexport?
def
zstor_2zurl
(
zstor
):
# There is, sadly, no unified way to do it, as even if storages are created via
# zodburi, after creation its uri is lost. And storages could be created not
# only through URI but e.g. via ZConfig and manually. We want to support all
...
...
wcfs/wcfs_test.py
View file @
a4d63fbb
...
...
@@ -45,7 +45,7 @@ def setup_module():
testdb
.
setup
()
zstor
=
testdb
.
getZODBStorage
()
testzurl
=
wcfs
.
_
zstor_2zurl
(
zstor
)
testzurl
=
wcfs
.
zstor_2zurl
(
zstor
)
zstor
.
close
()
testmntpt
=
wcfs
.
_mntpt_4zurl
(
testzurl
)
os
.
rmdir
(
testmntpt
)
...
...
@@ -86,7 +86,7 @@ def tidtime(tid):
def
test_zurlstable
():
for
i
in
range
(
10
):
zstor
=
testdb
.
getZODBStorage
()
zurl
=
wcfs
.
_
zstor_2zurl
(
zstor
)
zurl
=
wcfs
.
zstor_2zurl
(
zstor
)
zstor
.
close
()
assert
zurl
==
testzurl
...
...
@@ -122,7 +122,6 @@ def test_join_autostart():
# XXX parametrize zblk0, zblk1
# XXX select !wcfs mode so that we prepare data through !wcfs path.
@
func
def
test_wcfs
():
root
=
testdb
.
dbopen
()
...
...
@@ -197,9 +196,10 @@ def test_wcfs():
# commit data to f and make sure we can see it on wcfs
# use !wcfs mode so that we prepare data independently of wcfs code paths.
#hole = 10 XXX reenable
hole
=
1
fh
=
f
.
fileh_open
()
fh
=
f
.
fileh_open
(
_use_wcfs
=
False
)
vma
=
fh
.
mmap
(
hole
,
1
)
# 1 page at offset=10
s
=
b"hello world"
memcpy
(
vma
,
s
)
...
...
@@ -229,7 +229,7 @@ def test_wcfs():
# commit data again and make sure we can see both latest and snapshotted states.
tcommit1
=
Z
.
head
fh
=
f
.
fileh_open
()
fh
=
f
.
fileh_open
(
_use_wcfs
=
False
)
vma1
=
fh
.
mmap
(
hole
,
1
)
vma2
=
fh
.
mmap
(
hole
+
1
,
1
)
s1
=
b"hello 123"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment