RedisServantGroup *RedisProxy::group(const char *name) const { for (int i = 0; i < groupCount(); ++i) { RedisServantGroup* p = group(i); if (strcmp(name, p->groupName()) == 0) { return p; } } return NULL; }
bool CRedisProxyCfg::saveProxyLastState(RedisProxy* proxy) { TiXmlElement* pRootNode = (TiXmlElement*)m_operateXmlPointer->get_rootElement(); string nodeHash = "hash_mapping"; TiXmlElement* pOldHashMap; if (GetNodePointerByName(pRootNode, nodeHash, pOldHashMap)) { pRootNode->RemoveChild(pOldHashMap); } TiXmlElement hashMappingNode("hash_mapping"); for (int i = 0; i < proxy->slotCount(); ++i) { TiXmlElement hashNode("hash"); hashNode.SetAttribute("value", i); hashNode.SetAttribute("group_name", proxy->groupBySlot(i)->groupName()); hashMappingNode.InsertEndChild(hashNode); } pRootNode->InsertEndChild(hashMappingNode); // key mapping string nodeKey = "key_mapping"; TiXmlElement* pKey; if (GetNodePointerByName(pRootNode, nodeKey, pKey)) { pRootNode->RemoveChild(pKey); } TiXmlElement keyMappingNode("key_mapping"); StringMap<RedisServantGroup*>& keyMapping = proxy->keyMapping(); StringMap<RedisServantGroup*>::iterator it = keyMapping.begin(); for (; it != keyMapping.end(); ++it) { String key = it->first; TiXmlElement keyNode("key"); keyNode.SetAttribute("key_name", key.data()); RedisServantGroup* group = it->second; if (group != NULL) { keyNode.SetAttribute("group_name", group->groupName()); } keyMappingNode.InsertEndChild(keyNode); } pRootNode->InsertEndChild(keyMappingNode); // add time time_t now = time(NULL); char fileName[512]; struct tm* current_time = localtime(&now); sprintf(fileName,"onecache%d%02d%02d%02d.xml", current_time->tm_year + 1900, current_time->tm_mon + 1, current_time->tm_mday, current_time->tm_hour); bool ok = m_operateXmlPointer->m_docPointer->SaveFile(fileName); return ok; }
void RedisProxy::handleClientPacket(const char *key, int len, ClientPacket *packet) { RedisServantGroup* group = mapToGroup(key, len); if (!group) { packet->setFinishedState(ClientPacket::RequestError); return; } RedisServant* servant = group->findUsableServant(packet); if (servant) { servant->handle(packet); } else { if (m_autoEjectGroup) { m_groupMutex.lock(); m_proxyManager.setGroupTTL(group, m_groupRetryTime, m_ejectAfterRestoreEnabled); m_groupMutex.unlock(); } packet->setFinishedState(ClientPacket::RequestError); } }
void startOneCache(void) { CRedisProxyCfg* cfg = CRedisProxyCfg::instance(); setupSignal(); EventLoop listenerLoop; bool twemproxyMode = cfg->isTwemproxyMode(); const int points_per_server = 160; const int pointer_per_hash = 4; int slot_index = 0; RedisProxy proxy; proxy.setEventLoop(&listenerLoop); loop = &listenerLoop; CProxyMonitor monitor; proxy.setMonitor(&monitor); const int defaultPort = 8221; int port = cfg->port(); if (port <= 0) { LOG(Logger::Debug, "Port %d invalid, use default port %d", defaultPort); port = defaultPort; } if (!proxy.run(HostAddress(port))) { exit(APP_EXIT_KEY); } proxy.setTwemproxyModeEnabled(twemproxyMode); EventLoopThreadPool pool; pool.start(cfg->threadNum()); proxy.setEventLoopThreadPool(&pool); const SVipInfo* vipInfo = cfg->vipInfo(); proxy.setVipName(vipInfo->if_alias_name); proxy.setVipAddress(vipInfo->vip_address); proxy.setVipEnabled(vipInfo->enable); const SHashInfo* sHashInfo = cfg->hashInfo(); if (!twemproxyMode) { proxy.setSlotCount(sHashInfo->hash_value_max); } else { proxy.setSlotCount(cfg->groupCnt() * points_per_server); } const GroupOption* groupOption = cfg->groupOption(); proxy.setGroupRetryTime(groupOption->group_retry_time); proxy.setAutoEjectGroupEnabled(groupOption->auto_eject_group); proxy.setEjectAfterRestoreEnabled(groupOption->eject_after_restore); proxy.setPassword(cfg->password()); for (int i = 0; i < cfg->groupCnt(); ++i) { const CGroupInfo* info = cfg->group(i); RedisServantGroup* group = new RedisServantGroup; RedisServantGroupPolicy* policy = RedisServantGroupPolicy::createPolicy(info->groupPolicy()); group->setGroupName(info->groupName()); group->setPolicy(policy); const HostInfoList& hostList = info->hosts(); HostInfoList::const_iterator itHost = hostList.begin(); for (; itHost != hostList.end(); ++itHost) { const CHostInfo& hostInfo = (*itHost); RedisServant* servant = new RedisServant; RedisServant::Option opt; strcpy(opt.name, hostInfo.get_hostName().c_str()); opt.poolSize = hostInfo.get_connectionNum(); opt.reconnInterval = groupOption->backend_retry_interval; opt.maxReconnCount = groupOption->backend_retry_limit; servant->setOption(opt); servant->setRedisAddress(HostAddress(hostInfo.get_ip().c_str(), hostInfo.get_port())); servant->setEventLoop(proxy.eventLoop()); if (hostInfo.get_master()) { group->addMasterRedisServant(servant); } else { group->addSlaveRedisServant(servant); } servant->connectionPool()->setPassword(itHost->passWord()); } group->setEnabled(true); proxy.addRedisGroup(group); if (!twemproxyMode) { for (int i = info->hashMin(); i <= info->hashMax(); ++i) { proxy.setSlot(i, group); } for (int i = 0; i < cfg->hashMapCnt(); ++i) { const CHashMapping* mapping = cfg->hashMapping(i); RedisServantGroup* group = proxy.group(mapping->group_name); proxy.setSlot(mapping->hash_value, group); } } else { Slot* slot = proxy.slotData(); for (int pointer_index = 1; pointer_index <= points_per_server / pointer_per_hash; pointer_index++) { char host[86]; int hostlen = sprintf(host, "%s-%u", group->groupName(), pointer_index - 1); for (int x = 0; x < pointer_per_hash; x++) { slot[slot_index].group = group; slot[slot_index++].value = ketama_hash(host, hostlen, x); } } } } if (twemproxyMode) { LOG(Logger::Debug, "Twemproxy mode. dist=ketama slotcount=%d", proxy.slotCount()); Slot* slot = proxy.slotData(); int slotCount = proxy.slotCount(); qsort(slot, slotCount, sizeof(Slot), slot_item_cmp); } HashFunc func = hashfuncFromName(cfg->hashFunctin().c_str()); proxy.setHashFunction(func); for (int i = 0; i < cfg->keyMapCnt(); ++i) { const CKeyMapping* mapping = cfg->keyMapping(i); RedisServantGroup* group = proxy.group(mapping->group_name); if (group != NULL) { proxy.addGroupKeyMapping(mapping->key, strlen(mapping->key), group); } } LOG(Logger::Message, "Start the %s on port %d. PID: %d", APP_NAME, port, getpid()); listenerLoop.exec(); }