vector<Address> RecordManager::getAllRecord(string fileName, int recordSize, vector<vector<char>>& returnRecord){
	vector<Address> returnAddr;
	vector<char> nextBlock;
	vector<char> nextOffset;
	vector<char> tempRecord;
	Address addr;

	if (bmanager.getFileBlockNumber(fileName) == 0)
		return returnAddr;

	Address head(fileName, 0, 0);
	int headSize;
	if (recordSize < 20)
		headSize = 20;
	else
		headSize = recordSize;
	vector<char> headRecord = bmanager.read(head, headSize);
	setNextAddr(headRecord, nextBlock, nextOffset, headSize - 8);
	int size = getSize(headRecord);
	//cout << "size: " << size << endl;
	//cout << recordSize << endl;
	for (int i = 0; i < size; i++){
		//cout << char4ToInt(nextBlock) << " "<<char4ToInt(nextOffset) << endl;
		addr.setAddr(fileName, char4ToInt(nextBlock), char4ToInt(nextOffset));
		tempRecord = bmanager.read(addr, recordSize);
		returnRecord.push_back(tempRecord);
		returnAddr.push_back(addr);
		//printvc(tempRecord);
		setNextAddr(tempRecord, nextBlock, nextOffset, recordSize - 8);
	}
	return returnAddr;
}
vector<char> RecordManager::getNextRecord(Address addr, string fileName, int recordSize){
	vector<char> nextBlock;
	vector<char> nextOffset;
	vector<char> r=bmanager.read(addr, recordSize);
	setNextAddr(r, nextBlock, nextOffset, recordSize - 8);
	addr.setAddr(fileName, char4ToInt(nextBlock), char4ToInt(nextOffset));
	return bmanager.read(addr, recordSize);
}
vector<Address> RecordManager::findAllRecord(string fileName, const vector<int>& op, const vector<vector<char>>& value,
	const vector<int>& begin, const vector<int>& end, const vector<int> &type, int recordSize, 
	vector<vector<char>>& returnRecord, int toDelete){
	vector<Address> returnAddr;
	vector<Address> nullAddr;
	vector<char> nextBlock;
	vector<char> nextOffset;
	vector<char> tempRecord;
	Address addr;

	if (bmanager.getFileBlockNumber(fileName) == 0){
		return nullAddr;
	}

	Address head(fileName, 0, 0);
	int headSize;
	if (recordSize < 20)
		headSize = 20;
	else
		headSize = recordSize;
	vector<char> headRecord = bmanager.read(head, headSize);
	setNextAddr(headRecord, nextBlock, nextOffset, headSize - 8);
	int size = getSize(headRecord);
	//cout << "findallrecord: size: " << size << endl;

	for (int i = 0; i < size; i++){
		addr.setAddr(fileName, char4ToInt(nextBlock), char4ToInt(nextOffset));
		tempRecord = bmanager.read(addr,recordSize);
		int flag = 0;
		for (int j = 0; j < op.size(); j++){//取一条记录i和j个条件比
			int n=compareVc(value[j], tempRecord, begin[j], end[j], type[j]);
			if (n == 0 && (op[j] == 0 || op[j] == 3 || op[j] == 4))
				continue;
			else if (n == 1 && (op[j] == 1 || op[j] == 3 || op[j] == 5))
				continue;
			else if (n == 2 && (op[j] == 2 || op[j] == 4 || op[j] == 5))
				continue;
			else{
				flag = 1;
				break;
			}
		}
		//cout <<"flag: "<< flag << endl;
		if (flag==0){
			if (toDelete){
				//printvc(tempRecord);
				deleteRecord(tempRecord, fileName, recordSize, 1);
			}
			returnRecord.push_back(tempRecord);
			returnAddr.push_back(addr);
		}
		setNextAddr(tempRecord, nextBlock, nextOffset, recordSize - 8);
	}
	return returnAddr;
}
Address RecordManager::findLastRecord(string fileName, const vector<char>& key, int recordSize, int begin){
	Address addr(fileName, 0, 0);
	Address nullAddr;//空地址,没找到

	if (bmanager.getFileBlockNumber(fileName) == 0){
		return nullAddr;
	}
		
	int headSize;
	if (recordSize < 20)
		headSize = 20;
	else
		headSize = recordSize;

	vector<char> headRecord = bmanager.read(addr, headSize);//√
	vector<char> tempRecord;

	vector<char> nextBlock;
	vector<char> nextOffset;

	setNextAddr(headRecord, nextBlock, nextOffset, headSize - 8);
	int size = getSize(headRecord);//√
	int find = 0;
	int lastBlock = 0;
	int lastOffset = 0;
	for (int i = 0; i < size; i++){	
		addr.setAddr(fileName, char4ToInt(nextBlock), char4ToInt(nextOffset));//√
		tempRecord = bmanager.read(addr, recordSize);

		//以下输出不要删 有提速空间 减少查找次数!!
		/*cout <<fileName<< " "<<i << " : ";
		printvc(tempRecord);
		printvc(key);
		cout << tempRecord[begin] << tempRecord[begin+1] << endl;*/
		//判断是否相同
		for (int i = 0; i < key.size(); i++){
			find = 1;
			if (key[i] != tempRecord[i+begin]){
				find = 0;
				break;
			}
		}
		if (find)	{
			addr.setAddr(fileName, lastBlock, lastOffset);
			return addr;
		}
		lastBlock = char4ToInt(nextBlock);
		lastOffset = char4ToInt(nextOffset);
		//下一条地址
		setNextAddr(tempRecord, nextBlock, nextOffset, recordSize - 8);
	}
	return nullAddr;
}
void decSize(vector<char>& head, int m){
	vector<char> temp;
	for (int i = 0; i < 4; i++)
		temp.push_back(head[i]);
	int n = char4ToInt(temp);
	n -= m;
	intToChar4(n, temp);
	for (int i = 0; i < 4; i++)
		head[i] = temp[i];
}
int compareVc(const vector<char>& value, vector<char> record, int begin, int end, int type){
	vector<char> temp;
	temp.insert(temp.begin(), record.begin() + begin, record.begin() + end);
	if (type == 1){//int
		return compare(char4ToInt(temp), char4ToInt(value));
	}
	else if (type == 2){//float
		return compare(char4ToFloat(temp), char4ToFloat(value));
	}
	else{//char(n)
		string st = "";
		string sv = "";
		for (int i = 0; i < temp.size(); i++){
			st += temp[i];
		}
		for (int i = 0; i < value.size(); i++){
			sv += value[i];
		}
		return compare(st, sv);
	}
}
예제 #7
0
int showTable(const vector<vector<char>>& record, const vector<int>& type, const vector<string>& attr_show){
	vector<vector<string>> table;
	vector<string> column;
	vector<int> maxSize;
	int size;
	//record确定行数,type&attr_show确定列数
	int n = 0;
	for (int i = 0; i < attr_show.size(); i++){
		column.clear();
		column.push_back(attr_show[i]);
		size = attr_show[i].size();

		for (int j = 0; j < record.size(); j++){
			string t = "";
			if (type[i] == 1){//int
				int x = char4ToInt(subVector(record[j], n, n + 4));
				stringstream ss;
				ss << x;
				t = ss.str();
			}
			else if (type[i] == 2){//float
				float x = char4ToFloat(subVector(record[j], n, n + 4));
				stringstream ss;
				ss << x;
				t = ss.str();
			}
			else{
				vector<char> vt = subVector(record[j], n, n + type[i] - 3);
				for (int k = 0; k < vt.size(); k++){
					if (vt[k])
						t += vt[k];
				}
			}

			if (t.size()>size){
				size = t.size();
			}
			column.push_back(t);
		}
		table.push_back(column);
		maxSize.push_back(size);
		if (type[i] == 1 || type[i] == 2)
			n += 4;
		else
			n += (type[i] - 3);
	}

	drawTable(table, maxSize);

	return record.size();
}
int getSize(const vector<char>& head){
	vector<char> temp;
	for (int i = 0; i < 4; i++)
		temp.push_back(head[i]);
	return char4ToInt(temp);
}
int RecordManager::deleteRecord(const vector<char>& key, string fileName, int recordSize, int n){
	//cout << "deleterecord begin{" << endl;
	vector<char> nextBlock;
	vector<char> nextOffset;
	vector<char> delBlock;
	vector<char> delOffset;
	/*vector<char> delEndBlock;
	vector<char> delEndOffset;*/

	vector<char> headRecord;
	vector<char> lastRecord;
	vector<char> delRecord;
	vector<char> delEndRecord;

	Address head;
	Address lastAddr;
	Address delAddr;

	int attrNum=0;
	int headSize;
	if (recordSize < 20)
		headSize = 20;
	else
		headSize = recordSize;
	head.setAddr(fileName, 0, 0);
	headRecord = bmanager.read(head, headSize);

	//找到待删记录的上一条记录
	lastAddr = findLastRecord(fileName, key, recordSize,0); 
	if (lastAddr.isNullAddr()){//找不到此记录
		//cout << "isnull!" << endl;
		return 0;
	}
	int lastRecordSize = 0;

	if (lastAddr.isHead()){//如果lastRecord为head 那么recordSize有问题
		//cout << "is head!" << endl;
		lastRecordSize = headSize;
		lastRecord = headRecord;
	}
	else{
		lastRecordSize = recordSize;
		lastRecord = bmanager.read(lastAddr, lastRecordSize);
	}
	//printvc(lastRecord);
	//cout << "lastrecordsize: " << lastRecordSize << endl;
	//得到待删的记录
	setNextAddr(lastRecord, nextBlock, nextOffset, lastRecordSize - 8);
	delBlock = nextBlock;
	delOffset = nextOffset;
	delAddr.setAddr(fileName, char4ToInt(delBlock), char4ToInt(delOffset));
	delRecord = bmanager.read(delAddr, recordSize);
	//printvc(delRecord);
	if (delRecord.size()>50)
		attrNum = delRecord[50];//获得此表的attr数,只有在delete table时用到
	
	delEndRecord = delRecord;
	Address delEndAddr = delAddr;
	for (int i = 0; i < n - 1; i++){//删除连续的n条
		setNextAddr(delEndRecord, nextBlock, nextOffset, recordSize - 8);
		//delEndBlock = nextBlock;
		//delEndOffset = nextOffset;
		delEndAddr.setAddr(fileName, char4ToInt(nextBlock), char4ToInt(nextOffset));
		delEndRecord = bmanager.read(delAddr, recordSize);
	}
	//将del上一条记录指向delEnd的下一条记录
	setNextAddr(delEndRecord, nextBlock, nextOffset, recordSize - 8);
	if (lastAddr.isHead()){
		updateRecordPoint(headRecord, nextBlock, nextOffset, headSize - 8);
	}
	else{
		updateRecordPoint(lastRecord, nextBlock, nextOffset, lastRecordSize - 8);
		bmanager.write(lastAddr, lastRecord);
	}
	
	//修改delete链
	setNextAddr(headRecord, nextBlock, nextOffset, headSize - 16);//第一条被删记录
	updateRecordPoint(delEndRecord, nextBlock, nextOffset, recordSize - 8);//将delEndRecord指向第一条被删记录
	bmanager.write(delEndAddr, delEndRecord);//update过的都要写回!!
	updateRecordPoint(headRecord, delBlock, delOffset, headSize - 16);//head指向delRecord
	decSize(headRecord, n);
	bmanager.write(head,headRecord);

	//cout << "}deleterecord end 1" << endl;
	return attrNum;
}
Address RecordManager::insertRecord(vector<char>& newRecord, string fileName, int recordSize){
	Address addr(fileName, 0, 0);
	Address head(fileName, 0, 0);//head
	vector<char> headRecord;

	vector<char> nextBlock;
	vector<char> nextOffset;

	int newBlock;
	int newOffset;
	int headSize;
	if (recordSize < 20)
		headSize = 20;
	else
		headSize = recordSize;

	///////文件中无记录///////
	if (bmanager.getFileBlockNumber(fileName) == 0){
		bmanager.createFile(fileName);
		
		//清空文件头
		newHead(headRecord, headSize);

		//新纪录位置(0,1)
		newBlock = 0;
		newOffset = headSize;

		//新纪录指向head(不用改了,default)
	}
	else{
		headRecord = bmanager.read(head, headSize);
		int size = getSize(headRecord);
		if (size == 0){
			//清空文件头
			newHead(headRecord, headSize);

			//新纪录位置(0,1)
			newBlock = 0;
			newOffset = headSize;

			//新纪录指向head(不用改了,default)
		}
		///////文件中有记录///////
		else{
			//新纪录位置
			setNextAddr(headRecord, nextBlock, nextOffset, headSize- 16);//第一条被删的记录
			int delBlock = char4ToInt(nextBlock);
			int delOffset = char4ToInt(nextOffset);
			
			if (delBlock == 0 && delOffset == 0){//没有被删记录
				int n;//一块中的记录数
				int block = bmanager.getFileBlockNumber(fileName) - 1;
				int offset;
				int size = getSize(headRecord);//文件中的记录数(不包括head)
				if (block == 0){
					n = (4096 - headSize) / recordSize;//第一块中的record数
					if (size == n){
						newBlock = block + 1;
						newOffset = 0;
					}
					else{//size<n
						newBlock = block;
						newOffset = headSize + (size%n)*recordSize;
					}
				}
				else{
					n = 4096 / recordSize;//其他块中最多能放的record数
					if (size == (4096 - headSize) / recordSize+block*n){
						newBlock = block + 1;
						newOffset = 0;
					}
					else{
						newBlock = block;
						newOffset = ((size - (4096 - headSize) / recordSize) % n)*recordSize;
					}
				}
			}
			else{///有被删记录
				//空位在(delBlock,delOffset)
				newBlock = delBlock;
				newOffset = delOffset;
				//修改文件头中的del指针,使它指向第二条被删记录
				addr.setAddr(fileName, delBlock, delOffset);
				vector<char> tempRecord = bmanager.read(addr, recordSize);
				setNextAddr(tempRecord, nextBlock, nextOffset, recordSize - 8);
				updateRecordPoint(headRecord, nextBlock, nextOffset, headSize - 16);
			}
			
			//newRecord指向第一条记录
			setNextAddr(headRecord, nextBlock, nextOffset, headSize - 8); 
			updateRecordPoint(newRecord, nextBlock, nextOffset, recordSize - 8);
		}
	}
	
	//插入新记录
	
	addr.setAddr(fileName, newBlock, newOffset);
	bmanager.write(addr, newRecord);//√
	//更新head
	//head指向第一条记录
	intToChar4(newBlock, nextBlock);
	intToChar4(newOffset, nextOffset);
	updateRecordPoint(headRecord, nextBlock, nextOffset, headSize - 8);
	//更新head中的size
	incSize(headRecord);
	//写回headRecord
	bmanager.write(head, headRecord);//√

	return addr;
}
예제 #11
0
void processInput(int connfd, unsigned int secretKey) {
    size_t size;
    //buffers required by all commands
    unsigned char *secretKeyBuf = (unsigned char*)malloc(sizeof(char) * 4);
    unsigned char *requestBuf = (unsigned char*)malloc(sizeof(char) * 4);

    //get and put
    unsigned char *fileSizeBuf = (unsigned char*)malloc(sizeof(char) * 4);
    char *fileNameBuf = (char*)malloc(sizeof(char) * 80);
    char *fileContentsBuf;

    //list buffers
    unsigned char *returnListBuf;

    //return buffers
    unsigned char *returnCodeBuf = (unsigned char*)malloc(sizeof(char) * 4);
    unsigned char *returnSizeCodeBuf = (unsigned char*)malloc(sizeof(char) * 4);

    //RIO stuff
    rio_t rio;
    Rio_readinitb(&rio, connfd);

    //ints parsed from buffers
    unsigned int nsecretKey, request, fileSize;
    unsigned int bufferSize = 0; //for EOF
    //bools used for method logic (not necessary, but helps with reading the file)
    bool shouldUseFilename = false, error = false, list = false, get = false, put = false, del = false;
    
    //read in the secret key and type of request.
    size = Rio_readnb(&rio, secretKeyBuf, 4);
    if(size!=4){
        error = true;
    }
    size = Rio_readnb(&rio, requestBuf, 4);
    if(size!=4){
        error = true;
    }

    //convert the secret key and request buffers to ints
    nsecretKey = char4ToInt(secretKeyBuf);
    request = char4ToInt(requestBuf);
    printf("Secret Key = %d\n", nsecretKey);
    printf("Request Type = ");

    //check the secret keys and set error
    if (nsecretKey != secretKey)
    {
        error = true;
    }

    //print some stuff to the console depending on what command is requested
    switch(request) {
        case 0:
            //get
            printf("get\n");
            printf("Filename = ");
            shouldUseFilename = true;
            get = true;
            break;
        case 1:
            //put
            printf("put\n");
            printf("Filename = ");
            shouldUseFilename = true;
            put = true;
            break;
        case 2:
            //del
            printf("del\n");
            printf("Filename = ");
            shouldUseFilename = true;
            del = true;
            break;
        case 3:
            //list
            printf("list\n");
            printf("Filename = NONE\n");
            list = true;
            break;
        default:
            printf("undefined: %d\n",request);
            printf("Filename = NONE\n");
            error = true;
            break;
    }
    //if the command we're utilizing receives a filename, read it in.
    if (shouldUseFilename) {
        size = Rio_readnb(&rio, fileNameBuf, 80);
        printf("%s\n",fileNameBuf);
    }
    if (put && !error) {
        size = Rio_readnb(&rio, fileSizeBuf, 4);
        fileSize = char4ToInt(fileSizeBuf);
        //printf("Creating file buf of size %d\n",fileSize);
        fileContentsBuf = (char*)malloc(sizeof(char) * (fileSize+1));
        size = Rio_readnb(&rio, fileContentsBuf, fileSize);

        FILE *stream;
        char filePath[100];
        //create the file path
        strcpy(filePath, "./files/");
        strcat(filePath, fileNameBuf);
        if ((stream = fopen(filePath, "w")))
        {
            //write the file
            fwrite(fileContentsBuf, 1, fileSize, stream);
            //Debug print
            //printf("Write: %s\n",fileContentsBuf);
            fclose(stream);
        } else {
            //an error occurred writing the file
            perror("Put file");
            error = true;
        }
    }
    if (list && !error)
    {
         //for end of file
        DIR *d, *e;
        struct dirent *dir;
        //open the files directory
        d = opendir("./files");
        if (d)
        {
            while ((dir = readdir(d)) != NULL)
            {
                if (dir->d_type == DT_REG)
                {
                    //count up the length of each filename (for the length byte)
                    bufferSize += strlen(dir->d_name);
                    bufferSize += 1;
                }
            }
        }
        closedir(d);
        returnListBuf = (unsigned char*)malloc(sizeof(char) * bufferSize);
        e = opendir("./files");
        int counter = 0;
        if (e)
        {
            while ((dir = readdir(e)) != NULL)
            {
                if (dir->d_type == DT_REG)
                {
                    //print each name to a buffer
                    //printf("%s\n",dir->d_name);
                    char temp[strlen(dir->d_name) + 1];
                    sprintf(temp,"%s\n",dir->d_name);
                    memcpy(&returnListBuf[counter], temp, strlen(temp));
                    counter += strlen(temp);
                    // printf("%s\n", dir->d_name);   
                }
            }
        }
    }
    if(get && !error){
        FILE *stream;
        fileSize = 0;
        char filePath[100];
        strcpy(filePath, "./files/");
        strcat(filePath, fileNameBuf);
        //try to open the file (in the files directory)
        if ((stream = fopen(filePath, "rb")))
        {
            //Seek to the end of the file to determine the file size
            fseek(stream, 0L, SEEK_END);
            fileSize = ftell(stream);
            fseek(stream, 0L, SEEK_SET);
            //printf("fileSize: %d\n",fileSize);
            fileContentsBuf = (char*)malloc(sizeof(char) * (fileSize+1));
            size=fread(fileContentsBuf,1,fileSize,stream);
            fileContentsBuf[size]=0; //add EOF
            //Debug print
            //printf("Read: %s\n",fileContentsBuf);
            //printf("Size T: %lu\n", size);
            fclose(stream);
        } else {
            //an error occurred opening the file. It may not exist, or permissions aren't set
            perror("Open file");
            error = true;
        }
    }
    if(del && !error){
        char filePath[100];
        strcpy(filePath, "./files/");
        strcat(filePath, fileNameBuf);
        //delete the file at path
        //printf("deleting file at path: %s\n",filePath);
        int delResult = unlink(filePath);
        if(delResult != 0){
            error = true;
        }
    }
    //all input should be read in now. Now to handle the files themselves
    unsigned int returnCode;
    if(error){
        returnCode = -1;
        printf("Operation Status = error\n");
    } else{
        returnCode = 0;
        printf("Operation Status = success\n");
    }
    intToChar4(returnCode, returnCodeBuf);
    Rio_writen(connfd, returnCodeBuf, 4);
    //printf("sent\n");

    //only send the get and list info if there isn't an error
    if(!error){
        switch(request) {
            case 0:
                //get
                //bufferSize = strlen(fileContentsBuf) + 1;
                //printf("Size of file: %lu\n",size);
                intToChar4(size, returnSizeCodeBuf);
                Rio_writen(connfd, returnSizeCodeBuf, 4);
                Rio_writen(connfd, fileContentsBuf, size);
                // for (unsigned int i = 0; i < size; ++i)
                // {
                //     printf("%02x",fileContentsBuf[i]);
                // }
                break;
            case 3:
                //list
                //printf("Size of files list: %d\n",bufferSize);
                intToChar4(bufferSize, returnSizeCodeBuf);
                Rio_writen(connfd, returnSizeCodeBuf, 4);
                Rio_writen(connfd, returnListBuf, bufferSize);
                break;
            default:
                break;
        }
    }

    printf("--------------------------\n");
}