1*6fa2df46SAndroid Build Coastguard Worker // Copyright (C) 2021 The Android Open Source Project
2*6fa2df46SAndroid Build Coastguard Worker //
3*6fa2df46SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*6fa2df46SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*6fa2df46SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*6fa2df46SAndroid Build Coastguard Worker //
7*6fa2df46SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*6fa2df46SAndroid Build Coastguard Worker //
9*6fa2df46SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*6fa2df46SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*6fa2df46SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*6fa2df46SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*6fa2df46SAndroid Build Coastguard Worker // limitations under the License.
14*6fa2df46SAndroid Build Coastguard Worker
15*6fa2df46SAndroid Build Coastguard Worker #include <ditto/read_write_file.h>
16*6fa2df46SAndroid Build Coastguard Worker
17*6fa2df46SAndroid Build Coastguard Worker #include <ditto/logger.h>
18*6fa2df46SAndroid Build Coastguard Worker #include <ditto/shared_variables.h>
19*6fa2df46SAndroid Build Coastguard Worker
20*6fa2df46SAndroid Build Coastguard Worker #include <ditto/utils.h>
21*6fa2df46SAndroid Build Coastguard Worker
22*6fa2df46SAndroid Build Coastguard Worker namespace dittosuite {
23*6fa2df46SAndroid Build Coastguard Worker
ReadWriteFile(const std::string & name,const Params & params,int64_t size,int64_t block_size,int64_t starting_offset,Order access_order,uint32_t seed,Reseeding reseeding,int input_fd_key)24*6fa2df46SAndroid Build Coastguard Worker ReadWriteFile::ReadWriteFile(const std::string& name, const Params& params, int64_t size,
25*6fa2df46SAndroid Build Coastguard Worker int64_t block_size, int64_t starting_offset, Order access_order,
26*6fa2df46SAndroid Build Coastguard Worker uint32_t seed, Reseeding reseeding, int input_fd_key)
27*6fa2df46SAndroid Build Coastguard Worker : Instruction(name, params),
28*6fa2df46SAndroid Build Coastguard Worker size_(size),
29*6fa2df46SAndroid Build Coastguard Worker block_size_(block_size),
30*6fa2df46SAndroid Build Coastguard Worker starting_offset_(starting_offset),
31*6fa2df46SAndroid Build Coastguard Worker access_order_(access_order),
32*6fa2df46SAndroid Build Coastguard Worker gen_(seed),
33*6fa2df46SAndroid Build Coastguard Worker seed_(seed),
34*6fa2df46SAndroid Build Coastguard Worker reseeding_(reseeding),
35*6fa2df46SAndroid Build Coastguard Worker input_fd_key_(input_fd_key),
36*6fa2df46SAndroid Build Coastguard Worker update_size_(size == -1),
37*6fa2df46SAndroid Build Coastguard Worker update_block_size_(block_size == -1) {
38*6fa2df46SAndroid Build Coastguard Worker if (access_order == Order::kRandom && starting_offset != 0) {
39*6fa2df46SAndroid Build Coastguard Worker LOGE(
40*6fa2df46SAndroid Build Coastguard Worker "Starting offset is not 0, although the chosen access_order is RANDOM. Starting offset "
41*6fa2df46SAndroid Build Coastguard Worker "will be "
42*6fa2df46SAndroid Build Coastguard Worker "ignored");
43*6fa2df46SAndroid Build Coastguard Worker }
44*6fa2df46SAndroid Build Coastguard Worker }
45*6fa2df46SAndroid Build Coastguard Worker
CollectResults(const std::string & prefix)46*6fa2df46SAndroid Build Coastguard Worker std::unique_ptr<Result> ReadWriteFile::CollectResults(const std::string& prefix) {
47*6fa2df46SAndroid Build Coastguard Worker auto result = Instruction::CollectResults(prefix);
48*6fa2df46SAndroid Build Coastguard Worker result->AddMeasurement("bandwidth", bandwidth_sampler_.GetSamples());
49*6fa2df46SAndroid Build Coastguard Worker return result;
50*6fa2df46SAndroid Build Coastguard Worker }
51*6fa2df46SAndroid Build Coastguard Worker
SetUp()52*6fa2df46SAndroid Build Coastguard Worker void ReadWriteFile::SetUp() {
53*6fa2df46SAndroid Build Coastguard Worker if (reseeding_ == Reseeding::kEachRoundOfCycles) {
54*6fa2df46SAndroid Build Coastguard Worker gen_.seed(seed_);
55*6fa2df46SAndroid Build Coastguard Worker }
56*6fa2df46SAndroid Build Coastguard Worker }
57*6fa2df46SAndroid Build Coastguard Worker
SetUpSingle()58*6fa2df46SAndroid Build Coastguard Worker void ReadWriteFile::SetUpSingle() {
59*6fa2df46SAndroid Build Coastguard Worker int fd = std::get<int>(SharedVariables::Get(input_fd_key_));
60*6fa2df46SAndroid Build Coastguard Worker int64_t file_size = GetFileSize(syscall_, fd);
61*6fa2df46SAndroid Build Coastguard Worker
62*6fa2df46SAndroid Build Coastguard Worker if (update_size_) {
63*6fa2df46SAndroid Build Coastguard Worker size_ = file_size;
64*6fa2df46SAndroid Build Coastguard Worker }
65*6fa2df46SAndroid Build Coastguard Worker if (update_block_size_) {
66*6fa2df46SAndroid Build Coastguard Worker block_size_ = file_size;
67*6fa2df46SAndroid Build Coastguard Worker }
68*6fa2df46SAndroid Build Coastguard Worker
69*6fa2df46SAndroid Build Coastguard Worker if (block_size_ > file_size) {
70*6fa2df46SAndroid Build Coastguard Worker LOGF("Supplied block_size (" + std::to_string(block_size_) +
71*6fa2df46SAndroid Build Coastguard Worker ") is greater than total file size (" + std::to_string(file_size) +
72*6fa2df46SAndroid Build Coastguard Worker "). File path:" + GetFilePath(syscall_, fd));
73*6fa2df46SAndroid Build Coastguard Worker }
74*6fa2df46SAndroid Build Coastguard Worker
75*6fa2df46SAndroid Build Coastguard Worker buffer_ = std::unique_ptr<char[]>(new (std::nothrow) char[block_size_]);
76*6fa2df46SAndroid Build Coastguard Worker if (buffer_ == nullptr) {
77*6fa2df46SAndroid Build Coastguard Worker PLOGF("Error while allocating buffer for Read/Write");
78*6fa2df46SAndroid Build Coastguard Worker }
79*6fa2df46SAndroid Build Coastguard Worker std::fill(buffer_.get(), buffer_.get() + block_size_, 170); // 170 = 10101010
80*6fa2df46SAndroid Build Coastguard Worker
81*6fa2df46SAndroid Build Coastguard Worker if (reseeding_ == Reseeding::kEachCycle) {
82*6fa2df46SAndroid Build Coastguard Worker gen_.seed(seed_);
83*6fa2df46SAndroid Build Coastguard Worker }
84*6fa2df46SAndroid Build Coastguard Worker
85*6fa2df46SAndroid Build Coastguard Worker units_.clear();
86*6fa2df46SAndroid Build Coastguard Worker
87*6fa2df46SAndroid Build Coastguard Worker switch (access_order_) {
88*6fa2df46SAndroid Build Coastguard Worker case Order::kSequential: {
89*6fa2df46SAndroid Build Coastguard Worker int64_t offset = starting_offset_;
90*6fa2df46SAndroid Build Coastguard Worker for (int64_t i = 0; i < (size_ / block_size_); i++) {
91*6fa2df46SAndroid Build Coastguard Worker if (offset > file_size - block_size_) {
92*6fa2df46SAndroid Build Coastguard Worker offset = 0;
93*6fa2df46SAndroid Build Coastguard Worker }
94*6fa2df46SAndroid Build Coastguard Worker units_.push_back({block_size_, offset});
95*6fa2df46SAndroid Build Coastguard Worker offset += block_size_;
96*6fa2df46SAndroid Build Coastguard Worker }
97*6fa2df46SAndroid Build Coastguard Worker break;
98*6fa2df46SAndroid Build Coastguard Worker }
99*6fa2df46SAndroid Build Coastguard Worker case Order::kRandom: {
100*6fa2df46SAndroid Build Coastguard Worker std::uniform_int_distribution<> uniform_distribution(0, file_size - block_size_);
101*6fa2df46SAndroid Build Coastguard Worker
102*6fa2df46SAndroid Build Coastguard Worker for (int64_t i = 0; i < (size_ / block_size_); i++) {
103*6fa2df46SAndroid Build Coastguard Worker units_.push_back({block_size_, uniform_distribution(gen_)});
104*6fa2df46SAndroid Build Coastguard Worker }
105*6fa2df46SAndroid Build Coastguard Worker break;
106*6fa2df46SAndroid Build Coastguard Worker }
107*6fa2df46SAndroid Build Coastguard Worker }
108*6fa2df46SAndroid Build Coastguard Worker
109*6fa2df46SAndroid Build Coastguard Worker Instruction::SetUpSingle();
110*6fa2df46SAndroid Build Coastguard Worker }
111*6fa2df46SAndroid Build Coastguard Worker
RunSingle()112*6fa2df46SAndroid Build Coastguard Worker void ReadWriteFile::RunSingle() {}
113*6fa2df46SAndroid Build Coastguard Worker
WriteFile(const Params & params,int64_t size,int64_t block_size,int64_t starting_offset,Order access_order,uint32_t seed,Reseeding reseeding,bool fsync,int input_fd_key)114*6fa2df46SAndroid Build Coastguard Worker WriteFile::WriteFile(const Params& params, int64_t size, int64_t block_size,
115*6fa2df46SAndroid Build Coastguard Worker int64_t starting_offset, Order access_order, uint32_t seed,
116*6fa2df46SAndroid Build Coastguard Worker Reseeding reseeding, bool fsync, int input_fd_key)
117*6fa2df46SAndroid Build Coastguard Worker : ReadWriteFile(kName, params, size, block_size, starting_offset, access_order, seed, reseeding,
118*6fa2df46SAndroid Build Coastguard Worker input_fd_key),
119*6fa2df46SAndroid Build Coastguard Worker fsync_(fsync) {}
120*6fa2df46SAndroid Build Coastguard Worker
RunSingle()121*6fa2df46SAndroid Build Coastguard Worker void WriteFile::RunSingle() {
122*6fa2df46SAndroid Build Coastguard Worker int fd = std::get<int>(SharedVariables::Get(input_fd_key_));
123*6fa2df46SAndroid Build Coastguard Worker
124*6fa2df46SAndroid Build Coastguard Worker for (const auto& unit : units_) {
125*6fa2df46SAndroid Build Coastguard Worker if (syscall_.Write(fd, buffer_.get(), unit.count, unit.offset) == -1) {
126*6fa2df46SAndroid Build Coastguard Worker LOGF("Error while calling write()");
127*6fa2df46SAndroid Build Coastguard Worker }
128*6fa2df46SAndroid Build Coastguard Worker }
129*6fa2df46SAndroid Build Coastguard Worker
130*6fa2df46SAndroid Build Coastguard Worker if (fsync_ && syscall_.FSync(fd) != 0) {
131*6fa2df46SAndroid Build Coastguard Worker LOGF("Error while calling fsync()");
132*6fa2df46SAndroid Build Coastguard Worker }
133*6fa2df46SAndroid Build Coastguard Worker }
134*6fa2df46SAndroid Build Coastguard Worker
ReadFile(const Params & params,int64_t size,int64_t block_size,int64_t starting_offset,Order access_order,uint32_t seed,Reseeding reseeding,int fadvise,int input_fd_key)135*6fa2df46SAndroid Build Coastguard Worker ReadFile::ReadFile(const Params& params, int64_t size, int64_t block_size, int64_t starting_offset,
136*6fa2df46SAndroid Build Coastguard Worker Order access_order, uint32_t seed, Reseeding reseeding, int fadvise,
137*6fa2df46SAndroid Build Coastguard Worker int input_fd_key)
138*6fa2df46SAndroid Build Coastguard Worker : ReadWriteFile(kName, params, size, block_size, starting_offset, access_order, seed, reseeding,
139*6fa2df46SAndroid Build Coastguard Worker input_fd_key),
140*6fa2df46SAndroid Build Coastguard Worker fadvise_(fadvise) {}
141*6fa2df46SAndroid Build Coastguard Worker
SetUpSingle()142*6fa2df46SAndroid Build Coastguard Worker void ReadFile::SetUpSingle() {
143*6fa2df46SAndroid Build Coastguard Worker int fd = std::get<int>(SharedVariables::Get(input_fd_key_));
144*6fa2df46SAndroid Build Coastguard Worker int64_t file_size = GetFileSize(syscall_, fd);
145*6fa2df46SAndroid Build Coastguard Worker
146*6fa2df46SAndroid Build Coastguard Worker if (syscall_.FAdvise(fd, 0, file_size, fadvise_) != 0) {
147*6fa2df46SAndroid Build Coastguard Worker LOGF("Error while calling fadvise()");
148*6fa2df46SAndroid Build Coastguard Worker }
149*6fa2df46SAndroid Build Coastguard Worker ReadWriteFile::SetUpSingle();
150*6fa2df46SAndroid Build Coastguard Worker }
151*6fa2df46SAndroid Build Coastguard Worker
RunSingle()152*6fa2df46SAndroid Build Coastguard Worker void ReadFile::RunSingle() {
153*6fa2df46SAndroid Build Coastguard Worker int fd = std::get<int>(SharedVariables::Get(input_fd_key_));
154*6fa2df46SAndroid Build Coastguard Worker
155*6fa2df46SAndroid Build Coastguard Worker for (const auto& unit : units_) {
156*6fa2df46SAndroid Build Coastguard Worker if (syscall_.Read(fd, buffer_.get(), unit.count, unit.offset) == -1) {
157*6fa2df46SAndroid Build Coastguard Worker LOGF("Error while calling read()");
158*6fa2df46SAndroid Build Coastguard Worker }
159*6fa2df46SAndroid Build Coastguard Worker }
160*6fa2df46SAndroid Build Coastguard Worker }
161*6fa2df46SAndroid Build Coastguard Worker
TearDownSingle(bool is_last)162*6fa2df46SAndroid Build Coastguard Worker void ReadWriteFile::TearDownSingle(bool is_last) {
163*6fa2df46SAndroid Build Coastguard Worker Instruction::TearDownSingle(is_last);
164*6fa2df46SAndroid Build Coastguard Worker bandwidth_sampler_.Measure(size_, time_sampler_.GetSamples().back());
165*6fa2df46SAndroid Build Coastguard Worker }
166*6fa2df46SAndroid Build Coastguard Worker
167*6fa2df46SAndroid Build Coastguard Worker } // namespace dittosuite
168