1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413 |
- // # ifdef __cplusplus
- // extern "C" {
- // # endif
- //========================================================================================================================================================================================================200
- //======================================================================================================================================================150
- //====================================================================================================100
- //==================================================50
- //========================================================================================================================================================================================================200
- // INFORMATION
- //========================================================================================================================================================================================================200
- //======================================================================================================================================================150
- // UPDATE
- //======================================================================================================================================================150
- // 2009; Amittai Aviram; entire code written in C;
- // 2010; Jordan Fix and Andrew Wilkes; code converted to CUDA;
- // 2011.10; Lukasz G. Szafaryn; code converted to portable form, to C, OpenMP, CUDA, PGI versions;
- // 2011.12; Lukasz G. Szafaryn; Split different versions for Rodinia.
- // 2011.12; Lukasz G. Szafaryn; code converted to OpenCL;
- //======================================================================================================================================================150
- // DESCRIPTION
- //======================================================================================================================================================150
- // Description
- //======================================================================================================================================================150
- // USE
- //======================================================================================================================================================150
- // EXAMPLE:
- // ./a.out -file ./input/mil.txt
- // ...then enter any of the following commands after the prompt > :
- // f <x> -- Find the value under key <x>
- // p <x> -- Print the path from the root to key k and its associated value
- // t -- Print the B+ tree
- // l -- Print the keys of the leaves (bottom row of the tree)
- // v -- Toggle output of pointer addresses ("verbose") in tree and leaves.
- // k <x> -- Run <x> bundled queries on the CPU and GPU (B+Tree) (Selects random values for each search)
- // j <x> <y> -- Run a range search of <x> bundled queries on the CPU and GPU (B+Tree) with the range of each search of size <y>
- // x <z> -- Run a single search for value z on the GPU and CPU
- // y <a> <b> -- Run a single range search for range a-b on the GPU and CPU
- // q -- Quit. (Or use Ctl-D.)
- //======================================================================================================================================================150
- // END
- //======================================================================================================================================================150
- //========================================================================================================================================================================================================200
- // DEFINE/INCLUDE
- //========================================================================================================================================================================================================200
- //======================================================================================================================================================150
- // LIBRARIES
- //======================================================================================================================================================150
- #include <stdio.h> // (in directory known to compiler) needed by printf, stderr
- #include <limits.h> // (in directory known to compiler) needed by INT_MIN, INT_MAX
- // #include <sys/time.h> // (in directory known to compiler) needed by ???
- #include <math.h> // (in directory known to compiler) needed by log, pow
- #include <string.h> // (in directory known to compiler) needed by memset
- //======================================================================================================================================================150
- // COMMON
- //======================================================================================================================================================150
- #include "./common.h" // (in directory provided here)
- //======================================================================================================================================================150
- // DEFINE
- //======================================================================================================================================================150
- //======================================================================================================================================================150
- // UTILITIES
- //======================================================================================================================================================150
- #include "./util/timer/timer.h" // (in directory provided here)
- #include "./util/num/num.h" // (in directory provided here)
- //======================================================================================================================================================150
- // KERNEL HEADERS
- //======================================================================================================================================================150
- #include "./kernel/kernel_gpu_opencl_wrapper.h" // (in directory provided here)
- #include "./kernel/kernel_gpu_opencl_wrapper_2.h" // (in directory provided here)
- //======================================================================================================================================================150
- // HEADER
- //======================================================================================================================================================150
- #include "./main.h" // (in directory provided here)
- //======================================================================================================================================================150
- // END
- //======================================================================================================================================================150
- //========================================================================================================================================================================================================200
- // VARIABLES
- //========================================================================================================================================================================================================200
- // general variables
- knode *knodes;
- record *krecords;
- char *mem;
- long freeptr;
- long malloc_size;
- long size;
- long maxheight;
- /* The order determines the maximum and minimum
- * number of entries (keys and pointers) in any
- * node. Every node has at most order - 1 keys and
- * at least (roughly speaking) half that number.
- * Every leaf has as many pointers to data as keys,
- * and every internal node has one more pointer
- * to a subtree than the number of keys.
- * This global variable is initialized to the
- * default value.
- */
- int order = DEFAULT_ORDER;
- /* The queue is used to print the tree in
- * level order, starting from the root
- * printing each entire rank on a separate
- * line, finishing with the leaves.
- */
- node *queue = NULL;
- /* The user can toggle on and off the "verbose"
- * property, which causes the pointer addresses
- * to be printed out in hexadecimal notation
- * next to their corresponding keys.
- */
- bool verbose_output = false;
- //========================================================================================================================================================================================================200
- // FUNCTIONS
- //========================================================================================================================================================================================================200
- //======================================================================================================================================================150
- // Components
- //======================================================================================================================================================150
- void
- list_init( list_t *l,
- int32_t (*compare)(const void *key,
- const void *with),
- void (*datum_delete)(void *))
- {
- l->head = l->tail = NULL;
- l->length = 0;
- l->compare = compare;
- l->datum_delete = datum_delete;
- }
- void
- list_delete(list_t *l)
- {
- list_item_t *li, *del;
- for (li = l->head; li;) {
- del = li;
- li = li->next;
- list_item_delete(del, l->datum_delete);
- }
- l->head = l->tail = NULL;
- l->length = 0;
- }
- void
- list_reset(list_t *l)
- {
- list_delete(l);
- }
- void
- list_insert_item_head( list_t *l,
- list_item_t *i)
- {
- if (l->head) {
- i->next = l->head;
- l->head->pred = i;
- l->head = i;
- l->head->pred = NULL;
- } else {
- l->head = l->tail = i;
- i->next = i->pred = NULL;
- }
- l->length++;
- }
- void
- list_insert_item_tail( list_t *l,
- list_item_t *i)
- {
- if (l->head) {
- l->tail->next = i;
- i->pred = l->tail;
- i->next = NULL;
- l->tail = i;
- } else {
- l->head = l->tail = i;
- i->next = i->pred = NULL;
- }
- l->length++;
- }
- void
- list_insert_item_before(list_t *l,
- list_item_t *next,
- list_item_t *i)
- {
- /* Assume next is actually in the list! */
- /* If it's not, we may lose the list. */
- if (l->head == next) {
- i->next = next;
- i->pred = NULL;
- l->head = i;
- next->pred = i;
- } else {
- i->next = next;
- i->pred = next->pred;
- next->pred->next = i;
- next->pred = i;
- }
- l->length++;
- }
- void
- list_insert_item_after( list_t *l,
- list_item_t *pred,
- list_item_t *i)
- {
- /* Assume pred is actually in the list! */
- /* If it's not, we may lose the list. */
- if (l->tail == pred) {
- i->pred = pred;
- i->next = NULL;
- l->tail = i;
- pred->next = i;
- } else {
- i->pred = pred;
- i->next = pred->next;
- pred->next->pred = i;
- pred->next = i;
- }
- l->length++;
- }
- void
- list_insert_item_sorted(list_t *l,
- list_item_t *i)
- {
- list_item_t *itr;
- if (l->head) {
- for (itr = l->head; itr && l->compare(list_item_get_datum(i),
- list_item_get_datum(itr)) < 0;
- itr = itr->next)
- ;
- if (itr) {
- i->next = itr;
- i->pred = itr->pred;
- itr->pred = i;
- i->pred->next = i;
- } else {
- l->tail->next = i;
- i->pred = l->tail;
- i->next = NULL;
- l->tail = i;
- }
- } else {
- l->head = l->tail = i;
- i->pred = i->next = NULL;
- }
- l->length++;
- }
- void
- list_insert_head( list_t *l,
- void *v)
- {
- list_item_t *i;
- i = (list_item_t *)malloc(sizeof (*i));
- list_item_init(i, v);
- if (l->head) {
- i->next = l->head;
- l->head->pred = i;
- l->head = i;
- l->head->pred = NULL;
- } else {
- l->head = l->tail = i;
- i->next = i->pred = NULL;
- }
- l->length++;
- }
- void
- list_insert_tail( list_t *l,
- void *v)
- {
- list_item_t *i;
- i = (list_item_t *)malloc(sizeof (*i));
- list_item_init(i, v);
- if (l->head) {
- l->tail->next = i;
- i->pred = l->tail;
- i->next = NULL;
- l->tail = i;
- } else {
- l->head = l->tail = i;
- i->next = i->pred = NULL;
- }
- l->length++;
- }
- void
- list_insert_before( list_t *l,
- list_item_t *next,
- void *v)
- {
- list_item_t *i;
- i = (list_item_t *)malloc(sizeof (*i));
- list_item_init(i, v);
- /* Assume next is actually in the list! */
- /* If it's not, we may lose the list. */
- if (l->head == next) {
- i->next = next;
- i->pred = NULL;
- l->head = i;
- next->pred = i;
- } else {
- i->next = next;
- i->pred = next->pred;
- next->pred->next = i;
- next->pred = i;
- }
- l->length++;
- }
- void
- list_insert_after( list_t *l,
- list_item_t *pred,
- void *v)
- {
- list_item_t *i;
- i = (list_item_t *)malloc(sizeof (*i));
- list_item_init(i, v);
- /* Assume pred is actually in the list! */
- /* If it's not, we may lose the list. */
- if (l->tail == pred) {
- i->pred = pred;
- i->next = NULL;
- l->tail = i;
- pred->next = i;
- } else {
- i->pred = pred;
- i->next = pred->next;
- pred->next->pred = i;
- pred->next = i;
- }
- l->length++;
- }
- void
- list_insert_sorted( list_t *l,
- void *v)
- {
- list_item_t *itr;
- list_item_t *i;
- i = (list_item_t *)malloc(sizeof (*i));
- list_item_init(i, v);
- if (l->head) {
- for (itr = l->head; itr && l->compare(list_item_get_datum(i),
- list_item_get_datum(itr)) < 0;
- itr = itr->next)
- ;
- if (itr) {
- i->next = itr;
- i->pred = itr->pred;
- itr->pred = i;
- i->pred->next = i;
- } else {
- l->tail->next = i;
- i->pred = l->tail;
- i->next = NULL;
- l->tail = i;
- }
- } else {
- l->head = l->tail = i;
- i->pred = i->next = NULL;
- }
- l->length++;
- }
- void
- list_remove_item( list_t *l,
- list_item_t *i)
- {
- if (i == l->head) {
- l->head = l->head->next;
- if (l->head)
- l->head->pred = NULL;
- else
- l->tail = NULL;
- } else if (i == l->tail) {
- l->tail = l->tail->pred;
- l->tail->next = NULL;
- } else {
- i->pred->next = i->next;
- i->next->pred = i->pred;
- }
- l->length--;
- list_item_delete(i, l->datum_delete);
- }
- void
- list_remove_head(list_t *l)
- {
- list_remove_item(l, l->head);
- }
- void
- list_remove_tail(list_t *l)
- {
- list_remove_item(l, l->tail);
- }
- list_item_t*
- list_find_item( list_t *l,
- void *datum)
- {
- list_item_t *li;
- for (li = l->head; li && l->compare(datum, list_item_get_datum(li));
- li = li->next)
- ;
- return li;
- }
- list_item_t*
- list_get_head_item(list_t *l)
- {
- return l->head;
- }
- list_item_t*
- list_get_tail_item(list_t *l)
- {
- return l->tail;
- }
- void*
- list_find( list_t *l,
- void *datum)
- {
- list_item_t *li;
- for (li = l->head; li && l->compare(datum, list_item_get_datum(li));
- li = li->next)
- ;
- return li ? li->datum : NULL;
- }
- void*
- list_get_head(list_t *l)
- {
- return l->head ? l->head->datum : NULL;
- }
- void*
- list_get_tail(list_t *l)
- {
- return l->tail ? l->tail->datum : NULL;
- }
- uint32_t
- list_get_length(list_t *l)
- {
- return l->length;
- }
- bool
- list_is_empty(list_t *l)
- {
- return (l->length == 0);
- }
- bool
- list_not_empty(list_t *l)
- {
- return (l->length != 0);
- }
- void
- list_visit_items( list_t *l,
- void (*visitor)(void *v))
- {
- list_item_t *li;
- for (li = l->head; li; li = li->next)
- visitor(list_item_get_datum(li));
- }
- void
- list_item_init( list_item_t *li,
- void *datum)
- {
- li->pred = li->next = NULL;
- li->datum = datum;
- }
- void
- list_item_delete( list_item_t *li,
- void (*datum_delete)(void *datum))
- {
- if (datum_delete) {
- datum_delete(li->datum);
- }
- free(li);
- }
- void *
- list_item_get_datum(list_item_t *li)
- {
- return li->datum;
- }
- void
- list_iterator_init( list_t *l,
- list_iterator_t *li)
- {
- *li = l ? l->head : NULL;
- }
- void
- list_iterator_delete(list_iterator_t *li)
- {
- *li = NULL;
- }
- void
- list_iterator_next(list_iterator_t *li)
- {
- if (*li)
- *li = (*li)->next;
- }
- void
- list_iterator_prev(list_iterator_t *li)
- {
- if (*li)
- *li = (*li)->pred;
- }
- void *
- list_iterator_get_datum(list_iterator_t *li)
- {
- return *li ? (*li)->datum : NULL;
- }
- bool
- list_iterator_is_valid(list_iterator_t *li)
- {
- return (*li != NULL);
- }
- void
- list_reverse_iterator_init( list_t *l,
- list_reverse_iterator_t *li)
- {
- *li = l ? l->tail : NULL;
- }
- void
- list_reverse_iterator_delete(list_reverse_iterator_t *li)
- {
- *li = NULL;
- }
- void
- list_reverse_iterator_next(list_reverse_iterator_t *li)
- {
- if (*li)
- *li = (*li)->pred;
- }
- void
- list_reverse_iterator_prev(list_reverse_iterator_t *li)
- {
- if (*li)
- *li = (*li)->next;
- }
- void *
- list_reverse_iterator_get_datum(list_reverse_iterator_t *li)
- {
- return *li ? (*li)->datum : NULL;
- }
- bool
- list_reverse_iterator_is_valid(list_reverse_iterator_t *li)
- {
- return (li != NULL);
- }
- //======================================================================================================================================================150
- // OUTPUT AND UTILITIES
- //======================================================================================================================================================150
- /* */
- void *
- kmalloc(int size)
- {
- //printf("size: %d, current offset: %p\n",size,freeptr);
- void * r = (void *)freeptr;
- freeptr+=size;
- if(freeptr > malloc_size+(long)mem){
- printf("Memory Overflow\n");
- exit(1);
- }
- return r;
- }
- //transforms the current B+ Tree into a single, contiguous block of memory to be used on the GPU
- long
- transform_to_cuda( node * root,
- bool verbose)
- {
- struct timeval one,two;
- double time;
- gettimeofday (&one, NULL);
- long max_nodes = (long)(pow(order,log(size)/log(order/2.0)-1) + 1);
- malloc_size = size*sizeof(record) + max_nodes*sizeof(knode);
- mem = (char*)malloc(malloc_size);
- if(mem==NULL){
- printf("Initial malloc error\n");
- exit(1);
- }
- freeptr = (long)mem;
- krecords = (record * )kmalloc(size*sizeof(record));
- // printf("%d records\n", size);
- knodes = (knode *)kmalloc(max_nodes*sizeof(knode));
- // printf("%d knodes\n", max_nodes);
- queue = NULL;
- enqueue(root);
- node * n;
- knode * k;
- int i;
- long nodeindex = 0;
- long recordindex = 0;
- long queueindex = 0;
- knodes[0].location = nodeindex++;
-
- while( queue != NULL ) {
- n = dequeue();
- k = &knodes[queueindex];
- k->location = queueindex++;
- k->is_leaf = n->is_leaf;
- k->num_keys = n->num_keys+2;
- //start at 1 because 0 is set to INT_MIN
- k->keys[0]=INT_MIN;
- k->keys[k->num_keys-1]=INT_MAX;
- for(i=k->num_keys; i < order; i++)k->keys[i]=INT_MAX;
- if(!k->is_leaf){
- k->indices[0]=nodeindex++;
- // if(k->indices[0]>3953){
- // printf("ERROR: %d\n", k->indices[0]);
- // }
- for(i=1;i<k->num_keys-1;i++){
- k->keys[i] = n->keys[i-1];
- enqueue((node * )n->pointers[i-1]);
- k->indices[i] = nodeindex++;
- // if(k->indices[i]>3953){
- // printf("ERROR 1: %d\n", k->indices[i]);
- // }
- //knodes[nodeindex].location = nodeindex++;
- }
- //for final point of n
- enqueue((node * )n->pointers[i-1]);
- }
- else{
- k->indices[0]=0;
- for(i=1;i<k->num_keys-1;i++){
- k->keys[i] = n->keys[i-1];
- krecords[recordindex].value=((record *)n->pointers[i-1])->value;
- k->indices[i] = recordindex++;
- // if(k->indices[i]>3953){
- // printf("ERROR 2: %d\n", k->indices[i]);
- // }
- }
- }
-
- k->indices[k->num_keys-1]=queueindex;
- // if(k->indices[k->num_keys-1]>3953){
- // printf("ERROR 3: %d\n", k->indices[k->num_keys-1]);
- // }
- if(verbose){
- printf("Successfully created knode with index %d\n", k->location);
- printf("Is Leaf: %d, Num Keys: %d\n", k->is_leaf, k->num_keys);
- printf("Pointers: ");
- for(i=0;i<k->num_keys;i++)
- printf("%d | ", k->indices[i]);
- printf("\nKeys: ");
- for(i=0;i<k->num_keys;i++)
- printf("%d | ", k->keys[i]);
- printf("\n\n");
- }
- }
- long mem_used = size*sizeof(record)+(nodeindex)*sizeof(knode);
- if(verbose){
- for(i = 0; i < size; i++)
- printf("%d ", krecords[i].value);
- printf("\nNumber of records = %d, sizeof(record)=%d, total=%d\n",size,sizeof(record),size*sizeof(record));
- printf("Number of knodes = %d, sizeof(knode)=%d, total=%d\n",nodeindex,sizeof(knode),(nodeindex)*sizeof(knode));
- printf("\nDone Transformation. Mem used: %d\n", mem_used);
- }
- gettimeofday (&two, NULL);
- double oneD = one.tv_sec + (double)one.tv_usec * .000001;
- double twoD = two.tv_sec + (double)two.tv_usec * .000001;
- time = twoD-oneD;
- printf("Tree transformation took %f\n", time);
- return mem_used;
- }
- /* */
- list_t *
- findRange( node * root,
- int start,
- int end)
- {
- int i;
- node * c = find_leaf( root, start, false );
- if (c == NULL) return NULL;
-
- list_t * retList = (list_t *)malloc(sizeof(list_t));
- list_init(retList,NULL,NULL);
-
- int counter = 0;
- bool cont = true;
- while(cont && c!=0){
- cont = false;
- for(i = 0;i < c->num_keys;i++){
- if(c->keys[i] >= start && c->keys[i] <= end){
- //list_insert_tail(retList,(record *)c->pointers[i]);
- counter++;
- cont = true;
- }else{
- cont = false;
- break;
- }
- }
- c = (node *)c->pointers[order-1];
- }
- return retList;
- }
- /* First message to the user. */
- void
- usage_1( void )
- {
- printf("B+ Tree of Order %d.\n", order);
- printf("\tAmittai Aviram -- amittai.aviram@yale.edu Version %s\n", Version);
- printf("\tfollowing Silberschatz, Korth, Sidarshan, Database Concepts, 5th ed.\n\n");
- printf("To build a B+ tree of a different order, start again and enter the order\n");
- printf("as an integer argument: bpt <order>. ");
- printf("3 <= order <=20\n");
- printf("To start with input from a file of newline-delimited integers, start again and enter\n");
- printf("the order followed by the filename: bpt <order> <inputfile>.\n");
- }
- /* Second message to the user. */
- void
- usage_2( void )
- {
- printf("Enter any of the following commands after the prompt > :\n");
- printf("\ti <k> -- Insert <k> (an integer) as both key and value).\n");
- printf("\tf <k> -- Find the value under key <k>.\n");
- printf("\tp <k> -- Print the path from the root to key k and its associated value.\n");
- printf("\td <k> -- Delete key <k> and its associated value.\n");
- printf("\tx -- Destroy the whole tree. Start again with an empty tree of the same order.\n");
- printf("\tt -- Print the B+ tree.\n");
- printf("\tl -- Print the keys of the leaves (bottom row of the tree).\n");
- printf("\tv -- Toggle output of pointer addresses (\"verbose\") in tree and leaves.\n");
- printf("\tq -- Quit. (Or use Ctl-D.)\n");
- printf("\t? -- Print this help message.\n");
- }
- /* Helper function for printing the tree out. See print_tree. */
- void
- enqueue( node* new_node )
- {
- node * c;
- if (queue == NULL) {
- queue = new_node;
- queue->next = NULL;
- }
- else {
- c = queue;
- while(c->next != NULL) {
- c = c->next;
- }
- c->next = new_node;
- new_node->next = NULL;
- }
- }
- /* Helper function for printing the tree out. See print_tree. */
- node *
- dequeue( void )
- {
- node * n = queue;
- queue = queue->next;
- n->next = NULL;
- return n;
- }
- /* Prints the bottom row of keys of the tree (with their respective pointers, if the verbose_output flag is set. */
- void
- print_leaves( node* root )
- {
- int i;
- node * c = root;
- if (root == NULL) {
- printf("Empty tree.\n");
- return;
- }
- while (!c->is_leaf)
- c = (node *) c->pointers[0];
- while (true) {
- for (i = 0; i < c->num_keys; i++) {
- if (verbose_output)
- //printf("%x ", (unsigned int)c->pointers[i]);
- printf("%d ", c->keys[i]);
- }
- if (verbose_output)
- //printf("%x ", (unsigned int)c->pointers[order - 1]);
- if (c->pointers[order - 1] != NULL) {
- printf(" | ");
- c = (node *) c->pointers[order - 1];
- }
- else
- break;
- }
- printf("\n");
- }
- /* Utility function to give the height of the tree, which length in number of edges of the path from the root to any leaf. */
- int
- height( node* root )
- {
- int h = 0;
- node * c = root;
- while (!c->is_leaf) {
- c = (node *) c->pointers[0];
- h++;
- }
- return h;
- }
- /* Utility function to give the length in edges of the path from any node to the root. */
- int
- path_to_root( node* root, node* child )
- {
- int length = 0;
- node * c = child;
- while (c != root) {
- c = c->parent;
- length++;
- }
- return length;
- }
- /* Prints the B+ tree in the command line in level (rank) order, with the keys in each node and the '|' symbol to separate nodes. With the verbose_output flag set. the values of the pointers corresponding to the keys also appear next to their respective keys, in hexadecimal notation. */
- void
- print_tree( node* root )
- {
- node * n = NULL;
- int i = 0;
- int rank = 0;
- int new_rank = 0;
- if (root == NULL) {
- printf("Empty tree.\n");
- return;
- }
- queue = NULL;
- enqueue(root);
- while( queue != NULL ) {
- n = dequeue();
- if (n->parent != NULL && n == n->parent->pointers[0]) {
- new_rank = path_to_root( root, n );
- if (new_rank != rank) {
- rank = new_rank;
- printf("\n");
- }
- }
- if (verbose_output)
- printf("(%x)", n);
- for (i = 0; i < n->num_keys; i++) {
- if (verbose_output)
- printf("%x ", n->pointers[i]);
- printf("%d ", n->keys[i]);
- }
- if (!n->is_leaf)
- for (i = 0; i <= n->num_keys; i++)
- enqueue((node *) n->pointers[i]);
- if (verbose_output) {
- if (n->is_leaf)
- printf("%x ", n->pointers[order - 1]);
- else
- printf("%x ", n->pointers[n->num_keys]);
- }
- printf("| ");
- }
- printf("\n");
- }
- /* Traces the path from the root to a leaf, searching by key. Displays information about the path if the verbose flag is set. Returns the leaf containing the given key. */
- node *
- find_leaf( node* root, int key, bool verbose )
- {
- int i = 0;
- node * c = root;
- if (c == NULL) {
- if (verbose)
- printf("Empty tree.\n");
- return c;
- }
- while (!c->is_leaf) {
- if (verbose) {
- printf("[");
- for (i = 0; i < c->num_keys - 1; i++)
- printf("%d ", c->keys[i]);
- printf("%d] ", c->keys[i]);
- }
- i = 0;
- while (i < c->num_keys) {
- if (key >= c->keys[i])
- i++;
- else
- break;
- }
- if (verbose)
- printf("%d ->\n", i);
- c = (node *)c->pointers[i];
- }
- if (verbose) {
- printf("Leaf [");
- for (i = 0; i < c->num_keys - 1; i++)
- printf("%d ", c->keys[i]);
- printf("%d] ->\n", c->keys[i]);
- }
- return c;
- }
- /* Finds and returns the record to which a key refers. */
- record *
- find( node* root, int key, bool verbose )
- {
- int i = 0;
- node * c = find_leaf( root, key, verbose );
- if (c == NULL)
- return NULL;
- for (i = 0; i < c->num_keys; i++)
- if (c->keys[i] == key)
- break;
- if (i == c->num_keys)
- return NULL;
- else
- return (record *)c->pointers[i];
- }
- /* Finds the appropriate place to split a node that is too big into two. */
- int
- cut( int length )
- {
- if (length % 2 == 0)
- return length/2;
- else
- return length/2 + 1;
- }
- //======================================================================================================================================================150
- // INSERTION
- //======================================================================================================================================================150
- /* Creates a new record to hold the value to which a key refers. */
- record *
- make_record(int value)
- {
- record * new_record = (record *)malloc(sizeof(record));
- if (new_record == NULL) {
- perror("Record creation.");
- exit(EXIT_FAILURE);
- }
- else {
- new_record->value = value;
- }
- return new_record;
- }
- /* Creates a new general node, which can be adapted to serve as either a leaf or an internal node. */
- node *
- make_node( void )
- {
- node * new_node;
- new_node = (node *) malloc(sizeof(node));
- if (new_node == NULL) {
- perror("Node creation.");
- exit(EXIT_FAILURE);
- }
- new_node->keys = (int *) malloc( (order - 1) * sizeof(int) );
- if (new_node->keys == NULL) {
- perror("New node keys array.");
- exit(EXIT_FAILURE);
- }
- new_node->pointers = (void **) malloc( order * sizeof(void *) );
- if (new_node->pointers == NULL) {
- perror("New node pointers array.");
- exit(EXIT_FAILURE);
- }
- new_node->is_leaf = false;
- new_node->num_keys = 0;
- new_node->parent = NULL;
- new_node->next = NULL;
- return new_node;
- }
- /* Creates a new leaf by creating a node and then adapting it appropriately. */
- node *
- make_leaf( void )
- {
- node* leaf = make_node();
- leaf->is_leaf = true;
- return leaf;
- }
- /* Helper function used in insert_into_parent to find the index of the parent's pointer to the node to the left of the key to be inserted. */
- int
- get_left_index(node* parent, node* left)
- {
- int left_index = 0;
- while (left_index <= parent->num_keys &&
- parent->pointers[left_index] != left)
- left_index++;
- return left_index;
- }
- /* Inserts a new pointer to a record and its corresponding key into a leaf. Returns the altered leaf. */
- node *
- insert_into_leaf( node* leaf, int key, record* pointer )
- {
- int i, insertion_point;
- insertion_point = 0;
- while (insertion_point < leaf->num_keys && leaf->keys[insertion_point] < key)
- insertion_point++;
- for (i = leaf->num_keys; i > insertion_point; i--) {
- leaf->keys[i] = leaf->keys[i - 1];
- leaf->pointers[i] = leaf->pointers[i - 1];
- }
- leaf->keys[insertion_point] = key;
- leaf->pointers[insertion_point] = pointer;
- leaf->num_keys++;
- return leaf;
- }
- /* Inserts a new key and pointer to a new record into a leaf so as to exceed the tree's order, causing the leaf to be split in half. */
- node *
- insert_into_leaf_after_splitting( node* root,
- node* leaf,
- int key,
- record* pointer)
- {
- node * new_leaf;
- int * temp_keys;
- void ** temp_pointers;
- int insertion_index, split, new_key, i, j;
- new_leaf = make_leaf();
- temp_keys = (int *) malloc( order * sizeof(int) );
- if (temp_keys == NULL) {
- perror("Temporary keys array.");
- exit(EXIT_FAILURE);
- }
- temp_pointers = (void **) malloc( order * sizeof(void *) );
- if (temp_pointers == NULL) {
- perror("Temporary pointers array.");
- exit(EXIT_FAILURE);
- }
- insertion_index = 0;
- while (leaf->keys[insertion_index] < key && insertion_index < order - 1)
- insertion_index++;
- for (i = 0, j = 0; i < leaf->num_keys; i++, j++) {
- if (j == insertion_index) j++;
- temp_keys[j] = leaf->keys[i];
- temp_pointers[j] = leaf->pointers[i];
- }
- temp_keys[insertion_index] = key;
- temp_pointers[insertion_index] = pointer;
- leaf->num_keys = 0;
- split = cut(order - 1);
- for (i = 0; i < split; i++) {
- leaf->pointers[i] = temp_pointers[i];
- leaf->keys[i] = temp_keys[i];
- leaf->num_keys++;
- }
- for (i = split, j = 0; i < order; i++, j++) {
- new_leaf->pointers[j] = temp_pointers[i];
- new_leaf->keys[j] = temp_keys[i];
- new_leaf->num_keys++;
- }
- free(temp_pointers);
- free(temp_keys);
- new_leaf->pointers[order - 1] = leaf->pointers[order - 1];
- leaf->pointers[order - 1] = new_leaf;
- for (i = leaf->num_keys; i < order - 1; i++)
- leaf->pointers[i] = NULL;
- for (i = new_leaf->num_keys; i < order - 1; i++)
- new_leaf->pointers[i] = NULL;
- new_leaf->parent = leaf->parent;
- new_key = new_leaf->keys[0];
- return insert_into_parent(root, leaf, new_key, new_leaf);
- }
- /* Inserts a new key and pointer to a node into a node into which these can fit without violating the B+ tree properties. */
- node *
- insert_into_node( node* root,
- node* n,
- int left_index,
- int key,
- node* right)
- {
- int i;
- for (i = n->num_keys; i > left_index; i--) {
- n->pointers[i + 1] = n->pointers[i];
- n->keys[i] = n->keys[i - 1];
- }
- n->pointers[left_index + 1] = right;
- n->keys[left_index] = key;
- n->num_keys++;
- return root;
- }
- /* Inserts a new key and pointer to a node into a node, causing the node's size to exceed the order, and causing the node to split into two. */
- node *
- insert_into_node_after_splitting( node* root,
- node* old_node,
- int left_index,
- int key,
- node * right)
- {
- int i, j, split, k_prime;
- node * new_node, * child;
- int * temp_keys;
- node ** temp_pointers;
- /* First create a temporary set of keys and pointers
- * to hold everything in order, including
- * the new key and pointer, inserted in their
- * correct places.
- * Then create a new node and copy half of the
- * keys and pointers to the old node and
- * the other half to the new.
- */
- temp_pointers = (node **) malloc( (order + 1) * sizeof(node *) );
- if (temp_pointers == NULL) {
- perror("Temporary pointers array for splitting nodes.");
- exit(EXIT_FAILURE);
- }
- temp_keys = (int *) malloc( order * sizeof(int) );
- if (temp_keys == NULL) {
- perror("Temporary keys array for splitting nodes.");
- exit(EXIT_FAILURE);
- }
- for (i = 0, j = 0; i < old_node->num_keys + 1; i++, j++) {
- if (j == left_index + 1) j++;
- temp_pointers[j] = (node *) old_node->pointers[i];
- }
- for (i = 0, j = 0; i < old_node->num_keys; i++, j++) {
- if (j == left_index) j++;
- temp_keys[j] = old_node->keys[i];
- }
- temp_pointers[left_index + 1] = right;
- temp_keys[left_index] = key;
- /* Create the new node and copy
- * half the keys and pointers to the
- * old and half to the new.
- */
- split = cut(order);
- new_node = make_node();
- old_node->num_keys = 0;
- for (i = 0; i < split - 1; i++) {
- old_node->pointers[i] = temp_pointers[i];
- old_node->keys[i] = temp_keys[i];
- old_node->num_keys++;
- }
- old_node->pointers[i] = temp_pointers[i];
- k_prime = temp_keys[split - 1];
- for (++i, j = 0; i < order; i++, j++) {
- new_node->pointers[j] = temp_pointers[i];
- new_node->keys[j] = temp_keys[i];
- new_node->num_keys++;
- }
- new_node->pointers[j] = temp_pointers[i];
- free(temp_pointers);
- free(temp_keys);
- new_node->parent = old_node->parent;
- for (i = 0; i <= new_node->num_keys; i++) {
- child = (node *) new_node->pointers[i];
- child->parent = new_node;
- }
- /* Insert a new key into the parent of the two
- * nodes resulting from the split, with
- * the old node to the left and the new to the right.
- */
- return insert_into_parent(root, old_node, k_prime, new_node);
- }
- /* Inserts a new node (leaf or internal node) into the B+ tree. Returns the root of the tree after insertion. */
- node *
- insert_into_parent( node* root,
- node* left,
- int key,
- node* right)
- {
- int left_index;
- node * parent;
- parent = left->parent;
- /* Case: new root. */
- if (parent == NULL)
- return insert_into_new_root(left, key, right);
- /* Case: leaf or node. (Remainder of
- * function body.)
- */
- /* Find the parent's pointer to the left
- * node.
- */
- left_index = get_left_index(parent, left);
- /* Simple case: the new key fits into the node.
- */
- if (parent->num_keys < order - 1)
- return insert_into_node(root, parent, left_index, key, right);
- /* Harder case: split a node in order
- * to preserve the B+ tree properties.
- */
- return insert_into_node_after_splitting(root, parent, left_index, key, right);
- }
- /* Creates a new root for two subtrees and inserts the appropriate key into the new root. */
- node *
- insert_into_new_root( node* left,
- int key,
- node* right)
- {
- node * root = make_node();
- root->keys[0] = key;
- root->pointers[0] = left;
- root->pointers[1] = right;
- root->num_keys++;
- root->parent = NULL;
- left->parent = root;
- right->parent = root;
- return root;
- }
- /* First insertion: start a new tree. */
- node *
- start_new_tree( int key,
- record* pointer)
- {
- node * root = make_leaf();
- root->keys[0] = key;
- root->pointers[0] = pointer;
- root->pointers[order - 1] = NULL;
- root->parent = NULL;
- root->num_keys++;
- return root;
- }
- /* Master insertion function. Inserts a key and an associated value into the B+ tree, causing the tree to be adjusted however necessary to maintain the B+ tree properties. */
- node *
- insert( node* root,
- int key,
- int value )
- {
- record* pointer;
- node* leaf;
- /* The current implementation ignores duplicates. */
- if (find(root, key, false) != NULL)
- return root;
- /* Create a new record for the value. */
- pointer = make_record(value);
- /* Case: the tree does not exist yet. Start a new tree. */
- if (root == NULL)
- return start_new_tree(key, pointer);
- /* Case: the tree already exists. (Rest of function body.) */
- leaf = find_leaf(root, key, false);
- /* Case: leaf has room for key and pointer. */
- if (leaf->num_keys < order - 1) {
- leaf = insert_into_leaf(leaf, key, pointer);
- return root;
- }
- /* Case: leaf must be split. */
- return insert_into_leaf_after_splitting(root, leaf, key, pointer);
- }
- //======================================================================================================================================================150
- // DELETION
- //======================================================================================================================================================150
- /* Utility function for deletion. Retrieves the index of a node's nearest neighbor (sibling) to the left if one exists. If not (the node is the leftmost child), returns -1 to signify this special case. */
- int
- get_neighbor_index( node* n )
- {
- int i;
- /* Return the index of the key to the left
- * of the pointer in the parent pointing
- * to n.
- * If n is the leftmost child, this means
- * return -1.
- */
- for (i = 0; i <= n->parent->num_keys; i++)
- if (n->parent->pointers[i] == n)
- return i - 1;
- // Error state.
- printf("Search for nonexistent pointer to node in parent.\n");
- //printf("Node: %#x\n", (unsigned int)n);
- exit(EXIT_FAILURE);
- }
- /* */
- node*
- remove_entry_from_node( node* n,
- int key,
- node * pointer)
- {
- int i, num_pointers;
- // Remove the key and shift other keys accordingly.
- i = 0;
- while (n->keys[i] != key)
- i++;
- for (++i; i < n->num_keys; i++)
- n->keys[i - 1] = n->keys[i];
- // Remove the pointer and shift other pointers accordingly.
- // First determine number of pointers.
- num_pointers = n->is_leaf ? n->num_keys : n->num_keys + 1;
- i = 0;
- while (n->pointers[i] != pointer)
- i++;
- for (++i; i < num_pointers; i++)
- n->pointers[i - 1] = n->pointers[i];
- // One key fewer.
- n->num_keys--;
- // Set the other pointers to NULL for tidiness.
- // A leaf uses the last pointer to point to the next leaf.
- if (n->is_leaf)
- for (i = n->num_keys; i < order - 1; i++)
- n->pointers[i] = NULL;
- else
- for (i = n->num_keys + 1; i < order; i++)
- n->pointers[i] = NULL;
- return n;
- }
- /* */
- node*
- adjust_root(node* root)
- {
- node * new_root;
- /* Case: nonempty root.
- * Key and pointer have already been deleted,
- * so nothing to be done.
- */
- if (root->num_keys > 0)
- return root;
- /* Case: empty root.
- */
- // If it has a child, promote
- // the first (only) child
- // as the new root.
- if (!root->is_leaf) {
- new_root = (node *) root->pointers[0];
- new_root->parent = NULL;
- }
- // If it is a leaf (has no children),
- // then the whole tree is empty.
- else
- new_root = NULL;
- free(root->keys);
- free(root->pointers);
- free(root);
- return new_root;
- }
- /* Coalesces a node that has become too small after deletion with a neighboring node that can accept the additional entries without exceeding the maximum. */
- node*
- coalesce_nodes( node* root,
- node* n,
- node* neighbor,
- int neighbor_index,
- int k_prime)
- {
- int i, j, neighbor_insertion_index, n_start, n_end, new_k_prime;
- node * tmp;
- bool split;
- /* Swap neighbor with node if node is on the
- * extreme left and neighbor is to its right.
- */
- if (neighbor_index == -1) {
- tmp = n;
- n = neighbor;
- neighbor = tmp;
- }
- /* Starting point in the neighbor for copying
- * keys and pointers from n.
- * Recall that n and neighbor have swapped places
- * in the special case of n being a leftmost child.
- */
- neighbor_insertion_index = neighbor->num_keys;
-
- /*
- * Nonleaf nodes may sometimes need to remain split,
- * if the insertion of k_prime would cause the resulting
- * single coalesced node to exceed the limit order - 1.
- * The variable split is always false for leaf nodes
- * and only sometimes set to true for nonleaf nodes.
- */
- split = false;
- /* Case: nonleaf node.
- * Append k_prime and the following pointer.
- * If there is room in the neighbor, append
- * all pointers and keys from the neighbor.
- * Otherwise, append only cut(order) - 2 keys and
- * cut(order) - 1 pointers.
- */
- if (!n->is_leaf) {
- /* Append k_prime.
- */
- neighbor->keys[neighbor_insertion_index] = k_prime;
- neighbor->num_keys++;
- /* Case (default): there is room for all of n's keys and pointers
- * in the neighbor after appending k_prime.
- */
- n_end = n->num_keys;
- /* Case (special): k cannot fit with all the other keys and pointers
- * into one coalesced node.
- */
- n_start = 0; // Only used in this special case.
- if (n->num_keys + neighbor->num_keys >= order) {
- split = true;
- n_end = cut(order) - 2;
- }
- for (i = neighbor_insertion_index + 1, j = 0; j < n_end; i++, j++) {
- neighbor->keys[i] = n->keys[j];
- neighbor->pointers[i] = n->pointers[j];
- neighbor->num_keys++;
- n->num_keys--;
- n_start++;
- }
- /* The number of pointers is always
- * one more than the number of keys.
- */
- neighbor->pointers[i] = n->pointers[j];
- /* If the nodes are still split, remove the first key from
- * n.
- */
- if (split) {
- new_k_prime = n->keys[n_start];
- for (i = 0, j = n_start + 1; i < n->num_keys; i++, j++) {
- n->keys[i] = n->keys[j];
- n->pointers[i] = n->pointers[j];
- }
- n->pointers[i] = n->pointers[j];
- n->num_keys--;
- }
- /* All children must now point up to the same parent.
- */
- for (i = 0; i < neighbor->num_keys + 1; i++) {
- tmp = (node *)neighbor->pointers[i];
- tmp->parent = neighbor;
- }
- }
- /* In a leaf, append the keys and pointers of
- * n to the neighbor.
- * Set the neighbor's last pointer to point to
- * what had been n's right neighbor.
- */
- else {
- for (i = neighbor_insertion_index, j = 0; j < n->num_keys; i++, j++) {
- neighbor->keys[i] = n->keys[j];
- neighbor->pointers[i] = n->pointers[j];
- neighbor->num_keys++;
- }
- neighbor->pointers[order - 1] = n->pointers[order - 1];
- }
- if (!split) {
- root = delete_entry(root, n->parent, k_prime, n);
- free(n->keys);
- free(n->pointers);
- free(n);
- }
- else
- for (i = 0; i < n->parent->num_keys; i++)
- if (n->parent->pointers[i + 1] == n) {
- n->parent->keys[i] = new_k_prime;
- break;
- }
- return root;
- }
- /* Redistributes entries between two nodes when one has become too small after deletion but its neighbor is too big to append the small node's entries without exceeding the maximum */
- node*
- redistribute_nodes( node* root,
- node* n,
- node* neighbor,
- int neighbor_index,
- int k_prime_index,
- int k_prime)
- {
- int i;
- node * tmp;
- /* Case: n has a neighbor to the left.
- * Pull the neighbor's last key-pointer pair over
- * from the neighbor's right end to n's left end.
- */
- if (neighbor_index != -1) {
- if (!n->is_leaf)
- n->pointers[n->num_keys + 1] = n->pointers[n->num_keys];
- for (i = n->num_keys; i > 0; i--) {
- n->keys[i] = n->keys[i - 1];
- n->pointers[i] = n->pointers[i - 1];
- }
- if (!n->is_leaf) {
- n->pointers[0] = neighbor->pointers[neighbor->num_keys];
- tmp = (node *)n->pointers[0];
- tmp->parent = n;
- neighbor->pointers[neighbor->num_keys] = NULL;
- n->keys[0] = k_prime;
- n->parent->keys[k_prime_index] = neighbor->keys[neighbor->num_keys - 1];
- }
- else {
- n->pointers[0] = neighbor->pointers[neighbor->num_keys - 1];
- neighbor->pointers[neighbor->num_keys - 1] = NULL;
- n->keys[0] = neighbor->keys[neighbor->num_keys - 1];
- n->parent->keys[k_prime_index] = n->keys[0];
- }
- }
- /* Case: n is the leftmost child.
- * Take a key-pointer pair from the neighbor to the right.
- * Move the neighbor's leftmost key-pointer pair
- * to n's rightmost position.
- */
- else {
- if (n->is_leaf) {
- n->keys[n->num_keys] = neighbor->keys[0];
- n->pointers[n->num_keys] = neighbor->pointers[0];
- n->parent->keys[k_prime_index] = neighbor->keys[1];
- }
- else {
- n->keys[n->num_keys] = k_prime;
- n->pointers[n->num_keys + 1] = neighbor->pointers[0];
- tmp = (node *)n->pointers[n->num_keys + 1];
- tmp->parent = n;
- n->parent->keys[k_prime_index] = neighbor->keys[0];
- }
- for (i = 0; i < neighbor->num_keys; i++) {
- neighbor->keys[i] = neighbor->keys[i + 1];
- neighbor->pointers[i] = neighbor->pointers[i + 1];
- }
- if (!n->is_leaf)
- neighbor->pointers[i] = neighbor->pointers[i + 1];
- }
- /* n now has one more key and one more pointer;
- * the neighbor has one fewer of each.
- */
- n->num_keys++;
- neighbor->num_keys--;
- return root;
- }
- /* Deletes an entry from the B+ tree. Removes the record and its key and pointer from the leaf, and then makes all appropriate changes to preserve the B+ tree properties. */
- node*
- delete_entry( node* root,
- node* n,
- int key,
- void* pointer )
- {
- int min_keys;
- node * neighbor;
- int neighbor_index;
- int k_prime_index, k_prime;
- int capacity;
- // Remove key and pointer from node.
- n = remove_entry_from_node(n, key, (node *) pointer);
- /* Case: deletion from the root.
- */
- if (n == root)
- return adjust_root(root);
- /* Case: deletion from a node below the root.
- * (Rest of function body.)
- */
- /* Determine minimum allowable size of node,
- * to be preserved after deletion.
- */
- min_keys = n->is_leaf ? cut(order - 1) : cut(order) - 1;
- /* Case: node stays at or above minimum.
- * (The simple case.)
- */
- if (n->num_keys >= min_keys)
- return root;
- /* Case: node falls below minimum.
- * Either coalescence or redistribution
- * is needed.
- */
- /* Find the appropriate neighbor node with which
- * to coalesce.
- * Also find the key (k_prime) in the parent
- * between the pointer to node n and the pointer
- * to the neighbor.
- */
- neighbor_index = get_neighbor_index( n );
- k_prime_index = neighbor_index == -1 ? 0 : neighbor_index;
- k_prime = n->parent->keys[k_prime_index];
- neighbor = neighbor_index == -1 ? (node *) n->parent->pointers[1] :
- (node *)n->parent->pointers[neighbor_index];
- capacity = n->is_leaf ? order : order - 1;
- /* Coalescence. */
- if (neighbor->num_keys + n->num_keys < capacity)
- return coalesce_nodes(root, n, neighbor, neighbor_index, k_prime);
- /* Redistribution. */
- else
- return redistribute_nodes(root, n, neighbor, neighbor_index, k_prime_index, k_prime);
- }
- /* Master deletion function. */
- node*
- deleteVal( node* root,
- int key)
- {
- node * key_leaf;
- record * key_record;
- key_record = find(root, key, false);
- key_leaf = find_leaf(root, key, false);
- if (key_record != NULL && key_leaf != NULL) {
- free(key_record);
- root = delete_entry(root, key_leaf, key, key_record);
- }
- return root;
- }
- /* */
- void
- destroy_tree_nodes(node* root)
- {
- int i;
- if (root->is_leaf)
- for (i = 0; i < root->num_keys; i++)
- free(root->pointers[i]);
- else
- for (i = 0; i < root->num_keys + 1; i++)
- destroy_tree_nodes((node *) root->pointers[i]);
- free(root->pointers);
- free(root->keys);
- free(root);
- }
- /* */
- node*
- destroy_tree(node* root)
- {
- destroy_tree_nodes(root);
- return NULL;
- }
- //======================================================================================================================================================150
- // END
- //======================================================================================================================================================150
- //========================================================================================================================================================================================================200
- // MAIN FUNCTION
- //========================================================================================================================================================================================================200
- int
- main( int argc,
- char** argv )
- {
- printf("WG size of kernel 1 = %d WG size of kernel 2 = %d \n", DEFAULT_ORDER, DEFAULT_ORDER_2);
- // ------------------------------------------------------------60
- // figure out and display whether 32-bit or 64-bit architecture
- // ------------------------------------------------------------60
- // if(sizeof(int *)==8){
- // printf("64 bit machine\n");
- // }
- // else if(sizeof(int *)==4){
- // printf("32 bit machine\n");
- // }
- // ------------------------------------------------------------60
- // read inputs
- // ------------------------------------------------------------60
- // assing default values
- int cur_arg;
- int arch_arg;
- arch_arg = 0;
- int cores_arg;
- cores_arg = 1;
- char *input_file = NULL;
- char *command_file = NULL;
- char *output="output.txt";
- FILE * pFile;
- // go through arguments
- for(cur_arg=1; cur_arg<argc; cur_arg++){
- // check if -file
- if(strcmp(argv[cur_arg], "file")==0){
- // check if value provided
- if(argc>=cur_arg+1){
- input_file = argv[cur_arg+1];
- cur_arg = cur_arg+1;
- // value is not a number
- }
- // value not provided
- else{
- printf("ERROR: Missing value to -file parameter\n");
- return -1;
- }
- }
- else if(strcmp(argv[cur_arg], "command")==0){
- // check if value provided
- if(argc>=cur_arg+1){
- command_file = argv[cur_arg+1];
- cur_arg = cur_arg+1;
- // value is not a number
- }
- // value not provided
- else{
- printf("ERROR: Missing value to command parameter\n");
- return -1;
- }
- }
- }
- // Print configuration
- if((input_file==NULL)||(command_file==NULL))
- printf("Usage: ./b+tree file input_file command command_list\n");
- // For debug
- printf("Input File: %s \n", input_file);
- printf("Command File: %s \n", command_file);
- FILE * commandFile;
- long lSize;
- char * commandBuffer;
- size_t result;
- commandFile = fopen ( command_file, "rb" );
- if (commandFile==NULL) {fputs ("Command File error",stderr); exit (1);}
-
- // obtain file size:
- fseek (commandFile , 0 , SEEK_END);
- lSize = ftell (commandFile);
- rewind (commandFile);
- // allocate memory to contain the whole file:
- commandBuffer = (char*) malloc (sizeof(char)*lSize);
- if (commandBuffer == NULL) {fputs ("Command Buffer memory error",stderr); exit (2);}
-
- // copy the file into the buffer:
- result = fread (commandBuffer,1,lSize,commandFile);
- if (result != lSize) {fputs ("Command file reading error",stderr); exit (3);}
- /* the whole file is now loaded in the memory buffer. */
- // terminate
- fclose (commandFile);
- // For Debug
- char *sPointer=commandBuffer;
- printf("Command Buffer: \n");
- printf("%s",commandBuffer);
- //
- pFile = fopen (output,"w+");
- if (pFile==NULL)
- fputs ("Fail to open %s !\n",output);
- fprintf(pFile,"******starting******\n");
- fclose(pFile);
- // ------------------------------------------------------------60
- // general variables
- // ------------------------------------------------------------60
- FILE *file_pointer;
- node *root;
- root = NULL;
- record *r;
- int input;
- char instruction;
- order = DEFAULT_ORDER_2;
- verbose_output = false;
- //usage_1();
- //usage_2();
- // ------------------------------------------------------------60
- // get input from file, if file provided
- // ------------------------------------------------------------60
- if (input_file != NULL) {
- printf("Getting input from file %s...\n", argv[1]);
- // open input file
- file_pointer = fopen(input_file, "r");
- if (file_pointer == NULL) {
- perror("Failure to open input file.");
- exit(EXIT_FAILURE);
- }
- // get # of numbers in the file
- fscanf(file_pointer, "%d\n", &input);
- size = input;
- // save all numbers
- while (!feof(file_pointer)) {
- fscanf(file_pointer, "%d\n", &input);
- root = insert(root, input, input);
- }
- // close file
- fclose(file_pointer);
- //print_tree(root);
- //printf("Height of tree = %d\n", height(root));
- }
- else{
- printf("ERROR: Argument -file missing\n");
- return 0;
- }
- // ------------------------------------------------------------60
- // get tree statistics
- // ------------------------------------------------------------60
- printf("Transforming data to a GPU suitable structure...\n");
- long mem_used = transform_to_cuda(root,0);
- maxheight = height(root);
- long rootLoc = (long)knodes - (long)mem;
- // ------------------------------------------------------------60
- // process commands
- // ------------------------------------------------------------60
- char *commandPointer=commandBuffer;
- printf("Waiting for command\n");
- printf("> ");
- while (sscanf(commandPointer, "%c", &instruction) != EOF) {
- commandPointer++;
- switch (instruction) {
- // ----------------------------------------40
- // Insert
- // ----------------------------------------40
- case 'i':
- {
- scanf("%d", &input);
- while (getchar() != (int)'\n');
- root = insert(root, input, input);
- print_tree(root);
- break;
- }
- // ----------------------------------------40
- // n/a
- // ----------------------------------------40
- case 'f':
- {
- }
- // ----------------------------------------40
- // find
- // ----------------------------------------40
- case 'p':
- {
- scanf("%d", &input);
- while (getchar() != (int)'\n');
- r = find(root, input, instruction == 'p');
- if (r == NULL)
- printf("Record not found under key %d.\n", input);
- else
- printf("Record found: %d\n",r->value);
- break;
- }
- // ----------------------------------------40
- // delete value
- // ----------------------------------------40
- case 'd':
- {
- scanf("%d", &input);
- while (getchar() != (int)'\n');
- root = (node *) deleteVal(root, input);
- print_tree(root);
- break;
- }
- // ----------------------------------------40
- // destroy tree
- // ----------------------------------------40
- case 'x':
- {
- while (getchar() != (int)'\n');
- root = destroy_tree(root);
- print_tree(root);
- break;
- }
- // ----------------------------------------40
- // print leaves
- // ----------------------------------------40
- case 'l':
- {
- while (getchar() != (int)'\n');
- print_leaves(root);
- break;
- }
- // ----------------------------------------40
- // print tree
- // ----------------------------------------40
- case 't':
- {
- while (getchar() != (int)'\n');
- print_tree(root);
- break;
- }
- // ----------------------------------------40
- // toggle verbose output
- // ----------------------------------------40
- case 'v':
- {
- while (getchar() != (int)'\n');
- verbose_output = !verbose_output;
- break;
- }
- // ----------------------------------------40
- // quit
- // ----------------------------------------40
- case 'q':
- {
- while (getchar() != (int)'\n');
- return EXIT_SUCCESS;
- }
- // ----------------------------------------40
- // [GPU] find K (initK, findK)
- // ----------------------------------------40
- case 'k':
- {
- // get # of queries from user
- int count;
- sscanf(commandPointer, "%d", &count);
- while(*commandPointer!=32 && commandPointer!='\n')
- commandPointer++;
- printf("\n ******command: k count=%d \n",count);
- if(count > 65535){
- printf("ERROR: Number of requested querries should be 65,535 at most. (limited by # of CUDA blocks)\n");
- exit(0);
- }
- // INPUT: records CPU allocation (setting pointer in mem variable)
- record *records = (record *)mem;
- long records_elem = (long)rootLoc / sizeof(record);
- long records_mem = (long)rootLoc;
- printf("records_elem=%d, records_unit_mem=%d, records_mem=%d\n", (int)records_elem, (int)sizeof(record), (int)records_mem);
- // INPUT: knodes CPU allocation (setting pointer in mem variable)
- knode *knodes = (knode *)((long)mem + (long)rootLoc);
- long knodes_elem = ((long)(mem_used) - (long)rootLoc) / sizeof(knode);
- long knodes_mem = (long)(mem_used) - (long)rootLoc;
- printf("knodes_elem=%d, knodes_unit_mem=%d, knodes_mem=%d\n", (int)knodes_elem, (int)sizeof(knode), (int)knodes_mem);
- // INPUT: currKnode CPU allocation
- long *currKnode;
- currKnode = (long *)malloc(count*sizeof(long));
- // INPUT: offset CPU initialization
- memset(currKnode, 0, count*sizeof(long));
- // INPUT: offset CPU allocation
- long *offset;
- offset = (long *)malloc(count*sizeof(long));
- // INPUT: offset CPU initialization
- memset(offset, 0, count*sizeof(long));
- // INPUT: keys CPU allocation
- int *keys;
- keys = (int *)malloc(count*sizeof(int));
- // INPUT: keys CPU initialization
- int i;
- for(i = 0; i < count; i++){
- keys[i] = (rand()/(float)RAND_MAX)*size;
- }
- // OUTPUT: ans CPU allocation
- record *ans = (record *)malloc(sizeof(record)*count);
- // OUTPUT: ans CPU initialization
- for(i = 0; i < count; i++){
- ans[i].value = -1;
- }
- // OpenCL kernel
- kernel_gpu_opencl_wrapper( records,
- records_mem,
- knodes,
- knodes_elem,
- knodes_mem,
- order,
- maxheight,
- count,
- currKnode,
- offset,
- keys,
- ans);
- pFile = fopen (output,"aw+");
- if (pFile==NULL)
- {
- fputs ("Fail to open %s !\n",output);
- }
-
- fprintf(pFile,"\n ******command: k count=%d \n",count);
- for(i = 0; i < count; i++){
- fprintf(pFile, "%d %d\n",i, ans[i].value);
- }
- fprintf(pFile, " \n");
- fclose(pFile);
-
- // free memory
- free(currKnode);
- free(offset);
- free(keys);
- free(ans);
- // break out of case
- break;
- }
- // ----------------------------------------40
- // find range
- // ----------------------------------------40
- case 'r':
- {
- int start, end;
- scanf("%d", &start);
- scanf("%d", &end);
- if(start > end){
- input = start;
- start = end;
- end = input;
- }
- printf("For range %d to %d, ",start,end);
- list_t * ansList;
- ansList = findRange(root, start, end);
- printf("%d records found\n", list_get_length(ansList));
- //list_iterator_t iter;
- free(ansList);
- break;
- }
- // ----------------------------------------40
- // [GPU] find Range K (initK, findRangeK)
- // ----------------------------------------40
- case 'j':
- {
- // get # of queries from user
- int count;
- sscanf(commandPointer, "%d", &count);
- while(*commandPointer!=32 && commandPointer!='\n')
- commandPointer++;
- int rSize;
- sscanf(commandPointer, "%d", &rSize);
- while(*commandPointer!=32 && commandPointer!='\n')
- commandPointer++;
- printf("\n******command: j count=%d, rSize=%d \n",count, rSize);
- if(rSize > size || rSize < 0) {
- printf("Search range size is larger than data set size %d.\n", (int)size);
- exit(0);
- }
- // INPUT: knodes CPU allocation (setting pointer in mem variable)
- knode *knodes = (knode *)((long)mem + (long)rootLoc);
- long knodes_elem = ((long)(mem_used) - (long)rootLoc) / sizeof(knode);
- long knodes_mem = (long)(mem_used) - (long)rootLoc;
- printf("knodes_elem=%d, knodes_unit_mem=%d, knodes_mem=%d\n", (int)knodes_elem, (int)sizeof(knode), (int)knodes_mem);
- // INPUT: currKnode CPU allocation
- long *currKnode;
- currKnode = (long *)malloc(count*sizeof(long));
- // INPUT: offset CPU initialization
- memset (currKnode, 0, count*sizeof(long));
- // INPUT: offset CPU allocation
- long *offset;
- offset = (long *)malloc(count*sizeof(long));
- // INPUT: offset CPU initialization
- memset (offset, 0, count*sizeof(long));
- // INPUT: lastKnode CPU allocation
- long *lastKnode;
- lastKnode = (long *)malloc(count*sizeof(long));
- // INPUT: offset CPU initialization
- memset (lastKnode, 0, count*sizeof(long));
- // INPUT: offset_2 CPU allocation
- long *offset_2;
- offset_2 = (long *)malloc(count*sizeof(long));
- // INPUT: offset CPU initialization
- memset (offset_2, 0, count*sizeof(long));
- // INPUT: start, end CPU allocation
- int *start;
- start = (int *)malloc(count*sizeof(int));
- int *end;
- end = (int *)malloc(count*sizeof(int));
- // INPUT: start, end CPU initialization
- int i;
- for(i = 0; i < count; i++){
- start[i] = (rand()/(float)RAND_MAX)*size;
- end[i] = start[i]+rSize;
- if(end[i] >= size){
- start[i] = start[i] - (end[i] - size);
- end[i]= size-1;
- }
- }
- // INPUT: recstart, reclenght CPU allocation
- int *recstart;
- recstart = (int *)malloc(count*sizeof(int));
- int *reclength;
- reclength = (int *)malloc(count*sizeof(int));
- // OUTPUT: ans CPU initialization
- for(i = 0; i < count; i++){
- recstart[i] = 0;
- reclength[i] = 0;
- }
- // CUDA kernel
- kernel_gpu_opencl_wrapper_2(knodes,
- knodes_elem,
- knodes_mem,
- order,
- maxheight,
- count,
- currKnode,
- offset,
- lastKnode,
- offset_2,
- start,
- end,
- recstart,
- reclength);
-
- pFile = fopen (output,"aw+");
- if (pFile==NULL)
- {
- fputs ("Fail to open %s !\n",output);
- }
- fprintf(pFile,"\n******command: j count=%d, rSize=%d \n",count, rSize);
- for(i = 0; i < count; i++){
- fprintf(pFile, "%d %d %d\n",i, recstart[i],reclength[i]);
- }
- fprintf(pFile, " \n");
- fclose(pFile);
- // free memory
- free(currKnode);
- free(offset);
- free(lastKnode);
- free(offset_2);
- free(start);
- free(end);
- free(recstart);
- free(reclength);
- // break out of case
- break;
- }
- // ----------------------------------------40
- // default
- // ----------------------------------------40
- default:
- {
- //usage_2();
- break;
- }
- }
- printf("> ");
- }
- printf("\n");
- // ------------------------------------------------------------60
- // free remaining memory and exit
- // ------------------------------------------------------------60
- free(mem);
- return EXIT_SUCCESS;
- }
- //========================================================================================================================================================================================================200
- // END
- //========================================================================================================================================================================================================200
- // # ifdef __cplusplus
- // }
- // # endif
|