Beispiel #1
0
void ltrimCommand(redisClient *c) {
    robj *o;
    long start, end, llen, j, ltrim, rtrim;
    list *list;
    listNode *ln;

    if ((getLongFromObjectOrReply(c, c->argv[2], &start, NULL) != REDIS_OK) ||
        (getLongFromObjectOrReply(c, c->argv[3], &end, NULL) != REDIS_OK)) return;

    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.ok)) == NULL ||
        checkType(c,o,REDIS_LIST)) return;
    llen = listTypeLength(o);

    /* convert negative indexes */
    if (start < 0) start = llen+start;
    if (end < 0) end = llen+end;
    if (start < 0) start = 0;

    /* Invariant: start >= 0, so this test will be true when end < 0.
     * The range is empty when start > end or start >= length. */
    if (start > end || start >= llen) {
        /* Out of range start or start > end result in empty list */
        ltrim = llen;
        rtrim = 0;
    } else {
        if (end >= llen) end = llen-1;
        ltrim = start;
        rtrim = llen-end-1;
    }

    /* Remove list elements to perform the trim */
    if (o->encoding == REDIS_ENCODING_ZIPLIST) {
        o->ptr = ziplistDeleteRange(o->ptr,0,ltrim);
        o->ptr = ziplistDeleteRange(o->ptr,-rtrim,rtrim);
    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
        list = o->ptr;
        for (j = 0; j < ltrim; j++) {
            ln = listFirst(list);
            listDelNode(list,ln);
        }
        for (j = 0; j < rtrim; j++) {
            ln = listLast(list);
            listDelNode(list,ln);
        }
    } else {
        redisPanic("Unknown list encoding");
    }

    notifyKeyspaceEvent(REDIS_NOTIFY_LIST,"ltrim",c->argv[1],c->db->id);
    if (listTypeLength(o) == 0) {
        dbDelete(c->db,c->argv[1]);
        notifyKeyspaceEvent(REDIS_NOTIFY_GENERIC,"del",c->argv[1],c->db->id);
    }
    signalModifiedKey(c->db,c->argv[1]);
    server.dirty++;
    addReply(c,shared.ok);
}
Beispiel #2
0
void freeClientsInAsyncFreeQueue(void) {
    while (listLength(server.clients_to_close)) {
        listNode *ln = listFirst(server.clients_to_close);
        client *c = listNodeValue(ln);

        c->flags &= ~CLIENT_CLOSE_ASAP;
        freeClient(c);
        listDelNode(server.clients_to_close,ln);
    }
}
Beispiel #3
0
Datei: bio.c Projekt: dyu/disque
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]--;
    }
}
Beispiel #4
0
bool replyIfNestedErr(redisClient *c, redisClient *rfc, char *msg) {
    if (!respNotErr(rfc)) {
        listNode *ln   = listFirst(rfc->reply);
        robj     *emsg = ln->value;
        robj     *repl = _createStringObject(msg);
        repl->ptr      = sdscatlen(repl->ptr, emsg->ptr, sdslen(emsg->ptr));
        addReply(c, repl);
        decrRefCount(repl);
        return 0;
    }
    return 1;
}
Beispiel #5
0
void *IOThreadEntryPoint(void *arg) {
    iojob *j;
    listNode *ln;
    REDIS_NOTUSED(arg);

    pthread_detach(pthread_self());
    while(1) {
        /* Get a new job to process */
        lockThreadedIO();
        if (listLength(server.io_newjobs) == 0) {
            /* No new jobs in queue, exit. */
            redisLog(REDIS_DEBUG,"Thread %ld exiting, nothing to do",
                (long) pthread_self());
            server.io_active_threads--;
            unlockThreadedIO();
            return NULL;
        }
        ln = listFirst(server.io_newjobs);
        j = ln->value;
        listDelNode(server.io_newjobs,ln);
        /* Add the job in the processing queue */
        j->thread = pthread_self();
        listAddNodeTail(server.io_processing,j);
        ln = listLast(server.io_processing); /* We use ln later to remove it */
        unlockThreadedIO();
        redisLog(REDIS_DEBUG,"Thread %ld got a new job (type %d): %p about key '%s'",
            (long) pthread_self(), j->type, (void*)j, (char*)j->key->ptr);

        /* Process the Job */
        if (j->type == REDIS_IOJOB_LOAD) {
            vmpointer *vp = (vmpointer*)j->id;
            j->val = vmReadObjectFromSwap(j->page,vp->vtype);
        } else if (j->type == REDIS_IOJOB_PREPARE_SWAP) {
            j->pages = rdbSavedObjectPages(j->val);
        } else if (j->type == REDIS_IOJOB_DO_SWAP) {
            if (vmWriteObjectOnSwap(j->val,j->page) == REDIS_ERR)
                j->canceled = 1;
        }

        /* Done: insert the job into the processed queue */
        redisLog(REDIS_DEBUG,"Thread %ld completed the job: %p (key %s)",
            (long) pthread_self(), (void*)j, (char*)j->key->ptr);

        lockThreadedIO();
        listDelNode(server.io_processing,ln);
        listAddNodeTail(server.io_processed,j);
        unlockThreadedIO();

        /* Signal the main thread there is new stuff to process */
        redisAssert(write(server.io_ready_pipe_write,"x",1) == 1);
    }
    return NULL; /* never reached */
}
Beispiel #6
0
void printIList(tIlist * L){

  listFirst(L);

  while (L->active != NULL){
    printf("%p: ", (void *) L->active);
    printInstr(&L->active->instr);

    listNext(L);
  }

}
Beispiel #7
0
/* This should be called from any function PUSHing into lists.
 * 'c' is the "pushing client", 'key' is the key it is pushing data against,
 * 'ele' is the element pushed.
 *
 * If the function returns 0 there was no client waiting for a list push
 * against this key.
 *
 * If the function returns 1 there was a client waiting for a list push
 * against this key, the element was passed to this client thus it's not
 * needed to actually add it to the list and the caller should return asap. */
