Beispiel #1
0
 void ExpireCheck::Run()
 {
     uint64 start = get_current_epoch_millis();
     while (m_checking_db < ARDB_GLOBAL_DB)
     {
         uint64 now = get_current_epoch_millis();
         if (now - start >= 500)
         {
             return;
         }
         DBID nexdb = 0;
         if (!m_db->DBExist(m_checking_db, nexdb))
         {
             if (nexdb == m_checking_db || nexdb == ARDB_GLOBAL_DB)
             {
                 m_checking_db = 0;
                 return;
             }
             m_checking_db = nexdb;
         }
         m_db->CheckExpireKey(m_checking_db);
         m_checking_db++;
     }
     m_checking_db = 0;
 }
Beispiel #2
0
 void ExpireCheck::Run()
 {
     if (!m_server->GetConfig().master_host.empty())
     {
         /*
          * no expire on slave, master would sync the expire/del operations to slaves.
          */
         return;
     }
     Ardb& db = m_server->GetDB();
     uint64 start = get_current_epoch_millis();
     while (m_checking_db < ARDB_GLOBAL_DB)
     {
         uint64 now = get_current_epoch_millis();
         if (now - start >= 500)
         {
             return;
         }
         DBID nexdb = 0;
         if (!db.DBExist(m_checking_db, nexdb))
         {
             if (nexdb == m_checking_db || nexdb == ARDB_GLOBAL_DB)
             {
                 m_checking_db = 0;
                 return;
             }
             m_checking_db = nexdb;
         }
         db.CheckExpireKey(m_checking_db, 50, 10000, ExpireCheckCallback, this);
         m_checking_db++;
     }
     m_checking_db = 0;
 }
Beispiel #3
0
 void Run()
 {
     uint64 start = get_current_epoch_millis();
     for (int i = 0; i < 1000000; i++)
     {
         WriteLockGuard<SpinRWLock> guard(*lock);
         (*mm)[i] = 1;
     }
     uint64 end = get_current_epoch_millis();
     INFO_LOG("Cost %llums to write", (end - start));
 }
Beispiel #4
0
 void Run()
 {
     uint64 start = get_current_epoch_millis();
     for (int i = 0; i < 1000000; i++)
     {
         ReadLockGuard<SpinRWLock> guard(*lock);
         mm->find(i);
     }
     uint64 end = get_current_epoch_millis();
     INFO_LOG("Cost %llums to read", (end - start));
 }
Beispiel #5
0
 void ZSetCache::GetRange(const ZRangeSpec& range, bool with_scores, bool with_attrs, ValueVisitCallback* cb,
         void* cbdata)
 {
     uint64 start = get_current_epoch_millis();
     CacheReadLockGuard guard(m_lock);
     ZSetCaheElement min_ele(range.min.NumberValue(), "");
     ZSetCaheElement max_ele(range.max.NumberValue(), "");
     ZSetCacheElementSet::iterator min_it = m_cache.lower_bound(min_ele);
     ZSetCacheElementSet::iterator max_it = m_cache.lower_bound(max_ele);
     int cursor = 0;
     if (min_it != m_cache.end())
     {
         while (!range.contain_min && min_it != m_cache.end() && min_it->score == range.min.NumberValue())
         {
             min_it++;
         }
         while (range.contain_max && max_it != m_cache.end() && max_it->score == range.max.NumberValue())
         {
             max_it++;
         }
         while (min_it != max_it && min_it != m_cache.end())
         {
             ValueData v;
             Buffer buf(const_cast<char*>(min_it->value.data()), 0, min_it->value.size());
             v.Decode(buf);
             cb(v, cursor++, cbdata);
             if (with_scores)
             {
                 ValueData score;
                 score.SetDoubleValue(min_it->score);
                 cb(score, cursor++, cbdata);
             }
             if (with_attrs)
             {
                 ValueData attr_value;
                 Buffer attr_buf(const_cast<char*>(min_it->attr.data()), 0, min_it->attr.size());
                 attr_value.Decode(attr_buf);
                 cb(attr_value, cursor++, cbdata);
             }
             min_it++;
         }
     }
     uint64 end = get_current_epoch_millis();
     if (end - start > 10)
     {
         DEBUG_LOG("Cost %llums to get %d elements in between range [%.2f, %.2f]", end - start, cursor,
                 range.min.NumberValue(), range.max.NumberValue());
     }
 }
