prefix = $prefix; }//End Function protected function _connectMongoDB() { if (!is_object(self::$_mongodb)) { $this->_init(); } } protected function _init() { $server = defined('MONGODB_SERVER_CONFIG')?MONGODB_SERVER_CONFIG:"mongodb://localhost:27017"; $option = defined('MONGODB_OPTION_CONFIG')?eval(MONGODB_OPTION_CONFIG):array("connect" => TRUE); $m = self::getMongoClient($server, $option); $db = $m->erp; //todo 需要改成config配置 self::$_mongodb = $db->selectCollection(base_kvstore::kvprefix()); } static protected function getMongoClient($seeds = "", $options = array(), $retry = 3) { try { return new MongoClient($seeds, $options); } catch(Exception $e) { } if ($retry > 0) { return self::getMongoClient($seeds, $options, --$retry); } throw new Exception("I've tried several times getting MongoClient.. Is mongod really running?"); } /** * fetch * @param mixed $key key * @param mixed $value value * @param mixed $timeout_version timeout_version * @return mixed 返回值 */ public function fetch($key, &$value, $timeout_version=null) { $_interKey = $this->create_key($key); $store = cachecore::fetch($_interKey); if ($store===false) { if (self::__DEBUG) { self::$_rd ++ ; echo sprintf('Read %3d : %s _ %s
', self::$_rd, $this->prefix, $key); } $this->_connectMongoDB(); MongoCursor::$slaveOkay = true; $store = self::$_mongodb->findOne(array('key'=>$_interKey)); //更新内容到缓存服务器 if ($store) { cachecore::store($_interKey, serialize($store), 864000); } else { cachecore::store($_interKey, '', 3600); } } else { //兼容原有TT存储的序列化数据 if (!is_array($store)) { $store = unserialize($store); } } if(!empty($store) && $timeout_version < $store['dateline']){ if($store['ttl'] > 0 && ($store['dateline']+$store['ttl']) < time()){ return false; } $value = $store['value']; return true; } return false; }//End Function /** * store * @param mixed $key key * @param mixed $value value * @param mixed $ttl ttl * @return mixed 返回值 */ public function store($key, $value, $ttl=0) { $_interKey = $this->create_key($key); $store['value'] = $this->_encoding($value); $store['dateline'] = time(); $store['ttl'] = $ttl; $store['key'] = $_interKey; $store['o_key'] = $key; $store['kvfix'] = base_kvstore::kvprefix(); $store['prefix'] = $this->prefix; //先在Memcache中缓存一份 cachecore::store($_interKey, $store, 864000); if (self::__DEBUG) { self::$_wd ++ ; echo sprintf('Write %3d : %s _ %s
', self::$_wd, $this->prefix, $key); } $this->_connectMongoDB(); $res = self::$_mongodb->update(array('key'=>$_interKey), $store, array("upsert" => true)); return $res; }//End Function /** * 删除 * @param mixed $key key * @return mixed 返回值 */ public function delete($key) { $_interKey = $this->create_key($key); cachecore::store($_interKey, '',1); $this->_connectMongoDB(); return self::$_mongodb->remove(array('key'=>$_interKey)); }//End Function /** * recovery * @param mixed $record record * @return mixed 返回值 */ public function recovery($record) { if (isset($record['o_key']) && !empty($record['o_key'])) { $_interKey = $this->create_key($record['o_key']); } else { $_interKey = $this->create_key($record['key']); } $store['key'] = $_interKey; $store['o_key'] = $record['o_key'] ? $record['o_key'] : $record['key']; $store['value'] = $this->_encoding($record['value']); $store['dateline'] = $record['dateline']; $store['ttl'] = $record['ttl']; $store['kvfix'] = $record['kvfix'] ? $record['kvfix'] : base_kvstore::kvprefix(); $store['prefix'] = $record['prefix'] ? $record['prefix'] : $this->prefix; if (self::__DEBUG) { self::$_cd ++ ; echo sprintf('Recovery %3d : %s _ %s
', self::$_cd, $this->prefix, $store['o_key']); } $this->_connectMongoDB(); $res = self::$_mongodb->update(array('key'=>$_interKey), $store, array("upsert" => true)); return $res; }//End Function /** * persistence * @param mixed $dateline dateline * @return mixed 返回值 */ public function persistence($dateline = 0) { $db = kernel::database(); $this->_connectMongoDB(); $cursors = self::$_mongodb->find(); foreach ($cursors as $doc) { $isNew = $this->_getUpdateType($doc); $db->exec($this->_getKvSql($doc, $isNew)); } } private function _getKvSql($doc, $isnew) { $fields = array(); $fields['prefix'] = $doc['prefix']; $fields['key'] = $doc['o_key']; $fields['value'] = serialize($doc['value']); $fields['dateline'] = $doc['dateline']; $fields['ttl'] = $doc['ttl']; foreach($fields as $field => $value) { $_tmp[] = sprintf("`%s` = '%s'", $field, mysql_escape_string($value)); } if ($isnew) { return sprintf("INSERT INTO sdb_base_kvstore SET %s", join(' ,', $_tmp)); } else { return sprintf("UPDATE sdb_base_kvstore SET %s WHERE `prefix`='%s' AND `key`='%s'", join(' ,', $_tmp), mysql_escape_string($doc['prefix']), mysql_escape_string($doc['o_key'])); } } private function _getUpdateType($doc) { $sqlStr = sprintf("SELECT count(*) as c from sdb_base_kvstore WHERE `prefix`='%s' AND `key`='%s'", mysql_escape_string($doc['prefix']), mysql_escape_string($doc['o_key'])); $count = kernel::database()->count($sqlStr); return ($count > 0 ) ? false : true ; } private function _encoding($val) { if (!empty($val)) { if (is_array($val)) { foreach ($val as $k => $v) { $val[$k] = $this->_encoding($v); } return $val; } else { return mb_convert_encoding($val,'UTF-8','auto'); } } else { return $val; } } }//End Class