This is an automated email from the ASF dual-hosted git repository. amc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push: new 15001f8 Convert traffic_cache_tool to use ts_file 15001f8 is described below commit 15001f8541f7f67eda564dba91ba21e9aa67cf6b Author: Xavier Chi <chitianha...@gmail.com> AuthorDate: Tue Oct 16 10:46:35 2018 -0500 Convert traffic_cache_tool to use ts_file --- src/traffic_cache_tool/CacheDefs.cc | 10 +- src/traffic_cache_tool/CacheDefs.h | 17 ++- src/traffic_cache_tool/CacheScan.h | 4 +- src/traffic_cache_tool/CacheTool.cc | 159 +++++++++++++------------- src/traffic_cache_tool/File.cc | 136 ---------------------- src/traffic_cache_tool/File.h | 217 ------------------------------------ src/traffic_cache_tool/Makefile.inc | 3 +- 7 files changed, 99 insertions(+), 447 deletions(-) diff --git a/src/traffic_cache_tool/CacheDefs.cc b/src/traffic_cache_tool/CacheDefs.cc index 32a3c20..642f7c2 100644 --- a/src/traffic_cache_tool/CacheDefs.cc +++ b/src/traffic_cache_tool/CacheDefs.cc @@ -23,6 +23,8 @@ #include "CacheDefs.h" #include <iostream> +#include <fcntl.h> + using namespace std; using namespace ts; @@ -216,7 +218,7 @@ Stripe::Chunk::clear() Stripe::Stripe(Span *span, Bytes start, CacheStoreBlocks len) : _span(span), _start(start), _len(len) { - ts::bwprint(hashText, "{} {}:{}", span->_path.path(), _start.count(), _len.count()); + ts::bwprint(hashText, "{} {}:{}", span->_path.view(), _start.count(), _len.count()); CryptoContext().hash_immediate(hash_id, hashText.data(), static_cast<int>(hashText.size())); printf("hash id of stripe is hash of %.*s\n", static_cast<int>(hashText.size()), hashText.data()); } @@ -695,7 +697,7 @@ Stripe::check_loop(int s) int i = dir_next(e); if (f_bitset.test(i)) { // bit was set in a previous round so a loop is present - std::cout << "<check_loop> Loop present in Span" << this->_span->_path.path() << " Stripe: " << this->hashText + std::cout << "<check_loop> Loop present in Span" << this->_span->_path.string() << " Stripe: " << this->hashText << "Segment: " << s << std::endl; this->dir_init_segment(s); return 1; @@ -896,8 +898,8 @@ Stripe::loadMeta() alignas(SBSIZE) char stripe_buff[SBSIZE]; // Use when reading a single stripe block. alignas(SBSIZE) char stripe_buff2[SBSIZE]; // use to save the stripe freelist if (io_align > SBSIZE) { - return Errata::Message(0, 1, "Cannot load stripe ", _idx, " on span ", _span->_path, " because the I/O block alignment ", - io_align, " is larger than the buffer alignment ", SBSIZE); + return Errata::Message(0, 1, "Cannot load stripe ", _idx, " on span ", _span->_path.string(), + " because the I/O block alignment ", io_align, " is larger than the buffer alignment ", SBSIZE); } _directory._start = pos; diff --git a/src/traffic_cache_tool/CacheDefs.h b/src/traffic_cache_tool/CacheDefs.h index 929d37e..40695b1 100644 --- a/src/traffic_cache_tool/CacheDefs.h +++ b/src/traffic_cache_tool/CacheDefs.h @@ -32,8 +32,7 @@ #include "tscore/ink_file.h" #include <list> #include "tscore/CryptoHash.h" - -#include "File.h" +#include "tscore/ts_file.h" namespace tag { @@ -276,11 +275,12 @@ class DFA; // this class matches url of the format : scheme://hostname:port/path;params?query struct url_matcher { - url_matcher(ts::FilePath const &path) // file contains a list of regex + url_matcher(ts::file::path const &path) // file contains a list of regex { - ts::BulkFile cfile(path); - if (cfile.load() == 0) { - ts::TextView fileContent = cfile.content(); + std::error_code ec; + std::string load_content = ts::file::load(path, ec); + ts::TextView fileContent(load_content); + if (ec.value() == 0) { const char **patterns; std::vector<std::string> str_vec; int count = 0; @@ -355,7 +355,6 @@ using ts::CacheStripeBlocks; using ts::StripeMeta; using ts::CacheStripeDescriptor; using ts::Errata; -using ts::FilePath; using ts::CacheDirEntry; using ts::MemSpan; using ts::Doc; @@ -447,7 +446,7 @@ dir_to_offset(const CacheDirEntry *d, const CacheDirEntry *seg) struct Stripe; struct Span { - Span(FilePath const &path) : _path(path) {} + Span(ts::file::path const &path) : _path(path) {} Errata load(); Errata loadDevice(); bool isEmpty() const; @@ -462,7 +461,7 @@ struct Span { ts::Rv<Stripe *> allocStripe(int vol_idx, CacheStripeBlocks len); Errata updateHeader(); ///< Update serialized header and write to disk. - FilePath _path; ///< File system location of span. + ts::file::path _path; ///< File system location of span. ats_scoped_fd _fd; ///< Open file descriptor for span. int _vol_idx = 0; ///< Forced volume. CacheStoreBlocks _base; ///< Offset to first usable byte. diff --git a/src/traffic_cache_tool/CacheScan.h b/src/traffic_cache_tool/CacheScan.h index 3a7cdff..fc15447 100644 --- a/src/traffic_cache_tool/CacheScan.h +++ b/src/traffic_cache_tool/CacheScan.h @@ -43,9 +43,9 @@ class CacheScan url_matcher *u_matcher; public: - CacheScan(Stripe *str, ts::FilePath const &path) : stripe(str) + CacheScan(Stripe *str, ts::file::path const &path) : stripe(str) { - if (path.has_path()) { + if (!path.empty()) { u_matcher = new url_matcher(path); } }; diff --git a/src/traffic_cache_tool/CacheTool.cc b/src/traffic_cache_tool/CacheTool.cc index bc35c2f..f16a1e8 100644 --- a/src/traffic_cache_tool/CacheTool.cc +++ b/src/traffic_cache_tool/CacheTool.cc @@ -43,7 +43,6 @@ #include "tscore/ArgParser.h" #include <thread> -#include "File.h" #include "CacheDefs.h" #include "CacheScan.h" @@ -54,7 +53,6 @@ using ts::CacheStripeBlocks; using ts::StripeMeta; using ts::CacheStripeDescriptor; using ts::Errata; -using ts::FilePath; using ts::CacheDirEntry; using ts::MemSpan; using ts::Doc; @@ -64,8 +62,8 @@ extern int cache_config_min_average_object_size; extern CacheStoreBlocks Vol_hash_alloc_size; extern int OPEN_RW_FLAG; const Bytes ts::CacheSpan::OFFSET{CacheStoreBlocks{1}}; -FilePath SpanFile; -FilePath VolumeFile; +ts::file::path SpanFile; +ts::file::path VolumeFile; ts::ArgParser parser; Errata err; @@ -104,7 +102,7 @@ Volume::clear() /* --------------------------------------------------------------------------------------- */ /// Data parsed from the volume config file. struct VolumeConfig { - Errata load(FilePath const &path); + Errata load(ts::file::path const &path); /// Data direct from the config file. struct Data { @@ -185,10 +183,10 @@ VolumeConfig::convertToAbsolute(ts::CacheStripeBlocks n) struct Cache { ~Cache(); - Errata loadSpan(FilePath const &path); - Errata loadSpanConfig(FilePath const &path); - Errata loadSpanDirect(FilePath const &path, int vol_idx = -1, Bytes size = Bytes(-1)); - Errata loadURLs(FilePath const &path); + Errata loadSpan(ts::file::path const &path); + Errata loadSpanConfig(ts::file::path const &path); + Errata loadSpanDirect(ts::file::path const &path, int vol_idx = -1, Bytes size = Bytes(-1)); + Errata loadURLs(ts::file::path const &path); Errata allocStripe(Span *span, int vol_idx, CacheStripeBlocks len); @@ -216,7 +214,7 @@ Errata Cache::allocStripe(Span *span, int vol_idx, CacheStripeBlocks len) { auto rv = span->allocStripe(vol_idx, len); - std::cout << span->_path << ":" << vol_idx << std::endl; + std::cout << span->_path.string() << ":" << vol_idx << std::endl; if (rv.isOK()) { _volumes[vol_idx]._stripes.push_back(rv); } @@ -274,10 +272,10 @@ class VolumeAllocator public: VolumeAllocator(); - Errata load(FilePath const &spanFile, FilePath const &volumeFile); + Errata load(ts::file::path const &spanFile, ts::file::path const &volumeFile); Errata fillEmptySpans(); Errata fillAllSpans(); - Errata allocateSpan(FilePath const &spanFile); + Errata allocateSpan(ts::file::path const &spanFile); void dumpVolumes(); protected: @@ -288,14 +286,14 @@ protected: VolumeAllocator::VolumeAllocator() {} Errata -VolumeAllocator::load(FilePath const &spanFile, FilePath const &volumeFile) +VolumeAllocator::load(ts::file::path const &spanFile, ts::file::path const &volumeFile) { Errata zret; - if (!volumeFile) { + if (volumeFile.empty()) { zret.push(0, 9, "Volume config file not set"); } - if (!spanFile) { + if (spanFile.empty()) { zret.push(0, 9, "Span file not set"); } @@ -340,11 +338,11 @@ VolumeAllocator::fillEmptySpans() } Errata -VolumeAllocator::allocateSpan(FilePath const &input_file_path) +VolumeAllocator::allocateSpan(ts::file::path const &input_file_path) { Errata zret; for (auto span : _cache._spans) { - if (0 == strcmp(span->_path.path(), input_file_path.path())) { + if (span->_path.view() == input_file_path.view()) { std::cout << "===============================" << std::endl; if (span->_header) { zret.push(0, 1, "Disk already initialized with valid header"); @@ -389,8 +387,8 @@ VolumeAllocator::allocateFor(Span &span) int64_t total_shares = 0; if (Verbosity >= NORMAL) { - std::cout << "Allocating " << CacheStripeBlocks(round_down(span._len)).count() << " stripe blocks from span " << span._path - << std::endl; + std::cout << "Allocating " << CacheStripeBlocks(round_down(span._len)).count() << " stripe blocks from span " + << span._path.string() << std::endl; } // Walk the volumes and get the relative allocations. @@ -453,14 +451,17 @@ VolumeAllocator::allocateFor(Span &span) } /* --------------------------------------------------------------------------------------- */ Errata -Cache::loadSpan(FilePath const &path) +Cache::loadSpan(ts::file::path const &path) { Errata zret; - if (!path.has_path()) { + std::error_code ec; + auto fs = ts::file::status(path, ec); + + if (path.empty()) { zret = Errata::Message(0, EINVAL, "A span file specified by --spans is required"); - } else if (!path.is_readable()) { - zret = Errata::Message(0, EPERM, '\'', path.path(), "' is not readable."); - } else if (path.is_regular_file()) { + } else if (!ts::file::is_readable(path)) { + zret = Errata::Message(0, EPERM, '\'', path.string(), "' is not readable."); + } else if (ts::file::is_regular_file(fs)) { zret = this->loadSpanConfig(path); } else { zret = this->loadSpanDirect(path); @@ -469,7 +470,7 @@ Cache::loadSpan(FilePath const &path) } Errata -Cache::loadSpanDirect(FilePath const &path, int vol_idx, Bytes size) +Cache::loadSpanDirect(ts::file::path const &path, int vol_idx, Bytes size) { Errata zret; std::unique_ptr<Span> span(new Span(path)); @@ -503,16 +504,16 @@ Cache::loadSpanDirect(FilePath const &path, int vol_idx, Bytes size) } Errata -Cache::loadSpanConfig(FilePath const &path) +Cache::loadSpanConfig(ts::file::path const &path) { static const ts::TextView TAG_ID("id"); static const ts::TextView TAG_VOL("volume"); Errata zret; - - ts::BulkFile cfile(path); - if (0 == cfile.load()) { - ts::TextView content = cfile.content(); + std::error_code ec; + std::string load_content = ts::file::load(path, ec); + if (ec.value() == 0) { + ts::TextView content(load_content); while (content) { ts::TextView line = content.take_prefix_at('\n'); line.ltrim_if(&isspace); @@ -538,26 +539,26 @@ Cache::loadSpanConfig(FilePath const &path) } } } - zret = this->loadSpan(FilePath(path)); + zret = this->loadSpan(ts::file::path(path)); } } } else { - zret = Errata::Message(0, EBADF, "Unable to load ", path); + zret = Errata::Message(0, EBADF, "Unable to load ", path.string()); } return zret; } Errata -Cache::loadURLs(FilePath const &path) +Cache::loadURLs(ts::file::path const &path) { static const ts::TextView TAG_VOL("url"); ts::URLparser parser; Errata zret; - ts::BulkFile cfile(path); - if (0 == cfile.load()) { - ts::TextView content = cfile.content(); - + std::error_code ec; + std::string load_content = ts::file::load(path, ec); + if (ec.value() == 0) { + ts::TextView content(load_content); while (!content.empty()) { ts::TextView blob = content.take_prefix_at('\n'); @@ -577,7 +578,7 @@ Cache::loadURLs(FilePath const &path) } } } else { - zret = Errata::Message(0, EBADF, "Unable to load ", path); + zret = Errata::Message(0, EBADF, "Unable to load ", path.string()); } return zret; } @@ -588,10 +589,10 @@ Cache::dumpSpans(SpanDumpDepth depth) if (depth >= SpanDumpDepth::SPAN) { for (auto span : _spans) { if (nullptr == span->_header) { - std::cout << "Span: " << span->_path << " is uninitialized" << std::endl; + std::cout << "Span: " << span->_path.string() << " is uninitialized" << std::endl; } else { std::cout << "\n----------------------------------\n" - << "Span: " << span->_path << "\n----------------------------------\n" + << "Span: " << span->_path.string() << "\n----------------------------------\n" << "#Magic: " << span->_header->magic << " #Volumes: " << span->_header->num_volumes << " #in use: " << span->_header->num_used << " #free: " << span->_header->num_free << " #stripes: " << span->_header->num_diskvol_blks << " Len(bytes): " << span->_header->num_blocks.value() @@ -694,14 +695,17 @@ Errata Span::load() { Errata zret; - if (!_path.is_readable()) { - zret = Errata::Message(0, EPERM, _path, " is not readable."); - } else if (_path.is_char_device() || _path.is_block_device()) { + std::error_code ec; + auto fs = ts::file::status(_path, ec); + + if (!ts::file::is_readable(_path)) { + zret = Errata::Message(0, EPERM, _path.string(), " is not readable."); + } else if (ts::file::is_char_device(fs) || ts::file::is_block_device(fs)) { zret = this->loadDevice(); - } else if (_path.is_dir()) { + } else if (ts::file::is_dir(fs)) { zret.push(0, 1, "Directory support not yet available"); } else { - zret.push(0, EBADF, _path, " is not a valid file type"); + zret.push(0, EBADF, _path.string(), " is not a valid file type"); } return zret; } @@ -721,7 +725,7 @@ Span::loadDevice() #endif ; - ats_scoped_fd fd(_path.open(flags)); + ats_scoped_fd fd(!_path.empty() ? ::open(_path.c_str(), flags) : ats_scoped_fd()); if (fd.isValid()) { if (ink_file_get_geometry(fd, _geometry)) { @@ -749,21 +753,21 @@ Span::loadDevice() } _len = _header->num_blocks; } else { - zret = Errata::Message(0, 0, _path, " header is uninitialized or invalid"); - std::cout << "Span: " << _path << " header is uninitialized or invalid" << std::endl; + zret = Errata::Message(0, 0, _path.string(), " header is uninitialized or invalid"); + std::cout << "Span: " << _path.string() << " header is uninitialized or invalid" << std::endl; _len = round_down(_geometry.totalsz) - _base; } // valid FD means the device is accessible and has enough storage to be configured. _fd = fd.release(); _offset = _base + span_hdr_size; } else { - zret = Errata::Message(0, errno, "Failed to read from ", _path, '[', errno, ':', strerror(errno), ']'); + zret = Errata::Message(0, errno, "Failed to read from ", _path.string(), '[', errno, ':', strerror(errno), ']'); } } else { - zret = Errata::Message(0, 23, "Unable to get device geometry for ", _path); + zret = Errata::Message(0, 23, "Unable to get device geometry for ", _path.string()); } } else { - zret = Errata::Message(0, errno, "Unable to open ", _path); + zret = Errata::Message(0, errno, "Unable to open ", _path.string()); } return zret; } @@ -877,7 +881,7 @@ Span::clearPermanently() { if (OPEN_RW_FLAG) { alignas(512) static char zero[CacheStoreBlocks::SCALE]; // should be all zero, it's static. - std::cout << "Clearing " << _path << " permanently on disk "; + std::cout << "Clearing " << _path.string() << " permanently on disk "; ssize_t n = pwrite(_fd, zero, sizeof(zero), ts::CacheSpan::OFFSET); if (n == sizeof(zero)) { std::cout << "done"; @@ -898,7 +902,7 @@ Span::clearPermanently() strp->clear(); } } else { - std::cout << "Clearing " << _path << " not performed, write not enabled" << std::endl; + std::cout << "Clearing " << _path.string() << " not performed, write not enabled" << std::endl; } } @@ -1023,7 +1027,7 @@ Cache::key_to_stripe(CryptoHash *key, const char *hostname, int host_len) /* --------------------------------------------------------------------------------------- */ Errata -VolumeConfig::load(FilePath const &path) +VolumeConfig::load(ts::file::path const &path) { static const ts::TextView TAG_SIZE("size"); static const ts::TextView TAG_VOL("volume"); @@ -1032,9 +1036,10 @@ VolumeConfig::load(FilePath const &path) int ln = 0; - ts::BulkFile cfile(path); - if (0 == cfile.load()) { - ts::TextView content = cfile.content(); + std::error_code ec; + std::string load_content = ts::file::load(path, ec); + if (ec.value() == 0) { + ts::TextView content(load_content); while (content) { Data v; @@ -1098,7 +1103,7 @@ VolumeConfig::load(FilePath const &path) } } } else { - zret = Errata::Message(0, EBADF, "Unable to load ", path); + zret = Errata::Message(0, EBADF, "Unable to load ", path.string()); } return zret; } @@ -1132,10 +1137,10 @@ Simulate_Span_Allocation() { VolumeAllocator va; - if (!VolumeFile) { + if (VolumeFile.empty()) { err.push(0, 9, "Volume config file not set"); } - if (!SpanFile) { + if (SpanFile.empty()) { err.push(0, 9, "Span file not set"); } @@ -1165,7 +1170,7 @@ Clear_Spans() } void -Find_Stripe(FilePath const &input_file_path) +Find_Stripe(ts::file::path const &input_file_path) { // scheme=http user=u password=p host=172.28.56.109 path=somepath query=somequery port=1234 // input file format: scheme://hostname:port/somepath;params?somequery user=USER password=PASS @@ -1179,8 +1184,8 @@ Find_Stripe(FilePath const &input_file_path) // std::cout << h << " : is NOT valid" << std::endl; Cache cache; - if (input_file_path) { - printf("passed argv %s\n", input_file_path.path()); + if (!input_file_path.empty()) { + printf("passed argv %s\n", input_file_path.c_str()); } cache.loadURLs(input_file_path); if ((err = cache.loadSpan(SpanFile))) { @@ -1221,7 +1226,7 @@ walk_bucket_chain(std::string devicePath) if ((err = cache.loadSpan(SpanFile))) { cache.dumpSpans(Cache::SpanDumpDepth::SPAN); for (auto sp : cache._spans) { - if (devicePath.size() > 0 && 0 == strncmp(sp->_path.path(), devicePath.data(), devicePath.size())) { + if (devicePath.size() > 0 && sp->_path.view() == devicePath) { for (auto strp : sp->_stripes) { strp->loadMeta(); strp->loadDir(); @@ -1239,7 +1244,7 @@ Clear_Span(std::string devicePath) if ((err = cache.loadSpan(SpanFile))) { cache.dumpSpans(Cache::SpanDumpDepth::SPAN); for (auto sp : cache._spans) { - if (devicePath.size() > 0 && 0 == strncmp(sp->_path.path(), devicePath.data(), devicePath.size())) { + if (devicePath.size() > 0 && sp->_path.view() == devicePath) { printf("clearing %s\n", devicePath.data()); sp->clearPermanently(); } @@ -1255,7 +1260,7 @@ Check_Freelist(std::string devicePath) if ((err = cache.loadSpan(SpanFile))) { cache.dumpSpans(Cache::SpanDumpDepth::SPAN); for (auto sp : cache._spans) { - if (devicePath.size() > 0 && 0 == strncmp(sp->_path.path(), devicePath.data(), devicePath.size())) { + if (devicePath.size() > 0 && sp->_path.view() == devicePath) { printf("Scanning %s\n", devicePath.data()); for (auto strp : sp->_stripes) { strp->loadMeta(); @@ -1271,7 +1276,7 @@ Check_Freelist(std::string devicePath) } void -Init_disk(FilePath const &input_file_path) +Init_disk(ts::file::path const &input_file_path) { Cache cache; VolumeAllocator va; @@ -1286,7 +1291,7 @@ Init_disk(FilePath const &input_file_path) } void -Get_Response(FilePath const &input_file_path) +Get_Response(ts::file::path const &input_file_path) { // scheme=http user=u password=p host=172.28.56.109 path=somepath query=somequery port=1234 // input file format: scheme://hostname:port/somepath;params?somequery user=USER password=PASS @@ -1295,8 +1300,8 @@ Get_Response(FilePath const &input_file_path) // char* h= http://user:pass@IPADDRESS/path_to_file;?port <== this is the format we need Cache cache; - if (input_file_path) { - printf("passed argv %s\n", input_file_path.path()); + if (!input_file_path.empty()) { + printf("passed argv %s\n", input_file_path.c_str()); } cache.loadURLs(input_file_path); if ((err = cache.loadSpan(SpanFile))) { @@ -1321,13 +1326,13 @@ Get_Response(FilePath const &input_file_path) } } -void static scan_span(Span *span, ts::FilePath const ®ex_path) +void static scan_span(Span *span, ts::file::path const ®ex_path) { for (auto strp : span->_stripes) { strp->loadMeta(); strp->loadDir(); - if (regex_path.has_path()) { + if (!regex_path.empty()) { CacheScan cs(strp, regex_path); cs.Scan(true); } else { @@ -1338,7 +1343,7 @@ void static scan_span(Span *span, ts::FilePath const ®ex_path) } void -Scan_Cache(ts::FilePath const ®ex_path) +Scan_Cache(ts::file::path const ®ex_path) { Cache cache; std::vector<std::thread> threadPool; @@ -1358,7 +1363,7 @@ Scan_Cache(ts::FilePath const ®ex_path) int main(int argc, const char *argv[]) { - FilePath input_url_file; + ts::file::path input_url_file; std::string inputFile; parser.add_global_usage(std::string(argv[0]) + " --spans <SPAN> --volume <FILE> <COMMAND> [<SUBCOMMAND> ...]\n"); @@ -1394,13 +1399,13 @@ main(int argc, const char *argv[]) // parse the arguments auto arguments = parser.parse(argv); if (auto data = arguments.get("spans")) { - SpanFile = data.value().c_str(); + SpanFile = data.value(); } if (auto data = arguments.get("volumes")) { - VolumeFile = data.value().c_str(); + VolumeFile = data.value(); } if (auto data = arguments.get("input")) { - input_url_file = data.value().c_str(); + input_url_file = data.value(); } if (auto data = arguments.get("aos")) { cache_config_min_average_object_size = std::stoi(data.value()); diff --git a/src/traffic_cache_tool/File.cc b/src/traffic_cache_tool/File.cc deleted file mode 100644 index faa415e..0000000 --- a/src/traffic_cache_tool/File.cc +++ /dev/null @@ -1,136 +0,0 @@ -/** @file - - File support classes. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#include "File.h" -#include <unistd.h> -#include <fcntl.h> -#include <errno.h> - -namespace ts -{ -/** Combine two strings as file paths. - Trailing and leading separators for @a lhs and @a rhs respectively - are handled to yield exactly one separator. - @return A newly @x ats_malloc string of the combined paths. -*/ -std::string -path_join(std::string_view lhs, std::string_view rhs) -{ - size_t ln = lhs.size(); - size_t rn = rhs.size(); - const char *rptr = rhs.data(); // May need to be modified. - - if (ln && lhs[ln - 1] == '/') { - --ln; // drop trailing separator. - } - if (rn && *rptr == '/') { - --rn, ++rptr; // drop leading separator. - } - - std::string x; - x.resize(ln + rn + 2); - - memcpy(const_cast<char *>(x.data()), lhs.data(), ln); - x[ln] = '/'; - memcpy(const_cast<char *>(x.data()) + ln + 1, rptr, rn); - x[ln + rn + 1] = 0; // terminate string. - - return x; -} - -FilePath & -FilePath::operator=(char const *path) -{ - _path = path; - _stat_p = STAT_P::UNDEF; - return *this; -} - -bool -FilePath::is_readable() const -{ - return 0 == access(_path.c_str(), R_OK); -} - -FilePath -operator/(FilePath const &lhs, FilePath const &rhs) -{ - return static_cast<char const *>(lhs) / rhs; -} - -FilePath -operator/(char const *lhs, FilePath const &rhs) -{ - ats_scoped_str np; - - // If either path is empty, return the other path. - if (nullptr == lhs || 0 == *lhs) { - return rhs; - } - if (!rhs.has_path()) { - return FilePath(lhs); - } - - return FilePath(path_join(lhs, static_cast<const char *>(rhs))); -} - -ats_scoped_fd -FilePath::open(int flags) const -{ - return ats_scoped_fd(this->has_path() ? ::open(_path.c_str(), flags) : ats_scoped_fd()); -} - -int -BulkFile::load() -{ - ats_scoped_fd fd(this->open(O_RDONLY)); - int zret = 0; // return errno if something goes wrong. - struct stat info; - if (0 == fstat(fd, &info)) { - size_t n = info.st_size; - _content.resize(n + 2); - auto data = const_cast<char *>(_content.data()); - auto read_len = read(fd, data, n); - if (0 < read_len) { - _len = read_len; - // Force a trailing linefeed and nul. - memset(data + _len, 0, 2); - if (data[n - 1] != '\n') { - data[n] = '\n'; - ++_len; - } - } else { - zret = errno; - } - } else { - zret = errno; - } - return zret; -} - -TextView -BulkFile::content() const -{ - return {_content.data(), _len}; -} -} // namespace ts diff --git a/src/traffic_cache_tool/File.h b/src/traffic_cache_tool/File.h deleted file mode 100644 index 4991d37..0000000 --- a/src/traffic_cache_tool/File.h +++ /dev/null @@ -1,217 +0,0 @@ -/** @file - - File system support classes. - - @section license License - - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#pragma once - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include "tscore/ink_memory.h" -#include "tscpp/util/TextView.h" - -namespace ts -{ -/** A file class for supporting path operations. - */ -class FilePath -{ - typedef FilePath self; ///< Self reference type. -public: - FilePath(); - /// Construct from a null terminated string. - explicit FilePath(char const *path); - /// Construct from a string view. - explicit FilePath(TextView const &path); - /// Copy constructor - copies the path. - FilePath(self const &that); - /// Move constructor. - FilePath(self &&that); - /// Assign a new path. - self &operator=(char const *path); - /// Combine two paths, making sure there is exactly one separator between them. - self operator/(self const &rhs); - /// Create a new instance by appended @a path. - self operator/(char const *path); - /// Check if there is a path. - bool has_path() const; - /// Check if the path is absolute. - bool is_absolute() const; - /// Check if the path is not absolute. - bool is_relative() const; - /// Check if file is readable. - bool is_readable() const; - /// Access the path as a null terminated string. - operator const char *() const; - /// Access the path explicitly. - char const *path() const; - - /// Return the file type value. - int file_type() const; - /// Size of the file or block device. - off_t physical_size() const; - - bool is_char_device() const; - bool is_block_device() const; - bool is_dir() const; - bool is_regular_file() const; - - // Utility methods. - ats_scoped_fd open(int flags) const; - -protected: - /// Get the stat buffer. - /// @return A valid stat buffer or @c nullptr if the system call failed. - template <typename T> T stat(T (*f)(struct stat const *)) const; - - std::string _path; ///< File path. - - enum class STAT_P : int8_t { INVALID = -1, UNDEF = 0, VALID = 1 }; - mutable STAT_P _stat_p = STAT_P::UNDEF; ///< Whether _stat is valid. - mutable struct stat _stat; ///< File information. -}; - -/** A file support class for handling files as bulk content. - - @note This is used primarily for configuration files where the entire file is read every time - and it's rarely (if ever) useful to read it incrementally. The general scheme is the entire file - is read and then @c TextView elements are used to reference the bulk content. - - @internal The design goal of this class is to supplant the free functions later in this header. - - */ -class BulkFile : public FilePath -{ - typedef BulkFile self; ///< Self reference type. - typedef FilePath super; ///< Parent type. -public: - // Inherit super class constructors. - using super::super; - ///< Conversion constructor from base class. - BulkFile(super &&that); - /// Read the contents of the file in a local buffer. - /// @return @c errno - int load(); - TextView content() const; - -private: - std::string _content; ///< The file contents. - size_t _len = -1; ///< Length of file content. -}; - -/* ------------------------------------------------------------------- */ - -inline FilePath::FilePath() -{ - ink_zero(_stat); -} -inline FilePath::FilePath(char const *path) : _path(path) -{ - ink_zero(_stat); -} -inline FilePath::FilePath(TextView const &path) : _path(path.data(), path.size()) -{ - ink_zero(_stat); -} -inline FilePath::FilePath(self const &that) : _path(that._path) -{ - ink_zero(_stat); -} -inline FilePath::FilePath(self &&that) : _path(std::move(that._path)) -{ - ink_zero(_stat); -} -inline FilePath::operator const char *() const -{ - return _path.c_str(); -} -inline char const * -FilePath::path() const -{ - return _path.c_str(); -} - -inline bool -FilePath::has_path() const -{ - return !_path.empty(); -} -inline bool -FilePath::is_absolute() const -{ - return !_path.empty() && '/' == _path[0]; -} -inline bool -FilePath::is_relative() const -{ - return !this->is_absolute(); -} - -template <typename T> T FilePath::stat(T (*f)(struct stat const *)) const -{ - if (STAT_P::UNDEF == _stat_p) { - _stat_p = ::stat(_path.c_str(), &_stat) >= 0 ? STAT_P::VALID : STAT_P::INVALID; - } - return _stat_p == STAT_P::VALID ? f(&_stat) : T(); -} - -FilePath operator/(FilePath const &lhs, FilePath const &rhs); -FilePath operator/(char const *lhs, FilePath const &rhs); - -inline int -FilePath::file_type() const -{ - return this->stat<int>([](struct stat const *s) -> int { return s->st_mode & S_IFMT; }); -} - -inline bool -FilePath::is_dir() const -{ - return this->file_type() == S_IFDIR; -} -inline bool -FilePath::is_char_device() const -{ - return this->file_type() == S_IFCHR; -} -inline bool -FilePath::is_block_device() const -{ - return this->file_type() == S_IFBLK; -} -inline bool -FilePath::is_regular_file() const -{ - return this->file_type() == S_IFREG; -} - -inline off_t -FilePath::physical_size() const -{ - return this->stat<off_t>([](struct stat const *s) { return s->st_size; }); -} - -inline BulkFile::BulkFile(super &&that) : super(that) {} - -/* ------------------------------------------------------------------- */ -} // namespace ts -/* ------------------------------------------------------------------- */ diff --git a/src/traffic_cache_tool/Makefile.inc b/src/traffic_cache_tool/Makefile.inc index 9e24ab9..4c093cf 100644 --- a/src/traffic_cache_tool/Makefile.inc +++ b/src/traffic_cache_tool/Makefile.inc @@ -29,8 +29,6 @@ traffic_cache_tool_traffic_cache_tool_SOURCES = \ traffic_cache_tool/CacheDefs.h \ traffic_cache_tool/CacheDefs.cc \ traffic_cache_tool/CacheTool.cc \ - traffic_cache_tool/File.h \ - traffic_cache_tool/File.cc \ traffic_cache_tool/CacheScan.h \ traffic_cache_tool/CacheScan.cc @@ -43,6 +41,7 @@ traffic_cache_tool_traffic_cache_tool_LDADD = \ $(top_builddir)/src/tscore/.libs/ink_memory.o \ $(top_builddir)/src/tscore/.libs/ink_string.o \ $(top_builddir)/src/tscore/.libs/BufferWriterFormat.o \ + $(top_builddir)/src/tscore/.libs/ts_file.o \ $(top_builddir)/src/tscpp/util/.libs/TextView.o \ $(top_builddir)/lib/tsconfig/.libs/Errata.o \ $(top_builddir)/src/tscore/.libs/Regex.o \