Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iox-#1036 builder pattern for file lock #1418

Merged
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
467518d
iox-#1036 Implement builder pattern for file lock
elfenpiff Jun 24, 2022
d87d479
iox-#1036 Add doesEndWithPathSeparator function
elfenpiff Jun 24, 2022
3c1c5ae
iox-#1036 Add unit tests for doesEndWithPathSeparator
elfenpiff Jun 24, 2022
ebd64b1
iox-#1036 Add isValidPath with tests to helplets
elfenpiff Jun 24, 2022
d9acedc
iox-#1036 Use LogError() instead of cerr
elfenpiff Jun 24, 2022
905bea3
iox-#1036 Adapting the documentation of the file lock
elfenpiff Jun 24, 2022
0f9dbcc
iox-#1036 Update changelog
elfenpiff Jun 24, 2022
e39b8a4
iox-#1036 Integrate new FilelockBuilder in roudi memory manager and i…
elfenpiff Jun 27, 2022
b97af70
iox-#1036 Add permissions to file lock creation and adjust invalid na…
elfenpiff Jun 27, 2022
f38deec
iox-#1036 Adjusted comments, added documentation to public type alias…
elfenpiff Jun 27, 2022
1bb66cd
iox-#1036 Add parameter to doxygen, adjust PathName capacity so that …
elfenpiff Jun 28, 2022
6459f80
iox-#1036 merge master
elfenpiff Jun 28, 2022
afbf9a1
iox-#1036 Adjusted comment on FileName_t
elfenpiff Jun 28, 2022
beadb74
iox-#1036 Cut max supported file name length in half in windows since…
elfenpiff Jun 28, 2022
3b5a1b9
iox-#1036 Explain default values in doxygen
elfenpiff Jun 28, 2022
c4af17b
iox-#1036 Verify death message
elfenpiff Jun 28, 2022
6f729e0
iox-#1036 Add isValidPathEntry and do allow relative paths at the end…
elfenpiff Jun 28, 2022
b375c9f
iox-#1036 Rename isValidFilePath to isValidPathToFile and isValidPath…
elfenpiff Jun 28, 2022
23518d4
iox-#1036 Test and document isValidPathEntry
elfenpiff Jun 28, 2022
8010d98
iox-#1036 merge master
elfenpiff Jun 28, 2022
5d844a2
iox-#1036 Add expiration date to deprecated, remove unneeded function
elfenpiff Jun 29, 2022
b6ebbc0
iox-#1036 Remove deprecated function, refactor isValidPathEntry to re…
elfenpiff Jun 29, 2022
5274023
iox-#1036 Add test ids, mention removed isValidFilePath in api change…
elfenpiff Jun 29, 2022
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
16 changes: 16 additions & 0 deletions doc/website/release-notes/iceoryx-unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
- Extend `concatenate`, `operator+`, `unsafe_append` and `append` of `iox::cxx::string` for chars [\#208](https://github.com/eclipse-iceoryx/iceoryx/issues/208)
- Extend `unsafe_append` and `append` methods of `iox::cxx::string` for `std::string` [\#208](https://github.com/eclipse-iceoryx/iceoryx/issues/208)
- The iceoryx development environment supports multiple running docker containers [\#1410](https://github.com/eclipse-iceoryx/iceoryx/issues/1410)
- Use builder pattern in FileLock [\#1036](https://github.com/eclipse-iceoryx/iceoryx/issues/1036)
- Add the ability to adjust path and file permissions of the file lock

**Bugfixes:**

Expand Down Expand Up @@ -139,3 +141,17 @@
iox::posix::waitForTerminationRequest();
}
```

6. `FileLock` uses the builder pattern. Path and permissions can now be set.
```cpp
// before
auto fileLock = iox::posix::FileLock::create("lockFileName")
.expect("Oh no I couldn't create the lock file");

// after
auto fileLock = iox::posix::FileLockBuilder().name("lockFileName")
.path("/Now/I/Can/Add/A/Path")
.permission(iox::cxx::perms::owner_all)
.create()
.expect("Oh no I couldn't create the lock file");
```
2 changes: 1 addition & 1 deletion iceoryx_hoofs/include/iceoryx_hoofs/cxx/filesystem.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace cxx
/// The enum satisfies also all requirements of the BitmaskType, this means
/// the operators `|`, `&`, `^`, `~`, `|=`, `&=` and `^=` are implemented as
/// free functions as C++17 requires it.
enum class perms : uint64_t
enum class perms : uint32_t
{
/// @brief Deny everything
none = 0,
Expand Down
8 changes: 8 additions & 0 deletions iceoryx_hoofs/include/iceoryx_hoofs/cxx/helplets.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,14 @@ bool isValidFileName(const string<StringCapacity>& name) noexcept;
template <uint64_t StringCapacity>
bool isValidFilePath(const string<StringCapacity>& name) noexcept;

/// @brief returns true if the provided name is a valid path, otherwise false
template <uint64_t StringCapacity>
bool isValidPath(const string<StringCapacity>& name) noexcept;

/// @brief returns true if the provided name ends with a path separator, otherwise false
template <uint64_t StringCapacity>
bool doesEndWithPathSeparator(const string<StringCapacity>& name) noexcept;
elfenpiff marked this conversation as resolved.
Show resolved Hide resolved

/// @brief Converts a value of type F to a corresponding value of type T. This function needs to be specialized by the
/// user for the types to be converted.
/// @code
Expand Down
47 changes: 33 additions & 14 deletions iceoryx_hoofs/include/iceoryx_hoofs/internal/cxx/helplets.inl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021 by Apex.AI Inc. All rights reserved.
// Copyright (c) 2021 - 2022 by Apex.AI Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,8 @@
#ifndef IOX_HOOFS_CXX_HELPLETS_INL
#define IOX_HOOFS_CXX_HELPLETS_INL

#include "iceoryx_hoofs/cxx/helplets.hpp"

namespace iox
{
namespace cxx
Expand Down Expand Up @@ -64,23 +66,20 @@ inline bool isValidFileName(const string<StringCapacity>& name) noexcept
template <uint64_t StringCapacity>
inline bool isValidFilePath(const string<StringCapacity>& name) noexcept
{
if (name.empty())
if (doesEndWithPathSeparator(name))
elfenpiff marked this conversation as resolved.
Show resolved Hide resolved
{
return false;
}

uint64_t nameSize = name.size();
return isValidPath(name);
}

// a file path ends with the filename and not the path separator, only a
// directory can end with a path separator
auto numberOfPathSeparators = strlen(platform::IOX_PATH_SEPARATORS);
for (uint64_t i = 0; i < numberOfPathSeparators; ++i)
template <uint64_t StringCapacity>
inline bool isValidPath(const string<StringCapacity>& name) noexcept
{
if (name.empty())
{
const char lastCharacter = name.c_str()[nameSize - 1U];
if (lastCharacter == platform::IOX_PATH_SEPARATORS[i])
{
return false;
}
return false;
}

auto temp = name;
FerdinandSpitzschnueffler marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -124,18 +123,38 @@ inline bool isValidFilePath(const string<StringCapacity>& name) noexcept
}
}

return true;
}

template <uint64_t StringCapacity>
inline bool doesEndWithPathSeparator(const string<StringCapacity>& name) noexcept
{
if (name.empty())
{
return false;
}

char lastCharacter = name[name.size() - 1U];

for (uint64_t i = 0; i < iox::platform::IOX_NUMBER_OF_PATH_SEPARATORS; ++i)
{
if (lastCharacter == iox::platform::IOX_PATH_SEPARATORS[i])
{
return true;
}
}
return false;
}

template <typename F, typename T>
constexpr T from(const F) noexcept
inline constexpr T from(const F) noexcept
{
static_assert(always_false_v<F> && always_false_v<T>, "Conversion for the specified types is not implemented!\
Please specialize `template <typename F, typename T> constexpr T from(const F) noexcept`!");
}

template <typename T, typename F>
constexpr T into(const F e) noexcept
inline constexpr T into(const F e) noexcept
{
return from<F, T>(e);
}
Expand Down
66 changes: 45 additions & 21 deletions iceoryx_hoofs/include/iceoryx_hoofs/posix_wrapper/file_lock.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
#define IOX_HOOFS_POSIX_WRAPPER_FILE_LOCK_HPP

#include "iceoryx_hoofs/cxx/expected.hpp"
#include "iceoryx_hoofs/cxx/filesystem.hpp"
#include "iceoryx_hoofs/cxx/string.hpp"
#include "iceoryx_hoofs/design_pattern/creation.hpp"
#include "iceoryx_hoofs/design_pattern/builder.hpp"
#include "iceoryx_hoofs/platform/file.hpp"

namespace iox
{
Expand All @@ -27,10 +29,10 @@ namespace posix
enum class FileLockError
{
INVALID_FILE_NAME,
INVALID_PATH,
LOCKED_BY_OTHER_PROCESS,
ACCESS_DENIED,
QUOTA_EXHAUSTED,
INVALID_CHARACTERS_IN_FILE_NAME,
SYSTEM_LIMIT,
PROCESS_LIMIT,
NO_SUCH_DIRECTORY,
Expand All @@ -48,27 +50,30 @@ enum class FileLockError
/// if the process crashes with a segfault or using SIGKILL. 'lslocks' can be used to display all system-wide
/// locks (see man page)
/// @code
/// iox::posix::FileLock::create(nameOfmyLock)
/// .and_then([] { std::cout << "We aquired the lock!" << std::endl; })
/// .or_else([](auto& error) {
/// if (error == FileLockError::LOCKED_BY_OTHER_PROCESS)
/// {
/// std::cout << "Some other process is running and holds the lock!" << std::endl;
/// }
/// });
/// auto fileLock = iox::posix::FileLockBuilder().name("myLockName")
/// .path("/tmp")
/// .permission(iox::cxx::perms::owner_all)
/// .create()
/// .expect("Oh no I couldn't create the lock");
elfenpiff marked this conversation as resolved.
Show resolved Hide resolved
/// @endcode
class FileLock : public DesignPattern::Creation<FileLock, FileLockError>
class FileLock
{
public:
static constexpr int32_t ERROR_CODE = -1;
static constexpr int32_t INVALID_FD = -1;
static constexpr const char LOCK_FILE_SUFFIX[] = ".lock";
static constexpr uint64_t FILENAME_LENGTH = platform::IOX_MAX_FILENAME_LENGTH
- sizeof(platform::IOX_LOCK_FILE_PATH_PREFIX) / sizeof(char)
- sizeof(LOCK_FILE_SUFFIX) / sizeof(char);

/// @brief A file name without any containing slash (path separator)
/// For instance "myLock.lock"
using FileName_t = cxx::string<FILENAME_LENGTH>;
using PathName_t = cxx::string<platform::IOX_MAX_PATH_LENGTH>;
/// @brief The full path to the file, including the file
/// For instance "/path/to/myLock.lock"
using FilePath_t = cxx::string<platform::IOX_MAX_PATH_LENGTH>;
/// @brief The directory to the file
/// For instance "/path/to/"
using PathName_t = cxx::string<platform::IOX_MAX_PATH_LENGTH - FILENAME_LENGTH - 1>;
elfenpiff marked this conversation as resolved.
Show resolved Hide resolved

FileLock(const FileLock&) = delete;
FileLock& operator=(const FileLock&) = delete;
Expand All @@ -78,21 +83,40 @@ class FileLock : public DesignPattern::Creation<FileLock, FileLockError>
~FileLock() noexcept;

private:
enum class LockOperation : int32_t
{
LOCK = LOCK_EX | LOCK_NB,
UNLOCK = LOCK_UN
};

int32_t m_fd{INVALID_FD};
FileName_t m_name;
PathName_t m_fileLockPath;
FilePath_t m_fileLockPath;

/// @brief c'tor
/// @param[in] name of the created file lock in PATH_PREFIX
explicit FileLock(const FileName_t& name) noexcept;
private:
friend class FileLockBuilder;
FileLock(const int32_t fileDescriptor, const FilePath_t& path) noexcept;

void invalidate() noexcept;

cxx::expected<FileLockError> initializeFileLock() noexcept;
FileLockError convertErrnoToFileLockError(const int32_t errnum) const noexcept;
static FileLockError convertErrnoToFileLockError(const int32_t errnum, const FilePath_t& fileLockPath) noexcept;
cxx::expected<FileLockError> closeFileDescriptor() noexcept;
};

class FileLockBuilder
{
/// @brief Defines the file name of the lock
IOX_BUILDER_PARAMETER(FileLock::FileName_t, name, "")
elfenpiff marked this conversation as resolved.
Show resolved Hide resolved

/// @brief Defines the path where the lock is stored
IOX_BUILDER_PARAMETER(FileLock::PathName_t, path, platform::IOX_LOCK_FILE_PATH_PREFIX)

friend class DesignPattern::Creation<FileLock, FileLockError>;
/// @brief Defines the access permissions of the file lock
IOX_BUILDER_PARAMETER(cxx::perms, permission, cxx::perms::none)

public:
/// @brief Creates a file lock
/// @return a valid file lock or an FileLockError describing the error
cxx::expected<FileLock, FileLockError> create() noexcept;
};
} // namespace posix
} // namespace iox
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ constexpr uint64_t IOX_MAX_PATH_LENGTH = 1023U;
constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = true;
constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = PATH_MAX;
constexpr const char IOX_PATH_SEPARATORS[] = "/";
constexpr uint64_t IOX_NUMBER_OF_PATH_SEPARATORS = 1U;
constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 4096;
constexpr const char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/";
constexpr const char IOX_LOCK_FILE_PATH_PREFIX[] = "/tmp/";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = true;
// is defined
constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = 255U;
constexpr const char IOX_PATH_SEPARATORS[] = "/";
constexpr uint64_t IOX_NUMBER_OF_PATH_SEPARATORS = 1U;
constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 2048;
constexpr const char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/";
constexpr const char IOX_LOCK_FILE_PATH_PREFIX[] = "/tmp/";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ constexpr uint64_t IOX_MAX_PATH_LENGTH = 1023U;
constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = true;
constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = 1024U;
constexpr const char IOX_PATH_SEPARATORS[] = "/";
constexpr uint64_t IOX_NUMBER_OF_PATH_SEPARATORS = 1U;
constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 2048;
constexpr const char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/";
constexpr const char IOX_LOCK_FILE_PATH_PREFIX[] = "/var/lock/";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ constexpr uint64_t IOX_MAX_PATH_LENGTH = 1023U;
constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = true;
constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = PATH_MAX;
constexpr const char IOX_PATH_SEPARATORS[] = "/";
constexpr uint64_t IOX_NUMBER_OF_PATH_SEPARATORS = 1U;
constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 1024;
constexpr const char IOX_UDS_SOCKET_PATH_PREFIX[] = "/tmp/";
constexpr const char IOX_LOCK_FILE_PATH_PREFIX[] = "/tmp/";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ constexpr bool IOX_SHM_WRITE_ZEROS_ON_CREATION = false;
constexpr uint64_t IOX_MAX_SHM_NAME_LENGTH = 255U;
// yes, windows has two possible path separators!
constexpr const char IOX_PATH_SEPARATORS[] = "\\/";
constexpr uint64_t IOX_NUMBER_OF_PATH_SEPARATORS = 2U;
// unix domain sockets are not supported in windows but the variables have to be defined
// so that the code with stub implementation at least compiles
constexpr uint64_t IOX_UDS_SOCKET_MAX_MESSAGE_SIZE = 1024U;
Expand Down
Loading