Beispiel #6
0
void test_pthread_create_performance()
{
    uint64 start = get_current_epoch_millis();
    uint32 loop = 1000000;
    for (uint32 i = 0; i < loop; i++)
    {
        pthread_mutex_t mutex;
        pthread_mutexattr_t attr;
        pthread_mutexattr_init(&attr);
        pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_DEFAULT);
        pthread_mutex_init(&mutex, &attr);
        pthread_mutexattr_destroy(&attr);

        pthread_mutex_destroy(&mutex);
    }
    uint64 end = get_current_epoch_millis();
    INFO_LOG("Cost %llums to create/destory %u mutexes.", (end - start), loop);
}
Beispiel #7
0
 void Statistics::TrackOperationsPerSecond()
 {
     uint64 t = get_current_epoch_millis() - m_ops_sec_last_sample_time;
     ServerStatisticsTable::iterator it = m_server_stats.begin();
     while (it != m_server_stats.end())
     {
         ServerStatistics& st = it->second;
         long long ops = st.stat_numcommands - st.ops_sec_last_sample_ops;
         long long ops_sec;
         ops_sec = t > 0 ? (ops * 1000 / t) : 0;
         st.ops_sec_samples[st.ops_sec_idx] = ops_sec;
         st.ops_sec_idx = (st.ops_sec_idx + 1) % COMMS_OPS_SEC_SAMPLES;
         st.ops_sec_last_sample_ops = st.stat_numcommands;
         st.instantaneous_ops = 0;
         it++;
     }
     m_ops_sec_last_sample_time = get_current_epoch_millis();
 }
Beispiel #8
0
 int Ardb::TTL(Context& ctx, RedisCommandFrame& cmd)
 {
     uint64 ms;
     int err = GenericTTL(ctx, cmd.GetArguments()[0], ms);
     if (0 == err)
     {
         fill_int_reply(ctx.reply, (ms - get_current_epoch_millis()) / 1000);
     }
     return 0;
 }
Beispiel #9
0
 int Ardb::Expire(Context& ctx, RedisCommandFrame& cmd)
 {
     uint32 v = 0;
     if (!check_uint32_arg(ctx.reply, cmd.GetArguments()[1], v))
     {
         return 0;
     }
     int err = GenericExpire(ctx, cmd.GetArguments()[0], v * 1000 + get_current_epoch_millis());
     fill_int_reply(ctx.reply, err == 0 ? 1 : 0);
     return 0;
 }
Beispiel #10
0
 int CoroChannel::SyncWrite(Buffer& buffer, int timeout)
 {
     uint64 start = timeout > 0 ? get_current_epoch_millis() : 0;
     m_ch->GetOutputBuffer().Write(&buffer, buffer.ReadableBytes());
     m_ch->EnableWriting();
     CreateTimeoutTask(timeout);
     while (m_ch->GetOutputBuffer().ReadableBytes() > 0)
     {
         if (timeout > 0)
         {
             if (get_current_epoch_millis() - start >= timeout)
             {
                 return -1;
             }
         }
         if (0 != WaitCoro())
         {
             return -1;
         }
     }
     return 0;
 }
Beispiel #11
0
 int Ardb::PExpire(Context& ctx, RedisCommandFrame& cmd)
 {
     uint32 v = 0;
     if (!check_uint32_arg(ctx.reply, cmd.GetArguments()[1], v))
     {
         return 0;
     }
     ValueObject meta;
     int err = GenericExpire(ctx, cmd.GetArguments()[0], v + get_current_epoch_millis());
     CHECK_ARDB_RETURN_VALUE(ctx.reply, err);
     fill_int_reply(ctx.reply, err == 0 ? 1 : 0);
     return 0;
 }
