mirror of
https://github.com/trapexit/mergerfs.git
synced 2024-11-25 09:41:43 +08:00
add {,ep,msp}pfrd policies
Percentage Free Random Distribution Chooses a random branch based on the available space percentage free. IE: if branch A has 1G free and branch B has 2G then B should be chosen twice as often.
This commit is contained in:
parent
7ff995631e
commit
046844083f
23
README.md
23
README.md
|
@ -1,6 +1,6 @@
|
||||||
% mergerfs(1) mergerfs user manual
|
% mergerfs(1) mergerfs user manual
|
||||||
% Antonio SJ Musumeci <trapexit@spawn.link>
|
% Antonio SJ Musumeci <trapexit@spawn.link>
|
||||||
% 2020-08-07
|
% 2020-08-20
|
||||||
|
|
||||||
# NAME
|
# NAME
|
||||||
|
|
||||||
|
@ -306,22 +306,25 @@ Because of the nature of the behavior the policies act diffierently depending on
|
||||||
|
|
||||||
| Policy | Description |
|
| Policy | Description |
|
||||||
|------------------|------------------------------------------------------------|
|
|------------------|------------------------------------------------------------|
|
||||||
| all | Search: same as **epall**. Action: same as **epall**. Create: for **mkdir**, **mknod**, and **symlink** it will apply to all branches. **create** works like **ff**. |
|
| all | Search: Same as **epall**. Action: Same as **epall**. Create: for **mkdir**, **mknod**, and **symlink** it will apply to all branches. **create** works like **ff**. |
|
||||||
| epall (existing path, all) | Search: same as **epff** (but more expensive because it doesn't stop after finding a valid branch). Action: apply to all found. Create: for **mkdir**, **mknod**, and **symlink** it will apply to all found. **create** works like **epff** (but more expensive because it doesn't stop after finding a valid branch). |
|
| epall (existing path, all) | Search: Same as **epff** (but more expensive because it doesn't stop after finding a valid branch). Action: apply to all found. Create: for **mkdir**, **mknod**, and **symlink** it will apply to all found. **create** works like **epff** (but more expensive because it doesn't stop after finding a valid branch). |
|
||||||
| epff (existing path, first found) | Given the order of the branches, as defined at mount time or configured at runtime, act on the first one found where the relative path exists. |
|
| epff (existing path, first found) | Given the order of the branches, as defined at mount time or configured at runtime, act on the first one found where the relative path exists. |
|
||||||
| eplfs (existing path, least free space) | Of all the branches on which the relative path exists choose the drive with the least free space. |
|
| eplfs (existing path, least free space) | Of all the branches on which the relative path exists choose the drive with the least free space. |
|
||||||
| eplus (existing path, least used space) | Of all the branches on which the relative path exists choose the drive with the least used space. |
|
| eplus (existing path, least used space) | Of all the branches on which the relative path exists choose the drive with the least used space. |
|
||||||
| epmfs (existing path, most free space) | Of all the branches on which the relative path exists choose the drive with the most free space. |
|
| epmfs (existing path, most free space) | Of all the branches on which the relative path exists choose the drive with the most free space. |
|
||||||
|
| eppfrd (existing path, percentage free random distribution) | Like **pfrd** but limited to existing paths. |
|
||||||
| eprand (existing path, random) | Calls **epall** and then randomizes. Returns 1. |
|
| eprand (existing path, random) | Calls **epall** and then randomizes. Returns 1. |
|
||||||
| erofs | Exclusively return **-1** with **errno** set to **EROFS** (read-only filesystem). |
|
| erofs | Exclusively return **-1** with **errno** set to **EROFS** (read-only filesystem). |
|
||||||
| ff (first found) | Search: same as **epff**. Action: same as **epff**. Create: Given the order of the drives, as defined at mount time or configured at runtime, act on the first one found. |
|
| ff (first found) | Search: Same as **epff**. Action: Same as **epff**. Create: Given the order of the drives, as defined at mount time or configured at runtime, act on the first one found. |
|
||||||
| lfs (least free space) | Search: same as **eplfs**. Action: same as **eplfs**. Create: Pick the drive with the least available free space. |
|
| lfs (least free space) | Search: Same as **eplfs**. Action: Same as **eplfs**. Create: Pick the drive with the least available free space. |
|
||||||
| lus (least used space) | Search: same as **eplus**. Action: same as **eplus**. Create: Pick the drive with the least used space. |
|
| lus (least used space) | Search: Same as **eplus**. Action: Same as **eplus**. Create: Pick the drive with the least used space. |
|
||||||
| mfs (most free space) | Search: same as **epmfs**. Action: same as **epmfs**. Create: Pick the drive with the most available free space. |
|
| mfs (most free space) | Search: Same as **epmfs**. Action: Same as **epmfs**. Create: Pick the drive with the most available free space. |
|
||||||
| msplfs (most shared path, least free space) | Search: same as **eplfs**. Action: same as **eplfs**. Create: like **eplfs** but walk back the path if it fails to find a branch at that level. |
|
| msplfs (most shared path, least free space) | Search: Same as **eplfs**. Action: Same as **eplfs**. Create: like **eplfs** but walk back the path if it fails to find a branch at that level. |
|
||||||
| msplus (most shared path, least used space) | Search: same as **eplus**. Action: same as **eplus**. Create: like **eplus** but walk back the path if it fails to find a branch at that level. |
|
| msplus (most shared path, least used space) | Search: Same as **eplus**. Action: Same as **eplus**. Create: like **eplus** but walk back the path if it fails to find a branch at that level. |
|
||||||
| mspmfs (most shared path, most free space) | Search: same as **epmfss**. Action: same as **epmfs**. Create: like **eplmfs** but walk back the path if it fails to find a branch at that level. |
|
| mspmfs (most shared path, most free space) | Search: Same as **epmfss**. Action: Same as **epmfs**. Create: like **eplmfs** but walk back the path if it fails to find a branch at that level. |
|
||||||
|
| msppfrd (most shared path, percentage free random distribution) | Search: Same as **eppfrd**. Action: Same as **eppfrd**. Create: Like **eppfrd** but will walk back the path if it fails to find a branch at that level. |
|
||||||
| newest | Pick the file / directory with the largest mtime. |
|
| newest | Pick the file / directory with the largest mtime. |
|
||||||
|
| pfrd (percentage free random distribution) | Search: Same as **eppfrd**. Action: Same as **eppfrd**. Create: Chooses a branch at random with the likelihood of selection based on a branch's available space relative to the total. |
|
||||||
| rand (random) | Calls **all** and then randomizes. Returns 1. |
|
| rand (random) | Calls **all** and then randomizes. Returns 1. |
|
||||||
|
|
||||||
**NOTE:** If you are using an underlying filesystem that reserves blocks such as ext2, ext3, or ext4 be aware that mergerfs respects the reservation by using `f_bavail` (number of free blocks for unprivileged users) rather than `f_bfree` (number of free blocks) in policy calculations. **df** does NOT use `f_bavail`, it uses `f_bfree`, so direct comparisons between **df** output and mergerfs' policies is not appropriate.
|
**NOTE:** If you are using an underlying filesystem that reserves blocks such as ext2, ext3, or ext4 be aware that mergerfs respects the reservation by using `f_bavail` (number of free blocks for unprivileged users) rather than `f_bfree` (number of free blocks) in policy calculations. **df** does NOT use `f_bavail`, it uses `f_bfree`, so direct comparisons between **df** output and mergerfs' policies is not appropriate.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
.\"t
|
.\"t
|
||||||
.\" Automatically generated by Pandoc 1.19.2.4
|
.\" Automatically generated by Pandoc 1.19.2.4
|
||||||
.\"
|
.\"
|
||||||
.TH "mergerfs" "1" "2020\-08\-07" "mergerfs user manual" ""
|
.TH "mergerfs" "1" "2020\-08\-20" "mergerfs user manual" ""
|
||||||
.hy
|
.hy
|
||||||
.SH NAME
|
.SH NAME
|
||||||
.PP
|
.PP
|
||||||
|
@ -778,6 +778,11 @@ Of all the branches on which the relative path exists choose the drive
|
||||||
with the most free space.
|
with the most free space.
|
||||||
T}
|
T}
|
||||||
T{
|
T{
|
||||||
|
eppfrd (existing path, percentage free random distribution)
|
||||||
|
T}@T{
|
||||||
|
Like \f[B]pfrd\f[] but limited to existing paths.
|
||||||
|
T}
|
||||||
|
T{
|
||||||
eprand (existing path, random)
|
eprand (existing path, random)
|
||||||
T}@T{
|
T}@T{
|
||||||
Calls \f[B]epall\f[] and then randomizes.
|
Calls \f[B]epall\f[] and then randomizes.
|
||||||
|
@ -843,11 +848,27 @@ Create: like \f[B]eplmfs\f[] but walk back the path if it fails to find
|
||||||
a branch at that level.
|
a branch at that level.
|
||||||
T}
|
T}
|
||||||
T{
|
T{
|
||||||
|
msppfrd (most shared path, percentage free random distribution)
|
||||||
|
T}@T{
|
||||||
|
Search: same as \f[B]eppfrd\f[].
|
||||||
|
Action: same as \f[B]eppfrd\f[].
|
||||||
|
Create: Like \f[B]eppfrd\f[] but will walk back the path if it fails to
|
||||||
|
find a branch at that level.
|
||||||
|
T}
|
||||||
|
T{
|
||||||
newest
|
newest
|
||||||
T}@T{
|
T}@T{
|
||||||
Pick the file / directory with the largest mtime.
|
Pick the file / directory with the largest mtime.
|
||||||
T}
|
T}
|
||||||
T{
|
T{
|
||||||
|
pfrd (percentage free random distribution)
|
||||||
|
T}@T{
|
||||||
|
Search: same as \f[B]eppfrd\f[].
|
||||||
|
Action: same as \f[B]eppfrd\f[].
|
||||||
|
Create: Chooses a branch at random with the likelihood of selection
|
||||||
|
based on a branch\[aq]s available space relative to the total.
|
||||||
|
T}
|
||||||
|
T{
|
||||||
rand (random)
|
rand (random)
|
||||||
T}@T{
|
T}@T{
|
||||||
Calls \f[B]all\f[] and then randomizes.
|
Calls \f[B]all\f[] and then randomizes.
|
||||||
|
|
|
@ -32,6 +32,7 @@ const std::vector<Policy> Policy::_policies_ =
|
||||||
(POLICY(eplfs,PRESERVES_PATH))
|
(POLICY(eplfs,PRESERVES_PATH))
|
||||||
(POLICY(eplus,PRESERVES_PATH))
|
(POLICY(eplus,PRESERVES_PATH))
|
||||||
(POLICY(epmfs,PRESERVES_PATH))
|
(POLICY(epmfs,PRESERVES_PATH))
|
||||||
|
(POLICY(eppfrd,PRESERVES_PATH))
|
||||||
(POLICY(eprand,PRESERVES_PATH))
|
(POLICY(eprand,PRESERVES_PATH))
|
||||||
(POLICY(erofs,DOESNT_PRESERVE_PATH))
|
(POLICY(erofs,DOESNT_PRESERVE_PATH))
|
||||||
(POLICY(ff,DOESNT_PRESERVE_PATH))
|
(POLICY(ff,DOESNT_PRESERVE_PATH))
|
||||||
|
@ -41,7 +42,9 @@ const std::vector<Policy> Policy::_policies_ =
|
||||||
(POLICY(msplfs,PRESERVES_PATH))
|
(POLICY(msplfs,PRESERVES_PATH))
|
||||||
(POLICY(msplus,PRESERVES_PATH))
|
(POLICY(msplus,PRESERVES_PATH))
|
||||||
(POLICY(mspmfs,PRESERVES_PATH))
|
(POLICY(mspmfs,PRESERVES_PATH))
|
||||||
|
(POLICY(msppfrd,PRESERVES_PATH))
|
||||||
(POLICY(newest,DOESNT_PRESERVE_PATH))
|
(POLICY(newest,DOESNT_PRESERVE_PATH))
|
||||||
|
(POLICY(pfrd,DOESNT_PRESERVE_PATH))
|
||||||
(POLICY(rand,DOESNT_PRESERVE_PATH));
|
(POLICY(rand,DOESNT_PRESERVE_PATH));
|
||||||
|
|
||||||
const Policy * const Policy::policies = &_policies_[1];
|
const Policy * const Policy::policies = &_policies_[1];
|
||||||
|
@ -55,6 +58,7 @@ CONST_POLICY(epff);
|
||||||
CONST_POLICY(eplfs);
|
CONST_POLICY(eplfs);
|
||||||
CONST_POLICY(eplus);
|
CONST_POLICY(eplus);
|
||||||
CONST_POLICY(epmfs);
|
CONST_POLICY(epmfs);
|
||||||
|
CONST_POLICY(eppfrd);
|
||||||
CONST_POLICY(eprand);
|
CONST_POLICY(eprand);
|
||||||
CONST_POLICY(erofs);
|
CONST_POLICY(erofs);
|
||||||
CONST_POLICY(ff);
|
CONST_POLICY(ff);
|
||||||
|
@ -64,19 +68,21 @@ CONST_POLICY(mfs);
|
||||||
CONST_POLICY(msplfs);
|
CONST_POLICY(msplfs);
|
||||||
CONST_POLICY(msplus);
|
CONST_POLICY(msplus);
|
||||||
CONST_POLICY(mspmfs);
|
CONST_POLICY(mspmfs);
|
||||||
|
CONST_POLICY(msppfrd);
|
||||||
CONST_POLICY(newest);
|
CONST_POLICY(newest);
|
||||||
|
CONST_POLICY(pfrd);
|
||||||
CONST_POLICY(rand);
|
CONST_POLICY(rand);
|
||||||
|
|
||||||
const Policy&
|
const Policy&
|
||||||
Policy::find(const std::string &str)
|
Policy::find(const std::string &str)
|
||||||
{
|
{
|
||||||
for(int i = Enum::BEGIN; i != Enum::END; ++i)
|
for(int i = Enum::BEGIN; i != Enum::END; ++i)
|
||||||
{
|
{
|
||||||
if(policies[i] == str)
|
if(policies[i] == str)
|
||||||
return policies[i];
|
return policies[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return invalid;
|
return invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Policy&
|
const Policy&
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
eplfs,
|
eplfs,
|
||||||
eplus,
|
eplus,
|
||||||
epmfs,
|
epmfs,
|
||||||
|
eppfrd,
|
||||||
eprand,
|
eprand,
|
||||||
erofs,
|
erofs,
|
||||||
ff,
|
ff,
|
||||||
|
@ -46,7 +47,9 @@ public:
|
||||||
msplfs,
|
msplfs,
|
||||||
msplus,
|
msplus,
|
||||||
mspmfs,
|
mspmfs,
|
||||||
|
msppfrd,
|
||||||
newest,
|
newest,
|
||||||
|
pfrd,
|
||||||
rand,
|
rand,
|
||||||
END
|
END
|
||||||
};
|
};
|
||||||
|
@ -117,6 +120,7 @@ public:
|
||||||
static int eplfs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int eplfs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int eplus(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int eplus(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int epmfs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int epmfs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
|
static int eppfrd(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int eprand(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int eprand(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int erofs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int erofs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int ff(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int ff(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
|
@ -126,7 +130,9 @@ public:
|
||||||
static int msplfs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int msplfs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int msplus(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int msplus(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int mspmfs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int mspmfs(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
|
static int msppfrd(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int newest(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int newest(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
|
static int pfrd(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
static int rand(Category,const Branches&,const char *,cuint64_t,strvec*);
|
static int rand(Category,const Branches&,const char *,cuint64_t,strvec*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,6 +204,7 @@ public:
|
||||||
static const Policy &eplfs;
|
static const Policy &eplfs;
|
||||||
static const Policy ⩱
|
static const Policy ⩱
|
||||||
static const Policy &epmfs;
|
static const Policy &epmfs;
|
||||||
|
static const Policy &eppfrd;
|
||||||
static const Policy &eprand;
|
static const Policy &eprand;
|
||||||
static const Policy &erofs;
|
static const Policy &erofs;
|
||||||
static const Policy &ff;
|
static const Policy &ff;
|
||||||
|
@ -207,7 +214,9 @@ public:
|
||||||
static const Policy &msplfs;
|
static const Policy &msplfs;
|
||||||
static const Policy &msplus;
|
static const Policy &msplus;
|
||||||
static const Policy &mspmfs;
|
static const Policy &mspmfs;
|
||||||
|
static const Policy &msppfrd;
|
||||||
static const Policy &newest;
|
static const Policy &newest;
|
||||||
|
static const Policy &pfrd;
|
||||||
static const Policy &rand;
|
static const Policy &rand;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
273
src/policy_eppfrd.cpp
Normal file
273
src/policy_eppfrd.cpp
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "errno.hpp"
|
||||||
|
#include "fs_exists.hpp"
|
||||||
|
#include "fs_info.hpp"
|
||||||
|
#include "fs_path.hpp"
|
||||||
|
#include "fs_statvfs_cache.hpp"
|
||||||
|
#include "policy.hpp"
|
||||||
|
#include "policy_error.hpp"
|
||||||
|
#include "rnd.hpp"
|
||||||
|
#include "rwlock.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
struct BranchInfo
|
||||||
|
{
|
||||||
|
uint64_t spaceavail;
|
||||||
|
const string *basepath;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef vector<BranchInfo> BranchInfoVec;
|
||||||
|
|
||||||
|
namespace eppfrd
|
||||||
|
{
|
||||||
|
static
|
||||||
|
int
|
||||||
|
get_branchinfo_create(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
BranchInfoVec *branchinfo_,
|
||||||
|
uint64_t *sum_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int error;
|
||||||
|
BranchInfo bi;
|
||||||
|
fs::info_t info;
|
||||||
|
const Branch *branch;
|
||||||
|
rwlock::ReadGuard guard(&branches_.lock);
|
||||||
|
|
||||||
|
*sum_ = 0;
|
||||||
|
error = ENOENT;
|
||||||
|
for(size_t i = 0, ei = branches_.size(); i < ei; i++)
|
||||||
|
{
|
||||||
|
branch = &branches_[i];
|
||||||
|
|
||||||
|
if(branch->ro_or_nc())
|
||||||
|
error_and_continue(error,EROFS);
|
||||||
|
if(!fs::exists(branch->path,fusepath_))
|
||||||
|
error_and_continue(error,ENOENT);
|
||||||
|
rv = fs::info(branch->path,&info);
|
||||||
|
if(rv == -1)
|
||||||
|
error_and_continue(error,ENOENT);
|
||||||
|
if(info.readonly)
|
||||||
|
error_and_continue(error,EROFS);
|
||||||
|
if(info.spaceavail < minfreespace_)
|
||||||
|
error_and_continue(error,ENOSPC);
|
||||||
|
|
||||||
|
*sum_ += info.spaceavail;
|
||||||
|
|
||||||
|
bi.spaceavail = info.spaceavail;
|
||||||
|
bi.basepath = &branch->path;
|
||||||
|
branchinfo_->push_back(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
get_branchinfo_action(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
BranchInfoVec *branchinfo_,
|
||||||
|
uint64_t *sum_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int error;
|
||||||
|
BranchInfo bi;
|
||||||
|
fs::info_t info;
|
||||||
|
const Branch *branch;
|
||||||
|
rwlock::ReadGuard guard(&branches_.lock);
|
||||||
|
|
||||||
|
*sum_ = 0;
|
||||||
|
error = ENOENT;
|
||||||
|
for(size_t i = 0, ei = branches_.size(); i < ei; i++)
|
||||||
|
{
|
||||||
|
branch = &branches_[i];
|
||||||
|
|
||||||
|
if(branch->ro())
|
||||||
|
error_and_continue(error,EROFS);
|
||||||
|
if(!fs::exists(branch->path,fusepath_))
|
||||||
|
error_and_continue(error,ENOENT);
|
||||||
|
rv = fs::info(branch->path,&info);
|
||||||
|
if(rv == -1)
|
||||||
|
error_and_continue(error,ENOENT);
|
||||||
|
if(info.readonly)
|
||||||
|
error_and_continue(error,EROFS);
|
||||||
|
|
||||||
|
*sum_ += info.spaceavail;
|
||||||
|
|
||||||
|
bi.spaceavail = info.spaceavail;
|
||||||
|
bi.basepath = &branch->path;
|
||||||
|
branchinfo_->push_back(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
get_branchinfo_search(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
BranchInfoVec *branchinfo_,
|
||||||
|
uint64_t *sum_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
BranchInfo bi;
|
||||||
|
uint64_t spaceavail;
|
||||||
|
const Branch *branch;
|
||||||
|
rwlock::ReadGuard guard(&branches_.lock);
|
||||||
|
|
||||||
|
*sum_ = 0;
|
||||||
|
for(size_t i = 0, ei = branches_.size(); i < ei; i++)
|
||||||
|
{
|
||||||
|
branch = &branches_[i];
|
||||||
|
|
||||||
|
if(!fs::exists(branch->path,fusepath_))
|
||||||
|
continue;
|
||||||
|
rv = fs::statvfs_cache_spaceavail(branch->path,&spaceavail);
|
||||||
|
if(rv == -1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*sum_ += spaceavail;
|
||||||
|
|
||||||
|
bi.spaceavail = spaceavail;
|
||||||
|
bi.basepath = &branch->path;
|
||||||
|
branchinfo_->push_back(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
const
|
||||||
|
string*
|
||||||
|
get_branch(const BranchInfoVec &branchinfo_,
|
||||||
|
const uint64_t sum_)
|
||||||
|
{
|
||||||
|
uint64_t idx;
|
||||||
|
uint64_t threshold;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
threshold = RND::rand64(sum_);
|
||||||
|
for(size_t i = 0; i < branchinfo_.size(); i++)
|
||||||
|
{
|
||||||
|
idx += branchinfo_[i].spaceavail;
|
||||||
|
|
||||||
|
if(idx < threshold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return branchinfo_[i].basepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
create(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
vector<string> *paths_)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
uint64_t sum;
|
||||||
|
const string *basepath;
|
||||||
|
BranchInfoVec branchinfo;
|
||||||
|
|
||||||
|
branchinfo.reserve(branches_.size());
|
||||||
|
error = eppfrd::get_branchinfo_create(branches_,fusepath_,minfreespace_,&branchinfo,&sum);
|
||||||
|
basepath = eppfrd::get_branch(branchinfo,sum);
|
||||||
|
if(basepath == NULL)
|
||||||
|
return (errno=error,-1);
|
||||||
|
|
||||||
|
paths_->push_back(*basepath);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
action(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
vector<string> *paths_)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
uint64_t sum;
|
||||||
|
const string *basepath;
|
||||||
|
BranchInfoVec branchinfo;
|
||||||
|
|
||||||
|
branchinfo.reserve(branches_.size());
|
||||||
|
error = eppfrd::get_branchinfo_action(branches_,fusepath_,minfreespace_,&branchinfo,&sum);
|
||||||
|
basepath = eppfrd::get_branch(branchinfo,sum);
|
||||||
|
if(basepath == NULL)
|
||||||
|
return (errno=error,-1);
|
||||||
|
|
||||||
|
paths_->push_back(*basepath);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
search(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
vector<string> *paths_)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
uint64_t sum;
|
||||||
|
const string *basepath;
|
||||||
|
BranchInfoVec branchinfo;
|
||||||
|
|
||||||
|
branchinfo.reserve(branches_.size());
|
||||||
|
error = eppfrd::get_branchinfo_search(branches_,fusepath_,minfreespace_,&branchinfo,&sum);
|
||||||
|
basepath = eppfrd::get_branch(branchinfo,sum);
|
||||||
|
if(basepath == NULL)
|
||||||
|
return (errno=error,-1);
|
||||||
|
|
||||||
|
paths_->push_back(*basepath);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Policy::Func::eppfrd(const Category type_,
|
||||||
|
const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
vector<string> *paths_)
|
||||||
|
{
|
||||||
|
switch(type_)
|
||||||
|
{
|
||||||
|
case Category::CREATE:
|
||||||
|
return eppfrd::create(branches_,fusepath_,minfreespace_,paths_);
|
||||||
|
case Category::ACTION:
|
||||||
|
return eppfrd::action(branches_,fusepath_,minfreespace_,paths_);
|
||||||
|
default:
|
||||||
|
case Category::SEARCH:
|
||||||
|
return eppfrd::search(branches_,fusepath_,minfreespace_,paths_);
|
||||||
|
}
|
||||||
|
}
|
172
src/policy_msppfrd.cpp
Normal file
172
src/policy_msppfrd.cpp
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
/*
|
||||||
|
ISC License
|
||||||
|
|
||||||
|
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "errno.hpp"
|
||||||
|
#include "fs_exists.hpp"
|
||||||
|
#include "fs_info.hpp"
|
||||||
|
#include "fs_path.hpp"
|
||||||
|
#include "fs_statvfs_cache.hpp"
|
||||||
|
#include "policy.hpp"
|
||||||
|
#include "policy_error.hpp"
|
||||||
|
#include "rnd.hpp"
|
||||||
|
#include "rwlock.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
struct BranchInfo
|
||||||
|
{
|
||||||
|
uint64_t spaceavail;
|
||||||
|
const string *basepath;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef vector<BranchInfo> BranchInfoVec;
|
||||||
|
|
||||||
|
namespace msppfrd
|
||||||
|
{
|
||||||
|
static
|
||||||
|
int
|
||||||
|
create_1(const Branches &branches_,
|
||||||
|
const string &fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
BranchInfoVec *branchinfo_,
|
||||||
|
uint64_t *sum_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int error;
|
||||||
|
BranchInfo bi;
|
||||||
|
fs::info_t info;
|
||||||
|
const Branch *branch;
|
||||||
|
rwlock::ReadGuard guard(&branches_.lock);
|
||||||
|
|
||||||
|
*sum_ = 0;
|
||||||
|
error = ENOENT;
|
||||||
|
for(size_t i = 0, ei = branches_.size(); i < ei; i++)
|
||||||
|
{
|
||||||
|
branch = &branches_[i];
|
||||||
|
|
||||||
|
if(branch->ro_or_nc())
|
||||||
|
error_and_continue(error,EROFS);
|
||||||
|
if(!fs::exists(branch->path,fusepath_))
|
||||||
|
error_and_continue(error,ENOENT);
|
||||||
|
rv = fs::info(branch->path,&info);
|
||||||
|
if(rv == -1)
|
||||||
|
error_and_continue(error,ENOENT);
|
||||||
|
if(info.readonly)
|
||||||
|
error_and_continue(error,EROFS);
|
||||||
|
if(info.spaceavail < minfreespace_)
|
||||||
|
error_and_continue(error,ENOSPC);
|
||||||
|
|
||||||
|
*sum_ += info.spaceavail;
|
||||||
|
|
||||||
|
bi.spaceavail = info.spaceavail;
|
||||||
|
bi.basepath = &branch->path;
|
||||||
|
branchinfo_->push_back(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
get_branchinfo(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
BranchInfoVec *branchinfo_,
|
||||||
|
uint64_t *sum_)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
string fusepath;
|
||||||
|
|
||||||
|
fusepath = fusepath_;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
error = msppfrd::create_1(branches_,fusepath,minfreespace_,branchinfo_,sum_);
|
||||||
|
if(branchinfo_->size())
|
||||||
|
return error;
|
||||||
|
|
||||||
|
fusepath = fs::path::dirname(fusepath);
|
||||||
|
}
|
||||||
|
while(!fusepath.empty());
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
const
|
||||||
|
string*
|
||||||
|
get_branch(const BranchInfoVec &branchinfo_,
|
||||||
|
const uint64_t sum_)
|
||||||
|
{
|
||||||
|
uint64_t idx;
|
||||||
|
uint64_t threshold;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
threshold = RND::rand64(sum_);
|
||||||
|
for(size_t i = 0; i < branchinfo_.size(); i++)
|
||||||
|
{
|
||||||
|
idx += branchinfo_[i].spaceavail;
|
||||||
|
|
||||||
|
if(idx < threshold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return branchinfo_[i].basepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
create(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
vector<string> *paths_)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
uint64_t sum;
|
||||||
|
const string *basepath;
|
||||||
|
BranchInfoVec branchinfo;
|
||||||
|
|
||||||
|
branchinfo.reserve(branches_.size());
|
||||||
|
error = msppfrd::get_branchinfo(branches_,fusepath_,minfreespace_,&branchinfo,&sum);
|
||||||
|
basepath = msppfrd::get_branch(branchinfo,sum);
|
||||||
|
if(basepath == NULL)
|
||||||
|
return (errno=error,-1);
|
||||||
|
|
||||||
|
paths_->push_back(*basepath);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Policy::Func::msppfrd(const Category type_,
|
||||||
|
const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
vector<string> *paths_)
|
||||||
|
{
|
||||||
|
if(type_ == Category::CREATE)
|
||||||
|
return msppfrd::create(branches_,fusepath_,minfreespace_,paths_);
|
||||||
|
|
||||||
|
return Policy::Func::eppfrd(type_,branches_,fusepath_,minfreespace_,paths_);
|
||||||
|
}
|
140
src/policy_pfrd.cpp
Normal file
140
src/policy_pfrd.cpp
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "errno.hpp"
|
||||||
|
#include "fs_info.hpp"
|
||||||
|
#include "fs_path.hpp"
|
||||||
|
#include "policy.hpp"
|
||||||
|
#include "policy_error.hpp"
|
||||||
|
#include "rnd.hpp"
|
||||||
|
#include "rwlock.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
struct BranchInfo
|
||||||
|
{
|
||||||
|
uint64_t spaceavail;
|
||||||
|
const string *basepath;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef vector<BranchInfo> BranchInfoVec;
|
||||||
|
|
||||||
|
namespace pfrd
|
||||||
|
{
|
||||||
|
static
|
||||||
|
int
|
||||||
|
get_branchinfo(const Branches &branches_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
BranchInfoVec *branchinfo_,
|
||||||
|
uint64_t *sum_)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int error;
|
||||||
|
BranchInfo bi;
|
||||||
|
fs::info_t info;
|
||||||
|
const Branch *branch;
|
||||||
|
rwlock::ReadGuard guard(&branches_.lock);
|
||||||
|
|
||||||
|
*sum_ = 0;
|
||||||
|
error = ENOENT;
|
||||||
|
for(size_t i = 0, ei = branches_.size(); i < ei; i++)
|
||||||
|
{
|
||||||
|
branch = &branches_[i];
|
||||||
|
|
||||||
|
if(branch->ro_or_nc())
|
||||||
|
error_and_continue(error,EROFS);
|
||||||
|
rv = fs::info(branch->path,&info);
|
||||||
|
if(rv == -1)
|
||||||
|
error_and_continue(error,ENOENT);
|
||||||
|
if(info.readonly)
|
||||||
|
error_and_continue(error,EROFS);
|
||||||
|
if(info.spaceavail < minfreespace_)
|
||||||
|
error_and_continue(error,ENOSPC);
|
||||||
|
|
||||||
|
*sum_ += info.spaceavail;
|
||||||
|
|
||||||
|
bi.spaceavail = info.spaceavail;
|
||||||
|
bi.basepath = &branch->path;
|
||||||
|
branchinfo_->push_back(bi);
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
const
|
||||||
|
string*
|
||||||
|
get_branch(const BranchInfoVec &branchinfo_,
|
||||||
|
const uint64_t sum_)
|
||||||
|
{
|
||||||
|
uint64_t idx;
|
||||||
|
uint64_t threshold;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
threshold = RND::rand64(sum_);
|
||||||
|
for(size_t i = 0; i < branchinfo_.size(); i++)
|
||||||
|
{
|
||||||
|
idx += branchinfo_[i].spaceavail;
|
||||||
|
|
||||||
|
if(idx < threshold)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return branchinfo_[i].basepath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
create(const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
vector<string> *paths_)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
uint64_t sum;
|
||||||
|
const string *basepath;
|
||||||
|
BranchInfoVec branchinfo;
|
||||||
|
|
||||||
|
branchinfo.reserve(branches_.size());
|
||||||
|
error = pfrd::get_branchinfo(branches_,minfreespace_,&branchinfo,&sum);
|
||||||
|
basepath = pfrd::get_branch(branchinfo,sum);
|
||||||
|
if(basepath == NULL)
|
||||||
|
return (errno=error,-1);
|
||||||
|
|
||||||
|
paths_->push_back(*basepath);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
Policy::Func::pfrd(const Category type_,
|
||||||
|
const Branches &branches_,
|
||||||
|
const char *fusepath_,
|
||||||
|
const uint64_t minfreespace_,
|
||||||
|
vector<string> *paths_)
|
||||||
|
{
|
||||||
|
if(type_ == Category::CREATE)
|
||||||
|
return pfrd::create(branches_,fusepath_,minfreespace_,paths_);
|
||||||
|
|
||||||
|
return Policy::Func::eppfrd(type_,branches_,fusepath_,minfreespace_,paths_);
|
||||||
|
}
|
55
src/rnd.cpp
Normal file
55
src/rnd.cpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
/*
|
||||||
|
ISC License
|
||||||
|
|
||||||
|
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "rnd.hpp"
|
||||||
|
|
||||||
|
#include "wyhash.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
static uint64_t G_SEED;
|
||||||
|
static RND G_RND;
|
||||||
|
|
||||||
|
RND::RND()
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
gettimeofday(&tv,NULL);
|
||||||
|
|
||||||
|
G_SEED = ((tv.tv_sec << 32) | (tv.tv_usec));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
RND::rand64(void)
|
||||||
|
{
|
||||||
|
return wyrand(&G_SEED);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
RND::rand64(const uint64_t max_)
|
||||||
|
{
|
||||||
|
return (wyrand(&G_SEED) % max_);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
RND::rand64(const uint64_t min_,
|
||||||
|
const uint64_t max_)
|
||||||
|
{
|
||||||
|
return (min_ + (wyrand(&G_SEED) % (max_ - min_)));
|
||||||
|
}
|
33
src/rnd.hpp
Normal file
33
src/rnd.hpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
ISC License
|
||||||
|
|
||||||
|
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class RND
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RND();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static uint64_t rand64(void);
|
||||||
|
static uint64_t rand64(const uint64_t max_);
|
||||||
|
static uint64_t rand64(const uint64_t min_,
|
||||||
|
const uint64_t max_);
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user