Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
df39c67
filesystem: break out RawFile/RawInstance from File/Instance
sesmith177 Jan 30, 2019
62f8086
fix typo
sesmith177 Jan 30, 2019
6ba486c
Merge branch 'master' into filesystem-decorator
sesmith177 Feb 4, 2019
1f291bf
add CREATE + RDWR to spelling dictionary
sesmith177 Feb 4, 2019
43e5665
Merge branch 'master' into filesystem-decorator
sesmith177 Feb 5, 2019
3614b45
Merge branch 'master' into filesystem-decorator
sesmith177 Feb 5, 2019
f50508a
Merge branch 'master' into filesystem-decorator
sesmith177 Feb 5, 2019
779da9c
Address feedback
Feb 5, 2019
1b22c96
add todo
sesmith177 Feb 5, 2019
ac7d4c1
typedef -> using
sesmith177 Feb 6, 2019
a2c8c4f
wip
sesmith177 Feb 6, 2019
443a17a
wip
sesmith177 Feb 6, 2019
8f48f6c
Merge branch 'master' into filesystem-decorator
sesmith177 Feb 6, 2019
5db0857
rename File -> AccessLogFile and RawFile -> File
Feb 7, 2019
7e219e7
Merge branch 'master' into filesystem-decorator
sesmith177 Feb 11, 2019
05862aa
update todo
sesmith177 Feb 11, 2019
1b62da4
add Stats::Store& back to Api ctor
sesmith177 Feb 11, 2019
4b8fbb3
Merge branch 'master' into filesystem-decorator
sesmith177 Feb 13, 2019
91c161c
Merge branch 'master' into filesystem-decorator
sesmith177 Feb 13, 2019
f8e155d
Revert createApiForTest
Feb 13, 2019
685a541
Merge branch 'master' into filesystem-decorator
Feb 21, 2019
85458c4
only close open files
sesmith177 Feb 21, 2019
b973d12
Merge branch 'master' into filesystem-decorator
Feb 21, 2019
7db72ea
Merge branch 'master' into filesystem-decorator
Feb 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 1 addition & 12 deletions include/envoy/api/os_sys_calls.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ typedef SysCallResult<int> SysCallIntResult;
typedef SysCallResult<ssize_t> SysCallSizeResult;
typedef SysCallResult<void*> SysCallPtrResult;
typedef SysCallResult<std::string> SysCallStringResult;
typedef SysCallResult<bool> SysCallBoolResult;

