Skip to content

Commit

Permalink
Moved all of the file locking and directory managment features into f…
Browse files Browse the repository at this point in the history
…ileutils.hpp a la PR ledatelescope#132.
  • Loading branch information
jaycedowell committed Mar 18, 2020
1 parent 120da36 commit f9ed7bc
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 129 deletions.
99 changes: 99 additions & 0 deletions src/fileutils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2016-2020, The Bifrost Authors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of The Bifrost Authors nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#pragma once

#include <sys/file.h> // For flock
#include <sys/stat.h> // For fstat
#include <sys/types.h> // For getpid
#include <unistd.h> // For getpid
#include <system_error>

inline void make_dir(std::string path, int perms=775) {
if( std::system(("mkdir -p "+path+" -m "+std::to_string(perms)).c_str()) ) {
throw std::runtime_error("Failed to create path: "+path);
}
}
inline void remove_all(std::string path) {
if( std::system(("rm -rf "+path).c_str()) ) {
throw std::runtime_error("Failed to remove all: "+path);
}
}
inline void remove_dir(std::string path) {
if( std::system(("rmdir "+path+" 2> /dev/null").c_str()) ) {
throw std::runtime_error("Failed to remove dir: "+path);
}
}
inline void remove_file(std::string path) {
if( std::system(("rm -f "+path).c_str()) ) {
throw std::runtime_error("Failed to remove file: "+path);
}
}
inline bool file_exists(std::string path) {
struct stat s;
return !(stat(path.c_str(), &s) == -1
&& errno == ENOENT);
}
inline bool process_exists(pid_t pid) {
struct stat s;
return !(stat(("/proc/"+std::to_string(pid)).c_str(), &s) == -1
&& errno == ENOENT);
}

inline std::string get_dirname(std::string filename) {
// TODO: This is crude, but works for our proclog use-case
return filename.substr(0, filename.find_last_of("/"));
}

class LockFile {
std::string _lockfile;
int _fd;
public:
LockFile(LockFile const& ) = delete;
LockFile& operator=(LockFile const& ) = delete;
LockFile(std::string lockfile) : _lockfile(lockfile) {
while( true ) {
_fd = open(_lockfile.c_str(), O_CREAT, 600);
flock(_fd, LOCK_EX);
struct stat fd_stat, lockfile_stat;
fstat(_fd, &fd_stat);
stat(_lockfile.c_str(), &lockfile_stat);
// Compare inodes
if( fd_stat.st_ino == lockfile_stat.st_ino ) {
// Got the lock
break;
}
close(_fd);
}
}
~LockFile() {
unlink(_lockfile.c_str());
flock(_fd, LOCK_UN);
}
};

79 changes: 11 additions & 68 deletions src/memory.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019, The Bifrost Authors. All rights reserved.
* Copyright (c) 2016-2020, The Bifrost Authors. All rights reserved.
* Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -31,6 +31,7 @@
#include "utils.hpp"
#include "cuda.hpp"
#include "trace.hpp"
#include "fileutils.hpp"

#include <cstdlib> // For posix_memalign
#include <cstring> // For memcpy
Expand All @@ -54,64 +55,6 @@ static_assert(BF_IS_POW2(BF_ALIGNMENT), "BF_ALIGNMENT must be a power of 2");
#define BF_MAPPED_RING_DIR "/tmp/bifrost"
#endif

void mmake_dir(std::string path, int perms=775) {
if( std::system(("mkdir -p "+path+" -m "+std::to_string(perms)).c_str()) ) {
throw std::runtime_error("Failed to create path: "+path);
}
}
void mremove_all(std::string path) {
if( std::system(("rm -rf "+path).c_str()) ) {
throw std::runtime_error("Failed to remove all: "+path);
}
}
void mremove_dir(std::string path) {
if( std::system(("rmdir "+path+" 2> /dev/null").c_str()) ) {
throw std::runtime_error("Failed to remove dir: "+path);
}
}
void mremove_file(std::string path) {
if( std::system(("rm -f "+path).c_str()) ) {
throw std::runtime_error("Failed to remove file: "+path);
}
}
bool mprocess_exists(pid_t pid) {
struct stat s;
return !(stat(("/proc/"+std::to_string(pid)).c_str(), &s) == -1
&& errno == ENOENT);
}

std::string mget_dirname(std::string filename) {
// TODO: This is crude, but works for our proclog use-case
return filename.substr(0, filename.find_last_of("/"));
}

class MLockFile {
std::string _lockfile;
int _fd;
public:
MLockFile(MLockFile const& ) = delete;
MLockFile& operator=(MLockFile const& ) = delete;
MLockFile(std::string lockfile) : _lockfile(lockfile) {
while( true ) {
_fd = open(_lockfile.c_str(), O_CREAT, 600);
flock(_fd, LOCK_EX);
struct stat fd_stat, lockfile_stat;
fstat(_fd, &fd_stat);
stat(_lockfile.c_str(), &lockfile_stat);
// Compare inodes
if( fd_stat.st_ino == lockfile_stat.st_ino ) {
// Got the lock
break;
}
close(_fd);
}
}
~MLockFile() {
unlink(_lockfile.c_str());
flock(_fd, LOCK_UN);
}
};

