Buckets:
| // Copyright 2021 The Emscripten Authors. All rights reserved. | |
| // Emscripten is available under two separate licenses, the MIT license and the | |
| // University of Illinois/NCSA Open Source License. Both these licenses can be | |
| // found in the LICENSE file. | |
| // This file defines fuzzer workloads which primarily fuzz multi-threaded | |
| // operations. | |
| namespace wasmfs { | |
| bool ReadWrite::isSame(std::vector<char>& target) { | |
| std::set<char> seen; | |
| for (auto it = target.begin(); it != target.end() - 1; it++) { | |
| seen.insert(*it); | |
| if (seen.size() > 1) { | |
| printf("Read the following incorrect data: %s\n", target.data()); | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| void ReadWrite::writer() { | |
| while (!go) { | |
| std::this_thread::yield(); | |
| } | |
| while (!stop) { | |
| if (VERBOSE) { | |
| std::cout << std::this_thread::get_id() << " is running.\n"; | |
| } | |
| auto current = rand.upTo(work.size()); | |
| int bytesWritten = | |
| pwrite(fd, work[current].c_str(), work[current].size(), 0); | |
| assert(bytesWritten == work[current].size()); | |
| } | |
| } | |
| void ReadWrite::reader() { | |
| while (!go) { | |
| std::this_thread::yield(); | |
| } | |
| if (VERBOSE) { | |
| std::cout << std::this_thread::get_id() << " is running.\n"; | |
| } | |
| int size = work.begin()->size(); | |
| // Add room for null terminator. | |
| std::vector<char> buf(size + 1, 0); | |
| while (!stop) { | |
| std::fill(buf.begin(), buf.end(), 0); | |
| int bytesRead = pread(fd, buf.data(), size, 0); | |
| if (VERBOSE) { | |
| printf("Read the following data: %s\n", buf.data()); | |
| printf("Bytes read: %i", bytesRead); | |
| printf("Expected: %lu", work.begin()->size()); | |
| } | |
| assert(bytesRead == work.begin()->size()); | |
| assert(isSame(buf)); | |
| } | |
| } | |
| void ReadWrite::execute() { | |
| // This function should produce a string that consists of 1 character type. | |
| work.resize(1 + rand.upTo(MAX_WORK)); | |
| for (int i = 0; i < work.size(); i++) { | |
| work[i] = rand.getSingleSymbolString(FILE_SIZE); | |
| } | |
| // Generate a test file to read and write to. | |
| fd = open("test", O_CREAT | O_RDWR, 0777); | |
| assert(fd != -1); | |
| // Populate the file with initial data. | |
| assert(pwrite(fd, work.begin()->c_str(), work.begin()->size(), 0) != -1); | |
| // Create writer threads. | |
| std::vector<std::thread> writers; | |
| std::vector<std::thread> readers; | |
| for (int i = 0; i < NUM_WRITERS; i++) { | |
| std::thread th(&ReadWrite::writer, this); | |
| writers.emplace_back(std::move(th)); | |
| } | |
| for (int i = 0; i < NUM_READERS; i++) { | |
| std::thread th(&ReadWrite::reader, this); | |
| readers.emplace_back(std::move(th)); | |
| } | |
| // This atomic bool ensures that all threads have an equal chance of | |
| // starting first. | |
| go.store(true); | |
| std::this_thread::sleep_for(std::chrono::seconds(DURATION)); | |
| // Stop file operations after pre-defined duration. | |
| stop.store(true); | |
| for (auto& th : writers) { | |
| th.join(); | |
| } | |
| for (auto& th : readers) { | |
| th.join(); | |
| } | |
| // Clean up files. | |
| unlink("test"); | |
| close(fd); | |
| } | |
| } // namespace wasmfs | |
Xet Storage Details
- Size:
- 3 kB
- Xet hash:
- 24eda136af349d5215b2a25b257263be085c72503da4a2528004d4d8b063b4aa
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.