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]; }
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; }
int API::select(const string tableName, const vector<string> &attr, const vector<string> &op, const vector<string> &value, const vector<int>& type, const vector<int>& begin, int recordSize, vector<vector<char>>& returnRecord, int toDelete){ vector<int> end; vector<char> temp; vector<vector<char>> valuex; vector<int> opx; vector<Address> returnAddr; if (op.size()==0){//selete * from xxx;//无条件 if (toDelete){ //判断有无索引 vector<char> tName; sToVchar(tableName, tName); vector<vector<char>> returnRecord; vector<int> op; op.push_back(0); vector<vector<char>> value; value.push_back(tName); vector<int> begin; begin.push_back(50); vector<int> end; end.push_back(100); vector<int> type; type.push_back(53); Index index; rmanager.findAllRecord("index.catalog", op, value, begin, end, type, index.recordSize, returnRecord, 0); for (int i = 0; i < returnRecord.size(); i++){//若有 则清空索引文件 string temp = ""; for (int j = 0; j < 50; j++) if (returnRecord[i][j]) temp += returnRecord[i][j]; //bmanager.deleteFile(temp + ".index"); //cmanager.clearFile(temp + ".index"); imanager.rebuildIndex(temp); } return rmanager.deleteAll(tableName, recordSize); } else{ //cout << "okok" << endl; returnAddr=rmanager.getAllRecord(tableName, recordSize, returnRecord); //cout << "okok" << endl; return returnAddr.size(); } } else{//有条件 for (int i = 0; i < op.size(); i++){ if (type[i] == 1){//int end.push_back(begin[i] + 4); intToChar4(atoi(value[i].c_str()), temp); valuex.push_back(temp); opx.push_back(typeToInt(op[i])); } else if (type[i] == 2){//float end.push_back(begin[i] + 4); floatToChar4(atof(value[i].c_str()), temp); valuex.push_back(temp); opx.push_back(typeToInt(op[i])); } else{//char(n) end.push_back(begin[i] + type[i]-3); temp.clear(); for (int k = 0; k < value[i].size(); k++) temp.push_back(value[i][k]); //sToVchar(value[i], temp); valuex.push_back(temp); opx.push_back(typeToInt(op[i])); } } //判断属性是否都有索引 vector<int> in; vector<string> attrHasIndex; Index index; string indexName; int useIndex = 1; vector<char> key; vector<char> key1; sToVchar(tableName, key); for (int i = 0; i < attr.size(); i++){ int flag = 0; for (int j = 0; j < attrHasIndex.size(); j++)//查找这个属性有无在attrHasIndex中 if (attr[i] == attrHasIndex[j]){ flag = 1; break; } if (flag) continue; //查找这个属性上有无index key.erase(key.begin() + 50, key.end()); sToVchar(attr[i], key1); key.insert(key.end(), key1.begin(), key1.end()); Address addr = rmanager.findLastRecord("index.catalog", key, index.recordSize, 50); if (addr.isNullAddr()){//条件中有一个属性没有索引 //cout << attr[i] << ": no index!" << endl; useIndex = 0; break; } else{//有索引 //cout << attr[i] << ": index!" << endl; temp = rmanager.getNextRecord(addr, "index.catalog", index.recordSize); indexName = ""; for (int i = 0; i < 50; i++){ if (temp[i]) indexName += temp[i]; } attrHasIndex.push_back(indexName); in.push_back(i); } } //选择select方式 if (!useIndex||attrHasIndex.size()>1){ clock_t start = clock(); returnAddr = rmanager.findAllRecord(tableName, opx, valuex, begin, end, type, recordSize, returnRecord, toDelete); clock_t finish = clock(); printf("Time consumed: %f second\n", (double)(finish - start) / CLOCKS_PER_SEC); } else{//符合使用index加速的条件 if (toDelete == 0){//select cout << "use index" << endl; clock_t start = clock(); /*for (int i = 0; i < valuex.size(); i++) printvc(valuex[i]);*/ returnAddr = imanager.select(indexName, valuex, opx); //cout << "ok" << endl; returnRecord.clear(); for (int i = 0; i < returnAddr.size(); i++){ returnAddr[i].setAddrFile(tableName); returnRecord.push_back(rmanager.getRecord(returnAddr[i], recordSize)); } clock_t finish = clock(); printf("Time consumed: %f second\n", (double)(finish - start) / CLOCKS_PER_SEC); } else{//delete returnAddr = rmanager.findAllRecord(tableName, opx, valuex, begin, end, type, recordSize, returnRecord, toDelete); for (int i = 0; i < attrHasIndex.size(); i++) for (int j = 0; j < returnRecord.size(); j++) imanager.deleteKey(attrHasIndex[i], subVector(returnRecord[j], begin[in[i]], end[in[i]])); } } //returnAddr = rmanager.findAllRecord(tableName, opx, valuex, begin, end, type, recordSize, returnRecord, toDelete); return returnAddr.size(); } }
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"); }
int API::insert(const string tableName, const vector<string>& value,const vector<int>& type){ vector<char> temp; vector<char> valueForBtree; vector<char> tName; int k = -1; sToVchar(tableName, tName); Index index; string attrHasIndex = ""; string indexName = ""; Address addr = rmanager.findLastRecord("index.catalog", tName, index.recordSize, 50); if (addr.isNullAddr())//如果这个表上没有索引 ; else{ temp = rmanager.getNextRecord(addr, "index.catalog", index.recordSize); for (int i = 0; i < 50; i++){ if (temp[i + 100]) attrHasIndex += temp[i+100]; if (temp[i]) indexName += temp[i]; } k = cmanager.isExistAttr(tableName, attrHasIndex)-1;//第几个属性有index } vector<char> newRecord; int recordSize = 0; for (int i = 0; i < type.size(); i++){ if (type[i] == 1){//int intToChar4(atoi(value[i].c_str()), temp); recordSize += 4; } else if (type[i] == 2){//float floatToChar4(atof(value[i].c_str()), temp); recordSize += 4; } else{//char(n) temp.clear(); int n = type[i] - 3; for (int j = 0; j < n; j++){ if (j < value[i].size())//value[i]是string temp.push_back(value[i][j]); else temp.push_back(0); } recordSize += n; } newRecord.insert(newRecord.end(), temp.begin(), temp.end()); if (i == k){ valueForBtree = temp; } } for (int i = 0; i < 8; i++){ newRecord.push_back(0); } recordSize += 8; Address returnAddr = rmanager.insertRecord(newRecord, tableName, recordSize); if (indexName != "") imanager.insert(indexName, valueForBtree, returnAddr); return 1; }