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