int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele) {
    struct dictEntry *de;
    redisClient *receiver;
    int numclients;
    list *clients;
    listNode *ln;
    robj *dstkey, *dstobj;

    de = dictFind(c->db->blocking_keys,key);
    if (de == NULL) return 0;
    clients = dictGetVal(de);
    numclients = listLength(clients);

    /* Try to handle the push as long as there are clients waiting for a push.
     * Note that "numclients" is used because the list of clients waiting for a
     * push on "key" is deleted by unblockClient() when empty.
     *
     * This loop will have more than 1 iteration when there is a BRPOPLPUSH
     * that cannot push the target list because it does not contain a list. If
     * this happens, it simply tries the next client waiting for a push. */
    while (numclients--) {
        ln = listFirst(clients);
        redisAssertWithInfo(c,key,ln != NULL);
        receiver = ln->value;
        dstkey = receiver->bpop.target;

        /* Protect receiver->bpop.target, that will be freed by
         * the next unblockClientWaitingData() call. */
        if (dstkey) incrRefCount(dstkey);

        /* This should remove the first element of the "clients" list. */
        unblockClientWaitingData(receiver);

        if (dstkey == NULL) {
            /* BRPOP/BLPOP */
            addReplyMultiBulkLen(receiver,2);
            addReplyBulk(receiver,key);
            addReplyBulk(receiver,ele);
            return 1; /* Serve just the first client as in B[RL]POP semantics */
        } else {
            /* BRPOPLPUSH, note that receiver->db is always equal to c->db. */
            dstobj = lookupKeyWrite(receiver->db,dstkey);
            if (!(dstobj && checkType(receiver,dstobj,REDIS_LIST))) {
                rpoplpushHandlePush(c,receiver,dstkey,dstobj,ele);
                decrRefCount(dstkey);
                return 1;
            }
            decrRefCount(dstkey);
        }
    }

    return 0;
}
Beispiel #8
0
void ltrimCommand(redisClient *c) {
    robj *o;
    int start = atoi(c->argv[2]->ptr);
    int end = atoi(c->argv[3]->ptr);
    int llen;
    int j, ltrim, rtrim;
    list *list;
    listNode *ln;

    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.ok)) == NULL ||
        checkType(c,o,REDIS_LIST)) return;
    llen = listTypeLength(o);

    /* convert negative indexes */
    if (start < 0) start = llen+start;
    if (end < 0) end = llen+end;
    if (start < 0) start = 0;

    /* Invariant: start >= 0, so this test will be true when end < 0.
     * The range is empty when start > end or start >= length. */
    if (start > end || start >= llen) {
        /* Out of range start or start > end result in empty list */
        ltrim = llen;
        rtrim = 0;
    } else {
        if (end >= llen) end = llen-1;
        ltrim = start;
        rtrim = llen-end-1;
    }

    /* Remove list elements to perform the trim */
    if (o->encoding == REDIS_ENCODING_ZIPLIST) {
        o->ptr = ziplistDeleteRange(o->ptr,0,ltrim);
        o->ptr = ziplistDeleteRange(o->ptr,-rtrim,rtrim);
    } else if (o->encoding == REDIS_ENCODING_LINKEDLIST) {
        list = o->ptr;
        for (j = 0; j < ltrim; j++) {
            ln = listFirst(list);
            listDelNode(list,ln);
        }
        for (j = 0; j < rtrim; j++) {
            ln = listLast(list);
            listDelNode(list,ln);
        }
    } else {
        redisPanic("Unknown list encoding");
    }
    if (listTypeLength(o) == 0) dbDelete(c->db,c->argv[1]);
    touchWatchedKey(c->db,c->argv[1]);
    server.dirty++;
    addReply(c,shared.ok);
}
Beispiel #9
0
int isClientNeedSend(struct client *c)
{
    struct listNode *node;
    struct conn *send_conn;
    if (listLength(c->conns) && isClientValid(c)) {
        node = listFirst(c->conns);
        send_conn = listNodeValue(node);
        if (listLength(send_conn->send_queue) || send_conn->ready_send) {
            return 1;
        }
    }
    return 0;
}
Beispiel #10
0
// find matching value in list and remove. If found return 1
int removeMatchFromList(list *socklist, void *value) {
    listNode *node;
    if (socklist == NULL) return 0;
    node = listFirst(socklist);
    while (node != NULL) {
        if (listNodeValue(node) == value) {
            listDelNode(socklist, node);
            return 1;
        }
        node = listNextNode(node);
    }
    return 0;
}
Beispiel #11
0
void *bioProcessBackgroundJobs(void *arg) {
    struct bio_job *job;
#ifdef _WIN32
    size_t type = (size_t) arg;
#else
    unsigned long type = (unsigned long) arg;
#endif
    sigset_t sigset;

    pthread_detach(pthread_self());
    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))
        redisLog(REDIS_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_condvar[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 == REDIS_BIO_CLOSE_FILE) {
            close((long)job->arg1);
        } else if (type == REDIS_BIO_AOF_FSYNC) {
            aof_fsync((long)job->arg1);
        } else {
            redisPanic("Wrong job type in bioProcessBackgroundJobs().");
        }
        zfree(job);

        /* 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]--;
    }
}
Beispiel #12
0
/* result buffer aggregation is taken from scripting.c */
sds fakeClientResultBuffer(redisClient *c) {
    sds reply;

    if (listLength(c->reply) == 0 && c->bufpos < REDIS_REPLY_CHUNK_BYTES) {
        /* This is a fast path for the common case of a reply inside the
         * client static buffer. Don't create an SDS string but just use
         * the client buffer directly. */
        c->buf[c->bufpos] = '\0';
        reply = c->buf;
        c->bufpos = 0;
    } else {
        reply = sdsnewlen(c->buf, c->bufpos);
        c->bufpos = 0;
        while (listLength(c->reply)) {
            robj *o = listNodeValue(listFirst(c->reply));

            reply = sdscatlen(reply, o->ptr, sdslen(o->ptr));
            listDelNode(c->reply, listFirst(c->reply));
        }
    }

    return reply;
}
Beispiel #13
0
/* *
 * slotsdel slot1 [slot2 ...]
 * */
void
slotsdelCommand(redisClient *c) {
    int slots_slot[HASH_SLOTS_SIZE];
    int n = 0;
    if (c->argc <= 1) {
        addReplyErrorFormat(c, "wrong number of arguments for 'slotsdel' command");
        return;
    }
    int i;
    for (i = 1; i < c->argc; i ++) {
        int slot;
        if (parse_slot(c, c->argv[i], &slot) != 0) {
            return;
        }
        slots_slot[n] = slot;
        n ++;
    }
    for (i = 0; i < n; i ++) {
        dict *d = c->db->hash_slots[slots_slot[i]];
        int s = dictSize(d);
        if (s == 0) {
            continue;
        }
        list *l = listCreate();
        listSetFreeMethod(l, decrRefCountVoid);
        unsigned long cursor = 0;
        do {
            cursor = dictScan(d, cursor, slotsScanSdsKeyCallback, l);
        } while (cursor != 0);
        while (1) {
            listNode *head = listFirst(l);
            if (head == NULL) {
                break;
            }
            robj *key = listNodeValue(head);
            robj *keys[] = {key};
            slotsremove(c, keys, 1, 0);
            listDelNode(l, head);
        }
        listRelease(l);
    }
    addReplyMultiBulkLen(c, n);
    for (i = 0; i < n; i ++) {
        int n = slots_slot[i];
        int s = dictSize(c->db->hash_slots[n]);
        addReplyMultiBulkLen(c, 2);
        addReplyLongLong(c, n);
        addReplyLongLong(c, s);
    }
}
Beispiel #14
0
void *bioProcessBackgroundJobs(void *arg) {
	//bioInit创建一个进程,用来刷文件。arg参数就是这个线程对应应该处理的任务号,用来索引bio_jobs[type]
    struct bio_job *job;
    unsigned long type = (unsigned long) arg;//实际上就是jobid。序号
    sigset_t sigset;

    pthread_detach(pthread_self());
    pthread_mutex_lock(&bio_mutex[type]);//先锁一下,待会pthread_cond_wait
    /* 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))
        redisLog(REDIS_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) {
	//已经加锁了,进入等待bio_condvar[type]不为0,并立即解锁,等待。
	//等其他线程pthread_cond_signal的时候,会通知这个线程,别等待了,从而再次加锁,返回。
            pthread_cond_wait(&bio_condvar[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 == REDIS_BIO_CLOSE_FILE) {
            close((long)job->arg1);//关闭文件。
        } else if (type == REDIS_BIO_AOF_FSYNC) {
            aof_fsync((long)job->arg1);//同步刷新数据。
        } else {
            redisPanic("Wrong job type in bioProcessBackgroundJobs().");
        }
        zfree(job);

        /* 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]--;//递减这种类型的挂起计数。
    }
}
Beispiel #15
0
static fdi_t getNextFDIAvailable(aeEventLoop *eventLoop)
{
    listNode *fdi_node;
    fdi_t fdi;

    if (listLength(eventLoop->fdiMap->recycle_pool) > 0)
    {
        fdi_node = listFirst(eventLoop->fdiMap->recycle_pool);
        fdi = (fdi_t)fdi_node->value;
        listDelNode(eventLoop->fdiMap->recycle_pool, fdi_node);
        return fdi;
    }
    return eventLoop->fdiMap->next_available++;
}
Beispiel #16
0
int repl_slaveof(char *host, int port){

	// 如果 host 为空则表示清除 master 关系
	if(host == NULL){
		if(server.masterhost) sys_free(server.masterhost);
		server.masterhost = NULL;
		server.masterport = -1;
		if (server.master)cc_freeClient(server.master);
		if (server.repl_state == REPL_TRANSFER){
			multi_deleteFileEvent(server.el, server.repl_transfer_s, MULTI_READABLE);
			close(server.repl_transfer_s);
			close(server.repl_transfer_fd);
			unlink(server.repl_transfer_tmpfile);
			server.repl_state = REPL_NONE;
		} else if (server.repl_state == REPL_CONNECTING){
			multi_deleteFileEvent(server.el, server.repl_transfer_s, MULTI_WRITABLE|MULTI_READABLE);
			close(server.repl_transfer_s);
			server.repl_state = REPL_NONE;
		}
	// host 不为空, 则根据 host 连接 master
	} else if (host!=NULL && port!=0){
		server.masterhost = sys_malloc(ADDR_MAX_LEN);
		memcpy(server.masterhost, host, ADDR_MAX_LEN);
		server.masterport = port;
		if(server.master) cc_freeClient(server.master);
		listNode *ln;
		// 若存在 slave 则和slave断开连接
		while(listLength(server.slaves)) {
			ln = listFirst(server.slaves);
			cc_freeClient((clientContext*)ln->value);
		}
		// 若正在和某个 master 传输 db 数据, 则终止传输
		// 删除 db 文件
		if (server.repl_state == REPL_TRANSFER){
			multi_deleteFileEvent(server.el, server.repl_transfer_s, MULTI_READABLE);
			close(server.repl_transfer_s);
			close(server.repl_transfer_fd);
			unlink(server.repl_transfer_tmpfile);
			server.repl_state = REPL_NONE;
		}
		// 置 server 状态为需要与 master 建立连接状态
		server.repl_state = REPL_CONNECT;
		xlog(LOG_INFO, "slave connect: slave 创建 master ip=%s, port=%d\n",
				server.masterhost, server.masterport);
	} else {
		// 参数错误
		return -1;
	}
	return 0;
}
Beispiel #17
0
/* Find matching value in list and remove. If found return TRUE */
BOOL removeMatchFromList(list *requestlist, void *value) {
    listNode *node;
    if (requestlist == NULL) {
        return FALSE;
    }
    node = listFirst(requestlist);
    while (node != NULL) {
        if (listNodeValue(node) == value) {
            listDelNode(requestlist, node);
            return TRUE;
        }
        node = listNextNode(node);
    }
    return FALSE;
}
Beispiel #18
0
/* Return the older job of the specified type. */
time_t bioOlderJobOfType(int type) {
    time_t time;
    listNode *ln;
    struct bio_job *job;

    pthread_mutex_lock(&bio_mutex[type]);
    ln = listFirst(bio_jobs[type]);
    if (ln == NULL) {
        pthread_mutex_unlock(&bio_mutex[type]);
        return 0;
    }
    job = ln->value;
    time = job->time;
    pthread_mutex_unlock(&bio_mutex[type]);
    return time;
}
Beispiel #19
0
void *listFirstValue(list *l)
{
    listNode *node;
    
    if(l == NULL)
    {
        return NULL;
    }

    node = listFirst(l);
    if(node == NULL)
    {
        return NULL;
    }

    return listNodeValue(node);
}
Beispiel #20
0
/* This routine search the list for a specific element given by needle and
 * returns that element or NULL if it's not found. */
void *listSearch(list_t *list,int (*compare)(void *,void *),void *needle) {
	void *data;
	int found;
	/* At first we of course didn't find anything and especially when
	   we do not receive a list we make sure we did not found anything
	   as of yet. */
	found=0;
	/* Does any element exist in the list? */
	if((data=listFirst(list))!=NULL) {
		do {
			/* Yes, so search for our element... */
			if((found=compare(data,needle))) break;
			/* ...untill none left. */
		} while((data=listNext(list))!=NULL);
	}
	/* If we found our data return it, otherwise return NULL. */
	return(found?data:NULL);
}
Beispiel #21
0
/* This should be called from any function PUSHing into lists.
 * 'c' is the "pushing client", 'key' is the key it is pushing data against,
 * 'ele' is the element pushed.
 *
 * If the function returns 0 there was no client waiting for a list push
 * against this key.
 *
 * If the function returns 1 there was a client waiting for a list push
 * against this key, the element was passed to this client thus it's not
 * needed to actually add it to the list and the caller should return asap. */
int handleClientsWaitingListPush(redisClient *c, robj *key, robj *ele) {
    struct dictEntry *de;
    redisClient *receiver;
    list *l;
    listNode *ln;

    de = dictFind(c->db->blocking_keys,key);
    if (de == NULL) return 0;
    l = dictGetEntryVal(de);
    ln = listFirst(l);
    redisAssert(ln != NULL);
    receiver = ln->value;

    addReplySds(receiver,sdsnew("*2\r\n"));
    addReplyBulk(receiver,key);
    addReplyBulk(receiver,ele);
    unblockClientWaitingData(receiver);
    return 1;
}
Beispiel #22
0
int inter(MainData * data, tListOfInstr * instrList)
{
    listFirst(instrList);
    tInstr *instr;
    while (1)
    {
        instr = listGetData(ilist);         //vytáhnu instrukci
        if(instr == NULL)
            return internalError();
        TVarData *param1, *param2, *param3;
        int result;
        switch(instr->type)
        {
            /*******Aritmetické operace*******/

            case I_ADD:
                if((param2->type==tDouble) && (param3->type==tDouble))
                {
                    param1->type = tDouble;
                    param1->tDouble = param2->tDouble + param3->tDouble;
                }
                else if ((param2->type==tInteger) && (param3->type==tInteger))
                {
                    param1->type = tInteger;
                    param1->tInteger = param2->tInteger + param3->tInteger;
                }
                else if ((param2->type==tDouble) && (param3->type==tInteger))
                {
                    param1->type = tInteger;
                    param1->tInteger = param2->tDouble + param3->tInteger;
                }
                else if ((param2->type==tInteger) && (param3->type==tDouble))
                {
                    param1->type = tInteger;
                    param1->tInteger = param2->tInteger + param3->tDouble;
                }
                else return INTERPRET_ERR;
                break;

        }
    }
}
Beispiel #23
0
/* get data for socket / fd being monitored. Create if not found*/
aeSockState *aeGetSockState(void *apistate, SOCKET fd)
{
    int sindex;
    listNode *node;
    list *socklist;
    aeSockState *sockState;
    if (apistate == NULL)
		return NULL;

    sindex = aeSocketIndex(fd);
    socklist = &(((aeApiState *)apistate)->lookup[sindex]);
    node = listFirst(socklist);

    while (node != NULL)
	{
        sockState = (aeSockState *)listNodeValue(node);
        if (sockState->fd == fd)
		{
            return sockState;
        }

        node = listNextNode(node);
    }

    // not found. Do lazy create of sockState.
    sockState = (aeSockState *)zmalloc(sizeof(aeSockState));
    if (sockState != NULL)
	{
        sockState->fd = (int)fd;
        sockState->masks = 0;
        sockState->wreqs = 0;
        sockState->reqs = NULL;
        memset(&sockState->wreqlist, 0, sizeof(sockState->wreqlist));

        if (listAddNodeHead(socklist, sockState) != NULL) {
            return sockState;
        } else {
            zfree(sockState);
        }
    }
    return NULL;
}
Beispiel #24
0
void *bioProcessBackgroundJobs(void *arg) {
    struct bio_job *job;
#ifdef _WIN32
    size_t type = (size_t) arg;
#else
    unsigned long type = (unsigned long) arg;
#endif

    pthread_detach(pthread_self());
    pthread_mutex_lock(&bio_mutex[type]);
    while(1) {
        listNode *ln;

        /* The loop always starts with the lock hold. */
        if (listLength(bio_jobs[type]) == 0) {
            pthread_cond_wait(&bio_condvar[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 == REDIS_BIO_CLOSE_FILE) {
            close((long)(size_t)job->arg1);
        } else if (type == REDIS_BIO_AOF_FSYNC) {
            aof_fsync((long)(size_t)job->arg1);
        } else {
            redisPanic("Wrong job type in bioProcessBackgroundJobs().");
        }
        zfree(job);

        /* 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]--;
    }
}
Beispiel #25
0
/* get data for socket / fd being monitored */
aeSockState *aeGetExistingSockState(void *apistate, int fd) {
    int sindex;
    listNode *node;
    list *socklist;
    aeSockState *sockState;
    if (apistate == NULL) return NULL;

    sindex = aeSocketIndex(fd);
    socklist = &(((aeApiState *)apistate)->lookup[sindex]);
    node = listFirst(socklist);
    while (node != NULL) {
        sockState = (aeSockState *)listNodeValue(node);
        if (sockState->fd == fd) {
            return sockState;
        }
        node = listNextNode(node);
    }

    return NULL;
}
Beispiel #26
0
/* This function is called in the beforeSleep() function of the event loop
 * in order to process the pending input buffer of clients that were
 * unblocked after a blocking operation.
 * 取消所有在 unblocked_clients 链表中的客户端的阻塞状态
 *  */
void processUnblockedClients(void) {
    listNode *ln;
    redisClient *c;

    while (listLength(server.unblocked_clients)) {
        ln = listFirst(server.unblocked_clients);
        redisAssert(ln != NULL);
        c = ln->value;
        listDelNode(server.unblocked_clients,ln);
        c->flags &= ~REDIS_UNBLOCKED;
        c->btype = REDIS_BLOCKED_NONE;

        /* Process remaining data in the input buffer. */
        if (c->querybuf && sdslen(c->querybuf) > 0) {
            server.current_client = c;
            processInputBuffer(c);
            server.current_client = NULL;
        }
    }
}
Beispiel #27
0
/* get the first node value, 
 * and delete this node in this list
 */
void *listPop(list *l)
{
    listNode *node;
    void *value;
    
    if (l == NULL) {
        return NULL;
    }

    node = listFirst(l);
    if (node == NULL) {
        return NULL;
    }

    value = listNodeValue(node);
    ASSERT(value != NULL);
    
    listDelNode(l, node);

    return value;
}
Beispiel #28
0
static bool addDouble(redisClient *c,
                      redisClient *fc,
                      robj        *key,
                      robj        *val,
                      long        *instd,
                      bool         val_is_dbl) {
    robj *vals  = createObject(REDIS_STRING, NULL);
    if (val_is_dbl) {
        double d = *((double *)val);
        vals->ptr   = (key->encoding == REDIS_ENCODING_RAW) ?
            sdscatprintf(sdsempty(), "%ld,%s,%f", 
                          *instd, (char *)key->ptr, d) :
            sdscatprintf(sdsempty(), "%ld,%ld,%f",
                          *instd, (long)  key->ptr, d);
    } else if (val->encoding == REDIS_ENCODING_RAW) {
        vals->ptr   = (key->encoding == REDIS_ENCODING_RAW) ?
            sdscatprintf(sdsempty(), "%ld,%s,%s", 
                          *instd, (char *)key->ptr, (char *)val->ptr) :
            sdscatprintf(sdsempty(), "%ld,%ld,%s",
                          *instd, (long)  key->ptr, (char *)val->ptr);
    } else {
        vals->ptr   = (key->encoding == REDIS_ENCODING_RAW) ?
            sdscatprintf(sdsempty(), "%ld,%s,%ld", 
                          *instd, (char *)key->ptr, (long)val->ptr) :
            sdscatprintf(sdsempty(), "%ld,%ld,%ld",
                          *instd, (long)  key->ptr, (long)val->ptr);
    }
    fc->argv[2] = vals;
    //RL4 "DBL: INSERTING [1]: %s [2]: %s", fc->argv[1]->ptr, fc->argv[2]->ptr);
    legacyInsertCommand(fc);
    decrRefCount(vals);
    if (!respOk(fc)) { /* insert error */
        listNode *ln = listFirst(fc->reply);
        addReply(c, ln->value);
        return 0;
    }
    *instd = *instd + 1;
    return 1;
}
Beispiel #29
0
/* This function is called in the beforeSleep() function of the event loop
 * in order to process the pending input buffer of clients that were
 * unblocked after a blocking operation. */
void processUnblockedClients(void) {
    listNode *ln;
    client *c;

    while (listLength(server.unblocked_clients)) {
        ln = listFirst(server.unblocked_clients);
        serverAssert(ln != NULL);
        c = ln->value;
        listDelNode(server.unblocked_clients,ln);
        c->flags &= ~CLIENT_UNBLOCKED;

        /* Process remaining data in the input buffer, unless the client
         * is blocked again. Actually processInputBuffer() checks that the
         * client is not blocked before to proceed, but things may change and
         * the code is conceptually more correct this way. */
        if (!(c->flags & CLIENT_BLOCKED)) {
            if (c->querybuf && sdslen(c->querybuf) > 0) {
                processInputBuffer(c);
            }
        }
    }
}
Beispiel #30
0
/* This function is called in the beforeSleep() function of the event loop
 * in order to process the pending input buffer of clients that were
 * unblocked after a blocking operation. */
void processUnblockedClients(void) {
    listNode *ln;
    client *c;

    while (listLength(server.unblocked_clients)) {
        ln = listFirst(server.unblocked_clients);
        serverAssert(ln != NULL);
        c = ln->value;
        listDelNode(server.unblocked_clients,ln);
        c->flags &= ~CLIENT_UNBLOCKED;
        /* Note that the client may be blocked again at this point, since
         * a new blocking command was processed. In that case we just remove
         * it from the unblocked clients list without actually processing
         * its pending query buffer. */
        if (!(c->flags & CLIENT_BLOCKED)) {
            c->btype = BLOCKED_NONE;

            /* Process remaining data in the input buffer. */
            if (c->querybuf && sdslen(c->querybuf) > 0) {
                processInputBuffer(c);
            }
        }
    }
}