Configure.h 8.6 KB
Newer Older
W
wangguibao 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
/***************************************************************************
 * 
 * Copyright (c) 2008 Baidu.com, Inc. All Rights Reserved
 * $Id: Configure.h,v 1.15 2010/04/13 09:59:41 scmpf Exp $ 
 * 
 **************************************************************************/



/**
 * @file Configure.h
 * @author yingxiang(com@baidu.com)
 * @date 2008/12/21 17:59:12
 * @version $Revision: 1.15 $ 
 * @brief 新的Configure库
 * 			更多资料请参见:
 * 			http://com.baidu.com/twiki/bin/view/Main/LibConfig
 *  
 **/


#ifndef  __CONFIGURE_H_
#define  __CONFIGURE_H_

#include "ConfigGroup.h"
#include "sys/uio.h"
#include <vector>

#define CONFIG_GLOBAL "GLOBAL"
#define CONFIG_INCLUDE "$include"

namespace confIDL{
	struct idl_t;
}
namespace comcfg{
	const int MAX_INCLUDE_DEPTH = 1;
	class Reader;
	enum{
		CONFIG_VERSION_1_0,	//Config Version 1.0
	};
	/**
	 * @brief 配置句柄,其实是一个全局的[GLOBAL]配置组
	 *
	 * Configure是immutable的,即:无法修改,无法复用
	 *  所以load, rebuild, loadIVar三个接口互斥
	 * 要重新load,必须创建一个新的Configure句柄进行操作 
	 *
	 */
	class Configure : public ConfigGroup{
		public:
			/**
			 * @brief 从指定的文件中载入配置文件和约束文件
			 *
			 * @param [in] path   : const char* 配置文件的路径
			 * @param [in] conf   : const char* 配置文件名
			 * @param [in] range   : const char* 约束文件
			 * @param [in] version   : int 文件格式的版本(暂未使用)
			 * @return  int  0表示成功,其余为失败
			 * 				bsl::CONSTRAINT_ERROR  约束检查错误(如果不关心约束,可无视此错误)
			 * 				bsl::CONFIG_ERROR 配置文件解析错误
			 * 				bsl::ERROR 其它错误
			 * @retval   
			 * @see 
			 * @author yingxiang
			 * @date 2008/12/30 01:36:54
			 **/
			int load(const char * path, const char * conf, const char * range = NULL, int version = CONFIG_VERSION_1_0);
			/**
			 * @brief 从指定的文件中载入配置文件和约束文件,并检查是否有group重名情况,最后打印到日志
			 * 			默认行为与load()接口相同
			 *
			 * @param [in] path   : const char* 配置文件的路径
			 * @param [in] conf   : const char* 配置文件名
			 * @param [in] range   : const char* 约束文件
			 * @param [in] dupLevel  : enum GROUP_DUP_LEVEL 指定的重名等级,下列值之一
			 *				0: GROUP_DUP_LEVEL0 不检测是否有重名,与原接口行为相同,不打印
			 *				1: GROUP_DUP_LEVEL1 检测第一级group是否重名
			 *				2: GROUP_DUP_LEVEL2 检测所有深度下group是否重名
			 *				3: GROUP_DUP_LEVEL3 记录所有group名
			 * @param [in] version   : int 文件格式的版本(暂未使用)
			 * @return  int  0表示成功,其他值为失败
			 * 				bsl::CONSTRAINT_ERROR  约束检查错误(如果不关心约束,可无视此错误)
			 * 				bsl::CONFIG_ERROR 配置文件解析错误
			 * 				bsl::ERROR 其它错误
			 *              DUPLICATED_GROUP 有组重名,在GROUP_DUP_LEVEL0和GROUP_DUP_LEVEL3下,正常则返回0
			 * @retval   
			 * @see 
			 * @author linjieqiong 
			 * @date 20012/12/28 11:36:54
			 **/
			int load_ex(const char * path, const char * conf, const char * range = NULL,
					int dupLevel = GROUP_DUP_LEVEL0, int version = CONFIG_VERSION_1_0);
			/**
			 * @brief 从指定的文件中载入配置文件和约束文件,如果存在未被约束的配置项,则打印并报错
			 *
			 * @param [in] path   : const char* 配置文件的路径
			 * @param [in] conf   : const char* 配置文件名
			 * @param [in] range   : const char* 约束文件,如果指定了约束文件,则会在会后打印出未被约束的配置项
			 * @param [in] version   : int 文件格式的版本(暂未使用)
			 * @return  int  0表示成功,其余为失败
			 * 				bsl::CONSTRAINT_ERROR  约束检查错误(不满足约束,存在未被约束的配置项)(如果不关心约束,可无视此错误)
			 * 				bsl::CONFIG_ERROR 配置文件解析错误
			 * 				bsl::ERROR 其它错误
			 * @retval   
			 * @see 
			 * @author linjieqiong
			 * @date 2013/01/06 21:36:54
			 **/
			int load_ex2(const char * path, const char * conf, const char * range = NULL, int version = CONFIG_VERSION_1_0);
			/**
			 * @brief 将数据串行化到一个字节流,可以发网网络
			 * 			如果将这个字节流直接写入磁盘文件,不可以直接load回来,而需要读取后再rebuild
			 * @note 本api只能序列化原始配置文件镜像或ivar,不能反映在内存中对configure对象的修改
			 *			如需序列化实时内容,请使用dump_ex()
			 *
			 * @param [out] size_t * : 输出的字节流长度
			 * @return  char* 输出的字节流
			 * @retval   
			 * @see 
			 * @author yingxiang
			 * @date 2008/12/30 01:38:35
			 **/
			char * dump(size_t *);