class MappedMgr {
static constexpr const char* base_mapped_dir = BF_MAPPED_RING_DIR;
std::string _mapped_dir;
Expand All @@ -121,43 +64,43 @@ class MappedMgr {

void try_base_mapped_dir_cleanup() {
// Do this with a file lock to avoid interference from other processes
MLockFile lock(std::string(base_mapped_dir) + ".lock");
LockFile lock(std::string(base_mapped_dir) + ".lock");
DIR* dp;
// Remove pid dirs for which a corresponding process does not exist
if( (dp = opendir(base_mapped_dir)) ) {
struct dirent* ep;
while( (ep = readdir(dp)) ) {
pid_t pid = atoi(ep->d_name);
if( pid && !mprocess_exists(pid) ) {
mremove_all(std::string(base_mapped_dir) + "/" +
std::to_string(pid));
if( pid && !process_exists(pid) ) {
remove_all(std::string(base_mapped_dir) + "/" +
std::to_string(pid));
}
}
closedir(dp);
}
// Remove the base_logdir if it's empty
try { mremove_dir(base_mapped_dir); }
try { remove_dir(base_mapped_dir); }
catch( std::exception ) {}
}
void cleanup(std::string filename, int fd) {
if( fd >= 0 ) {
::close(fd);
}
try { mremove_file(filename); }
try { remove_file(filename); }
catch( std::exception ) {}
}
MappedMgr()
: _mapped_dir(std::string(base_mapped_dir) + "/" + std::to_string(getpid())) {
this->try_base_mapped_dir_cleanup();
mmake_dir(base_mapped_dir, 777);
mmake_dir(_mapped_dir);
make_dir(base_mapped_dir, 777);
make_dir(_mapped_dir);
}
~MappedMgr() {
for(auto& x : _filenames) {
this->free(x.first);
}
try {
mremove_all(_mapped_dir);
remove_all(_mapped_dir);
this->try_base_mapped_dir_cleanup();
} catch( std::exception ) {}
}
Expand Down
63 changes: 2 additions & 61 deletions src/proclog.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, The Bifrost Authors. All rights reserved.
* Copyright (c) 2016-2020, The Bifrost Authors. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
Expand Down Expand Up @@ -29,77 +29,18 @@
#include <bifrost/proclog.h>
#include "trace.hpp"
#include "proclog.hpp"
#include "fileutils.hpp"

#include <fstream>
#include <cstdlib> // For system
#include <cstdarg> // For va_start, va_list, va_end
#include <sys/file.h> // For flock
#include <sys/stat.h> // For fstat
#include <sys/types.h> // For getpid
#include <dirent.h> // For opendir, readdir, closedir
#include <unistd.h> // For getpid
#include <system_error>
#include <set>
#include <mutex>

void make_dir(std::string path, int perms=775) {
if( std::system(("mkdir -p "+path+" -m "+std::to_string(perms)).c_str()) ) {
throw std::runtime_error("Failed to create path: "+path);
}
}
void remove_all(std::string path) {
if( std::system(("rm -rf "+path).c_str()) ) {
throw std::runtime_error("Failed to remove all: "+path);
}
}
void remove_dir(std::string path) {
if( std::system(("rmdir "+path+" 2> /dev/null").c_str()) ) {
throw std::runtime_error("Failed to remove dir: "+path);
}
}
void remove_file(std::string path) {
if( std::system(("rm -f "+path).c_str()) ) {
throw std::runtime_error("Failed to remove file: "+path);
}
}
bool process_exists(pid_t pid) {
struct stat s;
return !(stat(("/proc/"+std::to_string(pid)).c_str(), &s) == -1
&& errno == ENOENT);
}

std::string get_dirname(std::string filename) {
// TODO: This is crude, but works for our proclog use-case
return filename.substr(0, filename.find_last_of("/"));
}

class LockFile {
std::string _lockfile;
int _fd;
public:
LockFile(LockFile const& ) = delete;
LockFile& operator=(LockFile const& ) = delete;
LockFile(std::string lockfile) : _lockfile(lockfile) {
while( true ) {
_fd = open(_lockfile.c_str(), O_CREAT, 600);
flock(_fd, LOCK_EX);
struct stat fd_stat, lockfile_stat;
fstat(_fd, &fd_stat);
stat(_lockfile.c_str(), &lockfile_stat);
// Compare inodes
if( fd_stat.st_ino == lockfile_stat.st_ino ) {
// Got the lock
break;
}
close(_fd);
}
}
~LockFile() {
unlink(_lockfile.c_str());
flock(_fd, LOCK_UN);
}
};

class ProcLogMgr {
static constexpr const char* base_logdir = "/dev/shm/bifrost";
std::string _logdir;
Expand Down

0 comments on commit f9ed7bc

Please sign in to comment.