added files
This commit is contained in:
parent
69bc9646e4
commit
e50051b8e6
5 changed files with 307 additions and 0 deletions
BIN
.DS_Store
vendored
Normal file
BIN
.DS_Store
vendored
Normal file
Binary file not shown.
145
buffer.hpp
Normal file
145
buffer.hpp
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
#pragma once
|
||||||
|
#include "record.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// Main buffer pool - owns all memory
|
||||||
|
class BufferPool {
|
||||||
|
private:
|
||||||
|
std::vector<Record> storage;
|
||||||
|
int buffer_capacity;
|
||||||
|
int num_buffers;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BufferPool(int num_buffers, int buffer_capacity)
|
||||||
|
: storage(num_buffers * buffer_capacity)
|
||||||
|
, buffer_capacity(buffer_capacity)
|
||||||
|
, num_buffers(num_buffers)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Record* get_buffer_ptr(int index)
|
||||||
|
{
|
||||||
|
return storage.data() + (index * buffer_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_buffer_capacity() const { return buffer_capacity; }
|
||||||
|
int get_num_buffers() const { return num_buffers; }
|
||||||
|
int total_capacity() const { return storage.size(); }
|
||||||
|
|
||||||
|
// Sort entire pool (for stage 1 - creating runs)
|
||||||
|
void sort_all(int count)
|
||||||
|
{
|
||||||
|
std::sort(storage.begin(), storage.begin() + count);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// View into a section of the buffer pool
|
||||||
|
class BufferView {
|
||||||
|
private:
|
||||||
|
Record* data;
|
||||||
|
int capacity;
|
||||||
|
int length;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BufferView(Record* ptr, int cap)
|
||||||
|
: data(ptr)
|
||||||
|
, capacity(cap)
|
||||||
|
, length(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read up to capacity records from stream
|
||||||
|
int read_from(std::istream& in)
|
||||||
|
{
|
||||||
|
length = 0;
|
||||||
|
for (int i = 0; i < capacity; i++) {
|
||||||
|
if (!(in >> data[i])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
length++;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write all current records to stream
|
||||||
|
bool write_to(std::ostream& out) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
out << data[i] << '\n';
|
||||||
|
if (!out)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For stage 2: peek at front record without consuming
|
||||||
|
const Record& front() const { return data[0]; }
|
||||||
|
|
||||||
|
// For stage 2: consume the front record
|
||||||
|
void pop_front()
|
||||||
|
{
|
||||||
|
if (length > 0) {
|
||||||
|
for (int i = 0; i < length - 1; i++) {
|
||||||
|
data[i] = data[i + 1];
|
||||||
|
}
|
||||||
|
length--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Refill from stream when buffer becomes empty during merge
|
||||||
|
bool refill_from(std::istream& in)
|
||||||
|
{
|
||||||
|
return read_from(in) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() const { return length; }
|
||||||
|
int get_capacity() const { return capacity; }
|
||||||
|
bool empty() const { return length == 0; }
|
||||||
|
bool full() const { return length == capacity; }
|
||||||
|
|
||||||
|
Record& operator[](int i) { return data[i]; }
|
||||||
|
const Record& operator[](int i) const { return data[i]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// For output buffer during merge
|
||||||
|
class OutputBuffer {
|
||||||
|
private:
|
||||||
|
Record* data;
|
||||||
|
int capacity;
|
||||||
|
int length;
|
||||||
|
|
||||||
|
public:
|
||||||
|
OutputBuffer(Record* ptr, int cap)
|
||||||
|
: data(ptr)
|
||||||
|
, capacity(cap)
|
||||||
|
, length(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add record to output buffer
|
||||||
|
bool add(const Record& rec)
|
||||||
|
{
|
||||||
|
if (length >= capacity) {
|
||||||
|
return false; // Buffer full
|
||||||
|
}
|
||||||
|
data[length++] = rec;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flush buffer to stream and reset
|
||||||
|
bool flush_to(std::ostream& out)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
out << data[i] << '\n';
|
||||||
|
if (!out)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
length = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool full() const { return length >= capacity; }
|
||||||
|
int size() const { return length; }
|
||||||
|
};
|
||||||
63
config.hpp
Normal file
63
config.hpp
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
#pragma once
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class Configuration {
|
||||||
|
public:
|
||||||
|
std::string input_file = "1.in";
|
||||||
|
std::string output_file = "1.in";
|
||||||
|
std::string directory = "tmp";
|
||||||
|
bool generate_data = false;
|
||||||
|
int N = 100000; // number of records in a file
|
||||||
|
int n = 101; // number of buffers
|
||||||
|
int b = 10; // blocking factor
|
||||||
|
|
||||||
|
static Configuration parse_args(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if (argc <= 1) {
|
||||||
|
std::cerr << "Please specify input arguments\n";
|
||||||
|
std::cerr << "Usage: " << argv[0] << " [-g] [-N count] [-i input] [-o output] [-d directory] [-n buffers] [-b block_size]\n";
|
||||||
|
throw std::invalid_argument("No input arguments");
|
||||||
|
}
|
||||||
|
Configuration config;
|
||||||
|
bool input_set = false;
|
||||||
|
int opt;
|
||||||
|
|
||||||
|
while ((opt = getopt(argc, argv, "i:o:d:gN:n:b:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'i':
|
||||||
|
config.input_file = optarg;
|
||||||
|
input_set = true;
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
config.output_file = optarg;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
config.directory = optarg;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
config.generate_data = true;
|
||||||
|
break;
|
||||||
|
case 'N':
|
||||||
|
config.N = std::stoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
config.n = std::stoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
config.b = std::stoi(optarg);
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
throw std::invalid_argument("Invalid command line argument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.generate_data && input_set) {
|
||||||
|
throw std::invalid_argument("Cannot specify both -g and -i options");
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
};
|
||||||
46
main.cpp
Normal file
46
main.cpp
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
#include "config.hpp"
|
||||||
|
#include "record.hpp"
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
int generate_file(int N, const std::string& filename)
|
||||||
|
{
|
||||||
|
std::ofstream out(filename);
|
||||||
|
if (!out) {
|
||||||
|
std::cerr << "Failed to open output file: " << filename << '\n';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < N; i++) {
|
||||||
|
Record rec = Record::random();
|
||||||
|
out << rec << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sort_file(const Configuration& opts)
|
||||||
|
{
|
||||||
|
// TODO: Implement sorting with new buffer classes
|
||||||
|
std::cout << "Sorting not yet implemented\n";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Configuration opts = Configuration::parse_args(argc, argv);
|
||||||
|
|
||||||
|
if (opts.generate_data) {
|
||||||
|
return generate_file(opts.N, opts.output_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sort_file(opts);
|
||||||
|
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "Error: " << e.what() << '\n';
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
53
record.hpp
Normal file
53
record.hpp
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#pragma once
|
||||||
|
#include <array>
|
||||||
|
#include <iostream>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
|
class Record {
|
||||||
|
public:
|
||||||
|
std::array<int, 5> a;
|
||||||
|
int x;
|
||||||
|
|
||||||
|
int evaluate() const
|
||||||
|
{
|
||||||
|
int out = 0;
|
||||||
|
int x_n = 1;
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
out += a[i] * x_n;
|
||||||
|
x_n *= x;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const Record& other) const
|
||||||
|
{
|
||||||
|
return evaluate() < other.evaluate();
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& os, const Record& r)
|
||||||
|
{
|
||||||
|
os << r.a[0] << ' ' << r.a[1] << ' ' << r.a[2] << ' '
|
||||||
|
<< r.a[3] << ' ' << r.a[4] << ' ' << r.x;
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::istream& operator>>(std::istream& is, Record& r)
|
||||||
|
{
|
||||||
|
is >> r.a[0] >> r.a[1] >> r.a[2] >> r.a[3] >> r.a[4] >> r.x;
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Record random()
|
||||||
|
{
|
||||||
|
static std::random_device rd;
|
||||||
|
static std::mt19937 gen(rd());
|
||||||
|
static std::uniform_int_distribution<int> dist;
|
||||||
|
|
||||||
|
Record r;
|
||||||
|
for (int& val : r.a) {
|
||||||
|
val = dist(gen);
|
||||||
|
}
|
||||||
|
r.x = dist(gen);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue