/* Copyright 2010 Nathan Phillip Brink, Ethan Zonca, Matthew Orlando This file is a part of DistRen. DistRen is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. DistRen is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with DistRen. If not, see . */ #include "common/config.h" #include "user_mgr.h" #include "common/asprintf.h" #include #include #include #include #include #include #include #include #include #include #include struct user_mgr_info { struct user *user_array; int current_users; int user_array_size; } user_mgr_info; int resize_user_array() { int counter; int counter2; // create array twice the size of the current amount of users user_mgr_info.user_array_size = user_mgr_info.current_users * 2; struct user *new_user_array = malloc(sizeof(struct user) * user_mgr_info.user_array_size); // this copies the original user_array over to the new one // using two counters allows the array to be resized at any time // leaving exactly 1 open space between each user when it is done; counter2 = 0; for(counter = 0; counter < user_mgr_info.current_users; counter++) { if(user_mgr_info.user_array[counter].username != 0) { new_user_array[counter2*2] = user_mgr_info.user_array[counter]; counter2++; } } // cleanup old array free(user_mgr_info.user_array); // change the pointer to point to the new user array user_mgr_info.user_array = new_user_array; return 1; } struct user *findUser(char *nameOfUser) { int high; int low; int middle; int result; high = user_mgr_info.user_array_size - 1; low = 0; result = -1; for(middle = (low+high)/2; 1 == 1; middle = (low+high)/2) { // in case middle lands on a part of the array with no user while(user_mgr_info.user_array[middle].username == 0) { if(result < 0) middle --; else middle ++; } // this is where the array is cut in half and the half that the nameOfUser is on is kept result = strcmp(nameOfUser, user_mgr_info.user_array[middle].username); if(result == 0) return &user_mgr_info.user_array[middle]; else if(result < 0) high = middle; else low = middle; // in case the user doesn't exist if(high-low <= 0) return 0; } } int deleteUser(struct user *user_ptr) { free(user_ptr->username); memset(user_ptr, '\0', sizeof(struct user)); user_mgr_info.current_users--; return 1; backup_list_XML(); } int createUser(struct user *user_ptr, char *nameOfUser) { // clear old memory memset(user_ptr, '\0', sizeof(struct user)); user_ptr->username = nameOfUser; user_ptr->render_power = 0; user_ptr->last_job = 0; user_mgr_info.current_users++; return 1; } // places the new user at position index in the array, moves other users if it needs to int placeUser(int index, char *nameOfUser) { int higher; int lower; int total_moves; total_moves = 0; // I shift data in the array to create an open the space where the user should be added // but first I figure out which way is the shortest if(user_mgr_info.user_array[index].username != 0) { higher = index + 1; while(user_mgr_info.user_array[higher].username != 0) higher++; lower = index - 1; while(user_mgr_info.user_array[lower].username != 0) lower--; // here the data is shifted to open up a space if(index - lower < higher - index) { total_moves = index - lower; for(; lower < index; lower++) memcpy(&user_mgr_info.user_array[lower], &user_mgr_info.user_array[lower + 1], sizeof(struct user)); } else { total_moves = higher - index; for(; higher > index; higher--) memcpy(&user_mgr_info.user_array[higher], &user_mgr_info.user_array[higher - 1], sizeof(struct user)); } } // add the user to the array createUser(&user_mgr_info.user_array[index], nameOfUser); if(total_moves > 50) resize_user_array(); return 1; } int addUser(char *nameOfUser) { int high; int low; int middle; int result; high = user_mgr_info.user_array_size - 1; low = 0; result = -1; for(middle = (low+high)/2; 1 == 1; middle = (low+high)/2) { // in case middle lands on a part of the array with no user while(user_mgr_info.user_array[middle].username == 0) { if(result < 0) middle--; else middle++; } // this is where the array is cut in half and the half that the nameOfUser is on is kept result = strcmp(nameOfUser, user_mgr_info.user_array[middle].username); if(result == 0) return 0; else if(result < 0) high = middle; else low = middle; // once there are less than 10 possible places for the user to be placed // break out of this loop and begin next loop if(high-low <= 10) break; } // this function starts at the low index number, and goes up until it finds a // username that is bigger than it alphabetically, and tells the userPlacer // that it needs to go 1 before that spot for(; low <= high; low++) { while(user_mgr_info.user_array[low].username == 0) low++; result = strcmp(nameOfUser, user_mgr_info.user_array[low].username) < 0; if(result < 0) { placeUser(low - 1, nameOfUser); return 1; } if(result == 0) { fprintf(stderr, "user already exists"); return 0; } } backup_list_XML(); return 0; } int initialize_users() { struct stat buffer; // cif user_list.xml exists if(stat("user_list.xml", &buffer) == 0) { restart_From_XML_backup(); } else { user_mgr_info.current_users = 0; user_mgr_info.user_array_size = 50; user_mgr_info.user_array = malloc(sizeof(struct user) * 50); } // if XML file is not found create new array of size 50 return 1; } /********************************** XMLness *****************************/ int backup_list_XML() { xmlTextWriterPtr writer; char *tmp; int counter; writer = xmlNewTextWriterFilename("user_list.xml", 0); xmlTextWriterStartDocument(writer, NULL, "utf-8", NULL); // create root element user_list xmlTextWriterStartElement(writer, (xmlChar*)"user_list"); _distren_asprintf(&tmp, "%d", user_mgr_info.current_users); xmlTextWriterWriteAttribute(writer, (xmlChar*)"amount_of_users", (xmlChar*)tmp); free(tmp); for(counter = 0; counter < user_mgr_info.user_array_size; counter++) { if(user_mgr_info.user_array[counter].username != 0) { xmlTextWriterStartElement(writer, (xmlChar*)"user"); xmlTextWriterWriteAttribute(writer, (xmlChar*)"name", (xmlChar*)user_mgr_info.user_array[counter].username); _distren_asprintf(&tmp, "%d", user_mgr_info.user_array[counter].last_job); xmlTextWriterWriteAttribute(writer, (xmlChar*)"last_job", (xmlChar*)tmp); free(tmp); _distren_asprintf(&tmp, "%d", user_mgr_info.user_array[counter].render_power); xmlTextWriterWriteAttribute(writer, (xmlChar*)"render_power", (xmlChar*)tmp); free(tmp); xmlTextWriterEndElement(writer); } } return 0; } int restart_From_XML_backup(){ xmlDocPtr doc; xmlNodePtr cur; int counter; doc = xmlParseFile("user_list.xml"); cur = xmlDocGetRootElement(doc); if (xmlStrcmp(cur->name, (xmlChar*)"user_list")) { fprintf(stderr, "xml document is wrong type"); xmlFreeDoc(doc); return 1; } user_mgr_info.current_users = atoi((char*)xmlGetProp(cur, (xmlChar*)"amount_of_users")); user_mgr_info.user_array_size = user_mgr_info.current_users * 2; user_mgr_info.user_array = malloc(sizeof(struct user) * user_mgr_info.user_array_size); cur = cur->xmlChildrenNode; for(counter = 0; cur->next; counter++){ user_mgr_info.user_array[counter*2].username = (char*)xmlGetProp(cur, (xmlChar*)"amount_of_users"); user_mgr_info.user_array[counter*2].last_job = atoi((char*)xmlGetProp(cur, (xmlChar*)"last_job")); user_mgr_info.user_array[counter*2].render_power = atoi((char*)xmlGetProp(cur, (xmlChar*)"render_power")); cur = cur->next; } return 0; }