			/**
			 * @brief 序列化configure对象的实时内存内容
			 *
			 * @param [in] buf	: dump_ex()输出的位置
			 * @param [in] bufsize	: buf的长度
			 * @param [in] restoreComment	: const int
			 *			0 RC_COMMENT 还原配置文件中的注释到输出
			 *			1 RC_NO_COMMENT 不还原配置文件中的注释内容到输出
			 *			2 RC_POSITION 还原的同时标记配置项在配置文件中的位置,格式: 
			 *					#this is the original comment
			 *					#[FILE:LINE]
			 *					[group]
			 *					#[FILE:LINE]
			 *					key : value
			 *
			 * @return int 写入buf的数据长度
			 * 			如果发生错误,返回-1
			 *			如果buf不够,返回实际长度的相反数
			 *			自动添加\0
			 *
			 * @author linjieqiong
			 * @version 1.2.9
			 * @date 2013/04/24 14:56:31
			 */
			int dump_ex(char *buf, const size_t bufsize,  const int restoreComment = 0);

			/**
			 * @brief 根据dump的字节流创建Configure
			 * 		根据字节流重建一个Configure的步骤是:
			 * 		1,getRebuildBuffer(size) 获取一个内部缓冲区
			 * 		2,将字节流中的数据拷贝到这个缓冲区
			 * 		3,调用rebuild重建数据
			 *
			 * 		调用本接口会清空现有的数据。
			 *
			 * @param [in] size   : size_t 字节流长度
			 * @return  char* 缓冲区
			 * @retval   
			 * @see 
			 * @author yingxiang
			 * @date 2008/12/30 01:39:38
			 **/
			char * getRebuildBuffer(size_t size);
			/**
			 * @brief 根据获得的字节流重建Configure数据
			 *
			 * @return  int 0为成功,其他为失败
			 * @retval   
			 * @see 
			 * @author yingxiang
			 * @date 2008/12/30 01:43:05
			 **/
			int rebuild();
			/**
			 * @brief 检查所有配置文件的最后更新时间(包括被$include)的配置文件
			 *        $include 限制层数为:MAX_INCLUDE_DEPTH
			 *        在执行lastConfigModify(),应确保原来的配置文件都没有被删除
			 *
			 * @return  time_t 所有配置文件中的最后更新时间
			 *                 返回0表示出错
			 * @retval   
			 * @see 
			 * @author yingxiang
			 * @date 2009/03/10 14:23:47
			**/
			time_t lastConfigModify();
			/**
			 * @brief 从一个IVar载入配置文件的数据
			 *        本接口与load/rebuild互斥
			 *        这个IVar必须是一个Dict类型
			 *
			 * @return  int 0成功,其余失败
			 * @retval   
			 * @see 
			 * @author yingxiang
			 * @date 2009/03/11 17:29:56
			**/
			int loadIVar(const bsl::var::IVar & );
			/**
			 * @brief 用约束文件检查一次
			 * @param [in] range   : const char* 约束文件
			 * @param [in] version   : int 文件格式的版本(暂未使用)
			 * @return  int  0表示成功,其余为失败
			 * 				bsl::CONSTRAINT_ERROR  约束检查错误
			 * 				bsl::ERROR 其它错误
			 **/
			int check_once(const char * range, int version = CONFIG_VERSION_1_0);
			/**
			 * @brief 检查conf文件中所有unit是否被约束,如果存在未被约束的项,则打印并返回错误
			 *
			 * @return  int 0 成功,其他是错误号
			 * 				bsl::CONSTRAINT_ERROR 约束检查错误
			 * @author linjieqiong
			 * @date 2013/01/07 17:32:10
 			 **/
			int checkConstraint();
			/**
			 * @brief 获取一个key的约束函数列表,注意group和array类型的约束函数是无作用的
			 * @param [in] key_path : const char* 该key在conf文件中的完整路径 
			 * @param [in] range   : const char* 约束文件,
			 * 				如果非空,先进行约束检查;
			 *				如果为空,将使用最近一次load类函数或check_once()函数所使用的约束文件
			 *
			 * @return  int 0 成功,其他是错误号
			 * 				bsl::CONSTRAINT_ERROR  约束检查错误
			 * 				bsl::ERROR 其它错误
			 * 
			 * @author linjieqiong
			 * @date 2013/01/10 10:50:00 
 			 **/
			int printKeyConstraint(const char *key_path, const char *range = NULL);

			virtual  ConfigUnit & operator= (ConfigUnit & unit) {
				return ConfigUnit::operator=(unit);
			}

			Configure();
			~Configure();
		protected:

			int load_1_0(const char * path, const char * conf, const char *range);
			void pushSubReader(const char * conf, int level = -1);
			friend class Reader;
			friend class Constraint;
			friend class ConfigGroup;
			friend class ConfigUnit;
			friend struct dump_conf;
			friend int cb_dumpConf(ConfigUnit *, void *);

			struct ReaderNode{//每一个conf文件
				str_t filename;
				Reader * reader;
				int level;
			};
			std::vector <ReaderNode *> _readers;
			str_t _path;
			Reader * _cur_reader;//当前在处理的文件
			int _cur_level;//当前文件的深度($include的层次)
			char * _dump_buffer;
			size_t _dump_size;
			confIDL::idl_t * _idl;
			void changeSection(str_t str);
			void pushPair(const str_t& key, const str_t& value);
			
			ConfigGroup* _section;
			//depth是一个调试变量
			int _depth;
	};
}



#endif  //__CONFIGURE_H_

/* vim: set ts=4 sw=4 sts=4 tw=100 */