BadgerDB
|
00001 #include "catalog.h" 00002 #include <cstdlib> 00003 #include <sstream> 00004 #include <cstring> 00005 #include "index.h" 00006 #include "exceptions/attribute_not_found_exception.h" 00007 #include "exceptions/index_not_found_exception.h" 00008 #include "exceptions/index_already_exists_exception.h" 00009 #include "exceptions/end_of_file_exception.h" 00010 #include "exceptions/bad_opcodes_exception.h" 00011 00012 namespace badgerdb { 00013 00014 static int attrCmp(const void* a1, const void* a2) 00015 { 00016 return ((AttrDesc*)a1)->attrOffset - ((AttrDesc*)a2)->attrOffset; 00017 } 00018 00019 AttrCatalog::AttrCatalog(BufMgr *bufferMgr) 00020 :FileScan(ATTRCATNAME, bufferMgr) 00021 { 00022 } 00023 00024 void AttrCatalog::getInfo(const std::string &relation, const std::string &attrName, AttrDesc &attrdesc) 00025 { 00026 RecordId rid; 00027 00028 startScan(0, relation.size() + 1, STRING, relation, EQ); 00029 00030 while(1) 00031 { 00032 try 00033 { 00034 scanNext(rid); 00035 std::string recordStr = getRecord(); 00036 00037 assert(sizeof(AttrDesc) == recordStr.size()); 00038 00039 memcpy(&attrdesc, recordStr.c_str(), sizeof(AttrDesc)); 00040 if(std::string(attrdesc.attrName) == attrName) 00041 break; 00042 } 00043 catch(EndOfFileException e) 00044 { 00045 throw AttributeNotFoundException(); 00046 } 00047 } 00048 00049 endScan(); 00050 } 00051 00052 00053 void AttrCatalog::addInfo(AttrDesc &attrdesc) 00054 { 00055 RecordId outRid; 00056 std::string new_data(reinterpret_cast<char*>(&attrdesc), sizeof(AttrDesc)); 00057 insertRecord(new_data, outRid); 00058 } 00059 00060 00061 void AttrCatalog::removeInfo(const std::string &relation, const std::string &attrName) 00062 { 00063 RecordId rid; 00064 AttrDesc attrdesc; 00065 00066 startScan(0, relation.size() + 1, STRING, relation, EQ); 00067 00068 while(1) 00069 { 00070 try 00071 { 00072 scanNext(rid); 00073 std::string recordStr = getRecord(); 00074 00075 assert(sizeof(AttrDesc) == recordStr.size()); 00076 00077 memcpy(&attrdesc, recordStr.c_str(), sizeof(AttrDesc)); 00078 if (std::string(attrdesc.attrName) == attrName) 00079 break; 00080 } 00081 catch(EndOfFileException e) 00082 { 00083 throw AttributeNotFoundException(); 00084 } 00085 } 00086 00087 endScan(); 00088 00089 deleteRecord(rid); 00090 } 00091 00092 void AttrCatalog::getRelInfo(const std::string &relation, int &attrCnt, AttrDesc *&attrs) 00093 { 00094 RecordId rid; 00095 00096 startScan(0, relation.size() + 1, STRING, relation, EQ); 00097 00098 attrCnt = 0; 00099 int curSize = 8; 00100 attrs = new AttrDesc [curSize]; 00101 00102 memset (attrs, 0, curSize*sizeof(AttrDesc)); // keep purify happy. 00103 00104 while(1) 00105 { 00106 try 00107 { 00108 scanNext(rid); 00109 std::string recordStr = getRecord(); 00110 00111 assert(sizeof(AttrDesc) == recordStr.size()); 00112 00113 ++attrCnt; 00114 00115 // Check if the attrs array can hold this entry. 00116 if (attrCnt > curSize) 00117 { 00118 // reallocate the attrs array and start over. 00119 AttrDesc* newArray = new AttrDesc [curSize*2]; // double the size of the array. 00120 memset (newArray, 0, curSize*2*sizeof(AttrDesc)); // keep purify happy. 00121 memcpy (newArray, attrs, curSize*sizeof(AttrDesc)); // copy the old contents 00122 delete [] attrs; // free up the previously allocated memory. 00123 attrs = newArray; // point to the new (larger) array. 00124 curSize *= 2; 00125 } 00126 00127 memcpy(&attrs[attrCnt - 1], recordStr.c_str(), sizeof(AttrDesc)); 00128 } 00129 catch(EndOfFileException e) 00130 { 00131 break; 00132 } 00133 } 00134 00135 endScan(); 00136 00137 qsort(attrs, attrCnt, sizeof(AttrDesc), badgerdb::attrCmp); 00138 } 00139 00140 // 00141 // Drops a relation. It performs the following steps: 00142 // 00143 // destroys any index files 00144 // removes the catalog entries for the relation 00145 // 00146 // Returns: 00147 // OK on success 00148 // error code otherwise 00149 // 00150 00151 void AttrCatalog::dropRelation(const std::string &relation) 00152 { 00153 AttrDesc *attrs; 00154 int attrCnt, i; 00155 00156 // get attribute information 00157 00158 getRelInfo(relation, attrCnt, attrs); 00159 00160 // first drop any index files 00161 // (this must occur before removeInfo() is called because 00162 // dropIndex computes offsets (needed in index filenames) 00163 // based on attrcat entries!) 00164 00165 for(i = 0; i < attrCnt; i++) 00166 { 00167 if(attrs[i].indexed) 00168 { 00169 dropIndex(relation, attrs[i].attrName); 00170 } 00171 } 00172 00173 // remove entries from catalog 00174 for(i = 0; i < attrCnt; i++) 00175 { 00176 removeInfo(relation, attrs[i].attrName); 00177 } 00178 00179 delete [] attrs; 00180 } 00181 00182 AttrCatalog::~AttrCatalog() 00183 { 00184 } 00185 00186 // 00187 // Creates an index on attribute `attrName' of relation `relation.' 00188 // It performs the following steps: 00189 // 00190 // creates the appropriate index file by instantiating an Index object, which 00191 // creates the index file. 00192 // marks the attribute `indexed' in attrcat 00193 // 00194 // Returns: 00195 // OK on success 00196 // error code otherwise 00197 // 00198 00199 void AttrCatalog::addIndex(const std::string &relation, const std::string &attrName) 00200 { 00201 AttrDesc ad; 00202 00203 // get attribute information 00204 getInfo(relation, attrName, ad); 00205 00206 if(ad.indexed) 00207 throw IndexAlreadyExistsException(); 00208 00209 // create index file 00210 Index index(relation, ad.attrOffset, ad.attrLen, (Datatype)ad.attrType, 1, bufMgr); 00211 //index.printBucs(); 00212 00213 // modify entry in attrcat 00214 ad.indexed = true; 00215 00216 removeInfo(relation, attrName); 00217 addInfo(ad); 00218 } 00219 00220 00221 00222 void AttrCatalog::dropIndex(const std::string &relation, const std::string &attrName) 00223 { 00224 AttrDesc ad; 00225 00226 // get attribute information 00227 getInfo(relation, attrName, ad); 00228 00229 if(ad.indexed == false) 00230 throw IndexNotFoundException(); 00231 00232 // destroy file 00233 std::ostringstream outputString; 00234 outputString << relation << '.' << ad.attrOffset << std::endl; 00235 std::string tmpString = outputString.str(); 00236 00237 File::remove(tmpString); 00238 00239 // modify entry in attrcat 00240 ad.indexed = false; 00241 00242 removeInfo(relation, attrName); 00243 addInfo(ad); 00244 } 00245 00246 }