class OsSysCalls {
public:
Expand All @@ -49,18 +50,6 @@ class OsSysCalls {
*/
virtual SysCallIntResult ioctl(int sockfd, unsigned long int request, void* argp) PURE;

/**
* Open file by full_path with given flags and mode.
* @return file descriptor.
*/
virtual SysCallIntResult open(const std::string& full_path, int flags, int mode) PURE;

/**
* Write num_bytes to fd from buffer.
* @return number of bytes written if non negative, otherwise error code.
*/
virtual SysCallSizeResult write(int fd, const void* buffer, size_t num_bytes) PURE;

/**
* @see writev (man 2 writev)
*/
Expand Down
124 changes: 91 additions & 33 deletions include/envoy/filesystem/filesystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,58 +14,61 @@ namespace Envoy {
namespace Filesystem {

/**
* Abstraction for a file on disk.
* Abstraction for a basic file on disk.
*/
class File {
class RawFile {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From an interface perspective, I'm not really sure what the difference is between a "raw" file and a "file." Can you at minimum add more comments and maybe think of a more descriptive name for File below?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for more comments. From my perspective a RawFile is an OS abstraction, and a File (maybe a better name would be good) adds Envoy semantics like stats and auto-flush.

RawFile needs to be re-implemented for different physical file layers, but the stats & auto-flush functionality can be shared across multiple RawFile impls.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I can tell, the only use of the File class is by the AccessLogManager, so maybe AccessLogFile or something like that might be better?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we leave it here I would probably do something like ThreadSafeFile or ThreadSafeAutoFlushFile or something. One other option is to actually completely move this file type and its creation into the access log manager interface, and then the filesystem interface just knows how to make "raw" or basic files, and then we can just call it File. WDYT?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think moving it into the access log manager interface makes sense -- we'll give it a look

public:
virtual ~File() {}
virtual ~RawFile() {}

/**
* Write data to the file.
* Open the file with O_RDWR | O_APPEND | O_CREAT
* The file will be closed when this object is destructed
*
* @return bool whether the open succeeded
*/
virtual void write(absl::string_view) PURE;
virtual Api::SysCallBoolResult open() PURE;

/**
* Reopen the file.
* Write the buffer to the file. The file must be explicitly opened before writing.
*
* @return ssize_t number of bytes written, or -1 for failure
*/
virtual void reopen() PURE;
virtual Api::SysCallSizeResult write(absl::string_view buffer) PURE;

/**
* Synchronously flush all pending data to disk.
* Close the file.
*
* @return bool whether the close succeeded
*/
virtual void flush() PURE;
};
virtual Api::SysCallBoolResult close() PURE;

typedef std::shared_ptr<File> FileSharedPtr;
/**
* @return bool is the file open
*/
virtual bool isOpen() PURE;

/**
* Captures state, properties, and stats of a file-system.
*/
class Instance {
public:
virtual ~Instance() {}
/**
* @return string the file path
*/
virtual std::string path() PURE;

/**
* Creates a file, overriding the flush-interval set in the class.
*
* @param path The path of the file to open.
* @param dispatcher The dispatcher used for set up timers to run flush().
* @param lock The lock.
* @param file_flush_interval_msec Number of milliseconds to delay before flushing.
* @return string a human-readable string describing the error code
*/
virtual FileSharedPtr createFile(const std::string& path, Event::Dispatcher& dispatcher,
Thread::BasicLockable& lock,
std::chrono::milliseconds file_flush_interval_msec) PURE;
virtual std::string errorToString(int error) PURE;
};

typedef std::unique_ptr<RawFile> RawFilePtr;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefer using RawFilePtr = std::unique_ptr<RawFile>;


class RawInstance {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems a little strange to me that we have a "raw" filesystem instance and then a "normal" filesystem instance. Why not just have a single filesystem that can create either "raw" or "regular" files? (Final names TBD).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue is that creating the "regular" file requires a Dispatcher, a lock, stats, and threading. In the final version of this (with Windows support), we want to be able to inject the platform specific filesystem code from here: https://github.com/envoyproxy/envoy/blob/f9107b26ccca409a13716b7b094bd87fec9765fb/source/exe/win32/platform_impl.h, similarly to how we inject the platform specific threading code.

To get around this, the "raw" filesystem instance doesn't know how to create "regular" files -- it is injected to the "normal" instance that does.

If this too strange, then maybe just the Api object will be able to create "regular" files (since they are not platform specific). This would end up reverting a bit of #5692, which wouldn't be a problem, except for the small bit of churn

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my comment above. Should we just have "regular" files be part of the access log manager interface since this is the interface the reopens them, etc.?

public:
virtual ~RawInstance() {}

/**
* Creates a file, using the default flush-interval for the class.
*
* @param path The path of the file to open.
* @param dispatcher The dispatcher used for set up timers to run flush().
* @param lock The lock.
* @param path The path of the RawFile
* @return a RawFilePtr. The file is not opened.
*/
virtual FileSharedPtr createFile(const std::string& path, Event::Dispatcher& dispatcher,
Thread::BasicLockable& lock) PURE;
virtual RawFilePtr createRawFile(const std::string& path) PURE;

/**
* @return bool whether a file exists on disk and can be opened for read.
Expand Down Expand Up @@ -109,6 +112,61 @@ class Instance {
virtual bool illegalPath(const std::string& path) PURE;
};

/**
* Abstraction for a file on disk. It is specifically designed for writing access logs.
*/
class File {
public:
virtual ~File() {}

/**
* Write data to the file.
*/
virtual void write(absl::string_view) PURE;

/**
* Reopen the file.
*/
virtual void reopen() PURE;

/**
* Synchronously flush all pending data to disk.
*/
virtual void flush() PURE;
};

typedef std::shared_ptr<File> FileSharedPtr;

/**
* Captures state, properties, and stats of a file-system.
*/
class Instance : public RawInstance {
public:
virtual ~Instance() {}

/**
* Creates a file, overriding the flush-interval set in the class.
*
* @param path The path of the file to open.
* @param dispatcher The dispatcher used for set up timers to run flush().
* @param lock The lock.
* @param file_flush_interval_msec Number of milliseconds to delay before flushing.
*/
virtual FileSharedPtr createFile(const std::string& path, Event::Dispatcher& dispatcher,
Thread::BasicLockable& lock,
std::chrono::milliseconds file_flush_interval_msec) PURE;

/**
* Creates a file, using the default flush-interval for the class.
*
* @param path The path of the file to open.
* @param dispatcher The dispatcher used for set up timers to run flush().
* @param lock The lock.
*/
virtual FileSharedPtr createFile(const std::string& path, Event::Dispatcher& dispatcher,
Thread::BasicLockable& lock) PURE;
};

typedef std::unique_ptr<Watcher> WatcherPtr;

enum class FileType { Regular, Directory, Other };
Expand Down
1 change: 1 addition & 0 deletions source/common/api/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ envoy_cc_library(
"//source/common/common:thread_lib",
"//source/common/event:dispatcher_lib",
"//source/common/filesystem:filesystem_lib",
"//source/common/filesystem:raw_instance_lib",
],
)

Expand Down
2 changes: 1 addition & 1 deletion source/common/api/api_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Impl::Impl(std::chrono::milliseconds file_flush_interval_msec,
Thread::ThreadFactory& thread_factory, Stats::Store& stats_store,
Event::TimeSystem& time_system)
: thread_factory_(thread_factory),
file_system_(file_flush_interval_msec, thread_factory, stats_store),
file_system_(file_flush_interval_msec, thread_factory, stats_store, raw_instance_),
time_system_(time_system) {}

Event::DispatcherPtr Impl::allocateDispatcher() {
Expand Down
4 changes: 4 additions & 0 deletions source/common/api/api_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "envoy/thread/thread.h"

#include "common/filesystem/filesystem_impl.h"
#include "common/filesystem/raw_instance_impl.h"

namespace Envoy {
namespace Api {
Expand All @@ -29,6 +30,9 @@ class Impl : public Api {

private:
Thread::ThreadFactory& thread_factory_;
// TODO(sesmith177): Inject a RawInstance& when we have separate versions
// for POSIX / Windows
Filesystem::RawInstanceImpl raw_instance_;
Filesystem::InstanceImpl file_system_;
Event::TimeSystem& time_system_;
};
Expand Down
10 changes: 0 additions & 10 deletions source/common/api/os_sys_calls_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,11 @@ SysCallIntResult OsSysCallsImpl::ioctl(int sockfd, unsigned long int request, vo
return {rc, errno};
}

SysCallIntResult OsSysCallsImpl::open(const std::string& full_path, int flags, int mode) {
const int rc = ::open(full_path.c_str(), flags, mode);
return {rc, errno};
}

SysCallIntResult OsSysCallsImpl::close(int fd) {
const int rc = ::close(fd);
return {rc, errno};
}

SysCallSizeResult OsSysCallsImpl::write(int fd, const void* buffer, size_t num_bytes) {
const ssize_t rc = ::write(fd, buffer, num_bytes);
return {rc, errno};
}

SysCallSizeResult OsSysCallsImpl::writev(int fd, const iovec* iovec, int num_iovec) {
const ssize_t rc = ::writev(fd, iovec, num_iovec);
return {rc, errno};
Expand Down
2 changes: 0 additions & 2 deletions source/common/api/os_sys_calls_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ class OsSysCallsImpl : public OsSysCalls {
// Api::OsSysCalls
SysCallIntResult bind(int sockfd, const sockaddr* addr, socklen_t addrlen) override;
SysCallIntResult ioctl(int sockfd, unsigned long int request, void* argp) override;
SysCallIntResult open(const std::string& full_path, int flags, int mode) override;
SysCallSizeResult write(int fd, const void* buffer, size_t num_bytes) override;
SysCallSizeResult writev(int fd, const iovec* iovec, int num_iovec) override;
SysCallSizeResult readv(int fd, const iovec* iovec, int num_iovec) override;
SysCallSizeResult recv(int socket, void* buffer, size_t length, int flags) override;
Expand Down
12 changes: 9 additions & 3 deletions source/common/filesystem/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,22 @@ envoy_cc_library(
srcs = ["filesystem_impl.cc"],
hdrs = ["filesystem_impl.h"],
deps = [
"//include/envoy/api:api_interface",
"//include/envoy/api:os_sys_calls_interface",
"//include/envoy/event:dispatcher_interface",
"//include/envoy/filesystem:filesystem_interface",
"//source/common/api:os_sys_calls_lib",
"//source/common/buffer:buffer_lib",
"//source/common/common:thread_lib",
],
)

envoy_cc_library(
name = "raw_instance_lib",
srcs = ["raw_instance_impl.cc"],
hdrs = ["raw_instance_impl.h"],
deps = [
"//include/envoy/filesystem:filesystem_interface",
],
)

envoy_cc_library(
name = "watcher_lib",
srcs = select({
Expand Down
Loading