void ThreadCreate(TThread ** const threadPP, void * const userHandle, TThreadProc * const func, TThreadDoneFn * const threadDone, bool const useSigchld, size_t const stackSize, const char ** const errorP) { TThread * threadP; MALLOCVAR(threadP); if (threadP == NULL) xmlrpc_asprintf(errorP, "Can't allocate memory for thread descriptor."); else { sigset_t oldBlockedSet; pid_t rc; threadP->nextInPoolP = NULL; threadP->threadDone = threadDone; threadP->userHandle = userHandle; threadP->useSigchld = useSigchld; threadP->pid = 0; /* We have to be sure we don't get the SIGCHLD for this child's death until the child is properly registered in the thread pool so that the handler will know who he is. */ blockSignalClass(SIGCHLD, &oldBlockedSet); rc = fork(); if (rc < 0) xmlrpc_asprintf(errorP, "fork() failed, errno=%d (%s)", errno, strerror(errno)); else if (rc == 0) { /* This is the child */ (*func)(userHandle); /* Note that thread cleanup (threadDone) is done by the _parent_, upon seeing our exit. */ exit(0); } else { /* This is the parent */ threadP->pid = rc; addToPool(threadP); sigprocmask(SIG_SETMASK, &oldBlockedSet, NULL); /* restore */ *errorP = NULL; *threadPP = threadP; } if (*errorP) { removeFromPool(threadP); free(threadP); } } }
void OperationList::registerObject(BaseObject *object, unsigned op_type, int object_idx, BaseObject *parent_obj) { ObjectType obj_type; Operation *operation=NULL; Table *parent_tab=NULL; Relationship *parent_rel=NULL; int obj_idx=-1; try { //Raises an error if the user tries to register an operation with null object if(!object) throw Exception(ERR_ASG_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); obj_type=object->getObjectType(); if((obj_type==OBJ_COLUMN || obj_type==OBJ_CONSTRAINT || obj_type==OBJ_INDEX || obj_type==OBJ_TRIGGER || obj_type==OBJ_RULE) && !parent_obj) throw Exception(ERR_OPR_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); else if(parent_obj && (((obj_type==OBJ_COLUMN || obj_type==OBJ_CONSTRAINT) && (parent_obj->getObjectType()!=OBJ_RELATIONSHIP && parent_obj->getObjectType()!=OBJ_TABLE)) || ((obj_type==OBJ_INDEX || obj_type==OBJ_TRIGGER || obj_type==OBJ_RULE) && parent_obj->getObjectType()!=OBJ_TABLE))) throw Exception(ERR_OPR_OBJ_INV_TYPE,__PRETTY_FUNCTION__,__FILE__,__LINE__); //If the operations list is full makes the automatic cleaning before inserting a new operation if(current_index == static_cast<int>(max_size-1)) removeOperations(); /* If adding an operation and the current index is not pointing to the end of the list (available redo / user ran undo operations) all elements from the current index to the end of the list will be deleted as well as the objects in the pool that were linked to the excluded operations */ if(current_index>=0 && static_cast<unsigned>(current_index)!=operations.size()) { //Gets the last operation index int i=operations.size()-1; //Removes all the operation while the current index isn't reached while(i >= current_index) { removeFromPool(i); i--; } //Validates the remaining operatoins after the deletion validateOperations(); } //Creates the new operation operation=new Operation; operation->op_type=op_type; operation->chain_type=next_op_chain; operation->original_obj=object; //Adds the object on te pool addToPool(object, op_type); //Assigns the pool object to the operation operation->pool_obj=object_pool.back(); if(next_op_chain==Operation::CHAIN_START) next_op_chain=Operation::CHAIN_MIDDLE; /* Performing specific operations according to the type of object. If the object has a parent object, it must be discovered and moreover it is necessary to find and store the index of the object in the list on the parent object */ if(obj_type==OBJ_COLUMN || obj_type==OBJ_CONSTRAINT || obj_type==OBJ_INDEX || obj_type==OBJ_TRIGGER || obj_type==OBJ_RULE) { TableObject *tab_obj=NULL; tab_obj=dynamic_cast<TableObject *>(object); if(parent_obj->getObjectType()==OBJ_TABLE) parent_tab=dynamic_cast<Table *>(parent_obj); else parent_rel=dynamic_cast<Relationship *>(parent_obj); /* Specific case to columns: on removal operations the permissions of the objects must be removed too */ if(obj_type==OBJ_COLUMN && op_type==Operation::OBJECT_REMOVED) model->removePermissions(tab_obj); else if(((obj_type==OBJ_TRIGGER && dynamic_cast<Trigger *>(tab_obj)->isReferRelationshipAddedColumn()) || (obj_type==OBJ_INDEX && dynamic_cast<Index *>(tab_obj)->isReferRelationshipAddedColumn()) || (obj_type==OBJ_CONSTRAINT && dynamic_cast<Constraint *>(tab_obj)->isReferRelationshipAddedColumn()))) { if(op_type==Operation::OBJECT_REMOVED) tab_obj->setParentTable(parent_tab); operation->xml_definition=model->validateObjectDefinition(tab_obj, SchemaParser::XML_DEFINITION); } operation->parent_obj=parent_obj; /* If there is a parent relationship will get the index of the object. Only columns and constraints are handled case the parent is a relationship */ if(parent_rel && (obj_type==OBJ_COLUMN || obj_type==OBJ_CONSTRAINT)) { //Case a specific index wasn't specified if(object_idx < 0) //Stores on the operation the index on its parent obj_idx=parent_rel->getObjectIndex(tab_obj); else //Assigns the specific index to operation obj_idx=object_idx; } //Case there is a parent table will get the object's index else if(parent_tab) { if(object_idx < 0) //Stores on the operation the index of object on its parent obj_idx=parent_tab->getObjectIndex(object->getName(false), obj_type); else obj_idx=object_idx; } //Raises an error if both parent table / relationship isn't allocated else throw Exception(ERR_OPR_NOT_ALOC_OBJECT,__PRETTY_FUNCTION__,__FILE__,__LINE__); } else { //Case a specific index wasn't specified if(object_idx < 0) //Stores on the operation the object index on the model obj_idx=model->getObjectIndex(object); else //Assigns the specific index to object obj_idx=object_idx; } operation->object_idx=obj_idx; operations.push_back(operation); current_index=operations.size(); } catch(Exception &e) { if(operation) { removeFromPool(object_pool.size()-1); delete(operation); } throw Exception(e.getErrorMessage(),e.getErrorType(),__PRETTY_FUNCTION__,__FILE__,__LINE__,&e); } }
void StackElement::Release() { if (pool && !IsShared()) addToPool(); CInterface::Release(); }