void _serverPanic(char *msg, char *file, int line) { bugReportStart(); serverLog(LL_WARNING,"------------------------------------------------"); serverLog(LL_WARNING,"!!! Software Failure. Press left mouse button to continue"); serverLog(LL_WARNING,"Guru Meditation: %s #%s:%d",msg,file,line); #ifdef HAVE_BACKTRACE serverLog(LL_WARNING,"(forcing SIGSEGV in order to print the stack trace)"); #endif serverLog(LL_WARNING,"------------------------------------------------"); *((char*)-1) = 'x'; }
/* Try to garbage collect the job. */ void tryJobGC(job *job) { if (job->state != JOB_STATE_ACKED) return; int dummy_ack = dictSize(job->nodes_delivered) == 0; serverLog(LL_VERBOSE,"GC %.42s", job->id); /* Don't overflow the count, it's only useful for the exponential delay. * Actually we'll keep trying forever. */ if (job->gc_retry != JOB_GC_RETRY_COUNT_MAX) job->gc_retry++; /* nodes_confirmed is used in order to store all the nodes that have the * job in ACKed state, so that the job can be evicted when we are * confident the job will not be reissued. */ if (job->nodes_confirmed == NULL) { job->nodes_confirmed = dictCreate(&clusterNodesDictType,NULL); dictAdd(job->nodes_confirmed,myself->name,myself); } /* Check ASAP if we already reached all the nodes. This special case * here is mainly useful when the job replication factor is 1, so * there is no SETACK to send, nor GOTCAK to receive. * * Also check if this is a dummy ACK but the cluster size is now 1: * in such a case we don't have other nodes to send SETACK to, we can * just remove the ACK. Note that dummy ACKs are not created at all * if the cluster size is 1, but this code path may be entered as a result * of the cluster getting resized to a single node. */ int all_nodes_reached = (!dummy_ack) && (dictSize(job->nodes_delivered) == dictSize(job->nodes_confirmed)); int dummy_ack_single_node = dummy_ack && server.cluster->size == 1; if (all_nodes_reached || dummy_ack_single_node) { serverLog(LL_VERBOSE, "Deleting %.48s: all nodes reached in tryJobGC()", job->id); unregisterJob(job); freeJob(job); return; } /* Send a SETACK message to all the nodes that may have a message but are * still not listed in the nodes_confirmed hash table. However if this * is a dummy ACK (created by ACKJOB command acknowledging a job we don't * know) we have to broadcast the SETACK to everybody in search of the * owner. */ dict *targets = dictSize(job->nodes_delivered) == 0 ? server.cluster->nodes : job->nodes_delivered; dictForeach(targets,de) clusterNode *node = dictGetVal(de); if (dictFind(job->nodes_confirmed,node->name) == NULL) clusterSendSetAck(node,job); dictEndForeach }
void _serverAssert(char *estr, char *file, int line) { bugReportStart(); serverLog(LL_WARNING,"=== ASSERTION FAILED ==="); serverLog(LL_WARNING,"==> %s:%d '%s' is not true",file,line,estr); #ifdef HAVE_BACKTRACE server.assert_failed = estr; server.assert_file = file; server.assert_line = line; serverLog(LL_WARNING,"(forcing SIGSEGV to print the bug report.)"); #endif *((char*)-1) = 'x'; }
void logStackContent(void **sp) { int i; for (i = 15; i >= 0; i--) { unsigned long addr = (unsigned long) sp+i; unsigned long val = (unsigned long) sp[i]; if (sizeof(long) == 4) serverLog(LL_WARNING, "(%08lx) -> %08lx", addr, val); else serverLog(LL_WARNING, "(%016lx) -> %016lx", addr, val); } }
void serverLogObjectDebugInfo(robj *o) { serverLog(LL_WARNING,"Object type: %d", o->type); serverLog(LL_WARNING,"Object encoding: %d", o->encoding); serverLog(LL_WARNING,"Object refcount: %d", o->refcount); if (o->type == OBJ_STRING && sdsEncodedObject(o)) { serverLog(LL_WARNING,"Object raw string len: %zu", sdslen(o->ptr)); if (sdslen(o->ptr) < 4096) { sds repr = sdscatrepr(sdsempty(),o->ptr,sdslen(o->ptr)); serverLog(LL_WARNING,"Object raw string content: %s", repr); sdsfree(repr); } } }
/* Initialize the background system, spawning the thread. */ void bioInit(void) { pthread_attr_t attr; pthread_t thread; size_t stacksize; int j; /* Initialization of state vars and objects */ for (j = 0; j < BIO_NUM_OPS; j++) { pthread_mutex_init(&bio_mutex[j],NULL); pthread_cond_init(&bio_condvar[j],NULL); bio_jobs[j] = listCreate(); bio_pending[j] = 0; } /* Set the stack size as by default it may be small in some system */ pthread_attr_init(&attr); pthread_attr_getstacksize(&attr,&stacksize); if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */ while (stacksize < DISQUE_THREAD_STACK_SIZE) stacksize *= 2; pthread_attr_setstacksize(&attr, stacksize); /* Ready to spawn our threads. We use the single argument the thread * function accepts in order to pass the job ID the thread is * responsible of. */ for (j = 0; j < BIO_NUM_OPS; j++) { void *arg = (void*)(unsigned long) j; if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) { serverLog(LL_WARNING,"Fatal: Can't initialize Background Jobs."); exit(1); } bio_threads[j] = thread; } }
static int backup_if_needed (char *filename) { char backupfile[256]; int off; struct stat filestat; if (arc.num_rdb_backups < 1) { return C_OK; } if (stat (filename, &filestat) != -1 && S_ISREG (filestat.st_mode)) { strcpy (backupfile, "dump-"); off = strftime (backupfile + 5, sizeof (backupfile) - 5, "%Y%m%d-%T", localtime (&filestat.st_mtime)); snprintf (backupfile + 5 + off, sizeof (backupfile) - 5 - off, "-%d.rdb", (int) getpid ()); if (rename (filename, backupfile) == -1) { serverLog (LL_WARNING, "Error backing up rdb file: %s", strerror (errno)); return C_ERR; } } return C_OK; }
void bugReportStart(void) { if (server.bug_report_start == 0) { serverLog(LL_WARNING, "\n\n=== DISQUE BUG REPORT START: Cut & paste starting from here ==="); server.bug_report_start = 1; } }
/* Kill the running bio threads in an unclean way. This function should be * used only when it's critical to stop the threads for some reason. * Currently Disque does this only on crash (for instance on SIGSEGV) in order * to perform a fast memory check without other threads messing with memory. */ void bioKillThreads(void) { int err, j; for (j = 0; j < BIO_NUM_OPS; j++) { if (pthread_cancel(bio_threads[j]) == 0) { if ((err = pthread_join(bio_threads[j],NULL)) != 0) { serverLog(LL_WARNING, "Bio thread for job type #%d can be joined: %s", j, strerror(err)); } else { serverLog(LL_WARNING, "Bio thread for job type #%d terminated",j); } } } }
static void printErrorStack(entry *e) { unsigned int i; char body[64]; if (e->type == -1) { sprintf(body, "Error trace"); } else if (e->type >= 253) { sprintf(body, "Error trace (%s)", types[e->type]); } else if (!e->key) { sprintf(body, "Error trace (%s: (unknown))", types[e->type]); } else { char tmp[41]; strncpy(tmp, e->key, 40); /* display truncation at the last 3 chars */ if (strlen(e->key) > 40) { memset(&tmp[37], '.', 3); } /* display unprintable characters as ? */ for (i = 0; i < strlen(tmp); i++) { if (tmp[i] <= 32) tmp[i] = '?'; } sprintf(body, "Error trace (%s: %s)", types[e->type], tmp); } printCentered(4, 80, body); /* display error stack */ for (i = 0; i < errors.level; i++) { serverLog(LL_WARNING, "0x%08lx - %s", (unsigned long) errors.offset[i], errors.error[i]); } }
static void mig_end (client * c) { serverLog (LL_NOTICE, "Client ask for migrate end"); if (arc.migrate_slot == NULL) { addReplyError (c, "Migration is not in progress. Unable to perform MIGEND."); return; } serverLog (LL_NOTICE, "Finishing migration"); sdsfree (arc.migrate_slot); arc.migrate_slot = NULL; addReply (c, shared.ok); return; }
void ChatServer::processMessage(UserInfoChanged *msg) { ChatClient client = m_clientList.getClient(msg->username); client.setUserInfo(msg->info); m_clientList.updateClient(client); QString log = "User " + msg->username + " changed his info"; emit updateTable("clients"); emit serverLog(esNotify, log); }
/* RDB check main: called form redis.c when Redis is executed with the * redis-check-rdb alias. */ int redis_check_rdb_main(char **argv, int argc) { if (argc != 2) { fprintf(stderr, "Usage: %s <rdb-file-name>\n", argv[0]); exit(1); } serverLog(LL_WARNING, "Checking RDB file %s", argv[1]); exit(redis_check_rdb(argv[1])); return 0; }
static void printCentered(int indent, int width, char* body) { char head[256], tail[256]; memset(head, '\0', 256); memset(tail, '\0', 256); memset(head, '=', indent); memset(tail, '=', width - 2 - indent - strlen(body)); serverLog(LL_WARNING, "%s %s %s", head, body, tail); }
void ChatServer::serverGotNewConnection() //activates when server got new incoming connection //isn't very important for us, cause server requires authorization //so we still waiting authorization/registration request from that son of a bitch { QTcpSocket *newSocket = m_tcpServer->nextPendingConnection(); connect(newSocket, SIGNAL(readyRead()), this, SLOT(serverGotNewMessage())); QString log = "Server got new connection from " + newSocket->peerAddress().toString() + ":" + QString::number(newSocket->peerPort()); emit serverLog(esNotify, log); }
static void redis_test_accept(aeEventLoop *el, int fd, void *privdata, int mask) { int cport, cfd, max = MAX_ACCEPTS_PER_CALL; char cip[NET_IP_STR_LEN]; UNUSED(el); UNUSED(mask); UNUSED(privdata); while(max--) { cfd = anetTcpAccept(server.neterr, fd, cip, sizeof(cip), &cport); if (cfd == ANET_ERR) { if (errno != EWOULDBLOCK) serverLog(LL_WARNING, "Accepting client connection: %s", server.neterr); return; } serverLog(LL_VERBOSE,"Accepted %s:%d", cip, cport); redis_accept_handler(cfd,0,cip); } }
/* Log information about the "current" client, that is, the client that is * currently being served by Disque. May be NULL if Disque is not serving a * client right now. */ void logCurrentClient(void) { if (server.current_client == NULL) return; client *cc = server.current_client; sds client; int j; serverLog(LL_WARNING, "--- CURRENT CLIENT INFO"); client = catClientInfoString(sdsempty(),cc); serverLog(LL_WARNING,"client: %s", client); sdsfree(client); for (j = 0; j < cc->argc; j++) { robj *decoded; decoded = getDecodedObject(cc->argv[j]); serverLog(LL_WARNING,"argv[%d]: '%s'", j, (char*)decoded->ptr); decrRefCount(decoded); } }
void debugCommand(client *c) { if (!strcasecmp(c->argv[1]->ptr,"segfault")) { *((char*)-1) = 'x'; } else if (!strcasecmp(c->argv[1]->ptr,"oom")) { void *ptr = zmalloc(ULONG_MAX); /* Should trigger an out of memory. */ zfree(ptr); addReply(c,shared.ok); } else if (!strcasecmp(c->argv[1]->ptr,"assert")) { if (c->argc >= 3) c->argv[2] = tryObjectEncoding(c->argv[2]); serverAssertWithInfo(c,c->argv[0],1 == 2); } else if (!strcasecmp(c->argv[1]->ptr,"flushall")) { flushServerData(); addReply(c,shared.ok); } else if (!strcasecmp(c->argv[1]->ptr,"loadaof")) { flushServerData(); if (loadAppendOnlyFile(server.aof_filename) != C_OK) { addReply(c,shared.err); return; } serverLog(LL_WARNING,"Append Only File loaded by DEBUG LOADAOF"); addReply(c,shared.ok); } else if (!strcasecmp(c->argv[1]->ptr,"sleep") && c->argc == 3) { double dtime = strtod(c->argv[2]->ptr,NULL); long long utime = dtime*1000000; struct timespec tv; tv.tv_sec = utime / 1000000; tv.tv_nsec = (utime % 1000000) * 1000; nanosleep(&tv, NULL); addReply(c,shared.ok); } else if (!strcasecmp(c->argv[1]->ptr,"error") && c->argc == 3) { sds errstr = sdsnewlen("-",1); errstr = sdscatsds(errstr,c->argv[2]->ptr); errstr = sdsmapchars(errstr,"\n\r"," ",2); /* no newlines in errors. */ errstr = sdscatlen(errstr,"\r\n",2); addReplySds(c,errstr); } else if (!strcasecmp(c->argv[1]->ptr,"structsize") && c->argc == 2) { sds sizes = sdsempty(); sizes = sdscatprintf(sizes,"bits:%d ",(sizeof(void*) == 8)?64:32); sizes = sdscatprintf(sizes,"job:%d ", (int)sizeof(job)); sizes = sdscatprintf(sizes,"queue:%d ", (int)sizeof(queue)); sizes = sdscatprintf(sizes,"robj:%d ",(int)sizeof(robj)); sizes = sdscatprintf(sizes,"dictentry:%d ",(int)sizeof(dictEntry)); sizes = sdscatprintf(sizes,"sdshdr5:%d ",(int)sizeof(struct sdshdr5)); sizes = sdscatprintf(sizes,"sdshdr8:%d ",(int)sizeof(struct sdshdr8)); sizes = sdscatprintf(sizes,"sdshdr16:%d ",(int)sizeof(struct sdshdr16)); sizes = sdscatprintf(sizes,"sdshdr32:%d ",(int)sizeof(struct sdshdr32)); sizes = sdscatprintf(sizes,"sdshdr64:%d ",(int)sizeof(struct sdshdr64)); addReplyBulkSds(c,sizes); } else { addReplyErrorFormat(c, "Unknown DEBUG subcommand or wrong number of arguments for '%s'", (char*)c->argv[1]->ptr); } }
void *bioProcessBackgroundJobs(void *arg) { struct bio_job *job; unsigned long type = (unsigned long) arg; sigset_t sigset; /* Make the thread killable at any time, so that bioKillThreads() * can work reliably. */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); pthread_mutex_lock(&bio_mutex[type]); /* Block SIGALRM so we are sure that only the main thread will * receive the watchdog signal. */ sigemptyset(&sigset); sigaddset(&sigset, SIGALRM); if (pthread_sigmask(SIG_BLOCK, &sigset, NULL)) serverLog(LL_WARNING, "Warning: can't mask SIGALRM in bio.c thread: %s", strerror(errno)); while(1) { listNode *ln; /* The loop always starts with the lock hold. */ if (listLength(bio_jobs[type]) == 0) { pthread_cond_wait(&bio_newjob_cond[type],&bio_mutex[type]); continue; } /* Pop the job from the queue. */ ln = listFirst(bio_jobs[type]); job = ln->value; /* It is now possible to unlock the background system as we know have * a stand alone job structure to process.*/ pthread_mutex_unlock(&bio_mutex[type]); /* Process the job accordingly to its type. */ if (type == BIO_CLOSE_FILE) { close((long)job->arg1); } else if (type == BIO_AOF_FSYNC) { aof_fsync((long)job->arg1); } else { serverPanic("Wrong job type in bioProcessBackgroundJobs()."); } zfree(job); /* Unblock threads blocked on bioWaitStepOfType() if any. */ pthread_cond_broadcast(&bio_step_cond[type]); /* Lock again before reiterating the loop, if there are no longer * jobs to process we'll block again in pthread_cond_wait(). */ pthread_mutex_lock(&bio_mutex[type]); listDelNode(bio_jobs[type],ln); bio_pending[type]--; } }
void ChatServer::processMessage(RegistrationRequest *msg, QTcpSocket *socket) //processing regisration message //registration logic stored in clientList, //we just call it and use results to send registration answer { if (!msg) { QString log = "Error processing registration request - message is empty"; emit serverLog(esMinor, log); return; } RegistrationAnswer *answer = new RegistrationAnswer(); switch (m_clientList.registrate(msg->username, msg->password)) { case GeneralClientList::rrOccupiedUsername: { answer->registrationResult = false; answer->denialReason = "Username allready reserved, please choose another"; break; } case GeneralClientList::rrBadUsername: { answer->registrationResult = false; answer->denialReason = "Your username isn't allowed"; break; } case GeneralClientList::rrRegSuccess: { answer->registrationResult = true; emit updateTable("clients"); emit updateTable("membership"); break; } } sendMessageToClient(socket, answer); // QString log = msg->username + ((answer->registrationResult) ? " was registered." : "wasn't registered"); emit serverLog(esNotify, log); // delete answer; }
void readClient(aeEventLoop *eventLoop, int fd, void *clientData, int mask) { UNUSED(mask); int nread; client *c = (client *)clientData; //取body长度 if (c->bufsize <= 0) { uint16_t size; nread = read(fd, (void *)&size, 2); if (nread <= 0) { serverLog(LL_VERBOSE, "Client closed connection fd:%d", c->fd); freeClient(c); return; } c->bufsize = (int)ntohs(size); return; } //取body nread = read(fd, (void *)(c->buf + c->bufpos), c->bufsize - c->bufpos); if (nread == -1) { if (errno == EAGAIN) { return; } else { serverLog(LL_VERBOSE, "Reading from client: %s",strerror(errno)); return; } } else if (nread == 0) { serverLog(LL_VERBOSE, "body Client closed connection fd:%d", c->fd); freeClient(c); return; } c->bufpos += nread; if (c->bufpos >= c->bufsize) { serverLog(LL_VERBOSE, "msg: %s", c->buf); //init c->bufpos = c->bufsize = 0; memset(c->buf, 0, PROTO_REPLY_CHUNK_BYTES); return; } }
/* ----------------------- */ void checkpointCommand (client * c) { sds bitarray; serverLog (LL_NOTICE, "Client ask for checkpoint"); /* Here we need to check if there is a background saving operation in progress */ if (server.rdb_child_pid != -1 || server.aof_child_pid != -1) { serverLog (LL_NOTICE, "Another background operation is in progress. Unable to perform CHECKPOINT."); addReplyError (c, "Unable to perform CHECKPOINT"); return; } /* set bitarray from argument */ bitarray = get_bitmap_from_argv (c->argc - 1, c->argv + 1); if (!bitarray) { addReplyError (c, "Invalid argument format."); return; } serverLog (LL_NOTICE, "Starting CHECKPOINT"); arc.checkpoint_slots = bitarray; if (rdbSaveBackground (arc.checkpoint_filename) != C_OK) { serverLog (LL_NOTICE, "Replication failed, can't CHECKPOINT"); addReplyError (c, "Unable to perform CHECKPOINT"); sdsfree (bitarray); arc.checkpoint_slots = NULL; return; } arc.checkpoint_seqnum = arc.smr_seqnum; //TODO 이건 여기가 아님. serverLog (LL_NOTICE, "Partial Checkpoint sequence num:%lld", arc.smr_seqnum); c->replstate = SLAVE_STATE_WAIT_BGSAVE_END; c->repldbfd = -1; arc.checkpoint_client = c; return; }
/* argv includes command itself */ static void mig_start (client * c, int argc, robj ** argv) { serverLog (LL_NOTICE, "Client ask for migrate start"); if (arc.migrate_slot != NULL) { addReplyError (c, "Another migration is in progress. Unable to perform MIGSTART."); return; } arc.migrate_slot = get_bitmap_from_argv (argc - 1, argv + 1); if (!arc.migrate_slot) { addReplyError (c, "Invalid argument format."); return; } serverLog (LL_NOTICE, "Starting migration"); addReply (c, shared.ok); return; }
static void redis_accept_handler(int fd, int flags, char *ip) { UNUSED(ip); redis_test_client *c; if ((c = redis_test_create_client(fd)) == NULL) { serverLog(LL_WARNING, "Error registering fd event for the new client: %s (fd=%d)", strerror(errno),fd); close(fd); /* May be already closed, just ignore errors */ return; } c->flags |= flags; }
void ChatServer::processMessage(DisconnectMessage *msg) //processing disconnect message from client //that's simple //we need only to delete client from client list //and close his socket //also we should reply disconnect fact in all client's channels { if (!msg) { QString log = "Error processing disconnect message - message is empty"; emit serverLog(esMinor, log); return; } QString messageText = msg->sender + " was disconnected from server."; emit serverLog(esNotify, messageText); QStringList channels = m_clientList.getChannelsForClient(msg->sender).keys(); ChannelSystemMessage *inform = new ChannelSystemMessage(); ChannelUserList *list; inform->message = msg->sender+ " leaved chat."; m_clientList.disconnect(msg->sender); for (int i = 0; i < channels.count(); ++i) { list = new ChannelUserList(); list->channelName = channels[i]; ChatChannel channel = m_clientList.getChannel(channels[i]); for(int j = 0; j < channel.userList.count(); j++) { //FIXME: GOVNOKOD list->userList.insert(channel.userList[j], getSendableState(channel.userList[j])); } sendMessageToChannel(channels[i], list); delete list; inform->channelName = channels[i]; sendMessageToChannel(channels[i], inform); } emit updateTable("clients"); delete inform; }
void _serverAssertPrintClientInfo(client *c) { int j; bugReportStart(); serverLog(LL_WARNING,"=== ASSERTION FAILED CLIENT CONTEXT ==="); serverLog(LL_WARNING,"client->flags = %d", c->flags); serverLog(LL_WARNING,"client->fd = %d", c->fd); serverLog(LL_WARNING,"client->argc = %d", c->argc); for (j=0; j < c->argc; j++) { char buf[128]; char *arg; if (c->argv[j]->type == OBJ_STRING && sdsEncodedObject(c->argv[j])) { arg = (char*) c->argv[j]->ptr; } else { snprintf(buf,sizeof(buf),"Object type: %d, encoding: %d", c->argv[j]->type, c->argv[j]->encoding); arg = buf; } serverLog(LL_WARNING,"client->argv[%d] = \"%s\" (refcount: %d)", j, arg, c->argv[j]->refcount); } }
void ChatServer::processMessage(ChannelListRequest *msg, QTcpSocket *socket) //new processMessage for ChannelListRequest { if (!msg) { QString log = "Error processing authorization request- message is empty"; emit serverLog(esMinor, log); return; } ChannelListMessage *chanListMsg = new ChannelListMessage(); if(msg->listType == ChannelListRequest::listOfAll) { chanListMsg->listType = ChannelListMessage::listOfAll; chanListMsg->channelList = m_clientList.getAllChanells(); sendMessageToClient(socket, chanListMsg); } else { chanListMsg->listType = ChannelListMessage::listOfJoined; chanListMsg->channelList = m_clientList.getChannelsForClient(msg->nick); sendMessageToClient(socket, chanListMsg); ChannelUserList *userListMsg = new ChannelUserList(); ChannelThemeChanged *theme = new ChannelThemeChanged(); QMap<QString, QString>::iterator channel = chanListMsg->channelList.begin(); for(;channel != chanListMsg->channelList.end(); ++channel) { QString channelName = channel.key(); ChatChannel tempChannel = m_clientList.getChannel(channelName); userListMsg->channelName = channel.key(); for(int i = 0; i < tempChannel.userList.count(); i++) { //FIXME: GOVNOKOD userListMsg->userList.insert(tempChannel.userList[i], getSendableState(tempChannel.userList[i])); } theme->channel = channel.key(); theme->theme = m_clientList.getChannel(userListMsg->channelName).topic(); sendMessageToChannel(channel.key(), userListMsg); sendMessageToClient(msg->nick, theme); } delete userListMsg; delete theme; UserInfoMessage *userInfo = new UserInfoMessage(); userInfo->username = msg->nick; userInfo->info = m_clientList.getClient(msg->nick).userInfo(); sendMessageToClient(msg->nick, userInfo); delete userInfo; } delete chanListMsg; }
void ChatServer::processMessage(ChannelMessage *msg) //processing channel message //we need to reply this message to all clients in channel, { //got channel message //need to reply it to all authorized clients in that channel if (!msg) { QString log = "Error processing channel message - message is empty"; emit serverLog(esMinor, log); return; } QString messageText = QString("%1: %2") .arg(msg->sender) .arg(msg->messageText); emit channelLog(msg->receiver, messageText); //and reply to all of receiver channel users a channel message sendMessageToChannel(msg->receiver, msg); }
void ChatServer::stopServer(const QString &shutdownReason) //stops server //we need to send disconnect messages to all channels { GeneralClientList::userSocketsList_t *userList = m_clientList.getAllSockets(); GeneralClientList::userSocketsListIterator_t itr(*userList); ServerShutdownMessage msg; msg.shutdownReason = shutdownReason; while(itr.hasNext()) sendMessageToClient(itr.next(), &msg); delete userList; m_clientList.disconnectAll(); QString log = tr("Server stopped."); m_tcpServer->close(); disconnect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(serverGotNewConnection())); disconnect(&m_clientList, SIGNAL(logMessage(ErrorStatus, QString&)), this, SLOT(replyLog(ErrorStatus, QString&))); emit serverLog(esNotify, log); delete m_tcpServer; }
void smemrmCommand(client *c) { long long ll_var; int mem_id; int free_cnt = 0; struct smem_t * smem_p = NULL; listNode *lnode; int j; for (j = 1; j < c->argc; j++){ // check the size if(getLongLongFromObject(c->argv[j],&ll_var) == C_OK){ //serverLog(LL_WARNING,"get share memory id: %lld", ll_var); mem_id = ll_var; // get the item from list lnode = listSearchKey(server.smem_list_available, &mem_id); if(lnode){ smem_p = lnode->value; // update the share memory used status server.share_memory_size -= smem_p->size; //serverLog(LL_WARNING,"[smemrmCommand] rm the id(%d) in list.", mem_id); listDelNode(server.smem_list_available, lnode); }else serverLog(LL_WARNING,"[smemrmCommand] not found the id(%d) in list, try to free.", mem_id); if(!smem_free_buffer(mem_id)){ free_cnt ++; } } } addReplyLongLong(c,free_cnt); return C_OK; }