Beispiel #12
0
			void Run()
			{
				IdleConn conn;
				uint64 now = get_current_epoch_millis();
				while (lru.PeekFront(conn) && (now - conn.ts >= maxIdleTime))
				{

					Channel* ch = serv->GetChannel(conn.conn_id);
					if (NULL != ch)
					{
						DEBUG_LOG("Closed timeout connection:%d.", ch->GetID());
						ch->Close();
					}
					lru.PopFront();
				}
			}
Beispiel #13
0
    int Ardb::GenericExpire(Context& ctx, const Slice& key, uint64 ms)
    {
        if (ms > 0 && get_current_epoch_millis() >= ms)
        {
            return 0;
        }
        if (m_cfg.slave_ignore_expire && ctx.IsSlave())
        {
            /*
             * ignore expire setting, but issue data change event for replication
             */
            ctx.data_change = true;
            return 0;
        }

        ValueObject meta;
        int err = GetMetaValue(ctx, key, KEY_END, meta);
        if (0 != err)
        {
            return err;
        }
        BatchWriteGuard guard(GetKeyValueEngine());
        if (meta.meta.expireat != ms && meta.meta.expireat > 0)
        {
            KeyObject expire;
            expire.key = key;
            expire.type = KEY_EXPIRATION_ELEMENT;
            expire.db = ctx.currentDB;
            expire.score.SetInt64(meta.meta.expireat);
            DelKeyValue(ctx, expire);
        }
        meta.meta.expireat = ms;
        SetKeyValue(ctx, meta);

        if (meta.meta.expireat > 0)
        {
            ValueObject vv(KEY_EXPIRATION_ELEMENT);
            vv.key.key = key;
            vv.key.type = KEY_EXPIRATION_ELEMENT;
            vv.key.db = ctx.currentDB;
            vv.key.score.SetInt64(meta.meta.expireat);
            SetKeyValue(ctx, vv);
        }
        return 0;
    }
Beispiel #14
0
	void ArdbServer::TouchIdleConn(Channel* ch)
	{
		static ThreadLocal<IdleConnManager> kLocalIdleConns;
		uint64 now = get_current_epoch_millis();
		IdleConn conn;
		conn.conn_id = ch->GetID();
		conn.ts = now;

		IdleConnManager& m = kLocalIdleConns.GetValue();
		if (m.timer_id == -1)
		{
			m.serv = &(ch->GetService());
			m.maxIdleTime = m_cfg.timeout * 1000;
			m.lru.SetMaxCacheSize(m_cfg.max_clients);
			m.timer_id = ch->GetService().GetTimer().Schedule(&m, 1, 5,
			        SECONDS);
		}
		IdleConn tmp;
		m.lru.Insert(conn.conn_id, conn, tmp);
	}
Beispiel #15
0
OP_NAMESPACE_BEGIN
    Statistics::Statistics() :
            m_ops_sec_last_sample_time(get_current_epoch_millis()),stat_expiredkeys(0)
    {
    }
