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::removeOperations(void) { BaseObject *object=NULL; TableObject *tab_obj=NULL; Table *tab=NULL; //Destroy the operations while(!operations.empty()) { delete(operations.back()); operations.pop_back(); } //Destroy the object pool while(!object_pool.empty()) removeFromPool(0); //Case there is not removed object while(!not_removed_objs.empty()) { object=not_removed_objs.back(); if(unallocated_objs.count(object)==0) tab_obj=dynamic_cast<TableObject *>(object); //Deletes the object if its not unallocated already or referenced on the model if(unallocated_objs.count(object)==0 && (!tab_obj && model->getObjectIndex(object) < 0)) { unallocated_objs[object]=true; delete(object); } else if(tab_obj && unallocated_objs.count(tab_obj)==0) { tab=dynamic_cast<Table *>(tab_obj->getParentTable()); //Deletes the object if its not unallocated already or referenced by some table if(!tab || (unallocated_objs.count(tab)==1) || (tab && unallocated_objs.count(tab)==0 && tab->getObjectIndex(tab_obj) < 0)) { unallocated_objs[tab_obj]=true; delete(tab_obj); } } not_removed_objs.pop_back(); tab_obj=NULL; } current_index=0; unallocated_objs.clear(); }
void PollSelect::set(int fd, natural waitFor, const Timeout &tm, void* userData) { if (fd < 0) throw InvalidParamException(THISLOCATION,1,"Invalid descriptor (negative value)"); natural fdindex = (natural)fd; if (fdindex > 1024 && fdindex > socketMap.length() * 4) throw InvalidParamException(THISLOCATION,1,"Invalid descriptor (too high value)"); if (fdindex >= socketMap.length()) { const FdInfo *oldMap = socketMap.data(); socketMap.resize(fdindex+1); FdInfo *newMap = socketMap.data(); if (oldMap != newMap) { //because items was moved to new address, we have to recalculate addresses of timeout map for (natural i = 0; i < timeoutMap.length(); i++) { natural ofs = timeoutMap[i].owner - oldMap; timeoutMap(i).owner = newMap + ofs; } } } FdInfo &fdinfo = socketMap(fdindex); removeOldTm(&fdinfo); fdinfo.timeout = tm; fdinfo.waitFor = waitFor; fdinfo.userData = userData; addNewTm(&fdinfo); if (waitFor == 0) { removeFromPool(fdinfo.poolpos); } else { POLLFD ev; ev.fd = fd; ev.events = (((waitFor & INetworkResource::waitForInput) != 0)?POLL_IN:0) | (((waitFor & INetworkResource::waitForOutput) != 0)?POLL_OUT:0) | (((waitFor & INetworkResource::waitForException) != 0)?POLL_PRI:0) ; ev.revents = 0; if (fdinfo.poolpos ==naturalNull) { fdinfo.poolpos = curpool.length(); curpool.add(ev); } else { curpool(fdinfo.poolpos) = ev; } } }
/* {{{ proto void shmop_close (int shmid) closes a shared memory segment */ int shmop_close (int shmid) //PHP_FUNCTION(shmop_close) { php_shmop *shmop; shm_dbg("\n FUNCTION shmop_close (int shmid) : %d \n",shmid); shmop = getFromPool(shmid); if (! shmop) { RETURN_FALSE; } // shmop_close doesn't delete the memory segment, it just detaches from it. // If you have created the block and need to delete it you must call shmop_delete **BEFORE** calling shmop_close // (for reasons outlined in shmop_delete help page notes). // if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &shmid) == FAILURE) { // return; // } shm_dbg("CALL shmdt(shmop->addr) : %p \n", shmop->addr ); if (shmdt(shmop->addr)) { // detach memory segment sprintf(errmsg, "can't detached segment (are you the owner?)"); //php_error_docref(NULL TSRMLS_CC, E_WARNING, "can't mark segment for deletion (are you the owner?)"); shm_dbg("%s\n",errmsg); removeFromPool(shmop->key); //zend_list_delete(shmid); RETURN_FALSE; }; removeFromPool(shmop->key); //zend_list_delete(shmid); shm_dbg("FUNCTION shmop_close : OK or NOT ... closed \n"); RETURN_TRUE; }
void OperationList::removeLastOperation(void) { if(!operations.empty()) { Operation *oper=NULL; bool end=false; vector<Operation *>::reverse_iterator itr; unsigned obj_idx=operations.size()-1; //Gets the last operation on the list using reverse iterator itr=operations.rbegin(); while(!end) { oper=(*itr); //Removes the object related to the operation from the pool removeFromPool(obj_idx); /* Stop condition for removing the operation: 1) The operation is not chained with others, or 2) If the last operation at the end of a chain all chained operations are removed including the first operation of the chain, when the latter is removed the iteration is stopped.*/ end=(ignore_chain || (!ignore_chain && (oper->chain_type==Operation::NO_CHAIN || oper->chain_type==Operation::CHAIN_START))); itr++; obj_idx--; } /* If the head of chaining is removed (CHAIN_START) marks that the next element in the list is the new start of chain */ if(oper && oper->chain_type==Operation::CHAIN_START) next_op_chain=Operation::CHAIN_START; //Validates the remaining operations validateOperations(); /* Points the current index to the end of list if it is beyond the last element */ if(static_cast<unsigned>(current_index) > operations.size()) current_index=operations.size(); } }
PollSelect::WaitStatus PollSelect::wait(const Timeout& tm, Result& result) { do { Timeout finTm = tm; if (!timeoutHeap.empty()) { Timeout p = timeoutHeap.top().owner->timeout; SysTime now = SysTime::now(); while (p.expired(now)) { FdInfo *owner = timeoutHeap.top().owner; removeOldTm(owner); if (owner->waitFor != 0) { result.fd = getFd(owner); result.flags = 0; result.userData = owner->userData; owner->waitFor = 0; removeFromPool(owner->poolpos); return waitEvent; } if (timeoutHeap.empty()) break; p = timeoutHeap.top().owner->timeout; } if (p < finTm) finTm = p; } natural timeout_msecs = finTm.getRemain().msecs(); int res = poll(curpool.data(),curpool.length(),timeout_msecs); if (res == -1) { if (errno != EINTR) throw ErrNoException(THISLOCATION,errno); } else if (res == 0) { if (tm.expired()) { return waitTimeout; } else { FdInfo *finfo = timeoutHeap.top().owner; removeOldTm(finfo); result.fd = getFd(finfo); result.flags = 0; result.userData = finfo->userData; finfo->waitFor = 0; removeFromPool(finfo->poolpos); return waitEvent; } } else { for (natural i = 0; i < curpool.length(); i++) { if (curpool[i].revents) { int fd = curpool[i].fd; int revents = curpool[i].revents; if (fd == wakeOut) { byte b; int r = read(wakeOut,&b,1); if (r == -1) throw ErrNoException(THISLOCATION, errno); result.fd = 0; result.userData = 0; result.reason = reason; return waitWakeUp; } else { FdInfo *finfo = socketMap.data()+fd; removeOldTm(finfo); removeFromPool(i); if (finfo->waitFor) { result.fd = fd; result.flags = (((revents & POLL_IN)!=0)?INetworkResource::waitForInput:0) | (((revents & POLL_OUT)!=0)?INetworkResource::waitForOutput:0) | (((revents & (POLL_PRI|POLL_ERR))!=0)?INetworkResource::waitForException:0); result.userData = finfo->userData; finfo->waitFor = 0; return waitEvent; } } } } } } while (true); }
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); } }
/* {{{ proto int shmop_open (int key, string flags, int mode, int size) gets and attaches a shared memory segment */ int shmop_open (int key, char* flags, int mode, int size) //PHP_FUNCTION(shmop_open) { size_t flags_len = strlen(flags); int shmatflg = 0, shmflg = 0, shmid = 0; struct shmid_ds shm; php_shmop *shmop, i_shmop; memset(&i_shmop, 0, sizeof(php_shmop)); // !! new instance for Linux and OsX shmop = &i_shmop; // shmop->key = key; // shmop->size = size; // shmop->shmflg = mode; // if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsll", &key, &flags, &flags_len, &mode, &size) == FAILURE) { // return; // } shm_dbg("\n FUNCTION shmop_open (int key, char* flags, int mode, int size) : %d, %s, %d, %d \n", key, flags, mode, size); if (shmPOOLcnt >= MAX_SHM_IDs) { sprintf(errmsg, "SHM POLL full"); goto err; } if (flags_len != 1) { sprintf(errmsg, "Shared memory - %s is not a valid flag", flags); //php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s is not a valid flag", flags); RETURN_FALSE; } switch (flags[0]) { case 'a': shmatflg |= SHM_RDONLY; break; case 'c': shmflg |= IPC_CREAT; break; case 'n': shmflg |= (IPC_CREAT | IPC_EXCL); break; case 'w': /* noop shm segment is being opened for read & write will fail if segment does not exist */ break; default: sprintf(errmsg, "Shared memory - invalid access mode"); //php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid access mode"); goto err; } if (shmflg & IPC_CREAT && size < 1) { sprintf(errmsg, "Shared memory segment size must be greater than zero"); //php_error_docref(NULL TSRMLS_CC, E_WARNING, "Shared memory segment size must be greater than zero"); goto err; } shm_dbg("CALL shmget(key, size, shmflg) : %d, %d, %d \n", key, size, shmflg ); //WIN creates shmop in pool, Linux, OsX in their's own system space //it must be maintained pool - check shm_wrk_copy shmid = shmget(key, size, shmflg); if (shmop->shmid == -1) { sprintf(errmsg, "unable to attach or create shared memory segment"); //php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to attach or create shared memory segment"); goto errKill; } if (! shm_wrk_copy) { // WINDOWS shm_wrk_copy = &i_shmop; } memcpy (shmop, shm_wrk_copy, sizeof(php_shmop)); shmop->key = key; shmop->shmid = shmid; shmop->shmatflg = shmatflg; shmop->shmflg = shmflg; shmop->size = size; //____________________________any OS ... save info here too__________________________ shmop = saveToPool(shmop); if (! shmop) { RETURN_FALSE; } //___________________________________________________________________________________ shm_dbg("CALL shmctl(shmop->shmid, IPC_STAT, &shm) : %d, %d, %p \n", shmop->shmid, IPC_STAT, &shm ); if (shmctl(shmop->shmid, IPC_STAT, &shm)) { sprintf(errmsg, "unable to get shared memory segment information"); //php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to get shared memory segment information"); goto errKill; } shm_dbg("CALL shmop->addr = shmat(shmop->shmid, 0, shmop->shmatflg) : %d, %d, %p \n", shmop->shmid, 0, shmop->shmatflg ); shmop->addr = shmat(shmop->shmid, 0, shmop->shmatflg); if (shmop->addr == (char*) -1) { sprintf(errmsg, "unable to attach to shared memory segment"); //php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to attach to shared memory segment"); goto errKill; } shmop->size = shm.shm_segsz; //shmop* already in stack //zend_list_insert(shmop, shm_type); return shmop->shmid; //RETURN_LONG(rsid); errKill: removeFromPool(shmop->key); //efree(shmop); err: shm_dbg("%s errno %d \n", errmsg, errno ); RETURN_FALSE; }