GitLab system status is available here and here

Commit 575ab547 authored by Michael Lanthier's avatar Michael Lanthier
Browse files

Initial commit

parents
## For students: change this path to the root of your code if this doesn't work
CODEROOT = ..
#CC = gcc
CC = g++
#CPPFLAGS = -Wall -I$(CODEROOT) -g # with debugging info
CPPFLAGS = -Wall -I$(CODEROOT) -g -std=c++0x # with debugging info and the C++11 feature
1. Basic information
Team Number:
CruzID of Submitter:
Student Name of Submitter:
Names of the other Team Members:
2. Internal Record Format
- Describe your record format design, and describe how your design provide O(1) field access. If your design does not provide O(1) field access, just mention that you haven't implemented this feature.
- Describe how you store a VarChar field.
3. Page Format
- Describe your page format design
4. Implementation Detail
- Other pertinent implementation detail goes here.
5. Other (optional)
- Freely use this section to tell us about other things about your Project1 solution that may help us understand and grade your solution.
include ../makefile.inc
all: librbf.a rbftest1 rbftest2 rbftest3 rbftest4 rbftest5 rbftest6 rbftest7 rbftest8 rbftest8b rbftest9 rbftest10 rbftest11 rbftest12
# c file dependencies
pfm.o: pfm.h
rbfm.o: rbfm.h
# lib file dependencies
librbf.a: librbf.a(pfm.o) # and possibly other .o files
librbf.a: librbf.a(rbfm.o)
rbftest1.o: pfm.h rbfm.h
rbftest2.o: pfm.h rbfm.h
rbftest3.o: pfm.h rbfm.h
rbftest4.o: pfm.h rbfm.h
rbftest5.o: pfm.h rbfm.h
rbftest6.o: pfm.h rbfm.h
rbftest7.o: pfm.h rbfm.h
rbftest8.o: pfm.h rbfm.h
rbftest8b.o: pfm.h rbfm.h
rbftest9.o: pfm.h rbfm.h
rbftest10.o: pfm.h rbfm.h
rbftest11.o: pfm.h rbfm.h
rbftest12.o: pfm.h rbfm.h
# binary dependencies
rbftest1: rbftest1.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest2: rbftest2.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest3: rbftest3.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest4: rbftest4.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest5: rbftest5.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest6: rbftest6.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest7: rbftest7.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest8: rbftest8.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest8b: rbftest8b.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest9: rbftest9.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest10: rbftest10.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest11: rbftest11.o librbf.a $(CODEROOT)/rbf/librbf.a
rbftest12: rbftest12.o librbf.a $(CODEROOT)/rbf/librbf.a
# dependencies to compile used libraries
.PHONY: $(CODEROOT)/rbf/librbf.a
$(CODEROOT)/rbf/librbf.a:
$(MAKE) -C $(CODEROOT)/rbf librbf.a
.PHONY: clean
clean:
-rm rbftest1 rbftest2 rbftest3 rbftest4 rbftest5 rbftest6 rbftest7 rbftest8 rbftest8b rbftest9 rbftest10 rbftest11 rbftest12 *.a *.o *~
#include "pfm.h"
PagedFileManager* PagedFileManager::_pf_manager = 0;
PagedFileManager* PagedFileManager::instance()
{
if(!_pf_manager)
_pf_manager = new PagedFileManager();
return _pf_manager;
}
PagedFileManager::PagedFileManager()
{
}
PagedFileManager::~PagedFileManager()
{
}
RC PagedFileManager::createFile(const string &fileName)
{
return -1;
}
RC PagedFileManager::destroyFile(const string &fileName)
{
return -1;
}
RC PagedFileManager::openFile(const string &fileName, FileHandle &fileHandle)
{
return -1;
}
RC PagedFileManager::closeFile(FileHandle &fileHandle)
{
return -1;
}
FileHandle::FileHandle()
{
readPageCounter = 0;
writePageCounter = 0;
appendPageCounter = 0;
}
FileHandle::~FileHandle()
{
}
RC FileHandle::readPage(PageNum pageNum, void *data)
{
return -1;
}
RC FileHandle::writePage(PageNum pageNum, const void *data)
{
return -1;
}
RC FileHandle::appendPage(const void *data)
{
return -1;
}
unsigned FileHandle::getNumberOfPages()
{
return -1;
}
RC FileHandle::collectCounterValues(unsigned &readPageCount, unsigned &writePageCount, unsigned &appendPageCount)
{
return -1;
}
#ifndef _pfm_h_
#define _pfm_h_
typedef unsigned PageNum;
typedef int RC;
typedef char byte;
#define PAGE_SIZE 4096
#include <string>
#include <climits>
using namespace std;
class FileHandle;
class PagedFileManager
{
public:
static PagedFileManager* instance(); // Access to the _pf_manager instance
RC createFile (const string &fileName); // Create a new file
RC destroyFile (const string &fileName); // Destroy a file
RC openFile (const string &fileName, FileHandle &fileHandle); // Open a file
RC closeFile (FileHandle &fileHandle); // Close a file
protected:
PagedFileManager(); // Constructor
~PagedFileManager(); // Destructor
private:
static PagedFileManager *_pf_manager;
};
class FileHandle
{
public:
// variables to keep the counter for each operation
unsigned readPageCounter;
unsigned writePageCounter;
unsigned appendPageCounter;
FileHandle(); // Default constructor
~FileHandle(); // Destructor
RC readPage(PageNum pageNum, void *data); // Get a specific page
RC writePage(PageNum pageNum, const void *data); // Write a specific page
RC appendPage(const void *data); // Append a specific page
unsigned getNumberOfPages(); // Get the number of pages in the file
RC collectCounterValues(unsigned &readPageCount, unsigned &writePageCount, unsigned &appendPageCount); // Put the current counter values into variables
};
#endif
#include "rbfm.h"
RecordBasedFileManager* RecordBasedFileManager::_rbf_manager = 0;
RecordBasedFileManager* RecordBasedFileManager::instance()
{
if(!_rbf_manager)
_rbf_manager = new RecordBasedFileManager();
return _rbf_manager;
}
RecordBasedFileManager::RecordBasedFileManager()
{
}
RecordBasedFileManager::~RecordBasedFileManager()
{
}
RC RecordBasedFileManager::createFile(const string &fileName) {
return -1;
}
RC RecordBasedFileManager::destroyFile(const string &fileName) {
return -1;
}
RC RecordBasedFileManager::openFile(const string &fileName, FileHandle &fileHandle) {
return -1;
}
RC RecordBasedFileManager::closeFile(FileHandle &fileHandle) {
return -1;
}
RC RecordBasedFileManager::insertRecord(FileHandle &fileHandle, const vector<Attribute> &recordDescriptor, const void *data, RID &rid) {
return -1;
}
RC RecordBasedFileManager::readRecord(FileHandle &fileHandle, const vector<Attribute> &recordDescriptor, const RID &rid, void *data) {
return -1;
}
RC RecordBasedFileManager::printRecord(const vector<Attribute> &recordDescriptor, const void *data) {
return -1;
}
#ifndef _rbfm_h_
#define _rbfm_h_
#include <string>
#include <vector>
#include <climits>
#include "../rbf/pfm.h"
using namespace std;
// Record ID
typedef struct
{
unsigned pageNum; // page number
unsigned slotNum; // slot number in the page
} RID;
// Attribute
typedef enum { TypeInt = 0, TypeReal, TypeVarChar } AttrType;
typedef unsigned AttrLength;
struct Attribute {
string name; // attribute name
AttrType type; // attribute type
AttrLength length; // attribute length
};
// Comparison Operator (NOT needed for part 1 of the project)
typedef enum { EQ_OP = 0, // no condition// =
LT_OP, // <
LE_OP, // <=
GT_OP, // >
GE_OP, // >=
NE_OP, // !=
NO_OP // no condition
} CompOp;
/********************************************************************************
The scan iterator is NOT required to be implemented for the part 1 of the project
********************************************************************************/
# define RBFM_EOF (-1) // end of a scan operator
// RBFM_ScanIterator is an iterator to go through records
// The way to use it is like the following:
// RBFM_ScanIterator rbfmScanIterator;
// rbfm.open(..., rbfmScanIterator);
// while (rbfmScanIterator(rid, data) != RBFM_EOF) {
// process the data;
// }
// rbfmScanIterator.close();
class RBFM_ScanIterator {
public:
RBFM_ScanIterator() {};
~RBFM_ScanIterator() {};
// Never keep the results in the memory. When getNextRecord() is called,
// a satisfying record needs to be fetched from the file.
// "data" follows the same format as RecordBasedFileManager::insertRecord().
RC getNextRecord(RID &rid, void *data) { return RBFM_EOF; };
RC close() { return -1; };
};
class RecordBasedFileManager
{
public:
static RecordBasedFileManager* instance();
RC createFile(const string &fileName);
RC destroyFile(const string &fileName);
RC openFile(const string &fileName, FileHandle &fileHandle);
RC closeFile(FileHandle &fileHandle);
// Format of the data passed into the function is the following:
// [n byte-null-indicators for y fields] [actual value for the first field] [actual value for the second field] ...
// 1) For y fields, there is n-byte-null-indicators in the beginning of each record.
// The value n can be calculated as: ceil(y / 8). (e.g., 5 fields => ceil(5 / 8) = 1. 12 fields => ceil(12 / 8) = 2.)
// Each bit represents whether each field value is null or not.
// If k-th bit from the left is set to 1, k-th field value is null. We do not include anything in the actual data part.
// If k-th bit from the left is set to 0, k-th field contains non-null values.
// If there are more than 8 fields, then you need to find the corresponding byte first,
// then find a corresponding bit inside that byte.
// 2) Actual data is a concatenation of values of the attributes.
// 3) For Int and Real: use 4 bytes to store the value;
// For Varchar: use 4 bytes to store the length of characters, then store the actual characters.
// !!! The same format is used for updateRecord(), the returned data of readRecord(), and readAttribute().
// For example, refer to the Q6 of Project 1 Environment document.
RC insertRecord(FileHandle &fileHandle, const vector<Attribute> &recordDescriptor, const void *data, RID &rid);
RC readRecord(FileHandle &fileHandle, const vector<Attribute> &recordDescriptor, const RID &rid, void *data);
// This method will be mainly used for debugging/testing.
// The format is as follows:
// field1-name: field1-value field2-name: field2-value ... \n
// (e.g., age: 24 height: 6.1 salary: 9000
// age: NULL height: 7.5 salary: 7500)
RC printRecord(const vector<Attribute> &recordDescriptor, const void *data);
/******************************************************************************************************************************************************************
IMPORTANT, PLEASE READ: All methods below this comment (other than the constructor and destructor) are NOT required to be implemented for the part 1 of the project
******************************************************************************************************************************************************************/
RC deleteRecord(FileHandle &fileHandle, const vector<Attribute> &recordDescriptor, const RID &rid);
// Assume the RID does not change after an update
RC updateRecord(FileHandle &fileHandle, const vector<Attribute> &recordDescriptor, const void *data, const RID &rid);
RC readAttribute(FileHandle &fileHandle, const vector<Attribute> &recordDescriptor, const RID &rid, const string &attributeName, void *data);
// Scan returns an iterator to allow the caller to go through the results one by one.
RC scan(FileHandle &fileHandle,
const vector<Attribute> &recordDescriptor,
const string &conditionAttribute,
const CompOp compOp, // comparision type such as "<" and "="
const void *value, // used in the comparison
const vector<string> &attributeNames, // a list of projected attributes
RBFM_ScanIterator &rbfm_ScanIterator);
public:
protected:
RecordBasedFileManager();
~RecordBasedFileManager();
private:
static RecordBasedFileManager *_rbf_manager;
};
#endif
#include <iostream>
#include <string>
#include <cassert>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdexcept>
#include <stdio.h>
#include "pfm.h"
#include "rbfm.h"
#include "test_util.h"
using namespace std;
int RBFTest_1(PagedFileManager *pfm)
{
// Functions Tested:
// 1. Create File
cout << endl << "***** In RBF Test Case 1 *****" << endl;
RC rc;
string fileName = "test1";
// Create a file named "test"
rc = pfm->createFile(fileName);
assert(rc == success && "Creating the file failed.");
rc = createFileShouldSucceed(fileName);
assert(rc == success && "Creating the file failed.");
// Create "test" again, should fail
rc = pfm->createFile(fileName);
assert(rc != success && "Creating the same file should fail.");
cout << "RBF Test Case 1 Finished! The result will be examined." << endl << endl;
return 0;
}
int main()
{
// To test the functionality of the paged file manager
PagedFileManager *pfm = PagedFileManager::instance();
// Remove files that might be created by previous test run
remove("test1");
RC rcmain = RBFTest_1(pfm);
return rcmain;
}
#include <fstream>
#include <iostream>
#include <string>
#include <cassert>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdexcept>
#include <stdio.h>
#include "pfm.h"
#include "rbfm.h"
#include "test_util.h"
using namespace std;
int RBFTest_10(RecordBasedFileManager *rbfm) {
// Functions tested
// 1. Open Record-Based File
// 2. Read Multiple Records
// 3. Close Record-Based File
// 4. Destroy Record-Based File
cout << endl << "***** In RBF Test Case 10 *****" << endl;
RC rc;
string fileName = "test9";
// Open the file "test9"
FileHandle fileHandle;
rc = rbfm->openFile(fileName, fileHandle);
assert(rc == success && "Opening the file should not fail.");
int numRecords = 2000;
void *record = malloc(1000);
void *returnedData = malloc(1000);
vector<Attribute> recordDescriptor;
createLargeRecordDescriptor(recordDescriptor);
vector<RID> rids;
vector<int> sizes;
RID tempRID;
// Read rids from the disk - do not use this code in your codebase. This is not a PAGE-BASED operation - for the test purpose only.
ifstream ridsFileRead("test9rids", ios::in | ios::binary);
unsigned pageNum;
unsigned slotNum;
if (ridsFileRead.is_open()) {
ridsFileRead.seekg(0,ios::beg);
for (int i = 0; i < numRecords; i++) {
ridsFileRead.read(reinterpret_cast<char*>(&pageNum), sizeof(unsigned));
ridsFileRead.read(reinterpret_cast<char*>(&slotNum), sizeof(unsigned));
if (i % 1000 == 0) {
cout << "loaded RID #" << i << ": " << pageNum << ", " << slotNum << endl;
}
tempRID.pageNum = pageNum;
tempRID.slotNum = slotNum;
rids.push_back(tempRID);
}
ridsFileRead.close();
}
assert(rids.size() == (unsigned) numRecords && "Reading records should not fail.");
// Read sizes vector from the disk - do not use this code in your codebase. This is not a PAGE-BASED operation - for the test purpose only.
ifstream sizesFileRead("test9sizes", ios::in | ios::binary);
int tempSize;
if (sizesFileRead.is_open()) {
sizesFileRead.seekg(0,ios::beg);
for (int i = 0; i < numRecords; i++) {
sizesFileRead.read(reinterpret_cast<char*>(&tempSize), sizeof(int));
if (i % 1000 == 0) {
cout << "loaded Sizes #" << i << ": " << tempSize << endl;
}
sizes.push_back(tempSize);
}
sizesFileRead.close();
}
assert(sizes.size() == (unsigned) numRecords && "Reading records should not fail.");
// NULL field indicator
int nullFieldsIndicatorActualSize = getActualByteForNullsIndicator(recordDescriptor.size());
unsigned char *nullsIndicator = (unsigned char *) malloc(nullFieldsIndicatorActualSize);
memset(nullsIndicator, 0, nullFieldsIndicatorActualSize);
for(int i = 0; i < numRecords; i++)
{
memset(record, 0, 1000);
memset(returnedData, 0, 1000);
rc = rbfm->readRecord(fileHandle, recordDescriptor, rids[i], returnedData);
assert(rc == success && "Reading a record should not fail.");
if (i % 1000 == 0) {
cout << endl << "Returned Data:" << endl;
rbfm->printRecord(recordDescriptor, returnedData);
}
int size = 0;
prepareLargeRecord(recordDescriptor.size(), nullsIndicator, i, record, &size);
if(memcmp(returnedData, record, sizes[i]) != 0)
{
cout << "[FAIL] Test Case 10 Failed!" << endl << endl;
free(record);
free(returnedData);
return -1;
}
}
cout << endl;
// Close the file "test9"
rc = rbfm->closeFile(fileHandle);
assert(rc == success && "Closing the file should not fail.");
rc = rbfm->destroyFile(fileName);
assert(rc == success && "Destroying the file should not fail.");
rc = destroyFileShouldSucceed(fileName);
assert(rc == success && "Destroying the file should not fail.");
free(record);
free(returnedData);
cout << "RBF Test Case 10 Finished! The result will be examined." << endl << endl;
remove("test9sizes");
remove("test9rids");
return 0;
}
int main()
{
// To test the functionality of the record-based file manager
RecordBasedFileManager *rbfm = RecordBasedFileManager::instance();
RC rcmain = RBFTest_10(rbfm);
return rcmain;
}
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <stdexcept>
#include <stdio.h>
#include "pfm.h"
#include "rbfm.h"
#include "test_util.h"
using namespace std;