Beispiel #16
0
    static void default_loghandler(LogLevel level, const char* filename, const char* function, int line,
                    const char* format, ...)
    {
        const char* levelstr = 0;
        uint64_t timestamp = get_current_epoch_millis();
        if (level > 0 && level < ALL_LOG_LEVEL)
        {
            levelstr = kLogLevelNames[level - 1];
        }
        else
        {
            levelstr = "???";
        }
        size_t log_line_size = k_default_log_line_buf_size;
        va_list args;
        std::string record;
        va_start(args, format);
        for (;;)
        {
            //char content[log_line_size + 1];
            char* content = new char[log_line_size + 1];
#ifndef va_copy
#define va_copy(dst, src)   memcpy(&(dst), &(src), sizeof(va_list))
#endif
            va_list aq;
            va_copy(aq, args);
            int sz = vsnprintf(content, log_line_size, format, aq);
            va_end(aq);
            if (sz < 0)
            {
                DELETE_A(content);
                return;
            }
            if ((size_t) sz < log_line_size)
            {
                record = content;
                DELETE_A(content);
                break;
            }
            log_line_size <<= 1;
            DELETE_A(content);
        }

        uint32 mills = timestamp % 1000;
        char timetag[256];
        struct tm& tm = get_current_tm();
        sprintf(timetag, "%02u-%02u %02u:%02u:%02u", tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
        LockGuard<ThreadMutex> guard(kLogMutex);
        fprintf(kLogFile, "[%u] %s,%03u %s %s\n", getpid(), timetag, mills, levelstr, record.c_str());
        fflush(kLogFile);
        if (!kLogFilePath.empty() && kLogFile != stdout)
        {
            long file_size = ftell(kLogFile);
            if (file_size < 0)
            {
                reopen_default_logfile();
            }
            else if ((uint32) file_size >= k_max_file_size)
            {
                rollover_default_logfile();
                reopen_default_logfile();
            }
        }
    }
Beispiel #17
0
 int Ardb::GeoSearch(Context& ctx, RedisCommandFrame& cmd)
 {
     GeoSearchOptions options;
     std::string err;
     if (0 != options.Parse(cmd.GetArguments(), err, 1))
     {
         fill_error_reply(ctx.reply, "%s", err.c_str());
         return 0;
     }
     ValueObject meta;
     int ret = GetMetaValue(ctx, cmd.GetArguments()[0], ZSET_META, meta);
     CHECK_ARDB_RETURN_VALUE(ctx.reply, ret);
     ctx.reply.type = REDIS_REPLY_ARRAY;
     if (0 != ret)
     {
         return 0;
     }
     uint64 t1 = get_current_epoch_millis();
     uint32 min_radius = 75; //magic number
     if (options.asc && options.limit > 0 && options.offset == 0 && options.radius > min_radius)
     {
         uint32 old_radius = options.radius;
         options.radius = min_radius;
         do
         {
             ctx.reply.Clear();
             int point_num = GeoSearchByOptions(ctx, meta, options);
             if(point_num < 0)
             {
                 break;
             }
             if (options.radius == old_radius)
             {
                 break;
             }
             if (point_num > 0)
             {
                 if (point_num >= options.limit)
                 {
                     break;
                 }
                 options.radius *= sqrt((options.limit / point_num) + 1);
             }
             else
             {
                 options.radius *= 8;
             }
             if (options.radius > old_radius)
             {
                 options.radius = old_radius;
             }
         } while (options.radius <= old_radius);
     }
     else
     {
         GeoSearchByOptions(ctx, meta, options);
     }
     ctx.reply.type = REDIS_REPLY_ARRAY;
     uint64 t2 = get_current_epoch_millis();
     DEBUG_LOG("####Cost %llums to range geosearch", t2 - t1);
     return 0;
 }
Beispiel #18
0
    int Ardb::GeoSearchByOptions(Context& ctx, ValueObject& meta, GeoSearchOptions& options)
    {
        uint64 start_time = get_current_epoch_micros();
        int ret = 0;
        double x = options.x, y = options.y;
        if (options.by_member)
        {
            Data element, score;
            element.SetString(options.member, true);
            ret = ZSetScore(ctx, meta, element, score);
            if (0 != ret || score.IsNil())
            {
                return -1;
            }
            GeoHashHelper::GetMercatorXYByHash(score.value.iv, x, y);
            //GeoHashHelper::GetXYByHash(score.value.iv, x, y);
        }
        else
        {
            if (options.coord_type != GEO_MERCATOR_TYPE)
            {
                x = GeoHashHelper::GetMercatorX(options.x);
                y = GeoHashHelper::GetMercatorY(options.y);
            }
        }
        DEBUG_LOG("####Step1: Cost %lluus", get_current_epoch_micros() - start_time);
        GeoPointArray points;
        ZSetRangeByScoreOptions fetch_options;
        fetch_options.withscores = false;
        fetch_options.op = OP_GET;
        fetch_options.fill_reply = false;
        fetch_options.fetch_geo_location = true;
        if (options.in_members)
        {
            StringSet::iterator it = options.submembers.begin();
            while (it != options.submembers.end())
            {
                Data element, score;
                element.SetString(*it, true);
                Location loc;
                ret = ZSetScore(ctx, meta, element, score, &loc);
                if (0 == ret)
                {
                    fetch_options.results.push_back(element);
                    fetch_options.locs.push_back(loc);
                }
                it++;
            }
        }
        else
        {
            GeoHashBitsSet ress;
            GeoHashHelper::GetAreasByRadiusV2(GEO_MERCATOR_TYPE, y, x, options.radius, ress);
            /*
             * Merge areas if possible to avoid disk search
             */
            std::vector<ZRangeSpec> range_array;
            GeoHashBitsSet::iterator rit = ress.begin();
            typedef TreeMap<uint64, uint64>::Type HashRangeMap;
            HashRangeMap tmp;
            while (rit != ress.end())
            {
                GeoHashBits& hash = *rit;
                GeoHashBits next = hash;
                next.bits++;
                tmp[GeoHashHelper::Allign60Bits(hash)] = GeoHashHelper::Allign60Bits(next);
                rit++;
            }
            HashRangeMap::iterator tit = tmp.begin();
            HashRangeMap::iterator nit = tmp.begin();
            nit++;
            while (tit != tmp.end())
            {
                ZRangeSpec range;
                range.contain_min = true;
                range.contain_max = true;
                range.min.SetInt64(tit->first);
                range.max.SetInt64(tit->second);
                while (nit != tmp.end() && nit->first == range.max.value.iv)
                {
                    range.max.SetInt64(nit->second);
                    nit++;
                    tit++;
                }
                range_array.push_back(range);
                nit++;
                tit++;
            }

            DEBUG_LOG("After areas merging, reduce searching area size from %u to %u", ress.size(), range_array.size());
            std::vector<ZRangeSpec>::iterator hit = range_array.begin();
            ZSetIterator* iter = NULL;
            while (hit != range_array.end())
            {
                ZRangeSpec& range = *hit;
                uint64 t1 = get_current_epoch_millis();
                ZSetRangeByScore(ctx, meta, range, fetch_options, iter);
                uint64 t2 = get_current_epoch_millis();
                DEBUG_LOG("####Cost %llums to range fetch", t2 - t1);
                hit++;
            }
            DELETE(iter);
        }
        DEBUG_LOG("####Step2: Cost %lluus", get_current_epoch_micros() - start_time);
        uint32 outrange = 0;
        LocationDeque::iterator lit = fetch_options.locs.begin();
        DataArray::iterator vit = fetch_options.results.begin();
        while (vit != fetch_options.results.end())
        {
            Location& loc = *lit;
            GeoPoint point;
            point.x = loc.x;
            point.y = loc.y;
            /*
             * distance accuracy is 0.2m
             */
            if (GeoHashHelper::GetDistanceSquareIfInRadius(GEO_MERCATOR_TYPE, x, y, point.x, point.y, options.radius,
                    point.distance, 0.2))
            {
                vit->GetDecodeString(point.value);
                /*
                 * filter by exclude/include
                 */
                if (!options.includes.empty() || !options.excludes.empty())
                {
                    Data subst;
                    subst.SetString(point.value, false);
                    bool matched = options.includes.empty() ? true : false;
                    if (!options.includes.empty())
                    {
                        StringStringMap::const_iterator sit = options.includes.begin();
                        while (sit != options.includes.end())
                        {
                            Data mv;
                            if (0 != MatchValueByPattern(ctx, sit->first, sit->second, subst, mv))
                            {
                                matched = false;
                                break;
                            }
                            else
                            {
                                matched = true;
                            }
                            sit++;
                        }
                    }
                    if (matched && !options.excludes.empty())
                    {
                        StringStringMap::const_iterator sit = options.excludes.begin();
                        while (sit != options.excludes.end())
                        {
                            Data mv;
                            if (0 == MatchValueByPattern(ctx, sit->first, sit->second, subst, mv))
                            {
                                matched = false;
                                break;
                            }
                            else
                            {
                                matched = true;
                            }
                            sit++;
                        }
                    }
                    if (matched)
                    {
                        points.push_back(point);
                    }
                }
                else
                {
                    points.push_back(point);
                }
            }
            else
            {
                outrange++;
            }
            vit++;
            lit++;
        }
        DEBUG_LOG("###Result size:%d,  outrange:%d", points.size(), outrange);
        DEBUG_LOG("####Step3: Cost %lluus", get_current_epoch_micros() - start_time);
        if (!options.nosort)
        {
            std::sort(points.begin(), points.end(), options.asc ? less_by_distance : great_by_distance);
        }
        DEBUG_LOG("####Step3.5: Cost %lluus", get_current_epoch_micros() - start_time);
        if (options.offset > 0)
        {
            if ((uint32) options.offset > points.size())
            {
                points.clear();
            }
            else
            {
                GeoPointArray::iterator start = points.begin() + options.offset;
                points.erase(points.begin(), start);
            }
        }
        if (options.limit > 0)
        {
            if ((uint32) options.limit < points.size())
            {
                GeoPointArray::iterator end = points.begin() + options.limit;
                points.erase(end, points.end());
            }
        }
        DEBUG_LOG("####Step4: Cost %lluus", get_current_epoch_micros() - start_time);
        ValueObjectMap meta_cache;
        GeoPointArray::iterator pit = points.begin();
        while (pit != points.end())
        {
            RedisReply& r = ctx.reply.AddMember();
            fill_str_reply(r, pit->value);
            GeoGetOptionArray::const_iterator ait = options.get_patterns.begin();
            while (ait != options.get_patterns.end())
            {
                if (ait->get_distances)
                {
                    RedisReply& rr = ctx.reply.AddMember();
                    rr.type = REDIS_REPLY_STRING;
                    char dbuf[128];
                    int dlen = snprintf(dbuf, sizeof(dbuf), "%.2f", sqrt(pit->distance));
                    rr.str.assign(dbuf, dlen);
                }
                else if (ait->get_coodinates)
                {
                    if (options.coord_type == GEO_WGS84_TYPE)
                    {
                        pit->x = GeoHashHelper::GetWGS84X(pit->x);
                        pit->y = GeoHashHelper::GetWGS84Y(pit->y);
                    }
                    RedisReply& rr1 = ctx.reply.AddMember();
                    RedisReply& rr2 = ctx.reply.AddMember();
                    if (options.coord_type == GEO_WGS84_TYPE)
                    {
                        fill_double_reply(rr1, pit->x);
                        fill_double_reply(rr2, pit->y);
                    }
                    else
                    {
                        char dbuf[128];
                        int dlen = snprintf(dbuf, sizeof(dbuf), "%.2f", pit->x);
                        rr1.type = REDIS_REPLY_STRING;
                        rr1.str.assign(dbuf, dlen);
                        dlen = snprintf(dbuf, sizeof(dbuf), "%.2f", pit->y);
                        rr2.type = REDIS_REPLY_STRING;
                        rr2.str.assign(dbuf, dlen);
                    }
                }
                else if (ait->hgetall)
                {
                    std::string keystr(ait->get_pattern.data(), ait->get_pattern.size());
                    string_replace(keystr, "*", pit->value);
                    RedisReply& rr = ctx.reply.AddMember();
                    rr.type = REDIS_REPLY_ARRAY;
                    HashGetAll(ctx, keystr, rr);
                }
                else
                {
                    Data v, attr;
                    v.SetString(pit->value, false);
                    GetValueByPattern(ctx, ait->get_pattern, v, attr, &meta_cache);
                    RedisReply& rr = ctx.reply.AddMember();
                    fill_value_reply(rr, attr);
                }
                ait++;
            }
            pit++;
        }
        DEBUG_LOG("####Step5: Cost %lluus", get_current_epoch_micros() - start_time);
        uint64 end_time = get_current_epoch_micros();
        DEBUG_LOG("Cost %llu microseconds to search.", end_time - start_time);
        return points.size();
    }