Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
mpd
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Иван Мажукин
mpd
Commits
06827cfc
Commit
06827cfc
authored
Mar 23, 2015
by
Max Kellermann
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fs/io/FileOutputStream: move code to new class BaseFileOutputStream
parent
6dc30979
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
101 additions
and
49 deletions
+101
-49
FileOutputStream.cxx
src/fs/io/FileOutputStream.cxx
+33
-37
FileOutputStream.hxx
src/fs/io/FileOutputStream.hxx
+68
-12
No files found.
src/fs/io/FileOutputStream.cxx
View file @
06827cfc
...
...
@@ -37,37 +37,33 @@ FileOutputStream::Create(Path path, Error &error)
#ifdef WIN32
FileOutputStream
::
FileOutputStream
(
Path
_path
,
Error
&
error
)
:
path
(
_path
),
handle
(
CreateFile
(
path
.
c_str
(),
GENERIC_WRITE
,
0
,
nullptr
,
CREATE_ALWAYS
,
FILE_ATTRIBUTE_NORMAL
|
FILE_FLAG_WRITE_THROUGH
,
nullptr
))
:
BaseFileOutputStream
(
_path
)
{
if
(
handle
==
INVALID_HANDLE_VALUE
)
{
const
auto
path_utf8
=
path
.
ToUTF8
();
SetHandle
(
CreateFile
(
_path
.
c_str
(),
GENERIC_WRITE
,
0
,
nullptr
,
CREATE_ALWAYS
,
FILE_ATTRIBUTE_NORMAL
|
FILE_FLAG_WRITE_THROUGH
,
nullptr
));
if
(
!
IsDefined
())
error
.
FormatLastError
(
"Failed to create %s"
,
path_utf8
.
c_str
());
}
GetPath
().
ToUTF8
().
c_str
());
}
bool
FileOutputStream
::
Write
(
const
void
*
data
,
size_t
size
,
Error
&
error
)
Base
FileOutputStream
::
Write
(
const
void
*
data
,
size_t
size
,
Error
&
error
)
{
assert
(
IsDefined
());
DWORD
nbytes
;
if
(
!
WriteFile
(
handle
,
data
,
size
,
&
nbytes
,
nullptr
))
{
const
auto
path_utf8
=
path
.
ToUTF8
();
error
.
FormatLastError
(
"Failed to write to %s"
,
path
_utf8
.
c_str
());
path
.
ToUTF8
()
.
c_str
());
return
false
;
}
if
(
size_t
(
nbytes
)
!=
size
)
{
const
auto
path_utf8
=
path
.
ToUTF8
();
error
.
FormatLastError
(
ERROR_DISK_FULL
,
"Failed to write to %s"
,
path
_utf8
.
c_str
());
path
.
ToUTF8
()
.
c_str
());
return
false
;
}
...
...
@@ -79,8 +75,7 @@ FileOutputStream::Commit(gcc_unused Error &error)
{
assert
(
IsDefined
());
CloseHandle
(
handle
);
handle
=
INVALID_HANDLE_VALUE
;
Close
();
return
true
;
}
...
...
@@ -89,9 +84,8 @@ FileOutputStream::Cancel()
{
assert
(
IsDefined
());
CloseHandle
(
handle
);
handle
=
INVALID_HANDLE_VALUE
;
RemoveFile
(
path
);
Close
();
RemoveFile
(
GetPath
());
}
#else
...
...
@@ -124,35 +118,36 @@ OpenTempFile(FileDescriptor &fd, Path path)
#endif
/* HAVE_LINKAT */
FileOutputStream
::
FileOutputStream
(
Path
_path
,
Error
&
error
)
:
path
(
_path
)
:
BaseFileOutputStream
(
_path
)
{
#ifdef HAVE_LINKAT
/* try Linux's O_TMPFILE first */
is_tmpfile
=
OpenTempFile
(
fd
,
path
);
is_tmpfile
=
OpenTempFile
(
SetFD
(),
GetPath
()
);
if
(
!
is_tmpfile
)
{
#endif
/* fall back to plain POSIX */
if
(
!
fd
.
Open
(
path
.
c_str
(),
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0666
))
error
.
FormatErrno
(
"Failed to create %s"
,
path
.
c_str
());
if
(
!
SetFD
().
Open
(
GetPath
().
c_str
(),
O_WRONLY
|
O_CREAT
|
O_TRUNC
,
0666
))
error
.
FormatErrno
(
"Failed to create %s"
,
GetPath
().
c_str
());
#ifdef HAVE_LINKAT
}
#endif
}
bool
FileOutputStream
::
Write
(
const
void
*
data
,
size_t
size
,
Error
&
error
)
Base
FileOutputStream
::
Write
(
const
void
*
data
,
size_t
size
,
Error
&
error
)
{
assert
(
IsDefined
());
ssize_t
nbytes
=
fd
.
Write
(
data
,
size
);
if
(
nbytes
<
0
)
{
error
.
FormatErrno
(
"Failed to write to %s"
,
path
.
c_str
());
error
.
FormatErrno
(
"Failed to write to %s"
,
GetPath
()
.
c_str
());
return
false
;
}
else
if
((
size_t
)
nbytes
<
size
)
{
error
.
FormatErrno
(
ENOSPC
,
"Failed to write to %s"
,
path
.
c_str
());
"Failed to write to %s"
,
GetPath
()
.
c_str
());
return
false
;
}
...
...
@@ -166,24 +161,25 @@ FileOutputStream::Commit(Error &error)
#if HAVE_LINKAT
if
(
is_tmpfile
)
{
RemoveFile
(
path
);
RemoveFile
(
GetPath
()
);
/* hard-link the temporary file to the final path */
char
fd_path
[
64
];
snprintf
(
fd_path
,
sizeof
(
fd_path
),
"/proc/self/fd/%d"
,
fd
.
Get
());
if
(
linkat
(
AT_FDCWD
,
fd_path
,
AT_FDCWD
,
path
.
c_str
(),
GetFD
()
.
Get
());
if
(
linkat
(
AT_FDCWD
,
fd_path
,
AT_FDCWD
,
GetPath
()
.
c_str
(),
AT_SYMLINK_FOLLOW
)
<
0
)
{
error
.
FormatErrno
(
"Failed to commit %s"
,
path
.
c_str
());
fd
.
Close
();
error
.
FormatErrno
(
"Failed to commit %s"
,
GetPath
().
c_str
());
Close
();
return
false
;
}
}
#endif
bool
success
=
fd
.
Close
();
bool
success
=
Close
();
if
(
!
success
)
error
.
FormatErrno
(
"Failed to commit %s"
,
path
.
c_str
());
error
.
FormatErrno
(
"Failed to commit %s"
,
GetPath
()
.
c_str
());
return
success
;
}
...
...
@@ -193,12 +189,12 @@ FileOutputStream::Cancel()
{
assert
(
IsDefined
());
fd
.
Close
();
Close
();
#ifdef HAVE_LINKAT
if
(
!
is_tmpfile
)
#endif
RemoveFile
(
path
);
RemoveFile
(
GetPath
()
);
}
#endif
src/fs/io/FileOutputStream.hxx
View file @
06827cfc
...
...
@@ -37,7 +37,7 @@
class
Path
;
class
FileOutputStream
final
:
public
OutputStream
{
class
BaseFileOutputStream
:
public
OutputStream
{
const
AllocatedPath
path
;
#ifdef WIN32
...
...
@@ -46,6 +46,73 @@ class FileOutputStream final : public OutputStream {
FileDescriptor
fd
;
#endif
protected
:
#ifdef WIN32
template
<
typename
P
>
BaseFileOutputStream
(
P
&&
_path
)
:
path
(
std
::
forward
<
P
>
(
_path
)),
handle
(
INVALID_HANDLE_VALUE
)
{}
#else
template
<
typename
P
>
BaseFileOutputStream
(
P
&&
_path
)
:
path
(
std
::
forward
<
P
>
(
_path
)),
fd
(
FileDescriptor
::
Undefined
())
{}
#endif
~
BaseFileOutputStream
()
{
assert
(
!
IsDefined
());
}
#ifdef WIN32
void
SetHandle
(
HANDLE
_handle
)
{
assert
(
!
IsDefined
());
handle
=
_handle
;
assert
(
IsDefined
());
}
#else
FileDescriptor
&
SetFD
()
{
assert
(
!
IsDefined
());
return
fd
;
}
const
FileDescriptor
&
GetFD
()
const
{
return
fd
;
}
#endif
bool
Close
()
{
assert
(
IsDefined
());
#ifdef WIN32
CloseHandle
(
handle
);
handle
=
INVALID_HANDLE_VALUE
;
return
true
;
#else
return
fd
.
Close
();
#endif
}
public
:
bool
IsDefined
()
const
{
#ifdef WIN32
return
handle
!=
INVALID_HANDLE_VALUE
;
#else
return
fd
.
IsDefined
();
#endif
}
Path
GetPath
()
const
{
return
path
;
}
/* virtual methods from class OutputStream */
bool
Write
(
const
void
*
data
,
size_t
size
,
Error
&
error
)
override
;
};
class
FileOutputStream
final
:
public
BaseFileOutputStream
{
#ifdef HAVE_LINKAT
/**
* Was O_TMPFILE used? If yes, then linkat() must be used to
...
...
@@ -64,19 +131,8 @@ public:
static
FileOutputStream
*
Create
(
Path
path
,
Error
&
error
);
bool
IsDefined
()
const
{
#ifdef WIN32
return
handle
!=
INVALID_HANDLE_VALUE
;
#else
return
fd
.
IsDefined
();
#endif
}
bool
Commit
(
Error
&
error
);
void
Cancel
();
/* virtual methods from class OutputStream */
bool
Write
(
const
void
*
data
,
size_t
size
,
Error
&
error
)
override
;
};
#endif
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