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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Kirill Smelkov
wendelin.core
Commits
2c2a094f
Commit
2c2a094f
authored
Mar 05, 2020
by
Kirill Smelkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
.
parent
a288e2bc
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
122 additions
and
26 deletions
+122
-26
wcfs/client/wcfs.cpp
wcfs/client/wcfs.cpp
+63
-25
wcfs/client/wcfs.h
wcfs/client/wcfs.h
+1
-1
wcfs/client/wcfs_misc.cpp
wcfs/client/wcfs_misc.cpp
+46
-0
wcfs/client/wcfs_misc.h
wcfs/client/wcfs_misc.h
+12
-0
No files found.
wcfs/client/wcfs.cpp
View file @
2c2a094f
...
...
@@ -69,7 +69,7 @@
// never shrink. It is indeed currently so, but will have to be revisited
// if/when wendelin.core adds bigfile truncation. Wcfs client restats
// wcfs/head/f at every transaction boundary (Conn.resync) and remembers f.size
// in FileH._headfsize for use during one transaction.
// in FileH._headfsize for use during one transaction
(%)
.
//
//
// Integration with wendelin.core virtmem layer
...
...
@@ -111,6 +111,7 @@
// (+) currently, for simplicity, there is one pinner thread for each connection.
// In the future, for efficiency, it might be reworked to be one pinner thread
// that serves all connections simultaneously.
// (%) see _headWait comments on how this has to be reworked.
// Wcfs client locking organization
...
...
@@ -167,6 +168,7 @@
#include <golang/errors.h>
#include <golang/fmt.h>
#include <golang/io.h>
#include <golang/time.h>
#include <algorithm>
#include <string>
...
...
@@ -181,6 +183,8 @@ using std::min;
using
std
::
max
;
using
std
::
vector
;
namespace
ioutil
=
io
::
ioutil
;
#define TRACE 0
#if TRACE
...
...
@@ -204,13 +208,21 @@ static error mmap_into_ro(void *addr, size_t size, os::File f, off_t offset);
// connect creates new Conn viewing WCFS state as of @at.
pair
<
Conn
,
error
>
WCFS
::
connect
(
zodb
::
Tid
at
)
{
WCFS
*
wc
=
this
;
xerr
::
Contextf
E
(
"
wcfs %s: connect @%s"
,
v
(
wc
->
mountpoint
),
v
(
at
));
xerr
::
Contextf
E
(
"
%s: connect @%s"
,
v
(
wc
),
v
(
at
));
etrace
(
""
);
error
err
;
// TODO support !isolated mode
// need to wait till `wcfs/head/at ≥ at` because e.g. Conn.open stats
// head/f to get f.headfsize.
err
=
wc
->
_headWait
(
at
);
if
(
err
!=
nil
)
{
return
make_pair
(
nil
,
E
(
err
));
}
WatchLink
wlink
;
error
err
;
tie
(
wlink
,
err
)
=
wc
->
_openwatch
();
if
(
err
!=
nil
)
return
make_pair
(
nil
,
E
(
err
));
...
...
@@ -227,25 +239,52 @@ pair<Conn, error> WCFS::connect(zodb::Tid at) {
return
wconn
->
_pinner
(
ctx
);
});
// need to wait till `wcfs/head/at ≥ at` because e.g. Conn.open stats
// head/f to get f.headfsize.
// XXX atMu.RLock ?
err
=
wconn
->
_headWait
(
at
);
if
(
err
!=
nil
)
{
// XXX bring conn down - stop pinner
return
make_pair
(
nil
,
E
(
err
));
}
return
make_pair
(
wconn
,
nil
);
}
// _headWait waits till wcfs/head/at becomes ≥ at.
//
// XXX locks condition?
// XXX place?
error
_Conn
::
_headWait
(
zodb
::
Tid
at
)
{
// XXX +ctx ?
// FIXME implement
//
// _headWait is currently needed, because client stats wcfs/head/f to get f
// size assuming that f size only ↑. The assumption is not generally valid
// (e.g. f might be truncated = hole puched for block at tail), but holds true
// for now. However to get correct results wcfs/head/f has to be statt'ed
// _after_ wcfs view of the database becomes ≥ wconn.at.
//
// TODO extend isolation protocol to report f size as of @at database state at
// watch init/update(*). This way there won't be need for headWait as correct
// file size @at will be returned by wcfs itself, which will also work if
// wcfs/head/f size is changed arbitrarily.
//
// (*) equivalient might be to send something like "pin #<bsize>.. Z" (pin
// blocks bsize till ∞ to zeros).
error
WCFS
::
_headWait
(
zodb
::
Tid
at
)
{
WCFS
*
wc
=
this
;
xerr
::
Contextf
E
(
"%s: headWait @%s"
,
v
(
wc
),
v
(
at
));
etrace
(
""
);
zodb
::
Tid
xat
;
string
xatStr
;
error
err
;
// XXX dumb implementation, because _headWait should go away.
while
(
1
)
{
tie
(
xatStr
,
err
)
=
ioutil
::
ReadFile
(
wc
->
_path
(
"head/at"
));
if
(
err
!=
nil
)
return
E
(
err
);
tie
(
xat
,
err
)
=
xstrconv
::
parseHex64
(
xatStr
);
if
(
err
!=
nil
)
return
E
(
fmt
::
errorf
(
"head/at: %w"
,
err
));
if
(
xat
>=
at
)
break
;
time
::
sleep
(
1E-6
);
// XXX -> time::millisecond
}
return
nil
;
}
...
...
@@ -555,22 +594,21 @@ error _Conn::resync(zodb::Tid at) {
wconn
.
_atMu
.
RUnlock
();
etrace
(
""
);
// bring wconn + fileh + mmaps down on error
bool
retok
=
false
;
defer
([
&
]()
{
if
(
!
retok
)
wconn
.
close
();
// ignore error
});
// XXX _downErr -> E
// XXX at ^ (increases) -> rejected by wcfs XXX or also precheck here?
//
first
wait for wcfs/head to be >= at.
// wait for wcfs/head to be >= at.
// we need this e.g. to be sure that head/f.size is at least as big that it will be @at state.
err
=
wconn
.
_headWait
(
at
);
err
=
wconn
.
_
wc
->
_
headWait
(
at
);
if
(
err
!=
nil
)
return
err
;
return
E
(
err
)
;
// bring wconn + fileh + mmaps down on error
bool
retok
=
false
;
defer
([
&
]()
{
if
(
!
retok
)
wconn
.
close
();
// ignore error
});
// lock wconn._atMu.W . This excludes everything else, and in
// particular _pinner_, from running and mutating files and mappings.
...
...
wcfs/client/wcfs.h
View file @
2c2a094f
...
...
@@ -152,6 +152,7 @@ struct WCFS {
pair
<
WatchLink
,
error
>
_openwatch
();
string
String
()
const
;
error
_headWait
(
zodb
::
Tid
at
);
};
// Conn represents logical connection that provides view of data on wcfs
...
...
@@ -208,7 +209,6 @@ private:
error
__pinner
(
context
::
Context
ctx
);
error
_pin1
(
PinReq
*
req
);
error
__pin1
(
PinReq
*
req
);
error
_headWait
(
zodb
::
Tid
at
);
};
// FileH represent isolated file view under Conn.
...
...
wcfs/client/wcfs_misc.cpp
View file @
2c2a094f
...
...
@@ -34,6 +34,9 @@ using namespace golang;
#include <memory>
// golang::
namespace
golang
{
// os::
namespace
os
{
...
...
@@ -178,6 +181,46 @@ error unmap(void *addr, size_t size) {
}
// mm::
// io::ioutil::
namespace
io
{
namespace
ioutil
{
tuple
<
string
,
error
>
ReadFile
(
const
string
&
path
)
{
// errctx is ok as returned by all calls.
os
::
File
f
;
error
err
;
tie
(
f
,
err
)
=
os
::
open
(
path
);
if
(
err
!=
nil
)
return
make_tuple
(
""
,
err
);
// XXX defer close
string
data
;
vector
<
char
>
buf
(
4096
);
while
(
1
)
{
int
n
;
tie
(
n
,
err
)
=
f
->
read
(
&
buf
[
0
],
buf
.
size
());
data
.
append
(
&
buf
[
0
],
n
);
if
(
err
!=
nil
)
{
if
(
err
==
io
::
EOF_
)
err
=
nil
;
break
;
}
}
error
err2
=
f
->
close
();
if
(
err
==
nil
)
err
=
err2
;
if
(
err
!=
nil
)
data
=
""
;
return
make_tuple
(
data
,
err
);
}
}}
// io::ioutil::
// xstrconv:: (strconv-like)
namespace
xstrconv
{
...
...
@@ -215,6 +258,9 @@ tuple<uint64_t, error> parseUint(const string& s) {
}
// xstrconv::
}
// golang::
// xerr::
namespace
xerr
{
...
...
wcfs/client/wcfs_misc.h
View file @
2c2a094f
...
...
@@ -55,6 +55,9 @@ using std::vector;
#include <sys/stat.h>
#include <fcntl.h>
// golang::
namespace
golang
{
// os::
namespace
os
{
...
...
@@ -116,6 +119,13 @@ namespace mm {
}
// mm::
// io::ioutil::
namespace
io
{
namespace
ioutil
{
tuple
<
string
,
error
>
ReadFile
(
const
string
&
path
);
}}
// io::ioutil::
// ---- misc ----
...
...
@@ -129,6 +139,8 @@ tuple<uint64_t, error> parseUint(const string& s);
}
// xstrconv::
}
// golang::
// zodb::
namespace
zodb
{
...
...
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