You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by hu...@apache.org on 2019/07/29 08:02:33 UTC

[dubbo-php-framework] 02/28: submit code

This is an automated email from the ASF dual-hosted git repository.

huxing pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-php-framework.git

commit e8ad24725e6d8155b008208db3c8252712d41bec
Author: zackhu <za...@lexinfintech.com>
AuthorDate: Thu Jun 28 16:30:26 2018 +0800

    submit code
---
 README.md                                          |  13 +
 agent/src/c/Makefile                               |   8 +
 agent/src/c/common/fsof_global.h                   |  40 +
 agent/src/c/common/fsof_url.c                      |  97 +++
 agent/src/c/common/fsof_url.h                      |  22 +
 agent/src/c/common/fsof_util.c                     | 149 ++++
 agent/src/c/common/fsof_util.h                     |  25 +
 agent/src/c/common/strmap.c                        | 530 ++++++++++++++
 agent/src/c/common/strmap.h                        | 366 ++++++++++
 agent/src/c/include/hiredis/adapters/ae.h          | 127 ++++
 agent/src/c/include/hiredis/adapters/glib.h        | 169 +++++
 agent/src/c/include/hiredis/adapters/ivykis.h      |  81 ++
 agent/src/c/include/hiredis/adapters/libev.h       | 147 ++++
 agent/src/c/include/hiredis/adapters/libevent.h    | 108 +++
 agent/src/c/include/hiredis/adapters/libuv.h       | 121 +++
 agent/src/c/include/hiredis/adapters/macosx.h      | 114 +++
 agent/src/c/include/hiredis/adapters/qt.h          | 135 ++++
 agent/src/c/include/hiredis/async.h                | 129 ++++
 agent/src/c/include/hiredis/hiredis.h              | 223 ++++++
 agent/src/c/include/hiredis/read.h                 | 111 +++
 agent/src/c/include/hiredis/sds.h                  | 273 +++++++
 agent/src/c/include/zlog.h                         | 265 +++++++
 agent/src/c/lib/libhiredis.a                       | Bin 0 -> 332078 bytes
 agent/src/c/lib/libzlog.a                          | Bin 0 -> 536320 bytes
 agent/src/c/release/agent_log.conf                 |   6 +
 agent/src/c/release/protect_agent_server.sh        |   7 +
 agent/src/c/release/start_agent_server.sh          |  18 +
 agent/src/c/service/fsof_log.c                     |  79 ++
 agent/src/c/service/fsof_log.h                     |  28 +
 agent/src/c/service/fsof_mq.c                      | 155 ++++
 agent/src/c/service/fsof_mq.h                      |  46 ++
 agent/src/c/service/fsof_redis.c                   | 242 ++++++
 agent/src/c/service/fsof_redis.h                   |  32 +
 agent/src/c/service/fsof_zookeeper.c               | 171 +++++
 agent/src/c/service/fsof_zookeeper.h               |  45 ++
 agent/src/c/service/mt_array.c                     |  72 ++
 agent/src/c/service/mt_array.h                     |  31 +
 agent/src/c/src/fsof_main.c                        | 524 +++++++++++++
 api/FSOFApi.php                                    |  68 ++
 arch.png                                           | Bin 0 -> 45859 bytes
 bin/app_admin.php                                  | 584 +++++++++++++++
 bin/restartall.sh                                  |  17 +
 common/BootStrap.php                               |  47 ++
 common/FrameAutoLoader.php                         |  70 ++
 common/config/FSOFCommonUtil.php                   |  75 ++
 common/config/FSOFConfigManager.php                | 228 ++++++
 common/config/FSOFConfigUtil.php                   |  99 +++
 common/config/FSOFConstants.php                    |  34 +
 common/file/FSOFRedis.php                          | 182 +++++
 common/file/FileSystemUtil.php                     | 132 ++++
 common/log/FSOFSystemUtil.php                      |  66 ++
 common/protocol/fsof/DubboParser.php               | 305 ++++++++
 common/protocol/fsof/DubboRequest.php              | 341 +++++++++
 common/protocol/fsof/DubboResponse.php             | 193 +++++
 common/url/FSOFUrl.php                             | 294 ++++++++
 config/app/conf/dev/provider/demo-provider.deploy  |  22 +
 config/app/conf/gray/provider/example.deploy       |  20 +
 config/app/conf/pre/provider/example.deploy        |  22 +
 config/app/conf/pro/provider/example.deploy        |  20 +
 config/global/conf/fsof.ini                        |  34 +
 consumer/FSOFConsumer.php                          | 113 +++
 consumer/FrameAutoLoader.php                       |  70 ++
 consumer/client/FSOFClient4Linux.php               |  91 +++
 consumer/client/IFSOFClient.php                    |  33 +
 consumer/fsof/FSOFProcessor.php                    | 342 +++++++++
 consumer/proxy/Proxy.php                           | 144 ++++
 consumer/proxy/ProxyFactory.php                    | 229 ++++++
 demo/demo-consumer/config/log4php.xml              |  12 +
 demo/demo-consumer/consumer/demo-consumer.consumer |  10 +
 demo/demo-consumer/server/Consumer.php             |  15 +
 demo/demo-provider/BootStrap.php                   |  24 +
 demo/demo-provider/config/log4php.xml              |  12 +
 demo/demo-provider/provider/demo-provider.provider |   9 +
 demo/demo-provider/server/DemoServiceImpl.php      |  18 +
 provider/FSOFProvider.php                          |  86 +++
 provider/FrameAutoLoader.php                       |  70 ++
 provider/common/Console.php                        |  56 ++
 provider/core/app/AppAutoLoader.php                | 129 ++++
 provider/core/app/AppContext.php                   |  84 +++
 provider/core/app/AppLauncher.php                  |  40 +
 provider/core/protocol/BaseProtocol.php            | 116 +++
 provider/core/protocol/BufferedProtocol.php        |  64 ++
 provider/core/protocol/IProtocol.php               |  33 +
 provider/core/server/BaseServer.php                | 812 +++++++++++++++++++++
 provider/core/server/FSOFRegistry.php              | 376 ++++++++++
 provider/core/server/IServer.php                   |  32 +
 provider/core/server/TcpServer.php                 |  32 +
 provider/fsof/FSOFProtocol.php                     | 480 ++++++++++++
 provider/monitor/AppMonitor.php                    | 124 ++++
 provider/monitor/OverloadMonitor.php               |  91 +++
 provider/monitor/ServiceMonitor.php                | 207 ++++++
 provider/shell/StartUp.php                         |  78 ++
 registry/BootStrap.php                             |  28 +
 registry/FrameAutoLoader.php                       |  70 ++
 registry/automatic/ConsumerProxy.php               | 112 +++
 registry/automatic/RegistryService.php             | 103 +++
 registry/automatic/RegistryServiceFactory.php      |  33 +
 registry/automatic/ZookeeperClient.php             | 299 ++++++++
 98 files changed, 12239 insertions(+)

diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7e0c38e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,13 @@
+# dubbo-php-framework
+dubbo-php-framework是一个用于php语言的RPC通讯框架,与dubbo在协议上完全兼容,可同时作为provider端和consumer端,使用zookeeper用于服务注册发现,序列化使用fastjson.
+
+![image](https://github.com/lexin-fintech/dubbo-php-framework/blob/master/arch.png)
+
+## 说明
+* php provider以多进程方式运行,其中worker进程用于处理具体业务,manager进程控制worker进程的生命周期,master进程处理网络IO.
+* agent监听registry中provider地址信息的变更并同步到本地redis,供本机上所有php consumer共享.
+* php consumer、redis、angent三者部署在所有consumer机器上,并且彼此以unix socket通信.
+* provider_admin部署在所有provider机器上,用于控制该机器上所有php provider的生命周期.
+
+
+[Quick start](https://github.com/lexin-fintech/dubbo-php-framework/wiki/Quick-Start)
\ No newline at end of file
diff --git a/agent/src/c/Makefile b/agent/src/c/Makefile
new file mode 100644
index 0000000..a228884
--- /dev/null
+++ b/agent/src/c/Makefile
@@ -0,0 +1,8 @@
+TARGET = release/agent
+CFLAGS = -g -Wall -lpthread -lzookeeper_mt   -L./lib -lhiredis -lzlog  -I./include
+CC = gcc
+$(TARGET):service/fsof_mq.c src/fsof_main.c service/fsof_zookeeper.c common/strmap.c service/fsof_redis.c service/fsof_log.c common/fsof_url.c common/fsof_util.c service/mt_array.c
+	$(CC) $^ $(CFLAGS)  -o $@ 
+.PHONY : clean
+clean:
+	rm -f $(TARGET)
diff --git a/agent/src/c/common/fsof_global.h b/agent/src/c/common/fsof_global.h
new file mode 100644
index 0000000..953c902
--- /dev/null
+++ b/agent/src/c/common/fsof_global.h
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef FSOF_GLOBAL_H
+#define FSOF_GLOBAL_H
+
+#define FSOF_ROOT_NAME "/dubbo"
+#define PROVIDER_NAME "/providers"
+#define PROVIDER_NODE_NAME "providers"
+#define CONSUMER_NAME "/consumers"
+#define ROUTERS_NAME  "/routers"
+#define CONFIGUREATORS_NAME "/configurators"
+#define CONFIGUREATORS_NODE_NAME "configurators"
+#define FSOF_REDIS_CONFIGURATOR_KEY_NAME "override"
+
+#define ZOOKEEPER_HOST "127.0.0.1:2181"
+#define DEFAULT_MAP_COUNT (10)
+#define REDIS_UNIX_SOCK  "/var/fsof/redis.sock"
+
+
+
+struct list {
+    char *value;
+    struct list *next;
+};
+
+#endif
diff --git a/agent/src/c/common/fsof_url.c b/agent/src/c/common/fsof_url.c
new file mode 100644
index 0000000..0cc9887
--- /dev/null
+++ b/agent/src/c/common/fsof_url.c
@@ -0,0 +1,97 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#include "fsof_url.h"
+#include <stdlib.h>
+#include <ctype.h>
+
+char * fsof_url_encode(char const *s, int len, int *new_length) {
+    unsigned char const *from, *end;
+    unsigned char c;
+    from = (unsigned char const*)s;
+    end = (unsigned char const*)s + len;
+    unsigned char *to = (unsigned char *) malloc(3 * len + 1);
+    unsigned char *start = to;
+
+    unsigned char hexchars[] = "0123456789ABCDEF";
+
+    while (from < end) {
+        c = *from++;
+
+        if (c == ' ') {
+            *to++ = '+';
+        } else if ((c < '0' && c != '-' && c != '.')
+                             ||(c < 'A' && c > '9')
+                             ||(c > 'Z' && c < 'a' && c != '_')
+                             ||(c > 'z')) {
+            to[0] = '%';
+            to[1] = hexchars[c >> 4];
+            to[2] = hexchars[c & 15];
+            to += 3;
+        } else {
+            *to++ = c;
+        }
+    }
+
+    *to = 0;
+    if (new_length) {
+        *new_length = to - start;
+    }
+
+    return (char *) start;
+}
+
+int fsof_url_decode(char *str, int len)
+{
+    char *dest = str;
+    char *data = str;
+    int value;
+    int c;
+
+    while (len--) {
+        if (*data == '+') {
+            *dest = ' ';
+        }
+        else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1))
+                                 && isxdigit((int) *(data + 2))) {
+            c = ((unsigned char *)(data+1))[0];
+            if (isupper(c)) {
+                c = tolower(c);
+            }
+
+            value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
+            c = ((unsigned char *)(data+1))[1];
+            if (isupper(c)) {
+                c = tolower(c);
+            }
+
+            value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
+            *dest = (char)value ;
+            data += 2;
+            len -= 2;
+        } else {
+            *dest = *data;
+        }
+        data++;
+        dest++;
+    }
+
+    *dest = '\0';
+    return dest - str;
+
+}
+
+
diff --git a/agent/src/c/common/fsof_url.h b/agent/src/c/common/fsof_url.h
new file mode 100644
index 0000000..6530daa
--- /dev/null
+++ b/agent/src/c/common/fsof_url.h
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef FSOF_URL_H
+#define FSOF_URL_H
+#define URL_ENCODE_BUF_LEN (4 * 1024)
+int fsof_url_decode(char *str, int len);
+char * fsof_url_encode(char const *s, int len, int *new_length);
+#endif
diff --git a/agent/src/c/common/fsof_util.c b/agent/src/c/common/fsof_util.c
new file mode 100644
index 0000000..c1f8cff
--- /dev/null
+++ b/agent/src/c/common/fsof_util.c
@@ -0,0 +1,149 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#include <fcntl.h>
+#include <unistd.h>
+#include "fsof_util.h"
+#include <string.h>
+#include <stdio.h>
+
+char * trim(char * src) {
+    int i = 0;
+    char *begin = src;
+    while(src[i] != '\0') {
+        if(src[i] != ' ') {
+            break;
+        }else {
+            begin++;
+        }
+        i++;
+    }
+
+    for(i = strlen(src)-1; i >= 0;  i--){
+        if(src[i] != ' '){
+            break;
+        }else {
+            src[i] = '\0';
+        }
+    }
+
+    return begin;
+}
+
+char *get_ini_key_string(char *title,char *key,char *filename) {
+    FILE *fp;
+    char szLine[1024]; 
+    static char tmpstr[1024];  
+    char *ret_str = NULL;
+    int rtnval;  
+    int i = 0;   
+    int flag = 0;  
+    char *tmp;  
+    
+    if((fp = fopen(filename, "r")) == NULL)   
+    {   
+        printf("have   no   such   file \n");  
+        return "";   
+    }  
+
+    while(!feof(fp))   
+    {   
+        rtnval = fgetc(fp);   
+        if(rtnval == EOF)   
+        {   
+            break;   
+        }   
+        else   
+        {   
+            szLine[i++] = rtnval;   
+        }   
+        if(rtnval == '\n')   
+        {   
+            szLine[--i] = '\0';  
+            i = 0;   
+            tmp = strchr(szLine, '=');   
+                                      
+            if(( tmp != NULL )&&(flag == 1)) { 
+                 if(strstr(szLine,key)!=NULL)   
+                 {   
+                    if ('#' == szLine[0])  
+                    {  
+                    }  
+                    else if ( '/' == szLine[0] && '/' == szLine[1] )  
+                    {  
+                                                                                                                                       
+                    }  
+                    else  
+                    {  
+                        strcpy(tmpstr,tmp+1);   
+                        fclose(fp);  
+                        ret_str = trim(tmpstr);
+                        return ret_str;   
+                    }  
+                 }  
+            }
+            else {
+                strcpy(tmpstr,"[");   
+                strcat(tmpstr,title);   
+                strcat(tmpstr,"]");  
+                if( strncmp(tmpstr,szLine,strlen(tmpstr)) == 0 )   
+                {  
+                    flag = 1;   
+                }  
+            }
+        }
+    }
+
+    fclose(fp);   
+    return ""; 
+                       
+}
+
+
+int get_current_path(char buf[],char *pFileName,int depth) {
+    char pidfile[64] = {0};  
+    char *p = NULL;
+    int bytes = 0;  
+    int fd = 0;  
+    int cur_dp = 0;
+
+    sprintf(pidfile, "/proc/%d/cmdline", getpid());  
+    fd = open(pidfile, O_RDONLY, 0);  
+    bytes = read(fd, buf, 256);  
+    close(fd);
+
+    p = &buf[strlen(buf)];  
+_AGAIN:
+    while ('/' != *p) {
+        *p = '\0';
+        if ((p - buf) == 0) {
+            return  1; //path now null,can't get depth dir
+        }
+        p--;
+    }
+
+    cur_dp++;
+    if (cur_dp < depth) {
+        p--;
+        goto  _AGAIN;
+    }
+    p++;
+
+    memcpy(p,pFileName,strlen(pFileName));  
+	p += strlen(pFileName);
+	*p = '\0';
+    return 0;
+}
diff --git a/agent/src/c/common/fsof_util.h b/agent/src/c/common/fsof_util.h
new file mode 100644
index 0000000..136dfc8
--- /dev/null
+++ b/agent/src/c/common/fsof_util.h
@@ -0,0 +1,25 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef FSOF_UTIL_H
+#define FSOF_UTIL_H
+
+#define MAX_CONFIG_PATH_LEN 260
+
+char *get_ini_key_string(char *title,char *key,char *filename);
+int get_current_path(char buf[],char *pFileName,int depth);
+
+#endif
diff --git a/agent/src/c/common/strmap.c b/agent/src/c/common/strmap.c
new file mode 100644
index 0000000..7716c19
--- /dev/null
+++ b/agent/src/c/common/strmap.c
@@ -0,0 +1,530 @@
+/*
+ *    strmap version 2.0.1
+ *
+ *    ANSI C hash table for strings.
+ *
+ *	  Version history:
+ *	  1.0.0 - initial release
+ *	  2.0.0 - changed function prefix from strmap to sm to ensure
+ *	      ANSI C compatibility 
+ *	  2.0.1 - improved documentation 
+ *
+ *    strmap.c
+ *
+ *    Copyright (c) 2009, 2011, 2013 Per Ola Kristensson.
+ *
+ *    Per Ola Kristensson <po...@cam.ac.uk> 
+ *    Inference Group, Department of Physics
+ *    University of Cambridge
+ *    Cavendish Laboratory
+ *    JJ Thomson Avenue
+ *    CB3 0HE Cambridge
+ *    United Kingdom
+ *
+ *    strmap is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    strmap is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public License
+ *    along with strmap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include "strmap.h"
+
+typedef struct Pair Pair;
+
+typedef struct Bucket Bucket;
+
+struct Pair {
+	char *key;
+	struct map_object *value;
+};
+
+struct Bucket {
+	unsigned int count;
+	Pair *pairs;
+};
+
+struct StrMap {
+	unsigned int count;
+	Bucket *buckets;
+};
+
+static Pair * get_pair(Bucket *bucket, const char *key);
+static unsigned long hash(const char *str);
+
+StrMap * sm_new(unsigned int capacity)
+{
+	StrMap *map;
+	
+	map = malloc(sizeof(StrMap));
+	if (map == NULL) {
+		return NULL;
+	}
+	map->count = capacity;
+	map->buckets = malloc(map->count * sizeof(Bucket));
+	if (map->buckets == NULL) {
+		free(map);
+		return NULL;
+	}
+	memset(map->buckets, 0, map->count * sizeof(Bucket));
+	return map;
+}
+
+void sm_delete(StrMap *map)
+{
+	unsigned int i, j, n, m;
+	Bucket *bucket;
+	Pair *pair;
+
+	if (map == NULL) {
+		return;
+	}
+	n = map->count;
+	bucket = map->buckets;
+	i = 0;
+	while (i < n) {
+		m = bucket->count;
+		pair = bucket->pairs;
+		j = 0;
+		while(j < m) {
+			free(pair->key);
+			free(pair->value);
+			pair++;
+			j++;
+		}
+		free(bucket->pairs);
+		bucket++;
+		i++;
+	}
+	free(map->buckets);
+	free(map);
+}
+
+int sm_del_pair(const StrMap *map, const char *key) {
+	unsigned int index;
+	Bucket *bucket;
+	Pair *pair;
+
+	if (map == NULL) {
+		return 0;
+	}
+	if (key == NULL) {
+		return 0;
+	}
+	index = hash(key) % map->count;
+	bucket = &(map->buckets[index]);
+	pair = get_pair(bucket, key);
+	if (pair == NULL) {
+		return 0;
+	}
+
+    return 0;
+}
+int sm_get(const StrMap *map, const char *key, struct map_object **out_buf)
+{
+	unsigned int index;
+	Bucket *bucket;
+	Pair *pair;
+
+	if (map == NULL) {
+		return 0;
+	}
+	if (key == NULL) {
+		return 0;
+	}
+	index = hash(key) % map->count;
+	bucket = &(map->buckets[index]);
+	pair = get_pair(bucket, key);
+	if (pair == NULL) {
+		return 0;
+	}
+	if (out_buf == NULL) {
+		return sizeof(*(pair->value));
+	}
+	if (out_buf == NULL) {
+		return 0;
+	}
+
+	//memcpy(out_buf, pair->value,sizeof(*out_buf));
+    *out_buf = pair->value;
+	return 1;
+}
+
+int sm_exists(const StrMap *map, const char *key)
+{
+	unsigned int index;
+	Bucket *bucket;
+	Pair *pair;
+
+	if (map == NULL) {
+		return 0;
+	}
+	if (key == NULL) {
+		return 0;
+	}
+	index = hash(key) % map->count;
+	bucket = &(map->buckets[index]);
+	pair = get_pair(bucket, key);
+	if (pair == NULL) {
+		return 0;
+	}
+	return 1;
+}
+
+int sm_put(StrMap *map, const char *key, struct map_object *value)
+{
+	unsigned int key_len, value_len, index;
+	Bucket *bucket;
+	Pair *tmp_pairs, *pair;
+	char *new_key;
+    struct map_object *new_value;
+
+	if (map == NULL) {
+		return 0;
+	}
+	if (key == NULL || value == NULL) {
+		return 0;
+	}
+	key_len = strlen(key);
+	value_len = sizeof(*value);
+	/* Get a pointer to the bucket the key string hashes to */
+	index = hash(key) % map->count;
+	bucket = &(map->buckets[index]);
+	/* Check if we can handle insertion by simply replacing
+	 * an existing value in a key-value pair in the bucket.
+	 */
+	if ((pair = get_pair(bucket, key)) != NULL) {
+		/* The bucket contains a pair that matches the provided key,
+		 * change the value for that pair to the new value.
+		 */
+			/* If the new value is larger than the old value, re-allocate
+			 * space for the new larger value.
+			 */
+        //memcpy(pair->value,value,sizeof(*value)); 
+        pair->value = value;//add by iceli resign the pointer to new value
+		return 1;
+	}
+	/* Allocate space for a new key and value */
+	new_key = malloc((key_len + 1) * sizeof(char));
+	if (new_key == NULL) {
+		return 0;
+	}
+    /*
+	new_value = malloc(value_len);
+	if (new_value == NULL) {
+		free(new_key);
+		return 0;
+	}
+    */
+    new_value = value;
+	/* Create a key-value pair */
+	if (bucket->count == 0) {
+		/* The bucket is empty, lazily allocate space for a single
+		 * key-value pair.
+		 */
+		bucket->pairs = malloc(sizeof(Pair));
+		if (bucket->pairs == NULL) {
+			free(new_key);
+			free(new_value);
+			return 0;
+		}
+		bucket->count = 1;
+	}
+	else {
+		/* The bucket wasn't empty but no pair existed that matches the provided
+		 * key, so create a new key-value pair.
+		 */
+		tmp_pairs = realloc(bucket->pairs, (bucket->count + 1) * sizeof(Pair));
+		if (tmp_pairs == NULL) {
+			free(new_key);
+			free(new_value);
+			return 0;
+		}
+		bucket->pairs = tmp_pairs;
+		bucket->count++;
+	}
+	/* Get the last pair in the chain for the bucket */
+	pair = &(bucket->pairs[bucket->count - 1]);
+	pair->key = new_key;
+	pair->value = new_value;
+	/* Copy the key and its value into the key-value pair */
+	strcpy(pair->key, key);
+    //memcpy(pair->value,value,value_len);//add by iceli  don't copy the same pointer
+	return 1;
+}
+
+int sm_get_count(const StrMap *map)
+{
+	unsigned int i, j, n, m;
+	unsigned int count;
+	Bucket *bucket;
+	Pair *pair;
+
+	if (map == NULL) {
+		return 0;
+	}
+	bucket = map->buckets;
+	n = map->count;
+	i = 0;
+	count = 0;
+	while (i < n) {
+		pair = bucket->pairs;
+		m = bucket->count;
+		j = 0;
+		while (j < m) {
+			count++;
+			pair++;
+			j++;
+		}
+		bucket++;
+		i++;
+	}
+	return count;
+}
+
+int sm_enum(const StrMap *map, sm_enum_func enum_func, const void *obj)
+{
+	unsigned int i, j, n, m;
+	Bucket *bucket;
+	Pair *pair;
+
+	if (map == NULL) {
+		return 0;
+	}
+	if (enum_func == NULL) {
+		return 0;
+	}
+	bucket = map->buckets;
+	n = map->count;
+	i = 0;
+	while (i < n) {
+		pair = bucket->pairs;
+		m = bucket->count;
+		j = 0;
+		while (j < m) {
+			enum_func(pair->key, pair->value, (struct map_object*)obj);
+			pair++;
+			j++;
+		}
+		bucket++;
+		i++;
+	}
+	return 1;
+}
+
+/*
+ * Returns a pair from the bucket that matches the provided key,
+ * or null if no such pair exist.
+ */
+static Pair * get_pair(Bucket *bucket, const char *key)
+{
+	unsigned int i, n;
+	Pair *pair;
+
+	n = bucket->count;
+	if (n == 0) {
+		return NULL;
+	}
+	pair = bucket->pairs;
+	i = 0;
+	while (i < n) {
+		if (pair->key != NULL && pair->value != NULL) {
+			if (strcmp(pair->key, key) == 0) {
+				return pair;
+			}
+		}
+		pair++;
+		i++;
+	}
+	return NULL;
+}
+
+/*
+ * Returns a hash code for the provided string.
+ */
+static unsigned long hash(const char *str)
+{
+	unsigned long hash = 5381;
+	int c;
+
+	while ((c = *str++)) {
+		hash = ((hash << 5) + hash) + c;
+	}
+	return hash;
+}
+
+/*
+
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+
+*/
diff --git a/agent/src/c/common/strmap.h b/agent/src/c/common/strmap.h
new file mode 100644
index 0000000..9c45ddf
--- /dev/null
+++ b/agent/src/c/common/strmap.h
@@ -0,0 +1,366 @@
+/*
+ *    strmap version 2.0.1
+ *
+ *    ANSI C hash table for strings.
+ *
+ *	  Version history:
+ *	  1.0.0 - initial release
+ *	  2.0.0 - changed function prefix from strmap to sm to ensure
+ *	      ANSI C compatibility
+ *	  2.0.1 - improved documentation 
+ *
+ *    strmap.h
+ *
+ *    Copyright (c) 2009, 2011, 2013 Per Ola Kristensson.
+ *
+ *    Per Ola Kristensson <po...@cam.ac.uk> 
+ *    Inference Group, Department of Physics
+ *    University of Cambridge
+ *    Cavendish Laboratory
+ *    JJ Thomson Avenue
+ *    CB3 0HE Cambridge
+ *    United Kingdom
+ *
+ *    strmap is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    strmap is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public License
+ *    along with strmap.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef _STRMAP_H_
+#define _STRMAP_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#define MAP_OBJECT_CB_TYPE 1
+
+typedef struct StrMap StrMap;
+
+struct map_object {
+    unsigned char type;
+    unsigned char status;
+    void *ptr;
+};
+
+/*
+ * This callback function is called once per key-value when iterating over
+ * all keys associated to values.
+ *
+ * Parameters:
+ *
+ * key: A pointer to a null-terminated C string. The string must not
+ * be modified by the client.
+ *
+ * value: A pointer to a null-terminated C string. The string must
+ * not be modified by the client.
+ *
+ * obj: A pointer to a client-specific object. This parameter may be
+ * null.
+ *
+ * Return value: None.
+ */
+typedef void(*sm_enum_func)(const char *key, const struct map_object *value, const void *obj);
+
+/*
+ * Creates a string map.
+ *
+ * Parameters:
+ *
+ * capacity: The number of top-level slots this string map
+ * should allocate. This parameter must be > 0.
+ *
+ * Return value: A pointer to a string map object, 
+ * or null if a new string map could not be allocated.
+ */
+StrMap * sm_new(unsigned int capacity);
+
+/*
+ * Releases all memory held by a string map object.
+ *
+ * Parameters:
+ *
+ * map: A pointer to a string map. This parameter cannot be null.
+ * If the supplied string map has been previously released, the
+ * behaviour of this function is undefined.
+ *
+ * Return value: None.
+ */
+void sm_delete(StrMap *map);
+
+/*
+ * Returns the value associated with the supplied key.
+ *
+ * Parameters:
+ *
+ * map: A pointer to a string map. This parameter cannot be null.
+ *
+ * key: A pointer to a null-terminated C string. This parameter cannot
+ * be null.
+ *
+ * out_buf: A pointer to an output buffer which will contain the value,
+ * if it exists and fits into the buffer.
+ *
+ * n_out_buf: The size of the output buffer in bytes.
+ *
+ * Return value: If out_buf is set to null and n_out_buf is set to 0 the return
+ * value will be the number of bytes required to store the value (if it exists)
+ * and its null-terminator. For all other parameter configurations the return value
+ * is 1 if an associated value was found and completely copied into the output buffer,
+ * 0 otherwise.
+ */
+int sm_get(const StrMap *map, const char *key, struct map_object **out_buf);
+
+
+int sm_del_pair(const StrMap *map, const char *key);
+
+/*
+ * Queries the existence of a key.
+ *
+ * Parameters:
+ *
+ * map: A pointer to a string map. This parameter cannot be null.
+ *
+ * key: A pointer to a null-terminated C string. This parameter cannot
+ * be null.
+ *
+ * Return value: 1 if the key exists, 0 otherwise.
+ */
+int sm_exists(const StrMap *map, const char *key);
+
+/*
+ * Associates a value with the supplied key. If the key is already
+ * associated with a value, the previous value is replaced.
+ *
+ * Parameters:
+ *
+ * map: A pointer to a string map. This parameter cannot be null.
+ *
+ * key: A pointer to a null-terminated C string. This parameter
+ * cannot be null. The string must have a string length > 0. The
+ * string will be copied.
+ *
+ * value: A pointer to a null-terminated C string. This parameter
+ * cannot be null. The string must have a string length > 0. The
+ * string will be copied.
+ *
+ * Return value: 1 if the association succeeded, 0 otherwise.
+ */
+int sm_put(StrMap *map, const char *key, struct map_object *value);
+
+/*
+ * Returns the number of associations between keys and values.
+ *
+ * Parameters:
+ *
+ * map: A pointer to a string map. This parameter cannot be null.
+ *
+ * Return value: The number of associations between keys and values.
+ */
+int sm_get_count(const StrMap *map);
+
+/*
+ * An enumerator over all associations between keys and values.
+ *
+ * Parameters:
+ *
+ * map: A pointer to a string map. This parameter cannot be null.
+ *
+ * enum_func: A pointer to a callback function that will be
+ * called by this procedure once for every key associated
+ * with a value. This parameter cannot be null.
+ *
+ * obj: A pointer to a client-specific object. This parameter will be
+ * passed back to the client's callback function. This parameter can
+ * be null.
+ *
+ * Return value: 1 if enumeration completed, 0 otherwise.
+ */
+int sm_enum(const StrMap *map, sm_enum_func enum_func, const void *obj);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/*
+
+		   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
+
+*/
\ No newline at end of file
diff --git a/agent/src/c/include/hiredis/adapters/ae.h b/agent/src/c/include/hiredis/adapters/ae.h
new file mode 100644
index 0000000..5c551c2
--- /dev/null
+++ b/agent/src/c/include/hiredis/adapters/ae.h
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIREDIS_AE_H__
+#define __HIREDIS_AE_H__
+#include <sys/types.h>
+#include <ae.h>
+#include "../hiredis.h"
+#include "../async.h"
+
+typedef struct redisAeEvents {
+    redisAsyncContext *context;
+    aeEventLoop *loop;
+    int fd;
+    int reading, writing;
+} redisAeEvents;
+
+static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
+    ((void)el); ((void)fd); ((void)mask);
+
+    redisAeEvents *e = (redisAeEvents*)privdata;
+    redisAsyncHandleRead(e->context);
+}
+
+static void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
+    ((void)el); ((void)fd); ((void)mask);
+
+    redisAeEvents *e = (redisAeEvents*)privdata;
+    redisAsyncHandleWrite(e->context);
+}
+
+static void redisAeAddRead(void *privdata) {
+    redisAeEvents *e = (redisAeEvents*)privdata;
+    aeEventLoop *loop = e->loop;
+    if (!e->reading) {
+        e->reading = 1;
+        aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e);
+    }
+}
+
+static void redisAeDelRead(void *privdata) {
+    redisAeEvents *e = (redisAeEvents*)privdata;
+    aeEventLoop *loop = e->loop;
+    if (e->reading) {
+        e->reading = 0;
+        aeDeleteFileEvent(loop,e->fd,AE_READABLE);
+    }
+}
+
+static void redisAeAddWrite(void *privdata) {
+    redisAeEvents *e = (redisAeEvents*)privdata;
+    aeEventLoop *loop = e->loop;
+    if (!e->writing) {
+        e->writing = 1;
+        aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e);
+    }
+}
+
+static void redisAeDelWrite(void *privdata) {
+    redisAeEvents *e = (redisAeEvents*)privdata;
+    aeEventLoop *loop = e->loop;
+    if (e->writing) {
+        e->writing = 0;
+        aeDeleteFileEvent(loop,e->fd,AE_WRITABLE);
+    }
+}
+
+static void redisAeCleanup(void *privdata) {
+    redisAeEvents *e = (redisAeEvents*)privdata;
+    redisAeDelRead(privdata);
+    redisAeDelWrite(privdata);
+    free(e);
+}
+
+static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {
+    redisContext *c = &(ac->c);
+    redisAeEvents *e;
+
+    /* Nothing should be attached when something is already attached */
+    if (ac->ev.data != NULL)
+        return REDIS_ERR;
+
+    /* Create container for context and r/w events */
+    e = (redisAeEvents*)malloc(sizeof(*e));
+    e->context = ac;
+    e->loop = loop;
+    e->fd = c->fd;
+    e->reading = e->writing = 0;
+
+    /* Register functions to start/stop listening for events */
+    ac->ev.addRead = redisAeAddRead;
+    ac->ev.delRead = redisAeDelRead;
+    ac->ev.addWrite = redisAeAddWrite;
+    ac->ev.delWrite = redisAeDelWrite;
+    ac->ev.cleanup = redisAeCleanup;
+    ac->ev.data = e;
+
+    return REDIS_OK;
+}
+#endif
diff --git a/agent/src/c/include/hiredis/adapters/glib.h b/agent/src/c/include/hiredis/adapters/glib.h
new file mode 100644
index 0000000..f61631b
--- /dev/null
+++ b/agent/src/c/include/hiredis/adapters/glib.h
@@ -0,0 +1,169 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef __HIREDIS_GLIB_H__
+#define __HIREDIS_GLIB_H__
+
+#include <glib.h>
+
+#include "../hiredis.h"
+#include "../async.h"
+
+typedef struct
+{
+    GSource source;
+    redisAsyncContext *ac;
+    GPollFD poll_fd;
+} RedisSource;
+
+static void
+redis_source_add_read (gpointer data)
+{
+    RedisSource *source = (RedisSource *)data;
+    g_return_if_fail(source);
+    source->poll_fd.events |= G_IO_IN;
+    g_main_context_wakeup(g_source_get_context((GSource *)data));
+}
+
+static void
+redis_source_del_read (gpointer data)
+{
+    RedisSource *source = (RedisSource *)data;
+    g_return_if_fail(source);
+    source->poll_fd.events &= ~G_IO_IN;
+    g_main_context_wakeup(g_source_get_context((GSource *)data));
+}
+
+static void
+redis_source_add_write (gpointer data)
+{
+    RedisSource *source = (RedisSource *)data;
+    g_return_if_fail(source);
+    source->poll_fd.events |= G_IO_OUT;
+    g_main_context_wakeup(g_source_get_context((GSource *)data));
+}
+
+static void
+redis_source_del_write (gpointer data)
+{
+    RedisSource *source = (RedisSource *)data;
+    g_return_if_fail(source);
+    source->poll_fd.events &= ~G_IO_OUT;
+    g_main_context_wakeup(g_source_get_context((GSource *)data));
+}
+
+static void
+redis_source_cleanup (gpointer data)
+{
+    RedisSource *source = (RedisSource *)data;
+
+    g_return_if_fail(source);
+
+    redis_source_del_read(source);
+    redis_source_del_write(source);
+    /*
+     * It is not our responsibility to remove ourself from the
+     * current main loop. However, we will remove the GPollFD.
+     */
+    if (source->poll_fd.fd >= 0) {
+        g_source_remove_poll((GSource *)data, &source->poll_fd);
+        source->poll_fd.fd = -1;
+    }
+}
+
+static gboolean
+redis_source_prepare (GSource *source,
+                      gint    *timeout_)
+{
+    RedisSource *redis = (RedisSource *)source;
+    *timeout_ = -1;
+    return !!(redis->poll_fd.events & redis->poll_fd.revents);
+}
+
+static gboolean
+redis_source_check (GSource *source)
+{
+    RedisSource *redis = (RedisSource *)source;
+    return !!(redis->poll_fd.events & redis->poll_fd.revents);
+}
+
+static gboolean
+redis_source_dispatch (GSource      *source,
+                       GSourceFunc   callback,
+                       gpointer      user_data)
+{
+    RedisSource *redis = (RedisSource *)source;
+
+    if ((redis->poll_fd.revents & G_IO_OUT)) {
+        redisAsyncHandleWrite(redis->ac);
+        redis->poll_fd.revents &= ~G_IO_OUT;
+    }
+
+    if ((redis->poll_fd.revents & G_IO_IN)) {
+        redisAsyncHandleRead(redis->ac);
+        redis->poll_fd.revents &= ~G_IO_IN;
+    }
+
+    if (callback) {
+        return callback(user_data);
+    }
+
+    return TRUE;
+}
+
+static void
+redis_source_finalize (GSource *source)
+{
+    RedisSource *redis = (RedisSource *)source;
+
+    if (redis->poll_fd.fd >= 0) {
+        g_source_remove_poll(source, &redis->poll_fd);
+        redis->poll_fd.fd = -1;
+    }
+}
+
+static GSource *
+redis_source_new (redisAsyncContext *ac)
+{
+    static GSourceFuncs source_funcs = {
+        .prepare  = redis_source_prepare,
+        .check     = redis_source_check,
+        .dispatch = redis_source_dispatch,
+        .finalize = redis_source_finalize,
+    };
+    redisContext *c = &ac->c;
+    RedisSource *source;
+
+    g_return_val_if_fail(ac != NULL, NULL);
+
+    source = (RedisSource *)g_source_new(&source_funcs, sizeof *source);
+    source->ac = ac;
+    source->poll_fd.fd = c->fd;
+    source->poll_fd.events = 0;
+    source->poll_fd.revents = 0;
+    g_source_add_poll((GSource *)source, &source->poll_fd);
+
+    ac->ev.addRead = redis_source_add_read;
+    ac->ev.delRead = redis_source_del_read;
+    ac->ev.addWrite = redis_source_add_write;
+    ac->ev.delWrite = redis_source_del_write;
+    ac->ev.cleanup = redis_source_cleanup;
+    ac->ev.data = source;
+
+    return (GSource *)source;
+}
+
+#endif /* __HIREDIS_GLIB_H__ */
diff --git a/agent/src/c/include/hiredis/adapters/ivykis.h b/agent/src/c/include/hiredis/adapters/ivykis.h
new file mode 100644
index 0000000..6a12a86
--- /dev/null
+++ b/agent/src/c/include/hiredis/adapters/ivykis.h
@@ -0,0 +1,81 @@
+#ifndef __HIREDIS_IVYKIS_H__
+#define __HIREDIS_IVYKIS_H__
+#include <iv.h>
+#include "../hiredis.h"
+#include "../async.h"
+
+typedef struct redisIvykisEvents {
+    redisAsyncContext *context;
+    struct iv_fd fd;
+} redisIvykisEvents;
+
+static void redisIvykisReadEvent(void *arg) {
+    redisAsyncContext *context = (redisAsyncContext *)arg;
+    redisAsyncHandleRead(context);
+}
+
+static void redisIvykisWriteEvent(void *arg) {
+    redisAsyncContext *context = (redisAsyncContext *)arg;
+    redisAsyncHandleWrite(context);
+}
+
+static void redisIvykisAddRead(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+    iv_fd_set_handler_in(&e->fd, redisIvykisReadEvent);
+}
+
+static void redisIvykisDelRead(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+    iv_fd_set_handler_in(&e->fd, NULL);
+}
+
+static void redisIvykisAddWrite(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+    iv_fd_set_handler_out(&e->fd, redisIvykisWriteEvent);
+}
+
+static void redisIvykisDelWrite(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+    iv_fd_set_handler_out(&e->fd, NULL);
+}
+
+static void redisIvykisCleanup(void *privdata) {
+    redisIvykisEvents *e = (redisIvykisEvents*)privdata;
+
+    iv_fd_unregister(&e->fd);
+    free(e);
+}
+
+static int redisIvykisAttach(redisAsyncContext *ac) {
+    redisContext *c = &(ac->c);
+    redisIvykisEvents *e;
+
+    /* Nothing should be attached when something is already attached */
+    if (ac->ev.data != NULL)
+        return REDIS_ERR;
+
+    /* Create container for context and r/w events */
+    e = (redisIvykisEvents*)malloc(sizeof(*e));
+    e->context = ac;
+
+    /* Register functions to start/stop listening for events */
+    ac->ev.addRead = redisIvykisAddRead;
+    ac->ev.delRead = redisIvykisDelRead;
+    ac->ev.addWrite = redisIvykisAddWrite;
+    ac->ev.delWrite = redisIvykisDelWrite;
+    ac->ev.cleanup = redisIvykisCleanup;
+    ac->ev.data = e;
+
+    /* Initialize and install read/write events */
+    IV_FD_INIT(&e->fd);
+    e->fd.fd = c->fd;
+    e->fd.handler_in = redisIvykisReadEvent;
+    e->fd.handler_out = redisIvykisWriteEvent;
+    e->fd.handler_err = NULL;
+    e->fd.cookie = e->context;
+
+    iv_fd_register(&e->fd);
+
+    return REDIS_OK;
+}
+#endif
diff --git a/agent/src/c/include/hiredis/adapters/libev.h b/agent/src/c/include/hiredis/adapters/libev.h
new file mode 100644
index 0000000..2bf8d52
--- /dev/null
+++ b/agent/src/c/include/hiredis/adapters/libev.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIREDIS_LIBEV_H__
+#define __HIREDIS_LIBEV_H__
+#include <stdlib.h>
+#include <sys/types.h>
+#include <ev.h>
+#include "../hiredis.h"
+#include "../async.h"
+
+typedef struct redisLibevEvents {
+    redisAsyncContext *context;
+    struct ev_loop *loop;
+    int reading, writing;
+    ev_io rev, wev;
+} redisLibevEvents;
+
+static void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) {
+#if EV_MULTIPLICITY
+    ((void)loop);
+#endif
+    ((void)revents);
+
+    redisLibevEvents *e = (redisLibevEvents*)watcher->data;
+    redisAsyncHandleRead(e->context);
+}
+
+static void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) {
+#if EV_MULTIPLICITY
+    ((void)loop);
+#endif
+    ((void)revents);
+
+    redisLibevEvents *e = (redisLibevEvents*)watcher->data;
+    redisAsyncHandleWrite(e->context);
+}
+
+static void redisLibevAddRead(void *privdata) {
+    redisLibevEvents *e = (redisLibevEvents*)privdata;
+    struct ev_loop *loop = e->loop;
+    ((void)loop);
+    if (!e->reading) {
+        e->reading = 1;
+        ev_io_start(EV_A_ &e->rev);
+    }
+}
+
+static void redisLibevDelRead(void *privdata) {
+    redisLibevEvents *e = (redisLibevEvents*)privdata;
+    struct ev_loop *loop = e->loop;
+    ((void)loop);
+    if (e->reading) {
+        e->reading = 0;
+        ev_io_stop(EV_A_ &e->rev);
+    }
+}
+
+static void redisLibevAddWrite(void *privdata) {
+    redisLibevEvents *e = (redisLibevEvents*)privdata;
+    struct ev_loop *loop = e->loop;
+    ((void)loop);
+    if (!e->writing) {
+        e->writing = 1;
+        ev_io_start(EV_A_ &e->wev);
+    }
+}
+
+static void redisLibevDelWrite(void *privdata) {
+    redisLibevEvents *e = (redisLibevEvents*)privdata;
+    struct ev_loop *loop = e->loop;
+    ((void)loop);
+    if (e->writing) {
+        e->writing = 0;
+        ev_io_stop(EV_A_ &e->wev);
+    }
+}
+
+static void redisLibevCleanup(void *privdata) {
+    redisLibevEvents *e = (redisLibevEvents*)privdata;
+    redisLibevDelRead(privdata);
+    redisLibevDelWrite(privdata);
+    free(e);
+}
+
+static int redisLibevAttach(EV_P_ redisAsyncContext *ac) {
+    redisContext *c = &(ac->c);
+    redisLibevEvents *e;
+
+    /* Nothing should be attached when something is already attached */
+    if (ac->ev.data != NULL)
+        return REDIS_ERR;
+
+    /* Create container for context and r/w events */
+    e = (redisLibevEvents*)malloc(sizeof(*e));
+    e->context = ac;
+#if EV_MULTIPLICITY
+    e->loop = loop;
+#else
+    e->loop = NULL;
+#endif
+    e->reading = e->writing = 0;
+    e->rev.data = e;
+    e->wev.data = e;
+
+    /* Register functions to start/stop listening for events */
+    ac->ev.addRead = redisLibevAddRead;
+    ac->ev.delRead = redisLibevDelRead;
+    ac->ev.addWrite = redisLibevAddWrite;
+    ac->ev.delWrite = redisLibevDelWrite;
+    ac->ev.cleanup = redisLibevCleanup;
+    ac->ev.data = e;
+
+    /* Initialize read/write events */
+    ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ);
+    ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE);
+    return REDIS_OK;
+}
+
+#endif
diff --git a/agent/src/c/include/hiredis/adapters/libevent.h b/agent/src/c/include/hiredis/adapters/libevent.h
new file mode 100644
index 0000000..1c2b271
--- /dev/null
+++ b/agent/src/c/include/hiredis/adapters/libevent.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIREDIS_LIBEVENT_H__
+#define __HIREDIS_LIBEVENT_H__
+#include <event.h>
+#include "../hiredis.h"
+#include "../async.h"
+
+typedef struct redisLibeventEvents {
+    redisAsyncContext *context;
+    struct event rev, wev;
+} redisLibeventEvents;
+
+static void redisLibeventReadEvent(int fd, short event, void *arg) {
+    ((void)fd); ((void)event);
+    redisLibeventEvents *e = (redisLibeventEvents*)arg;
+    redisAsyncHandleRead(e->context);
+}
+
+static void redisLibeventWriteEvent(int fd, short event, void *arg) {
+    ((void)fd); ((void)event);
+    redisLibeventEvents *e = (redisLibeventEvents*)arg;
+    redisAsyncHandleWrite(e->context);
+}
+
+static void redisLibeventAddRead(void *privdata) {
+    redisLibeventEvents *e = (redisLibeventEvents*)privdata;
+    event_add(&e->rev,NULL);
+}
+
+static void redisLibeventDelRead(void *privdata) {
+    redisLibeventEvents *e = (redisLibeventEvents*)privdata;
+    event_del(&e->rev);
+}
+
+static void redisLibeventAddWrite(void *privdata) {
+    redisLibeventEvents *e = (redisLibeventEvents*)privdata;
+    event_add(&e->wev,NULL);
+}
+
+static void redisLibeventDelWrite(void *privdata) {
+    redisLibeventEvents *e = (redisLibeventEvents*)privdata;
+    event_del(&e->wev);
+}
+
+static void redisLibeventCleanup(void *privdata) {
+    redisLibeventEvents *e = (redisLibeventEvents*)privdata;
+    event_del(&e->rev);
+    event_del(&e->wev);
+    free(e);
+}
+
+static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
+    redisContext *c = &(ac->c);
+    redisLibeventEvents *e;
+
+    /* Nothing should be attached when something is already attached */
+    if (ac->ev.data != NULL)
+        return REDIS_ERR;
+
+    /* Create container for context and r/w events */
+    e = (redisLibeventEvents*)malloc(sizeof(*e));
+    e->context = ac;
+
+    /* Register functions to start/stop listening for events */
+    ac->ev.addRead = redisLibeventAddRead;
+    ac->ev.delRead = redisLibeventDelRead;
+    ac->ev.addWrite = redisLibeventAddWrite;
+    ac->ev.delWrite = redisLibeventDelWrite;
+    ac->ev.cleanup = redisLibeventCleanup;
+    ac->ev.data = e;
+
+    /* Initialize and install read/write events */
+    event_set(&e->rev,c->fd,EV_READ,redisLibeventReadEvent,e);
+    event_set(&e->wev,c->fd,EV_WRITE,redisLibeventWriteEvent,e);
+    event_base_set(base,&e->rev);
+    event_base_set(base,&e->wev);
+    return REDIS_OK;
+}
+#endif
diff --git a/agent/src/c/include/hiredis/adapters/libuv.h b/agent/src/c/include/hiredis/adapters/libuv.h
new file mode 100644
index 0000000..3cdf3d3
--- /dev/null
+++ b/agent/src/c/include/hiredis/adapters/libuv.h
@@ -0,0 +1,121 @@
+#ifndef __HIREDIS_LIBUV_H__
+#define __HIREDIS_LIBUV_H__
+#include <stdlib.h>
+#include <uv.h>
+#include "../hiredis.h"
+#include "../async.h"
+#include <string.h>
+
+typedef struct redisLibuvEvents {
+  redisAsyncContext* context;
+  uv_poll_t          handle;
+  int                events;
+} redisLibuvEvents;
+
+
+static void redisLibuvPoll(uv_poll_t* handle, int status, int events) {
+  redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
+
+  if (status != 0) {
+    return;
+  }
+
+  if (events & UV_READABLE) {
+    redisAsyncHandleRead(p->context);
+  }
+  if (events & UV_WRITABLE) {
+    redisAsyncHandleWrite(p->context);
+  }
+}
+
+
+static void redisLibuvAddRead(void *privdata) {
+  redisLibuvEvents* p = (redisLibuvEvents*)privdata;
+
+  p->events |= UV_READABLE;
+
+  uv_poll_start(&p->handle, p->events, redisLibuvPoll);
+}
+
+
+static void redisLibuvDelRead(void *privdata) {
+  redisLibuvEvents* p = (redisLibuvEvents*)privdata;
+
+  p->events &= ~UV_READABLE;
+
+  if (p->events) {
+    uv_poll_start(&p->handle, p->events, redisLibuvPoll);
+  } else {
+    uv_poll_stop(&p->handle);
+  }
+}
+
+
+static void redisLibuvAddWrite(void *privdata) {
+  redisLibuvEvents* p = (redisLibuvEvents*)privdata;
+
+  p->events |= UV_WRITABLE;
+
+  uv_poll_start(&p->handle, p->events, redisLibuvPoll);
+}
+
+
+static void redisLibuvDelWrite(void *privdata) {
+  redisLibuvEvents* p = (redisLibuvEvents*)privdata;
+
+  p->events &= ~UV_WRITABLE;
+
+  if (p->events) {
+    uv_poll_start(&p->handle, p->events, redisLibuvPoll);
+  } else {
+    uv_poll_stop(&p->handle);
+  }
+}
+
+
+static void on_close(uv_handle_t* handle) {
+  redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
+
+  free(p);
+}
+
+
+static void redisLibuvCleanup(void *privdata) {
+  redisLibuvEvents* p = (redisLibuvEvents*)privdata;
+
+  uv_close((uv_handle_t*)&p->handle, on_close);
+}
+
+
+static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {
+  redisContext *c = &(ac->c);
+
+  if (ac->ev.data != NULL) {
+    return REDIS_ERR;
+  }
+
+  ac->ev.addRead  = redisLibuvAddRead;
+  ac->ev.delRead  = redisLibuvDelRead;
+  ac->ev.addWrite = redisLibuvAddWrite;
+  ac->ev.delWrite = redisLibuvDelWrite;
+  ac->ev.cleanup  = redisLibuvCleanup;
+
+  redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p));
+
+  if (!p) {
+    return REDIS_ERR;
+  }
+
+  memset(p, 0, sizeof(*p));
+
+  if (uv_poll_init(loop, &p->handle, c->fd) != 0) {
+    return REDIS_ERR;
+  }
+
+  ac->ev.data    = p;
+  p->handle.data = p;
+  p->context     = ac;
+
+  return REDIS_OK;
+}
+#endif
diff --git a/agent/src/c/include/hiredis/adapters/macosx.h b/agent/src/c/include/hiredis/adapters/macosx.h
new file mode 100644
index 0000000..72121f6
--- /dev/null
+++ b/agent/src/c/include/hiredis/adapters/macosx.h
@@ -0,0 +1,114 @@
+//
+//  Created by Дмитрий Бахвалов on 13.07.15.
+//  Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
+//
+
+#ifndef __HIREDIS_MACOSX_H__
+#define __HIREDIS_MACOSX_H__
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "../hiredis.h"
+#include "../async.h"
+
+typedef struct {
+    redisAsyncContext *context;
+    CFSocketRef socketRef;
+    CFRunLoopSourceRef sourceRef;
+} RedisRunLoop;
+
+static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) {
+    if( redisRunLoop != NULL ) {
+        if( redisRunLoop->sourceRef != NULL ) {
+            CFRunLoopSourceInvalidate(redisRunLoop->sourceRef);
+            CFRelease(redisRunLoop->sourceRef);
+        }
+        if( redisRunLoop->socketRef != NULL ) {
+            CFSocketInvalidate(redisRunLoop->socketRef);
+            CFRelease(redisRunLoop->socketRef);
+        }
+        free(redisRunLoop);
+    }
+    return REDIS_ERR;
+}
+
+static void redisMacOSAddRead(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
+}
+
+static void redisMacOSDelRead(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
+}
+
+static void redisMacOSAddWrite(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
+}
+
+static void redisMacOSDelWrite(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
+}
+
+static void redisMacOSCleanup(void *privdata) {
+    RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
+    freeRedisRunLoop(redisRunLoop);
+}
+
+static void redisMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) {
+    redisAsyncContext* context = (redisAsyncContext*) info;
+
+    switch (callbackType) {
+        case kCFSocketReadCallBack:
+            redisAsyncHandleRead(context);
+            break;
+
+        case kCFSocketWriteCallBack:
+            redisAsyncHandleWrite(context);
+            break;
+
+        default:
+            break;
+    }
+}
+
+static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLoop) {
+    redisContext *redisCtx = &(redisAsyncCtx->c);
+
+    /* Nothing should be attached when something is already attached */
+    if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR;
+
+    RedisRunLoop* redisRunLoop = (RedisRunLoop*) calloc(1, sizeof(RedisRunLoop));
+    if( !redisRunLoop ) return REDIS_ERR;
+
+    /* Setup redis stuff */
+    redisRunLoop->context = redisAsyncCtx;
+
+    redisAsyncCtx->ev.addRead  = redisMacOSAddRead;
+    redisAsyncCtx->ev.delRead  = redisMacOSDelRead;
+    redisAsyncCtx->ev.addWrite = redisMacOSAddWrite;
+    redisAsyncCtx->ev.delWrite = redisMacOSDelWrite;
+    redisAsyncCtx->ev.cleanup  = redisMacOSCleanup;
+    redisAsyncCtx->ev.data     = redisRunLoop;
+
+    /* Initialize and install read/write events */
+    CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL };
+
+    redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd,
+                                                       kCFSocketReadCallBack | kCFSocketWriteCallBack,
+                                                       redisMacOSAsyncCallback,
+                                                       &socketCtx);
+    if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop);
+
+    redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redisRunLoop->socketRef, 0);
+    if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop);
+
+    CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, kCFRunLoopDefaultMode);
+
+    return REDIS_OK;
+}
+
+#endif
+
diff --git a/agent/src/c/include/hiredis/adapters/qt.h b/agent/src/c/include/hiredis/adapters/qt.h
new file mode 100644
index 0000000..5cc02e6
--- /dev/null
+++ b/agent/src/c/include/hiredis/adapters/qt.h
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (C) 2014 Pietro Cerutti <ga...@gahr.ch>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef __HIREDIS_QT_H__
+#define __HIREDIS_QT_H__
+#include <QSocketNotifier>
+#include "../async.h"
+
+static void RedisQtAddRead(void *);
+static void RedisQtDelRead(void *);
+static void RedisQtAddWrite(void *);
+static void RedisQtDelWrite(void *);
+static void RedisQtCleanup(void *);
+
+class RedisQtAdapter : public QObject {
+
+    Q_OBJECT
+
+    friend
+    void RedisQtAddRead(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->addRead();
+    }
+
+    friend
+    void RedisQtDelRead(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->delRead();
+    }
+
+    friend
+    void RedisQtAddWrite(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->addWrite();
+    }
+
+    friend
+    void RedisQtDelWrite(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->delWrite();
+    }
+
+    friend
+    void RedisQtCleanup(void * adapter) {
+        RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
+        a->cleanup();
+    }
+
+    public:
+        RedisQtAdapter(QObject * parent = 0)
+            : QObject(parent), m_ctx(0), m_read(0), m_write(0) { }
+
+        ~RedisQtAdapter() {
+            if (m_ctx != 0) {
+                m_ctx->ev.data = NULL;
+            }
+        }
+
+        int setContext(redisAsyncContext * ac) {
+            if (ac->ev.data != NULL) {
+                return REDIS_ERR;
+            }
+            m_ctx = ac;
+            m_ctx->ev.data = this;
+            m_ctx->ev.addRead = RedisQtAddRead;
+            m_ctx->ev.delRead = RedisQtDelRead;
+            m_ctx->ev.addWrite = RedisQtAddWrite;
+            m_ctx->ev.delWrite = RedisQtDelWrite;
+            m_ctx->ev.cleanup = RedisQtCleanup;
+            return REDIS_OK;
+        }
+
+    private:
+        void addRead() {
+            if (m_read) return;
+            m_read = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Read, 0);
+            connect(m_read, SIGNAL(activated(int)), this, SLOT(read()));
+        }
+
+        void delRead() {
+            if (!m_read) return;
+            delete m_read;
+            m_read = 0;
+        }
+
+        void addWrite() {
+            if (m_write) return;
+            m_write = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Write, 0);
+            connect(m_write, SIGNAL(activated(int)), this, SLOT(write()));
+        }
+
+        void delWrite() {
+            if (!m_write) return;
+            delete m_write;
+            m_write = 0;
+        }
+
+        void cleanup() {
+            delRead();
+            delWrite();
+        }
+
+    private slots:
+        void read() { redisAsyncHandleRead(m_ctx); }
+        void write() { redisAsyncHandleWrite(m_ctx); }
+
+    private:
+        redisAsyncContext * m_ctx;
+        QSocketNotifier * m_read;
+        QSocketNotifier * m_write;
+};
+
+#endif /* !__HIREDIS_QT_H__ */
diff --git a/agent/src/c/include/hiredis/async.h b/agent/src/c/include/hiredis/async.h
new file mode 100644
index 0000000..59cbf46
--- /dev/null
+++ b/agent/src/c/include/hiredis/async.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
+ * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIREDIS_ASYNC_H
+#define __HIREDIS_ASYNC_H
+#include "hiredis.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct redisAsyncContext; /* need forward declaration of redisAsyncContext */
+struct dict; /* dictionary header is included in async.c */
+
+/* Reply callback prototype and container */
+typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*);
+typedef struct redisCallback {
+    struct redisCallback *next; /* simple singly linked list */
+    redisCallbackFn *fn;
+    void *privdata;
+} redisCallback;
+
+/* List of callbacks for either regular replies or pub/sub */
+typedef struct redisCallbackList {
+    redisCallback *head, *tail;
+} redisCallbackList;
+
+/* Connection callback prototypes */
+typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);
+typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);
+
+/* Context for an async connection to Redis */
+typedef struct redisAsyncContext {
+    /* Hold the regular context, so it can be realloc'ed. */
+    redisContext c;
+
+    /* Setup error flags so they can be used directly. */
+    int err;
+    char *errstr;
+
+    /* Not used by hiredis */
+    void *data;
+
+    /* Event library data and hooks */
+    struct {
+        void *data;
+
+        /* Hooks that are called when the library expects to start
+         * reading/writing. These functions should be idempotent. */
+        void (*addRead)(void *privdata);
+        void (*delRead)(void *privdata);
+        void (*addWrite)(void *privdata);
+        void (*delWrite)(void *privdata);
+        void (*cleanup)(void *privdata);
+    } ev;
+
+    /* Called when either the connection is terminated due to an error or per
+     * user request. The status is set accordingly (REDIS_OK, REDIS_ERR). */
+    redisDisconnectCallback *onDisconnect;
+
+    /* Called when the first write event was received. */
+    redisConnectCallback *onConnect;
+
+    /* Regular command callbacks */
+    redisCallbackList replies;
+
+    /* Subscription callbacks */
+    struct {
+        redisCallbackList invalid;
+        struct dict *channels;
+        struct dict *patterns;
+    } sub;
+} redisAsyncContext;
+
+/* Functions that proxy to hiredis */
+redisAsyncContext *redisAsyncConnect(const char *ip, int port);
+redisAsyncContext *redisAsyncConnectBind(const char *ip, int port, const char *source_addr);
+redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port,
+                                                  const char *source_addr);
+redisAsyncContext *redisAsyncConnectUnix(const char *path);
+int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn);
+int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn);
+void redisAsyncDisconnect(redisAsyncContext *ac);
+void redisAsyncFree(redisAsyncContext *ac);
+
+/* Handle read/write events */
+void redisAsyncHandleRead(redisAsyncContext *ac);
+void redisAsyncHandleWrite(redisAsyncContext *ac);
+
+/* Command functions for an async context. Write the command to the
+ * output buffer and register the provided callback. */
+int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap);
+int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...);
+int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen);
+int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/agent/src/c/include/hiredis/hiredis.h b/agent/src/c/include/hiredis/hiredis.h
new file mode 100644
index 0000000..d2a6e90
--- /dev/null
+++ b/agent/src/c/include/hiredis/hiredis.h
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
+ * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
+ *                     Jan-Erik Rediger <janerik at fnordig dot com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HIREDIS_H
+#define __HIREDIS_H
+#include "read.h"
+#include <stdarg.h> /* for va_list */
+#include <sys/time.h> /* for struct timeval */
+#include <stdint.h> /* uintXX_t, etc */
+#include "sds.h" /* for sds */
+
+#define HIREDIS_MAJOR 0
+#define HIREDIS_MINOR 13
+#define HIREDIS_PATCH 3
+#define HIREDIS_SONAME 0.13
+
+/* Connection type can be blocking or non-blocking and is set in the
+ * least significant bit of the flags field in redisContext. */
+#define REDIS_BLOCK 0x1
+
+/* Connection may be disconnected before being free'd. The second bit
+ * in the flags field is set when the context is connected. */
+#define REDIS_CONNECTED 0x2
+
+/* The async API might try to disconnect cleanly and flush the output
+ * buffer and read all subsequent replies before disconnecting.
+ * This flag means no new commands can come in and the connection
+ * should be terminated once all replies have been read. */
+#define REDIS_DISCONNECTING 0x4
+
+/* Flag specific to the async API which means that the context should be clean
+ * up as soon as possible. */
+#define REDIS_FREEING 0x8
+
+/* Flag that is set when an async callback is executed. */
+#define REDIS_IN_CALLBACK 0x10
+
+/* Flag that is set when the async context has one or more subscriptions. */
+#define REDIS_SUBSCRIBED 0x20
+
+/* Flag that is set when monitor mode is active */
+#define REDIS_MONITORING 0x40
+
+/* Flag that is set when we should set SO_REUSEADDR before calling bind() */
+#define REDIS_REUSEADDR 0x80
+
+#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */
+
+/* number of times we retry to connect in the case of EADDRNOTAVAIL and
+ * SO_REUSEADDR is being used. */
+#define REDIS_CONNECT_RETRIES  10
+
+/* strerror_r has two completely different prototypes and behaviors
+ * depending on system issues, so we need to operate on the error buffer
+ * differently depending on which strerror_r we're using. */
+#ifndef _GNU_SOURCE
+/* "regular" POSIX strerror_r that does the right thing. */
+#define __redis_strerror_r(errno, buf, len)                                    \
+    do {                                                                       \
+        strerror_r((errno), (buf), (len));                                     \
+    } while (0)
+#else
+/* "bad" GNU strerror_r we need to clean up after. */
+#define __redis_strerror_r(errno, buf, len)                                    \
+    do {                                                                       \
+        char *err_str = strerror_r((errno), (buf), (len));                     \
+        /* If return value _isn't_ the start of the buffer we passed in,       \
+         * then GNU strerror_r returned an internal static buffer and we       \
+         * need to copy the result into our private buffer. */                 \
+        if (err_str != (buf)) {                                                \
+            strncpy((buf), err_str, ((len) - 1));                              \
+            buf[(len)-1] = '\0';                                               \
+        }                                                                      \
+    } while (0)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This is the reply object returned by redisCommand() */
+typedef struct redisReply {
+    int type; /* REDIS_REPLY_* */
+    long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
+    size_t len; /* Length of string */
+    char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
+    size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
+    struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
+} redisReply;
+
+redisReader *redisReaderCreate(void);
+
+/* Function to free the reply objects hiredis returns by default. */
+void freeReplyObject(void *reply);
+
+/* Functions to format a command according to the protocol. */
+int redisvFormatCommand(char **target, const char *format, va_list ap);
+int redisFormatCommand(char **target, const char *format, ...);
+int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
+int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen);
+void redisFreeCommand(char *cmd);
+void redisFreeSdsCommand(sds cmd);
+
+enum redisConnectionType {
+    REDIS_CONN_TCP,
+    REDIS_CONN_UNIX,
+};
+
+/* Context for a connection to Redis */
+typedef struct redisContext {
+    int err; /* Error flags, 0 when there is no error */
+    char errstr[128]; /* String representation of error when applicable */
+    int fd;
+    int flags;
+    char *obuf; /* Write buffer */
+    redisReader *reader; /* Protocol reader */
+
+    enum redisConnectionType connection_type;
+    struct timeval *timeout;
+
+    struct {
+        char *host;
+        char *source_addr;
+        int port;
+    } tcp;
+
+    struct {
+        char *path;
+    } unix_sock;
+
+} redisContext;
+
+redisContext *redisConnect(const char *ip, int port);
+redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
+redisContext *redisConnectNonBlock(const char *ip, int port);
+redisContext *redisConnectBindNonBlock(const char *ip, int port,
+                                       const char *source_addr);
+redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
+                                                const char *source_addr);
+redisContext *redisConnectUnix(const char *path);
+redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
+redisContext *redisConnectUnixNonBlock(const char *path);
+redisContext *redisConnectFd(int fd);
+
+/**
+ * Reconnect the given context using the saved information.
+ *
+ * This re-uses the exact same connect options as in the initial connection.
+ * host, ip (or path), timeout and bind address are reused,
+ * flags are used unmodified from the existing context.
+ *
+ * Returns REDIS_OK on successful connect or REDIS_ERR otherwise.
+ */
+int redisReconnect(redisContext *c);
+
+int redisSetTimeout(redisContext *c, const struct timeval tv);
+int redisEnableKeepAlive(redisContext *c);
+void redisFree(redisContext *c);
+int redisFreeKeepFd(redisContext *c);
+int redisBufferRead(redisContext *c);
+int redisBufferWrite(redisContext *c, int *done);
+
+/* In a blocking context, this function first checks if there are unconsumed
+ * replies to return and returns one if so. Otherwise, it flushes the output
+ * buffer to the socket and reads until it has a reply. In a non-blocking
+ * context, it will return unconsumed replies until there are no more. */
+int redisGetReply(redisContext *c, void **reply);
+int redisGetReplyFromReader(redisContext *c, void **reply);
+
+/* Write a formatted command to the output buffer. Use these functions in blocking mode
+ * to get a pipeline of commands. */
+int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);
+
+/* Write a command to the output buffer. Use these functions in blocking mode
+ * to get a pipeline of commands. */
+int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
+int redisAppendCommand(redisContext *c, const char *format, ...);
+int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
+
+/* Issue a command to Redis. In a blocking context, it is identical to calling
+ * redisAppendCommand, followed by redisGetReply. The function will return
+ * NULL if there was an error in performing the request, otherwise it will
+ * return the reply. In a non-blocking context, it is identical to calling
+ * only redisAppendCommand and will always return NULL. */
+void *redisvCommand(redisContext *c, const char *format, va_list ap);
+void *redisCommand(redisContext *c, const char *format, ...);
+void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/agent/src/c/include/hiredis/read.h b/agent/src/c/include/hiredis/read.h
new file mode 100644
index 0000000..2988aa4
--- /dev/null
+++ b/agent/src/c/include/hiredis/read.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
+ * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef __HIREDIS_READ_H
+#define __HIREDIS_READ_H
+#include <stdio.h> /* for size_t */
+
+#define REDIS_ERR -1
+#define REDIS_OK 0
+
+/* When an error occurs, the err flag in a context is set to hold the type of
+ * error that occurred. REDIS_ERR_IO means there was an I/O error and you
+ * should use the "errno" variable to find out what is wrong.
+ * For other values, the "errstr" field will hold a description. */
+#define REDIS_ERR_IO 1 /* Error in read or write */
+#define REDIS_ERR_EOF 3 /* End of file */
+#define REDIS_ERR_PROTOCOL 4 /* Protocol error */
+#define REDIS_ERR_OOM 5 /* Out of memory */
+#define REDIS_ERR_OTHER 2 /* Everything else... */
+
+#define REDIS_REPLY_STRING 1
+#define REDIS_REPLY_ARRAY 2
+#define REDIS_REPLY_INTEGER 3
+#define REDIS_REPLY_NIL 4
+#define REDIS_REPLY_STATUS 5
+#define REDIS_REPLY_ERROR 6
+
+#define REDIS_READER_MAX_BUF (1024*16)  /* Default max unused reader buffer. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct redisReadTask {
+    int type;
+    int elements; /* number of elements in multibulk container */
+    int idx; /* index in parent (array) object */
+    void *obj; /* holds user-generated value for a read task */
+    struct redisReadTask *parent; /* parent task */
+    void *privdata; /* user-settable arbitrary field */
+} redisReadTask;
+
+typedef struct redisReplyObjectFunctions {
+    void *(*createString)(const redisReadTask*, char*, size_t);
+    void *(*createArray)(const redisReadTask*, int);
+    void *(*createInteger)(const redisReadTask*, long long);
+    void *(*createNil)(const redisReadTask*);
+    void (*freeObject)(void*);
+} redisReplyObjectFunctions;
+
+typedef struct redisReader {
+    int err; /* Error flags, 0 when there is no error */
+    char errstr[128]; /* String representation of error when applicable */
+
+    char *buf; /* Read buffer */
+    size_t pos; /* Buffer cursor */
+    size_t len; /* Buffer length */
+    size_t maxbuf; /* Max length of unused buffer */
+
+    redisReadTask rstack[9];
+    int ridx; /* Index of current read task */
+    void *reply; /* Temporary reply pointer */
+
+    redisReplyObjectFunctions *fn;
+    void *privdata;
+} redisReader;
+
+/* Public API for the protocol parser. */
+redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn);
+void redisReaderFree(redisReader *r);
+int redisReaderFeed(redisReader *r, const char *buf, size_t len);
+int redisReaderGetReply(redisReader *r, void **reply);
+
+#define redisReaderSetPrivdata(_r, _p) (int)(((redisReader*)(_r))->privdata = (_p))
+#define redisReaderGetObject(_r) (((redisReader*)(_r))->reply)
+#define redisReaderGetError(_r) (((redisReader*)(_r))->errstr)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/agent/src/c/include/hiredis/sds.h b/agent/src/c/include/hiredis/sds.h
new file mode 100644
index 0000000..394f8b5
--- /dev/null
+++ b/agent/src/c/include/hiredis/sds.h
@@ -0,0 +1,273 @@
+/* SDSLib 2.0 -- A C dynamic strings library
+ *
+ * Copyright (c) 2006-2015, Salvatore Sanfilippo <antirez at gmail dot com>
+ * Copyright (c) 2015, Oran Agra
+ * Copyright (c) 2015, Redis Labs, Inc
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   * Redistributions of source code must retain the above copyright notice,
+ *     this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ *   * Neither the name of Redis nor the names of its contributors may be used
+ *     to endorse or promote products derived from this software without
+ *     specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __SDS_H
+#define __SDS_H
+
+#define SDS_MAX_PREALLOC (1024*1024)
+
+#include <sys/types.h>
+#include <stdarg.h>
+#include <stdint.h>
+
+typedef char *sds;
+
+/* Note: sdshdr5 is never used, we just access the flags byte directly.
+ * However is here to document the layout of type 5 SDS strings. */
+struct __attribute__ ((__packed__)) sdshdr5 {
+    unsigned char flags; /* 3 lsb of type, and 5 msb of string length */
+    char buf[];
+};
+struct __attribute__ ((__packed__)) sdshdr8 {
+    uint8_t len; /* used */
+    uint8_t alloc; /* excluding the header and null terminator */
+    unsigned char flags; /* 3 lsb of type, 5 unused bits */
+    char buf[];
+};
+struct __attribute__ ((__packed__)) sdshdr16 {
+    uint16_t len; /* used */
+    uint16_t alloc; /* excluding the header and null terminator */
+    unsigned char flags; /* 3 lsb of type, 5 unused bits */
+    char buf[];
+};
+struct __attribute__ ((__packed__)) sdshdr32 {
+    uint32_t len; /* used */
+    uint32_t alloc; /* excluding the header and null terminator */
+    unsigned char flags; /* 3 lsb of type, 5 unused bits */
+    char buf[];
+};
+struct __attribute__ ((__packed__)) sdshdr64 {
+    uint64_t len; /* used */
+    uint64_t alloc; /* excluding the header and null terminator */
+    unsigned char flags; /* 3 lsb of type, 5 unused bits */
+    char buf[];
+};
+
+#define SDS_TYPE_5  0
+#define SDS_TYPE_8  1
+#define SDS_TYPE_16 2
+#define SDS_TYPE_32 3
+#define SDS_TYPE_64 4
+#define SDS_TYPE_MASK 7
+#define SDS_TYPE_BITS 3
+#define SDS_HDR_VAR(T,s) struct sdshdr##T *sh = (void*)((s)-(sizeof(struct sdshdr##T)));
+#define SDS_HDR(T,s) ((struct sdshdr##T *)((s)-(sizeof(struct sdshdr##T))))
+#define SDS_TYPE_5_LEN(f) ((f)>>SDS_TYPE_BITS)
+
+static inline size_t sdslen(const sds s) {
+    unsigned char flags = s[-1];
+    switch(flags&SDS_TYPE_MASK) {
+        case SDS_TYPE_5:
+            return SDS_TYPE_5_LEN(flags);
+        case SDS_TYPE_8:
+            return SDS_HDR(8,s)->len;
+        case SDS_TYPE_16:
+            return SDS_HDR(16,s)->len;
+        case SDS_TYPE_32:
+            return SDS_HDR(32,s)->len;
+        case SDS_TYPE_64:
+            return SDS_HDR(64,s)->len;
+    }
+    return 0;
+}
+
+static inline size_t sdsavail(const sds s) {
+    unsigned char flags = s[-1];
+    switch(flags&SDS_TYPE_MASK) {
+        case SDS_TYPE_5: {
+            return 0;
+        }
+        case SDS_TYPE_8: {
+            SDS_HDR_VAR(8,s);
+            return sh->alloc - sh->len;
+        }
+        case SDS_TYPE_16: {
+            SDS_HDR_VAR(16,s);
+            return sh->alloc - sh->len;
+        }
+        case SDS_TYPE_32: {
+            SDS_HDR_VAR(32,s);
+            return sh->alloc - sh->len;
+        }
+        case SDS_TYPE_64: {
+            SDS_HDR_VAR(64,s);
+            return sh->alloc - sh->len;
+        }
+    }
+    return 0;
+}
+
+static inline void sdssetlen(sds s, size_t newlen) {
+    unsigned char flags = s[-1];
+    switch(flags&SDS_TYPE_MASK) {
+        case SDS_TYPE_5:
+            {
+                unsigned char *fp = ((unsigned char*)s)-1;
+                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);
+            }
+            break;
+        case SDS_TYPE_8:
+            SDS_HDR(8,s)->len = newlen;
+            break;
+        case SDS_TYPE_16:
+            SDS_HDR(16,s)->len = newlen;
+            break;
+        case SDS_TYPE_32:
+            SDS_HDR(32,s)->len = newlen;
+            break;
+        case SDS_TYPE_64:
+            SDS_HDR(64,s)->len = newlen;
+            break;
+    }
+}
+
+static inline void sdsinclen(sds s, size_t inc) {
+    unsigned char flags = s[-1];
+    switch(flags&SDS_TYPE_MASK) {
+        case SDS_TYPE_5:
+            {
+                unsigned char *fp = ((unsigned char*)s)-1;
+                unsigned char newlen = SDS_TYPE_5_LEN(flags)+inc;
+                *fp = SDS_TYPE_5 | (newlen << SDS_TYPE_BITS);
+            }
+            break;
+        case SDS_TYPE_8:
+            SDS_HDR(8,s)->len += inc;
+            break;
+        case SDS_TYPE_16:
+            SDS_HDR(16,s)->len += inc;
+            break;
+        case SDS_TYPE_32:
+            SDS_HDR(32,s)->len += inc;
+            break;
+        case SDS_TYPE_64:
+            SDS_HDR(64,s)->len += inc;
+            break;
+    }
+}
+
+/* sdsalloc() = sdsavail() + sdslen() */
+static inline size_t sdsalloc(const sds s) {
+    unsigned char flags = s[-1];
+    switch(flags&SDS_TYPE_MASK) {
+        case SDS_TYPE_5:
+            return SDS_TYPE_5_LEN(flags);
+        case SDS_TYPE_8:
+            return SDS_HDR(8,s)->alloc;
+        case SDS_TYPE_16:
+            return SDS_HDR(16,s)->alloc;
+        case SDS_TYPE_32:
+            return SDS_HDR(32,s)->alloc;
+        case SDS_TYPE_64:
+            return SDS_HDR(64,s)->alloc;
+    }
+    return 0;
+}
+
+static inline void sdssetalloc(sds s, size_t newlen) {
+    unsigned char flags = s[-1];
+    switch(flags&SDS_TYPE_MASK) {
+        case SDS_TYPE_5:
+            /* Nothing to do, this type has no total allocation info. */
+            break;
+        case SDS_TYPE_8:
+            SDS_HDR(8,s)->alloc = newlen;
+            break;
+        case SDS_TYPE_16:
+            SDS_HDR(16,s)->alloc = newlen;
+            break;
+        case SDS_TYPE_32:
+            SDS_HDR(32,s)->alloc = newlen;
+            break;
+        case SDS_TYPE_64:
+            SDS_HDR(64,s)->alloc = newlen;
+            break;
+    }
+}
+
+sds sdsnewlen(const void *init, size_t initlen);
+sds sdsnew(const char *init);
+sds sdsempty(void);
+sds sdsdup(const sds s);
+void sdsfree(sds s);
+sds sdsgrowzero(sds s, size_t len);
+sds sdscatlen(sds s, const void *t, size_t len);
+sds sdscat(sds s, const char *t);
+sds sdscatsds(sds s, const sds t);
+sds sdscpylen(sds s, const char *t, size_t len);
+sds sdscpy(sds s, const char *t);
+
+sds sdscatvprintf(sds s, const char *fmt, va_list ap);
+#ifdef __GNUC__
+sds sdscatprintf(sds s, const char *fmt, ...)
+    __attribute__((format(printf, 2, 3)));
+#else
+sds sdscatprintf(sds s, const char *fmt, ...);
+#endif
+
+sds sdscatfmt(sds s, char const *fmt, ...);
+sds sdstrim(sds s, const char *cset);
+void sdsrange(sds s, int start, int end);
+void sdsupdatelen(sds s);
+void sdsclear(sds s);
+int sdscmp(const sds s1, const sds s2);
+sds *sdssplitlen(const char *s, int len, const char *sep, int seplen, int *count);
+void sdsfreesplitres(sds *tokens, int count);
+void sdstolower(sds s);
+void sdstoupper(sds s);
+sds sdsfromlonglong(long long value);
+sds sdscatrepr(sds s, const char *p, size_t len);
+sds *sdssplitargs(const char *line, int *argc);
+sds sdsmapchars(sds s, const char *from, const char *to, size_t setlen);
+sds sdsjoin(char **argv, int argc, char *sep);
+sds sdsjoinsds(sds *argv, int argc, const char *sep, size_t seplen);
+
+/* Low level functions exposed to the user API */
+sds sdsMakeRoomFor(sds s, size_t addlen);
+void sdsIncrLen(sds s, int incr);
+sds sdsRemoveFreeSpace(sds s);
+size_t sdsAllocSize(sds s);
+void *sdsAllocPtr(sds s);
+
+/* Export the allocator used by SDS to the program using SDS.
+ * Sometimes the program SDS is linked to, may use a different set of
+ * allocators, but may want to allocate or free things that SDS will
+ * respectively free or allocate. */
+void *sds_malloc(size_t size);
+void *sds_realloc(void *ptr, size_t size);
+void sds_free(void *ptr);
+
+#ifdef REDIS_TEST
+int sdsTest(int argc, char *argv[]);
+#endif
+
+#endif
diff --git a/agent/src/c/include/zlog.h b/agent/src/c/include/zlog.h
new file mode 100644
index 0000000..a123825
--- /dev/null
+++ b/agent/src/c/include/zlog.h
@@ -0,0 +1,265 @@
+/*
+ * This file is part of the zlog Library.
+ *
+ * Copyright (C) 2011 by Hardy Simpson <Ha...@gmail.com>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING in base directory.
+ */
+
+#ifndef __zlog_h
+#define __zlog_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h> /* for va_list */
+#include <stdio.h> /* for size_t */
+
+# if defined __GNUC__
+#   define ZLOG_CHECK_PRINTF(m,n) __attribute__((format(printf,m,n)))
+# else 
+#   define ZLOG_CHECK_PRINTF(m,n)
+# endif
+
+typedef struct zlog_category_s zlog_category_t;
+
+int zlog_init(const char *confpath);
+int zlog_reload(const char *confpath);
+void zlog_fini(void);
+
+void zlog_profile(void);
+
+zlog_category_t *zlog_get_category(const char *cname);
+
+int zlog_put_mdc(const char *key, const char *value);
+char *zlog_get_mdc(const char *key);
+void zlog_remove_mdc(const char *key);
+void zlog_clean_mdc(void);
+
+void zlog(zlog_category_t * category,
+	const char *file, size_t filelen,
+	const char *func, size_t funclen,
+	long line, int level,
+	const char *format, ...) ZLOG_CHECK_PRINTF(8,9);
+void vzlog(zlog_category_t * category,
+	const char *file, size_t filelen,
+	const char *func, size_t funclen,
+	long line, int level,
+	const char *format, va_list args);
+void hzlog(zlog_category_t * category,
+	const char *file, size_t filelen,
+	const char *func, size_t funclen,
+	long line, int level,
+	const void *buf, size_t buflen);
+
+int dzlog_init(const char *confpath, const char *cname);
+int dzlog_set_category(const char *cname);
+
+void dzlog(const char *file, size_t filelen,
+	const char *func, size_t funclen,
+	long line, int level,
+	const char *format, ...) ZLOG_CHECK_PRINTF(7,8);
+void vdzlog(const char *file, size_t filelen,
+	const char *func, size_t funclen,
+	long line, int level,
+	const char *format, va_list args);
+void hdzlog(const char *file, size_t filelen,
+	const char *func, size_t funclen,
+	long line, int level,
+	const void *buf, size_t buflen);
+
+typedef struct zlog_msg_s {
+	char *buf;
+	size_t len;
+	char *path;
+} zlog_msg_t;
+
+typedef int (*zlog_record_fn)(zlog_msg_t *msg);
+int zlog_set_record(const char *rname, zlog_record_fn record);
+
+/******* useful macros, can be redefined at user's h file **********/
+
+typedef enum {
+	ZLOG_LEVEL_DEBUG = 20,
+	ZLOG_LEVEL_INFO = 40,
+	ZLOG_LEVEL_NOTICE = 60,
+	ZLOG_LEVEL_WARN = 80,
+	ZLOG_LEVEL_ERROR = 100,
+	ZLOG_LEVEL_FATAL = 120
+} zlog_level; 
+
+#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
+# if defined __GNUC__ && __GNUC__ >= 2
+#  define __func__ __FUNCTION__
+# else
+#  define __func__ "<unknown>"
+# endif
+#endif
+
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+/* zlog macros */
+#define zlog_fatal(cat, ...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_FATAL, __VA_ARGS__)
+#define zlog_error(cat, ...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_ERROR, __VA_ARGS__)
+#define zlog_warn(cat, ...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_WARN, __VA_ARGS__)
+#define zlog_notice(cat, ...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_NOTICE, __VA_ARGS__)
+#define zlog_info(cat, ...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_INFO, __VA_ARGS__)
+#define zlog_debug(cat, ...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_DEBUG, __VA_ARGS__)
+/* dzlog macros */
+#define dzlog_fatal(...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_FATAL, __VA_ARGS__)
+#define dzlog_error(...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_ERROR, __VA_ARGS__)
+#define dzlog_warn(...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_WARN, __VA_ARGS__)
+#define dzlog_notice(...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_NOTICE, __VA_ARGS__)
+#define dzlog_info(...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_INFO, __VA_ARGS__)
+#define dzlog_debug(...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_DEBUG, __VA_ARGS__)
+#elif defined __GNUC__
+/* zlog macros */
+#define zlog_fatal(cat, format, args...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_FATAL, format, ##args)
+#define zlog_error(cat, format, args...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_ERROR, format, ##args)
+#define zlog_warn(cat, format, args...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_WARN, format, ##args)
+#define zlog_notice(cat, format, args...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_NOTICE, format, ##args)
+#define zlog_info(cat, format, args...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_INFO, format, ##args)
+#define zlog_debug(cat, format, args...) \
+	zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_DEBUG, format, ##args)
+/* dzlog macros */
+#define dzlog_fatal(format, args...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_FATAL, format, ##args)
+#define dzlog_error(format, args...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_ERROR, format, ##args)
+#define dzlog_warn(format, args...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_WARN, format, ##args)
+#define dzlog_notice(format, args...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_NOTICE, format, ##args)
+#define dzlog_info(format, args...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_INFO, format, ##args)
+#define dzlog_debug(format, args...) \
+	dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_DEBUG, format, ##args)
+#endif
+
+/* vzlog macros */
+#define vzlog_fatal(cat, format, args) \
+	vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_FATAL, format, args)
+#define vzlog_error(cat, format, args) \
+	vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_ERROR, format, args)
+#define vzlog_warn(cat, format, args) \
+	vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_WARN, format, args)
+#define vzlog_notice(cat, format, args) \
+	vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_NOTICE, format, args)
+#define vzlog_info(cat, format, args) \
+	vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_INFO, format, args)
+#define vzlog_debug(cat, format, args) \
+	vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_DEBUG, format, args)
+
+/* hzlog macros */
+#define hzlog_fatal(cat, buf, buf_len) \
+	hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_FATAL, buf, buf_len)
+#define hzlog_error(cat, buf, buf_len) \
+	hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_ERROR, buf, buf_len)
+#define hzlog_warn(cat, buf, buf_len) \
+	hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_WARN, buf, buf_len)
+#define hzlog_notice(cat, buf, buf_len) \
+	hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_NOTICE, buf, buf_len)
+#define hzlog_info(cat, buf, buf_len) \
+	hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_INFO, buf, buf_len)
+#define hzlog_debug(cat, buf, buf_len) \
+	hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_DEBUG, buf, buf_len)
+
+
+/* vdzlog macros */
+#define vdzlog_fatal(format, args) \
+	vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_FATAL, format, args)
+#define vdzlog_error(format, args) \
+	vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_ERROR, format, args)
+#define vdzlog_warn(format, args) \
+	vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_WARN, format, args)
+#define vdzlog_notice(format, args) \
+	vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_NOTICE, format, args)
+#define vdzlog_info(format, args) \
+	vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_INFO, format, args)
+#define vdzlog_debug(format, args) \
+	vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_DEBUG, format, args)
+
+/* hdzlog macros */
+#define hdzlog_fatal(buf, buf_len) \
+	hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_FATAL, buf, buf_len)
+#define hdzlog_error(buf, buf_len) \
+	hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_ERROR, buf, buf_len)
+#define hdzlog_warn(buf, buf_len) \
+	hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_WARN, buf, buf_len)
+#define hdzlog_notice(buf, buf_len) \
+	hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_NOTICE, buf, buf_len)
+#define hdzlog_info(buf, buf_len) \
+	hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_INFO, buf, buf_len)
+#define hdzlog_debug(buf, buf_len) \
+	hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
+	ZLOG_LEVEL_DEBUG, buf, buf_len)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/agent/src/c/lib/libhiredis.a b/agent/src/c/lib/libhiredis.a
new file mode 100644
index 0000000..685a959
Binary files /dev/null and b/agent/src/c/lib/libhiredis.a differ
diff --git a/agent/src/c/lib/libzlog.a b/agent/src/c/lib/libzlog.a
new file mode 100644
index 0000000..e1f0c43
Binary files /dev/null and b/agent/src/c/lib/libzlog.a differ
diff --git a/agent/src/c/release/agent_log.conf b/agent/src/c/release/agent_log.conf
new file mode 100644
index 0000000..5496202
--- /dev/null
+++ b/agent/src/c/release/agent_log.conf
@@ -0,0 +1,6 @@
+[global]
+file perms = 644
+[formats]
+simple	= "%d.%ms %m%n"
+[rules]
+fsof_agent.INFO            "../../../../../dubbo-php-framework/agent/log/agent/agent.%d(%F).log", 100M; simple
diff --git a/agent/src/c/release/protect_agent_server.sh b/agent/src/c/release/protect_agent_server.sh
new file mode 100644
index 0000000..df69a9b
--- /dev/null
+++ b/agent/src/c/release/protect_agent_server.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+cd $(dirname $0) 
+agent_server=$(ps aux | grep 'release/agent_server' | grep -v grep| wc -l)
+if [ "$agent_server" -eq "0" ]; then
+    /bin/bash  start_agent_server.sh
+fi
diff --git a/agent/src/c/release/start_agent_server.sh b/agent/src/c/release/start_agent_server.sh
new file mode 100644
index 0000000..966fcdf
--- /dev/null
+++ b/agent/src/c/release/start_agent_server.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+log_dir="../../../../../dubbo-php-framework/agent/log/agent"
+
+if [ ! -d $log_dir ]; then
+    mkdir -p $log_dir
+fi
+
+process=$(ps aux  | grep -v "grep" | grep "release/agent_server" | wc -l) 
+if [ "$process" -ne "0" ]; then
+       ps aux |grep -v "grep" |grep "release/agent_server"|awk '{print $2}'|xargs kill -9
+fi
+
+cd ../../../../../dubbo-php-framework/agent/src/c/release
+cp agent agent_server
+chmod  u+x agent_server
+cur_dir=$(pwd)
+$cur_dir/agent_server 600 ../../../../../dubbo-php-framework/config/global/conf/fsof.ini
diff --git a/agent/src/c/service/fsof_log.c b/agent/src/c/service/fsof_log.c
new file mode 100644
index 0000000..e79b7a3
--- /dev/null
+++ b/agent/src/c/service/fsof_log.c
@@ -0,0 +1,79 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#include "fsof_log.h"
+#include <zlog.h>
+#include <time.h>
+#include <string.h>
+#include "../common/fsof_util.h"
+
+
+#define LOG_INFO_MAX_LEN  (8 * 1024)
+#define LOG_DEBUG_INFO_NAME "fsof_agent_log"
+
+static zlog_category_t *g_zc;
+static char g_zlog_conf[MAX_CONFIG_PATH_LEN] = {0};
+
+
+void fsof_log_info(enum log_level level,const char *format,...) {
+    char log_info[LOG_INFO_MAX_LEN] = {0};
+    va_list v_log;
+
+    va_start(v_log,format);
+    vsnprintf(log_info,LOG_INFO_MAX_LEN,format,v_log);
+    va_end(v_log);
+    
+    if (g_zc != NULL) {
+        switch (level) {
+            case INFO:
+                zlog_info(g_zc,log_info);
+                break;
+            case ERROR:
+                zlog_error(g_zc,log_info);
+                break;
+            case DEBUG:
+                zlog_debug(g_zc,log_info);
+        }
+    }
+}
+
+void fsof_log_close() {
+    if (g_zc != NULL) {
+        zlog_fini();
+        g_zc = NULL;
+    }
+}
+
+int fsof_log_init() {
+    int err = 0;
+
+    get_current_path(g_zlog_conf,"agent_log.conf",1);
+    err = zlog_init(g_zlog_conf);;
+    if (err > 0) {
+        return err;
+    }
+
+    g_zc = zlog_get_category("fsof_agent");
+    if (g_zc == NULL) {
+        zlog_fini();
+        err = 1;
+        return err;
+    }
+
+    fsof_log_info(INFO,"log init succeed--------------!!!\n");
+
+    return 0; //
+}
diff --git a/agent/src/c/service/fsof_log.h b/agent/src/c/service/fsof_log.h
new file mode 100644
index 0000000..50ea9c8
--- /dev/null
+++ b/agent/src/c/service/fsof_log.h
@@ -0,0 +1,28 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef FSOF_LOG_H
+#define FSOF_LOG_H
+
+enum log_level{
+    DEBUG = 1,
+    INFO,
+    ERROR
+};
+int fsof_log_init();
+void fsof_log_info(enum log_level level,const char *format,...);
+void fsof_log_close();
+#endif
diff --git a/agent/src/c/service/fsof_mq.c b/agent/src/c/service/fsof_mq.c
new file mode 100644
index 0000000..211dc87
--- /dev/null
+++ b/agent/src/c/service/fsof_mq.c
@@ -0,0 +1,155 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#include  "fsof_mq.h"
+#include <string.h>
+#include <assert.h>
+
+#define DEFAULT_QUEUE_SIZE (1024)
+
+struct fsof_queue {
+    int cap;
+    int head;
+    int tail;
+    int lock;
+    struct fsof_message *queue;
+};
+
+struct fsof_queue* fsof_mq_create() {
+    struct fsof_queue *q = malloc(sizeof(struct fsof_queue));
+    if (q == NULL) {
+        //log info error malloc failed exit
+        exit(-1);
+    }
+   
+    q->cap = DEFAULT_QUEUE_SIZE;
+    q->head = 0;
+    q->tail = 0;
+    q->lock = 0;
+    q->queue = malloc(sizeof(struct fsof_message) * q->cap);
+    if (q->queue == NULL) {
+        //log info error malloc failed exit
+        free(q);
+        exit(-1);
+    }
+    
+    return q;
+}
+
+//expand queue 
+static void fsof_expand_queue(struct fsof_queue *q) {
+    struct fsof_message *new_queue = malloc(sizeof(*new_queue) * q->cap * 2);
+	
+    int i;    
+    for (i = 0; i < q->cap; i++) {
+        new_queue[i] = q->queue[i];
+    }
+
+    q->head = 0;
+    q->tail = q->cap;
+    q->cap *= 2;
+    free(q->queue);
+    q->queue = new_queue;
+}
+
+void fsof_mq_push(struct fsof_queue *q,struct fsof_message *message) {
+    assert(message);
+    LOCK(q);
+
+    q->queue[q->tail++] = *message;
+    if (q->tail >= q->cap) {
+        q->tail = 0;
+    }
+
+    if (q->head == q->tail) {
+        fsof_expand_queue(q);
+    }
+
+    UNLOCK(q);
+}
+
+int fsof_mq_pop(struct fsof_queue *q,struct fsof_message *message) {
+    int ret = 0;  
+    LOCK(q);
+
+    if (q->head != q->tail) {
+        *message = q->queue[q->head++]; 
+        ret = 1;
+        
+        if (q->head >= q->cap) {
+            q->head = 0;
+        }
+    }
+    
+    UNLOCK(q);
+    return ret;
+}
+
+int fsof_mq_len(struct fsof_queue *q) {
+    int len = 0;
+    LOCK(q);
+
+    if (q->head <= q->tail) {
+        len = q->tail - q->head;
+    }else {
+        len = q->tail + q->cap - q->head;
+    }
+
+    UNLOCK(q);
+    return len;
+}
+
+int fsof_mq_clear(struct fsof_queue *q) {
+	LOCK(q);
+	UNLOCK(q);
+	int i,j = 0;
+	for (i = 0; i < q->cap; i++) {
+		if (q->queue[i].key != NULL) {
+			free(q->queue[i].key);
+		}
+
+		for (j = 0; j < q->queue[i].count; j++) {
+			if (q->queue[i].value[j] != NULL) {
+				free(q->queue[i].value[j]);
+			}
+		}
+	}
+	memset(q->queue,0,sizeof(struct fsof_message) * q->cap);
+	return 0;
+}
+
+void fsof_mq_destroy(struct fsof_queue *q) {
+
+    if(NULL != q) {
+        if(NULL != q->queue) {
+            int i,j = 0;
+            for (i = 0; i < q->cap; i++) {
+                if (q->queue[i].key != NULL) {
+                    free(q->queue[i].key);
+                }
+
+                for (j = 0; j < q->queue[i].count; j++) {
+                    if (q->queue[i].value[j] != NULL) {
+                        free(q->queue[i].value[j]);
+                    }
+                }
+            }
+            free(q->queue);
+        }
+	 
+        free(q);
+    }
+}
diff --git a/agent/src/c/service/fsof_mq.h b/agent/src/c/service/fsof_mq.h
new file mode 100644
index 0000000..c31f4d1
--- /dev/null
+++ b/agent/src/c/service/fsof_mq.h
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef FSOF_MESSAGE_QUEUE_H
+#define FSOF_MESSAGE_QUEUE_H
+#include <stdlib.h>
+#include <stdint.h>
+
+#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
+#define UNLOCK(q) __sync_lock_release(&(q)->lock);
+
+struct fsof_message {
+    char *key;
+    char **value;
+    int count; //total providers count
+};
+
+struct fsof_queue;
+
+//push data into message queue
+void fsof_mq_push(struct fsof_queue *q,struct fsof_message *message);
+//pop data  from message queue
+int fsof_mq_pop(struct fsof_queue *q,struct fsof_message *message);
+//message queue len
+int  fsof_mq_len(struct fsof_queue *q);
+//message queue struct create
+struct fsof_queue* fsof_mq_create();
+//clear message
+int fsof_mq_clear(struct fsof_queue *q);
+//message queue destroy
+void fsof_mq_destroy(struct fsof_queue *q);
+
+#endif
diff --git a/agent/src/c/service/fsof_redis.c b/agent/src/c/service/fsof_redis.c
new file mode 100644
index 0000000..919d160
--- /dev/null
+++ b/agent/src/c/service/fsof_redis.c
@@ -0,0 +1,242 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#include "fsof_redis.h"
+#include "fsof_mq.h"
+#include "mt_array.h"
+#include "fsof_log.h"
+#include <hiredis/hiredis.h>  
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <netinet/in.h>
+
+#define UNIX_PATH_LEN (100)
+
+struct array_object {
+    char *data_ptr;
+};
+
+extern char g_str_localip[INET_ADDRSTRLEN];
+static redisContext* g_redis_conn = NULL;
+static char unix_path[UNIX_PATH_LEN] = {0};
+
+/*
+* compare zookeeper provider list with redis provider list,then delete not exists list and add new provider list
+*/
+int compare_and_set_val(const struct fsof_message *message) {
+    struct redisReply *object = NULL;
+    struct redisReply *reply = fsof_redis_get(message->key);
+    if (reply != NULL && reply->elements > 0 && message->count > 0) {
+        //mt_array_t *same_list = mt_array_create(message->count,sizeof(struct array_object));
+        mt_array_t *new_list = mt_array_create(message->count,sizeof(struct array_object));
+        mt_array_t *delete_list = mt_array_create(message->count,sizeof(struct array_object));
+        //assert(same_list != NULL);
+        assert(new_list != NULL);
+        assert(delete_list != NULL);
+
+        struct array_object *tmp_object = NULL;
+        int i = 0;
+        int j = 0;
+        for (; i < reply->elements; i++) {
+            object = reply->element[i]; 
+            if (object != NULL) {
+                for (; j < message->count; j++) {
+                    if (strcmp(object->str,message->value[j]) == 0) {//equal
+                        break;
+                    }
+                } 
+
+                if (j == message->count) {//not found need delete
+                    tmp_object = (struct array_object*)mt_array_push(delete_list);
+                    assert(tmp_object != NULL);
+                    if (tmp_object != NULL) {
+                        tmp_object->data_ptr = object->str;
+                    }
+                }
+
+                if (j < message->count) { //found same value
+                    //nothing to do
+                }
+
+                j = 0;
+            }
+        }
+
+        i = j = 0;
+        for (; i < message->count; i++) {
+            for (; j < reply->elements; j++) {
+                object = reply->element[j]; 
+                if (strcmp(object->str,message->value[i]) == 0) {//equal
+                    break;
+                }
+            }
+
+            if (j == reply->elements) { // not found new value 
+                tmp_object = (struct array_object*)mt_array_push(new_list);
+                assert(tmp_object != NULL);
+                if (tmp_object != NULL) {
+                    tmp_object->data_ptr = message->value[i];
+                }
+            }
+
+            j = 0;
+        }
+
+        if (delete_list->nelts > 0) {
+            struct array_object *ptr = NULL;
+            struct redisReply *tmp_reply = NULL;
+            i = 0;
+            for (; i < delete_list->nelts; i++) {
+                ptr = (struct array_object*)(delete_list->elts + i * delete_list->size);
+                fsof_log_info(INFO,"BEGIN Delete val is %s succeed,key is %s\n",ptr->data_ptr,message->key);
+__DELETE_AGAIN:
+                tmp_reply = redisCommand(g_redis_conn,"lrem %s 0 %s",message->key,ptr->data_ptr); //delete value
+                if (tmp_reply == NULL) {
+                    fsof_redis_close();
+                    fsof_redis_init(unix_path);
+                    goto __DELETE_AGAIN;
+                }
+
+                fsof_log_info(INFO,"Delete val is %s succeed,key is %s\n",ptr->data_ptr,message->key);
+                freeReplyObject(tmp_reply);
+            }
+        }
+
+        if (new_list->nelts > 0) {
+            i = 0;
+            struct array_object *ptr = NULL;
+            struct redisReply *tmp_reply = NULL;
+            for (; i < new_list->nelts; i++) {
+                ptr = (struct array_object*)(new_list->elts + i * new_list->size);
+__NEW_AGAIN:
+                tmp_reply = redisCommand(g_redis_conn,"lpush %s %s",message->key,ptr->data_ptr);
+                if (tmp_reply == NULL) {
+                    fsof_redis_close();
+                    fsof_redis_init(unix_path);
+                    goto __NEW_AGAIN;
+                }
+                fsof_log_info(INFO,"Insert val is %s succeed,key is %s\n",ptr->data_ptr,message->key);
+                freeReplyObject(tmp_reply);
+            }
+        }
+
+        mt_array_destroy(delete_list);
+        mt_array_destroy(new_list);
+        //mt_array_destroy(same_list);
+        freeReplyObject(reply);  
+    } else {
+        return fsof_redis_setval(message); //directly set new value list
+    }
+    return 0;
+}
+
+//set list into redis
+int fsof_redis_setval(const struct fsof_message *message) {
+    assert(message);
+    int i = 0;
+    struct redisReply *reply = NULL;
+
+
+    if (message->count > 0) {
+        for (i = 0; i < message->count; i++) {
+            if (message->value[i] != NULL) {
+__SET_AGAIN:
+                reply = redisCommand(g_redis_conn,"lpush %s %s",message->key,message->value[i]);
+                if (reply == NULL) {
+                    fsof_redis_close();
+                    fsof_redis_init(unix_path);
+                    goto __SET_AGAIN;
+                }
+
+                freeReplyObject(reply);
+            }
+        }
+    }
+    
+    return 0;
+}
+
+struct redisReply* fsof_redis_get(const char *path) {
+    struct redisReply *reply = NULL;
+
+__GET_AGAIN:
+    reply = redisCommand(g_redis_conn,"lrange %s 0 -1",path);
+    if (reply == NULL) {
+        //occured an bad error ,need rejoin redis server
+        fsof_redis_close();
+        fsof_redis_init(unix_path);
+        goto __GET_AGAIN;
+    } else {
+        if (reply->type != REDIS_REPLY_ARRAY) {  //value type must be array
+            freeReplyObject(reply);  
+            return NULL; 
+        }
+    }
+    
+    return reply;
+}
+
+int fsof_redis_delete(const char *path) {
+    int err = 0;
+    struct redisReply *reply = NULL;
+
+__DELETE_AGAIN:
+    reply = redisCommand(g_redis_conn,"del %s",path);
+    if (reply == NULL) {
+        //occured an bad error ,need rejoin redis server
+        fsof_redis_close();
+        fsof_redis_init(unix_path);
+        goto __DELETE_AGAIN;
+    } else {
+        freeReplyObject(reply);
+    }
+    
+    return err;
+}
+
+void fsof_redis_close() {
+    redisFree(g_redis_conn);
+}
+
+int fsof_redis_init(const char *path) {
+    int ret = 0;
+    struct timeval start = {0};
+    struct timeval end = {0};
+    int exec_time = 0;
+    struct timeval time;
+
+    time.tv_sec = 0;
+    time.tv_usec = 60;
+
+    do {
+        gettimeofday(&start,NULL);
+        g_redis_conn = redisConnectUnixWithTimeout(path,time);
+        gettimeofday(&end,NULL);
+        exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_sec - start.tv_sec); //calculate execute time
+        ret = g_redis_conn->err;
+
+        if (ret > 0) {
+            fsof_log_info(INFO,"%s|FSOF_AGENT|%d|connect redis timeout!|connect_redis|%d",g_str_localip,ret,exec_time);
+            sleep(300);
+        }
+    }while(ret);
+
+    strcpy(unix_path,path);
+    fsof_log_info(INFO,"%s|FSOF_AGENT|%d|connect redis succeed!|connect_redis|%d",g_str_localip,ret,exec_time);
+    return 0;
+}
+
diff --git a/agent/src/c/service/fsof_redis.h b/agent/src/c/service/fsof_redis.h
new file mode 100644
index 0000000..0fdaf5e
--- /dev/null
+++ b/agent/src/c/service/fsof_redis.h
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef FSOF_REDIS_H
+#define FSOF_REDIS_H
+
+struct fsof_message;
+
+int fsof_redis_init(const char *path);
+int fsof_redis_delete(const char *path);
+//compare redis exists provider list with zookeeper exists provider list add by iceli
+int compare_and_set_val(const struct fsof_message *message);
+//directly set zookeeper exists provider list into redis when redis can't find exists provider list add by iceli
+int fsof_redis_setval(const struct fsof_message *message);
+struct redisReply* fsof_redis_get(const char *path);
+void fsof_redis_close();
+
+
+#endif
diff --git a/agent/src/c/service/fsof_zookeeper.c b/agent/src/c/service/fsof_zookeeper.c
new file mode 100644
index 0000000..c5a2bd6
--- /dev/null
+++ b/agent/src/c/service/fsof_zookeeper.c
@@ -0,0 +1,171 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#include "fsof_zookeeper.h"
+#include "../common/strmap.h"
+#include "../common/fsof_global.h"
+#include <assert.h>
+#include <errno.h>
+
+#define TIME_OUT 30000
+#define ZOOKEEPER_VERSION -1
+
+extern int errno;
+
+struct provider_callback {
+    watcher_fn watcher_cb;
+};
+
+
+static zhandle_t* g_zkhandle = NULL;
+static watcher_fn g_watcher_fn; 
+struct StrMap *g_provider_map;
+
+
+void fsof_zk_create(const char *path,bool ephemeral) {
+    //nothing to do
+}
+
+int fsof_zk_delete(const char *path) {
+    int ret;
+    ret = zoo_delete(g_zkhandle,path,-1);
+    
+    return ret;
+}
+
+struct String_vector * fsof_zk_get_children(const char *path) {
+    int ret = -1;
+    struct map_object *object_val = NULL;
+    struct provider_callback *cb = NULL;
+    struct String_vector *str_list = NULL;
+
+    if (g_zkhandle == NULL) {
+        return NULL;
+    }
+
+    str_list = malloc(sizeof(*str_list));
+    if (str_list == NULL) {
+        //log error
+        exit(-1);
+    }
+	
+    memset(str_list, 0, sizeof(*str_list));
+    sm_get(g_provider_map,path,&object_val); 
+   
+    if (object_val != NULL && object_val->status == 1) { //succeed
+        if (object_val->type == MAP_OBJECT_CB_TYPE) {
+            cb = object_val->ptr;
+            ret = zoo_wget_children(g_zkhandle,path,cb->watcher_cb,NULL,str_list);
+        }
+    } else { //0 error,can't get provider callback
+        ret = zoo_wget_children(g_zkhandle,path,NULL,NULL,str_list);
+    }
+
+    if (ret < 0) {
+        //log error 
+        free(str_list);
+        return NULL;
+    }
+
+    return str_list;
+}
+
+void fsof_zk_add_listener(const char *path,watcher_fn watcher) {
+    struct provider_callback *cb = NULL;
+    struct map_object *object_val = NULL;
+
+    if (sm_exists(g_provider_map,path)) { //exist
+        sm_get(g_provider_map,path,&object_val);
+        cb = (struct provider_callback*)object_val->ptr;
+        if (cb != NULL) {
+            if (cb->watcher_cb != watcher) { //not same
+                cb->watcher_cb = watcher;
+            }
+            object_val->status = 1;
+        }
+
+    } else { //create new one
+        cb = malloc(sizeof(*cb));
+        assert(cb);
+        object_val = malloc(sizeof(*object_val));
+        assert(object_val);
+        cb->watcher_cb = watcher;
+        object_val->type = MAP_OBJECT_CB_TYPE;
+        object_val->ptr  = cb;
+        object_val->status  = 1;
+        sm_put(g_provider_map,path,object_val);
+    }
+}
+
+void fsof_zk_remove_listener(const char *path,watcher_fn watcher) {
+    struct provider_callback *cb = NULL;
+    struct map_object *object_val = NULL;
+
+    if (sm_exists(g_provider_map,path)) { //exist
+        sm_get(g_provider_map,path,&object_val);
+        if (object_val != NULL) {
+            cb = (struct provider_callback*)object_val->ptr;
+            if (cb != NULL && cb->watcher_cb == watcher) {
+                object_val->status = 0;
+            }
+        }
+    }
+}
+
+void fsof_zk_add_state_listener(watcher_fn watcher) {
+    g_watcher_fn = watcher;
+}
+
+void fsof_zk_remove_state_listener(watcher_fn watcher) {
+    g_watcher_fn = NULL;
+}
+
+int fsof_zk_init(const char *host) {
+    int err = 0;
+
+    if (g_watcher_fn == NULL) {
+        //log error
+        exit(-1);
+    }
+
+    g_zkhandle = zookeeper_init(host,g_watcher_fn,TIME_OUT, 0, "hello zookeeper.", 0);
+    if (g_zkhandle == NULL) {
+        //log error
+        err = errno; //failed 
+        return err;
+    }
+
+    g_provider_map = sm_new(DEFAULT_MAP_COUNT);
+    if (g_provider_map == NULL) {
+        //log error malloc failed
+        exit(-1);
+    }   
+
+    return err;
+}
+
+void fsof_zk_close() {
+    if (g_zkhandle != NULL) {
+        zookeeper_close(g_zkhandle);
+
+        if (g_provider_map != NULL) {
+            sm_delete(g_provider_map);
+            g_provider_map = NULL;
+        }
+
+        g_zkhandle = NULL;
+    }
+}
diff --git a/agent/src/c/service/fsof_zookeeper.h b/agent/src/c/service/fsof_zookeeper.h
new file mode 100644
index 0000000..c0e52ad
--- /dev/null
+++ b/agent/src/c/service/fsof_zookeeper.h
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef FSOF_ZOOKEEPER_H
+#define FSOF_ZOOKEEPER_H
+#include "fsof_mq.h"
+#include <stdbool.h>
+#include <zookeeper/zookeeper.h>
+
+
+typedef void (*watcher_fn)(zhandle_t* zh, int type, int state,
+                const char* path, void* watcherCtx);
+void fsof_zk_create(const char *path,bool ephemeral);
+
+int fsof_zk_delete(const char *path);
+
+struct String_vector * fsof_zk_get_children(const char *path);
+
+void fsof_zk_add_listener(const char *path,watcher_fn watcher);
+
+void fsof_zk_remove_listener(const char *path,watcher_fn watcher);
+
+void fsof_zk_add_state_listener(watcher_fn watcher);
+
+void fsof_zk_remove_state_listener(watcher_fn watcher);
+
+int fsof_zk_init(const char *host);
+
+void fsof_zk_close();
+
+
+#endif
diff --git a/agent/src/c/service/mt_array.c b/agent/src/c/service/mt_array.c
new file mode 100644
index 0000000..5e525c0
--- /dev/null
+++ b/agent/src/c/service/mt_array.c
@@ -0,0 +1,72 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#include "mt_array.h"
+#include "string.h"
+
+static int mt_array_init(mt_array_t *m,int nalloc,int size);
+
+mt_array_t *mt_array_create(int nalloc,int size) {
+	mt_array_t *m = malloc(sizeof(mt_array_t));	
+	if (m == NULL) { //failed
+		return NULL;
+	}
+	int ret = mt_array_init(m,nalloc,size);
+	if (ret == -1) {
+		return NULL;
+	}
+	return m;
+}
+
+void *mt_array_push(mt_array_t *m) {
+	size_t size;
+	void *new,*elt;
+	if (m->nalloc == m->nelts) {//full
+		size = m->size * m->nalloc;
+		new = malloc(size * 2);	
+		if (new == NULL) {
+			return NULL;
+		}
+		memcpy(new,m->elts,size);
+		free(m->elts);
+		m->elts = new;
+		m->nalloc *= 2;
+	}
+
+	elt = (char*)m->elts + m->nelts * m->size;
+	m->nelts++;
+	return elt;
+
+}
+
+void mt_array_destroy(mt_array_t *m) {
+	if (m->elts != NULL) {
+		free(m->elts);
+		free(m);
+	}
+
+}
+
+static int mt_array_init(mt_array_t *m,int nalloc,int size) {
+	m->nelts = 0;
+	m->size = size;
+	m->nalloc = nalloc;
+	m->elts = malloc(nalloc * size);
+	if (m->elts == NULL) {
+		return -1;
+	}
+	return 0;
+}
diff --git a/agent/src/c/service/mt_array.h b/agent/src/c/service/mt_array.h
new file mode 100644
index 0000000..5af3bcd
--- /dev/null
+++ b/agent/src/c/service/mt_array.h
@@ -0,0 +1,31 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#ifndef MT_ARRAY_H
+#define MT_ARRAY_H
+#include <stdlib.h>
+
+typedef struct{
+	void *elts;
+	int nelts;
+	size_t size;
+	int nalloc;
+}mt_array_t;
+
+mt_array_t *mt_array_create(int nalloc,int size);
+void* mt_array_push(mt_array_t *m);
+void mt_array_destroy(mt_array_t *m);
+#endif
diff --git a/agent/src/c/src/fsof_main.c b/agent/src/c/src/fsof_main.c
new file mode 100644
index 0000000..8c71142
--- /dev/null
+++ b/agent/src/c/src/fsof_main.c
@@ -0,0 +1,524 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <assert.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <hiredis/hiredis.h>  
+#include "../service/fsof_mq.h"
+#include "../service/mt_array.h"
+#include "../service/fsof_zookeeper.h"
+#include "../common/fsof_global.h"
+#include "../common/fsof_util.h"
+#include "../service/fsof_redis.h"
+#include "../service/fsof_log.h"
+#include "../common/fsof_url.h"
+#include <sys/fcntl.h>
+#include <signal.h>
+
+//redis thread handle
+pthread_t g_redis_pid;
+//message queue ,store zookeeper node info
+struct fsof_queue *g_message_queue;
+//current zookeeper config path
+static char g_zookeeper_conf[MAX_CONFIG_PATH_LEN] = {0};
+//zookeeper url list
+static char g_zk_list[512] = {0};
+char g_str_localip[INET_ADDRSTRLEN] = {0};
+
+void init_zookeeper_env();
+static void set_all_providers_watcher(struct String_vector *list); //all providers add watcher 
+static void enum_provider_list(struct fsof_message *message);
+static void get_zk_root_children();
+
+//deal with signo  such as SIGALARM
+void sigroutine(int signo) {
+    //need to get zookeeper node info  from zk server manually
+    if (signo == SIGALRM) { 
+        fsof_log_info(ERROR,"Now recvied alarm signal\n");
+        get_zk_root_children();
+    }
+}
+
+//create thread
+static void create_thread(pthread_t *thread,void *(*start_routine) (void *),void *arg) {
+    if (pthread_create(thread,NULL,start_routine,arg)) {
+        //thread create failed
+        fsof_log_info(INFO,"create thread function called failed!\n");
+        exit(-1);
+    }
+}
+
+//redis worker thread ,main job is getting message from g_message_queue ,then write into redis 
+static void * thread_redis_work(void *p) {
+    int ret = 0;
+    int i = 0;
+    struct fsof_message message = {0};
+    struct timeval start = {0};
+    struct timeval end = {0};
+    int exec_time = 0;
+	
+    while(true) {
+        //pop message from g_message_queue
+        ret = fsof_mq_pop(g_message_queue,&message);
+        if (ret) {
+            //deal with message
+            if (message.count > 0) {
+                gettimeofday(&start,NULL);
+                ret = compare_and_set_val(&message);
+                gettimeofday(&end,NULL);
+                exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+                if (ret == 0) { 
+                    //insert succeed
+                    fsof_log_info(INFO,"%s|FSOF_AGENT|%d|set redis data succeed!|set_redis|%d",g_str_localip,0,exec_time);
+                } 
+            } else {
+                gettimeofday(&start,NULL);
+                fsof_redis_delete(message.key);
+                gettimeofday(&end,NULL);
+                exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+                fsof_log_info(DEBUG,"%s|FSOF_AGENT|%d|delete redis data  key succeed!|delete_redis|%d",g_str_localip,0,exec_time);
+            }
+            //enum every provider value and key
+            enum_provider_list(&message);
+            //free message content, message itself free by g_message_queue
+            for (i = 0; i < message.count; i++) {
+                if (message.value[i] != NULL) {
+                    free(message.value[i]);
+                }
+            }
+
+            free(message.key);
+            if (message.value != NULL) {
+                free(message.value);
+            }
+        } else {
+            //0.1 seconds
+            usleep(100000);
+        }
+
+    }
+    
+    return NULL;
+}
+
+static void parse_provider_key(struct String_vector *list,const char *path) {
+    int i ;
+    struct fsof_message message  = {0};
+    char url_encode_data[URL_ENCODE_BUF_LEN] = {0};
+    int nlen = 0;
+    int service_len = 0;
+    int provider_index = 0;
+    char  *provider_str = NULL;
+ 
+    //get service key
+    provider_str = strstr(path,PROVIDER_NAME);
+    provider_index = provider_str - path;
+    service_len = provider_index - sizeof(FSOF_ROOT_NAME);
+    if (service_len <= 0) {
+        return;
+    }
+
+    message.key = malloc(service_len + 1);
+    assert(message.key);
+    memcpy(message.key,path + sizeof(FSOF_ROOT_NAME),service_len);
+    message.key[service_len] = '\0';
+
+    if (list->count > 0) {
+        message.value = malloc(sizeof(char*) * list->count);
+        assert(message.value);
+        memset(message.value,0,sizeof(char*) * list->count);
+
+        int val_index = 0;
+        for (i = 0; i < list->count; i++) {
+            memcpy(url_encode_data,list->data[i],strlen(list->data[i]));
+            nlen = fsof_url_decode(url_encode_data,strlen(url_encode_data));
+            fsof_log_info(INFO,"key: %s,value: %s,nlen is %d\n",message.key,url_encode_data,nlen);
+			message.value[val_index] = malloc(nlen + 1);
+			assert(message.value[val_index]);
+			strcpy(message.value[val_index],url_encode_data);
+			message.value[val_index][nlen] = '\0';
+			val_index++;
+            memset(url_encode_data,0,URL_ENCODE_BUF_LEN);
+        }
+
+        message.count = val_index;
+
+    }else {
+        fsof_log_info(INFO,"parse key  child is zero,need to delete redis key %s\n",path);
+        //means delete provider key
+        message.count = 0; 
+    }
+
+    fsof_mq_push(g_message_queue,&message);
+
+}
+
+//enum provider list
+static void enum_provider_list(struct fsof_message *message) {
+    int i ;
+
+    for (i = 0; i < message->count; i++) {
+        fsof_log_info(INFO,"Enum provider key value is %s,path is %s\n",message->value[i],message->key);
+    }
+}
+
+static void fsof_provider_node_watcher(zhandle_t* zh, int type, int state,
+                                                 const char* path, void* watcherCtx) {
+    struct String_vector *str_list = NULL;
+    struct timeval start = {0};
+    struct timeval end   = {0};
+    int exec_time = 0;
+
+    if (type == ZOO_CHILD_EVENT) {
+
+		fsof_log_info(INFO,"%s children node has been changed ,need to get new children list\n",path);
+        if (strcmp(path,FSOF_ROOT_NAME) == 0) {
+            gettimeofday(&start,NULL);
+            str_list = fsof_zk_get_children(FSOF_ROOT_NAME);
+            gettimeofday(&end,NULL);
+            exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+
+            if (str_list != NULL) {
+                fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data succeed!|get_zookeeper|%d",g_str_localip,0,exec_time);
+                set_all_providers_watcher(str_list);
+            } else {
+                fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data failed!|get_zookeeper|%d",g_str_localip,-1,exec_time);
+            }
+        } else {
+            gettimeofday(&start,NULL);
+            str_list = fsof_zk_get_children(path);
+            gettimeofday(&end,NULL);
+            exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+
+            if (str_list != NULL) {
+                fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data succeed!|get_zookeeper|%d",g_str_localip,0,exec_time);
+                parse_provider_key(str_list,path);
+            } else {
+                fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data failed!|get_zookeeper|%d",g_str_localip,-1,exec_time);
+            }
+        }
+		
+        if (str_list != NULL) {
+            deallocate_String_vector(str_list);
+            free(str_list);
+        }		
+    }
+}
+
+//watcher service node ,when the service node children has been changed ,need to set provider watcher
+static void fsof_service_node_watcher(zhandle_t* zh, int type, int state,
+                                                const char* path, void* watcherCtx) {
+    struct String_vector *str_list = NULL;
+    struct String_vector *provider_list = NULL;
+    struct timeval start = {0};
+    struct timeval end   = {0};
+    int exec_time = 0;
+    char provider_key[512] = {0};
+    int i;
+
+    if (type == ZOO_CHILD_EVENT) {
+            fsof_log_info(INFO,"service node watcher  entered %s\n",path);
+            gettimeofday(&start,NULL);
+            str_list = fsof_zk_get_children(path);
+            gettimeofday(&end,NULL);
+            exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+
+            if (str_list != NULL) {
+                sprintf(provider_key,"%s%s",path,PROVIDER_NAME);
+                fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data succeed!|get_zookeeper|%d",g_str_localip,0,exec_time);
+
+                for (i = 0; i < str_list->count; i++) {
+                    if (strcmp(str_list->data[i],PROVIDER_NODE_NAME) == 0) {
+                        fsof_zk_add_listener(provider_key,fsof_provider_node_watcher);
+                        gettimeofday(&start,NULL);
+                        provider_list = fsof_zk_get_children(provider_key); 
+                        gettimeofday(&end,NULL);
+                        exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+
+                        if (provider_list != NULL) { //deal 
+                            //enum_provider_list(provider_list,provider_key);
+                            parse_provider_key(provider_list,provider_key);
+                            deallocate_String_vector(provider_list);
+                            free(provider_list);
+                            fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data succeed!|get_zookeeper|%d",g_str_localip,0,exec_time);
+                        } else {
+                            fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data failed!|get_zookeeper|%d",g_str_localip,-1,exec_time);
+                        }
+                        break;
+                    }
+                } 
+
+                deallocate_String_vector(str_list);
+                free(str_list);
+            } else {
+                fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data failed!|get_zookeeper|%d",g_str_localip,-1,exec_time);
+            }
+    }
+
+}
+
+static void set_all_providers_watcher(struct String_vector *list) {
+    struct String_vector *provider_list = NULL;
+    char provider_key[512] = {0};
+    struct timeval start = {0};
+    struct timeval end   = {0};
+    int exec_time = 0;
+    int i;
+
+    for (i = 0; i < list->count; i++) {
+        sprintf(provider_key,"%s/%s%s",FSOF_ROOT_NAME,list->data[i],PROVIDER_NAME);
+        fsof_zk_add_listener(provider_key,fsof_provider_node_watcher);
+        gettimeofday(&start,NULL);
+        provider_list = fsof_zk_get_children(provider_key); 
+        gettimeofday(&end,NULL);
+        exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+        
+        if (provider_list == NULL) {
+            fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data failed!|get_zookeeper|%d",g_str_localip,-1,exec_time);
+            memset(provider_key,0,sizeof(provider_key));
+            sprintf(provider_key,"%s/%s",FSOF_ROOT_NAME,list->data[i]);
+            fsof_zk_add_listener(provider_key,fsof_service_node_watcher);
+            gettimeofday(&start,NULL);
+            provider_list = fsof_zk_get_children(provider_key);
+            gettimeofday(&end,NULL);
+            exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+
+            if (provider_list == NULL) {
+                fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data failed!|get_zookeeper|%d",g_str_localip,-1,exec_time);
+            } else {
+                fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data succeed!|get_zookeeper|%d",g_str_localip,0,exec_time);
+            }
+        }else {
+            //enum_provider_list(provider_list,provider_key);
+            fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data succeed!|get_zookeeper|%d",g_str_localip,0,exec_time);
+            parse_provider_key(provider_list,provider_key);
+        }
+
+        memset(provider_key,0,sizeof(provider_key));
+        if (provider_list != NULL) {
+            deallocate_String_vector(provider_list);
+            free(provider_list);
+        }
+    }    
+}
+static void get_zk_root_children() {
+    struct timeval start = {0};
+    struct timeval end   = {0};
+    int exec_time = 0;
+    struct String_vector *str_list = NULL;
+
+    fsof_zk_add_listener(FSOF_ROOT_NAME,fsof_provider_node_watcher);
+    gettimeofday(&start,NULL);
+    str_list = fsof_zk_get_children(FSOF_ROOT_NAME);
+    gettimeofday(&end,NULL);
+    exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec); //calculate execute time
+
+    if (str_list != NULL) {
+        fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data succeed!|get_zookeeper|%d",g_str_localip,0,exec_time);
+        set_all_providers_watcher(str_list);
+    }else {
+        fsof_log_info(INFO,"%s|FSOF_AGENT|%d|get zookeeper data failed!|get_zookeeper|%d",g_str_localip,-1,exec_time);
+        fsof_log_info(INFO,"can't get children of key %s\n",FSOF_ROOT_NAME);
+    }
+
+    if (str_list != NULL) {
+        deallocate_String_vector(str_list);
+        free(str_list);
+    }
+}
+
+//watcher fsof root node  main event :ZOO_CONNECTED_STATE ZOO_EXPIRED_SESSION_STATE
+static void fsof_root_node_watcher(zhandle_t* zh, int type, int state,
+                                            const char* path, void* watcherCtx) {
+    if (type == ZOO_SESSION_EVENT) {
+        if(state == ZOO_CONNECTED_STATE) {
+            //begin get children from root node
+            get_zk_root_children();
+        } else if (state == ZOO_EXPIRED_SESSION_STATE  || state == ZOO_CONNECTING_STATE || state == ZOO_AUTH_FAILED_STATE) {
+            //log info  sesstion expired need rejoin
+            fsof_log_info(ERROR,"zookeeper session expired,need rejoin zookeeper\n");
+            fsof_zk_close();
+            init_zookeeper_env();
+        }
+    }
+}
+
+void parse_zk_config(char *src,char *dest) {
+    assert(src);
+    assert(dest);
+    char *ptr = NULL;
+    char *tail_ptr = src + strlen(src);
+
+    while ((ptr = strstr(src,"http://")) != 0) { 
+        if ((ptr - src) == 0) {
+            src += strlen("http://");
+        }
+        else if ((ptr - src) > 0) {
+            memcpy(dest,src,ptr - src);
+            dest += ptr - src;
+            src += ptr - src + strlen("http://");
+        }
+    }
+
+    if (ptr == NULL && src != tail_ptr) {
+        memcpy(dest,src,tail_ptr - src);
+    }
+}
+
+void init_zookeeper_env() {
+   int ret = 0;
+   char *zk_str = NULL;
+   struct timeval start = {0};
+   struct timeval end   = {0};
+   int exec_time = 0;
+
+   if (*g_zookeeper_conf != '\0') { 
+        //parse zookeeper config
+        fsof_log_info(INFO,"Now begin start parse zookeeper config file %s!\n",g_zookeeper_conf);
+        zk_str = get_ini_key_string("fsof_setting","zk_url_list",g_zookeeper_conf);
+        parse_zk_config(zk_str,g_zk_list);
+        fsof_log_info(INFO,"Now end start parse zookeeper config file %s,zk list str is %s!\n",g_zookeeper_conf,g_zk_list);
+   }
+   //set  root node watcher
+   fsof_zk_add_state_listener(fsof_root_node_watcher);
+
+   do{
+        gettimeofday(&start,NULL);
+        ret = fsof_zk_init(g_zk_list);
+        gettimeofday(&end,NULL);
+        exec_time = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_sec - start.tv_sec); //calculate execute time
+         
+        if (ret > 0) {
+            fsof_log_info(INFO,"%s|FSOF_AGENT|%d|connect zookeeper timeout!|connect_zookeeper|%d",g_str_localip,ret,exec_time);
+            sleep(300);
+        }
+    }while(ret);
+   
+    fsof_log_info(INFO,"%s|FSOF_AGENT|%d|connect zookeeper succeed!|connect_zookeeper|%d",g_str_localip,ret,exec_time);
+}
+
+static void get_local_ip() {
+    struct ifaddrs * ifAddrStruct = NULL;
+    void * tmpAddrPtr = NULL;
+
+    getifaddrs(&ifAddrStruct);
+    while (ifAddrStruct != NULL) {
+        
+        if (ifAddrStruct->ifa_addr->sa_family == AF_INET) {
+            tmpAddrPtr = &((struct sockaddr_in *)ifAddrStruct->ifa_addr)->sin_addr; 
+            inet_ntop(AF_INET, tmpAddrPtr, g_str_localip, INET_ADDRSTRLEN);
+        }
+
+        ifAddrStruct = ifAddrStruct->ifa_next;
+        memset(g_str_localip,0,INET_ADDRSTRLEN);
+    }
+}
+
+void cleanup_env() {
+   fsof_zk_close();
+   fsof_redis_close();
+   fsof_log_close();
+}
+
+//set process to daemon 
+void daemonize(void) {
+    int fd;
+
+    /* parent exits */
+    if (fork() != 0) {
+        exit(0); 
+    }
+
+    /* create a new session */	
+    setsid();
+
+    /* Every output goes to /dev/null. If Redis is daemonized but
+     * the 'logfile' is set to 'stdout' in the configuration file
+     * it will not log at all. */
+    if ((fd = open("/dev/null", O_RDWR, 0)) != -1) {
+        dup2(fd, STDIN_FILENO);
+        dup2(fd, STDOUT_FILENO);
+        dup2(fd , STDERR_FILENO);
+		
+		close(fd);
+    }
+}
+
+int main(int argc,char **argv) {
+    int err = 0;
+    struct itimerval timer_setting,old_val;
+    int timer_val = 0;
+
+    if (argc < 2){
+        fprintf(stderr,"parameters contains the timer value of zookeeper unit:second and the URL config of zookeeper!\n");
+        fprintf(stderr,"agent time conf/fsof.ini\n");
+        exit(0);
+    }
+    
+    //parameter contains the timer value of zookeeper unit:second
+    timer_val = atoi(argv[1]);
+    
+    //dubbo-php-framework/config/global/conf/fsof.ini
+    strncpy(g_zookeeper_conf, argv[2],  sizeof(g_zookeeper_conf) - 1 > strlen(argv[2]) ? strlen(argv[2]) : sizeof(g_zookeeper_conf) - 1);
+    if (access(g_zookeeper_conf, F_OK) == -1){
+        fprintf(stderr,"can not find conf/fsof.ini\n");
+        exit(0);
+    }
+    
+    //set process to daemon ,if failed ,directly exit
+    daemonize();
+    signal(SIGHUP, SIG_IGN);
+    signal(SIGPIPE, SIG_IGN);
+    signal(SIGALRM, sigroutine);
+
+    if (timer_val > 0) {
+        timer_setting.it_value.tv_sec = timer_val;
+        timer_setting.it_value.tv_usec = 0;
+        timer_setting.it_interval.tv_sec = timer_val;
+        timer_setting.it_interval.tv_usec = 0;
+        setitimer(ITIMER_REAL, &timer_setting, &old_val);   
+    }
+    
+    err = fsof_log_init();
+    if (err > 0) {
+        fprintf(stderr,"agent log init failed,exit!\n");
+        exit(-1);
+    }
+
+    get_local_ip();
+    g_message_queue = fsof_mq_create();
+    create_thread(&g_redis_pid,thread_redis_work,NULL);
+    fsof_redis_init(REDIS_UNIX_SOCK);
+    init_zookeeper_env();
+
+    pthread_join(g_redis_pid,NULL); 
+    fsof_mq_destroy(g_message_queue);
+    fsof_log_info(INFO,"fsof agent redis thread exit,need cleanup resource!\n");
+    
+    //cleanup
+    cleanup_env();
+   
+    return 0;
+}
+
diff --git a/api/FSOFApi.php b/api/FSOFApi.php
new file mode 100644
index 0000000..278674c
--- /dev/null
+++ b/api/FSOFApi.php
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+use com\fenqile\fsof\consumer\FSOFConsumer;
+use com\fenqile\fsof\consumer\proxy\ProxyFactory;
+
+class FSOFApi
+{
+	private static $__FSOF_CONSUMER_APP_NAME__ = NULL;
+	private static $__FSOF_CONSUMER_APP_SRC_PATH__ = NULL;
+
+    /**
+     * 设置Consumer运行上下文环境,在使用fsof_consumer时,该函数要最先调用
+     * @param $appName consumer app的名字
+     * @param $appSrcPath consumer app src源码的绝对路径
+     */
+	public static function configure($appName, $appSrcPath)
+	{
+		self::$__FSOF_CONSUMER_APP_NAME__ = $appName;
+		self::$__FSOF_CONSUMER_APP_SRC_PATH__ = $appSrcPath;
+	}
+
+    /**
+     *
+     *    获取指定provider服务的proxy对象
+     * @param $service  service配置文件中的key 例:com.alibaba.test.TestService      必选
+     * @param int $ioTimeout 连接超时时间和接收数据超时时间 单位 s;支持小数0.5 500ms
+     * @return \com\fenqile\fsof\consumer\proxy\Proxy|null
+     */
+	public static function newProxy($service ,$ioTimeout = 3)
+	{
+		$s = NULL;
+		if(empty(self::$__FSOF_CONSUMER_APP_NAME__) || empty(self::$__FSOF_CONSUMER_APP_SRC_PATH__))
+		{
+            \Logger::getLogger(__CLASS__)->error("appName or appSrcPath not set,please use FSOFApi::configure() for set.");
+            return null;
+		}
+		else
+		{
+			if(!is_numeric($ioTimeout) || $ioTimeout <= 0)
+			{
+				$ioTimeout = 3;
+			}
+            $consumerFile = dirname(__DIR__).DIRECTORY_SEPARATOR.'consumer'.DIRECTORY_SEPARATOR.'FSOFConsumer.php';
+            //加载FSOFConsumer
+            require_once($consumerFile);
+            $app_setting = array('app_name' => self::$__FSOF_CONSUMER_APP_NAME__, 'app_src' => self::$__FSOF_CONSUMER_APP_SRC_PATH__);
+            FSOFConsumer::init($app_setting);
+            $s = ProxyFactory::getInstance($service, $ioTimeout);
+		}
+		return $s;
+	}
+}
\ No newline at end of file
diff --git a/arch.png b/arch.png
new file mode 100644
index 0000000..05b60e1
Binary files /dev/null and b/arch.png differ
diff --git a/bin/app_admin.php b/bin/app_admin.php
new file mode 100644
index 0000000..13e6dc2
--- /dev/null
+++ b/bin/app_admin.php
@@ -0,0 +1,584 @@
+#!/usr/bin/php
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+require_once('log4php/Logger.php');
+
+use com\fenqile\fsof\common\config\FSOFConfigManager;
+
+define('FSOF_ROOT_PATH', __DIR__);
+define('FSOF_PROVIDER_PID_PATH', '/var/fsof/provider/');
+
+if(!defined("SIG_DFL")) define("SIG_DFL", 0);
+
+//加载commom
+$fsofCommonPath = dirname(FSOF_ROOT_PATH).DIRECTORY_SEPARATOR.'common';
+require_once($fsofCommonPath.DIRECTORY_SEPARATOR.'BootStrap.php');
+
+if(!defined("MASTER_PID_FILE_FORMAT")) define("MASTER_PID_FILE_FORMAT",'.master.pid');
+if(!defined("MANAGER_PID_FILE_FORMAT")) define("MANAGER_PID_FILE_FORMAT",'.manager.pid');
+
+if(!defined("FILTER_PROCESS_STATUS")) define("FILTER_PROCESS_STATUS",1);
+if(!defined("PS_CMD_WORK_PROCESS")) define("PS_CMD_WORK_PROCESS",2);
+
+if(!defined("PROVIDER_STATE_SUCCESS")) define("PROVIDER_STATE_SUCCESS",0);
+if(!defined("PROVIDER_STATE_FAILED")) define("PROVIDER_STATE_FAILED",1);
+if(!defined("PROVIDER_STATE_RUNNING")) define("PROVIDER_STATE_RUNNING",2);
+
+//检查swoole及zookeeper、redis是否安装
+if(!extension_loaded('swoole'))
+{
+	fwrite(STDERR,"\033[31;40m [ERROR] \033[0m no swoole extension.\n".PHP_EOL);
+	exit(1);
+}
+if (!extension_loaded('zookeeper'))
+{
+	fwrite(STDERR,"\033[31;40m [ERROR] \033[0m no zookeeper extension.\n".PHP_EOL);
+	exit(1);
+}
+if (!extension_loaded('redis'))
+{
+	fwrite(STDERR,"\033[31;40m [ERROR] \033[0m no redis extension.\n".PHP_EOL);
+	exit(1);
+}
+
+//php app_admin.php ServerName start
+if($argc == 3)
+{
+	$name = $argv[1];
+	$cmd = $argv[2];
+}
+else if (2 == $argc)
+{
+	$cmd = $argv[1];
+}
+else
+{
+	printInfo();
+	exit(1);
+}
+
+//新命令格式:app_admin cmd appname
+$cmds = array('start','stop','reload','status','restart','list','startall','shutdown','reloadall','extstart','extrestart');
+$one_cmds = array('start','stop','reload','restart','extstart','extrestart');
+$all_cmds = array('list','startall','shutdown','reloadall');
+if (!in_array($cmd,$cmds ) || (empty($name)&& in_array($cmd,$one_cmds)) || (!empty($name) && in_array($cmd,$all_cmds)))
+{
+	printInfo();
+	exit(1);
+}
+
+if(3 == $argc)
+{
+    echo "--------app_admin.php $name $cmd--------".PHP_EOL;
+}
+else
+{
+    echo "--------app_admin.php $cmd--------".PHP_EOL;
+}
+
+$config = FSOFConfigManager::getProviderAppDeploy($name);
+if(isset($config['server']['log_cfg_file_path']) && !empty($config['server']['log_cfg_file_path']))
+{
+    \Logger::configure($config['server']['log_cfg_file_path']);
+    date_default_timezone_set('PRC');
+}
+
+//执行所有的控制命令
+if($cmd == 'list')
+{
+	$configArr = FSOFConfigManager::getProviderAppList();
+	echo "---------your server list:---------".PHP_EOL;
+	foreach($configArr as $k => $v)
+	{
+		echo basename($v, '.deploy').PHP_EOL;
+	}
+	echo '----------------------------'.PHP_EOL;
+	exit(1);
+}
+else if ("startall" == $cmd)
+{
+	$providerList = FSOFConfigManager::getProviderAppList();
+	foreach($providerList as $k => $v)
+	{
+		$name = basename($v, '.deploy');
+		startProvider($name, "start");
+	}
+}
+else if ("reloadall" == $cmd || "shutdown" == $cmd)
+{
+	$providerList = FSOFConfigManager::getRunProviderList();
+	foreach($providerList as $k => $v)
+	{
+		$name = basename($v, MASTER_PID_FILE_FORMAT);
+		if ("reloadall" == $cmd)
+		{
+			reloadProvider($name);
+		}
+		else
+		{
+			stopProvider($name);
+			echo "server {$name} stop  \033[32;40m [SUCCESS] \033[0m".PHP_EOL;
+		}
+	}
+}
+else if ("reload" == $cmd)
+{
+	reloadProvider($name);
+}
+else if ("start" == $cmd || "extstart" == $cmd)
+{
+	$ret = startProvider($name, $cmd);
+	if (!$ret)
+	{
+		exit(1);
+	}
+}
+else if ("restart" == $cmd || "extrestart" == $cmd)
+{
+	$ret = restartProvider($name, $cmd);
+	if (!$ret)
+	{
+		exit(1);
+	}
+}
+else if ("stop" == $cmd )
+{
+	stopProvider($name);
+	echo "server {$name} stop  \033[32;40m [SUCCESS] \033[0m".PHP_EOL;
+}
+else if("status" == $cmd)
+{
+	if(empty($name))
+	{
+		$providerList = FSOFConfigManager::getProviderAppList();
+		foreach($providerList as $k => $v)
+		{
+			$name = basename($v, '.deploy');
+			getProviderStatus($name);
+		}
+	}
+	else
+	{
+		getProviderStatus($name);
+	}
+}
+
+function startServ($cmd, $name)
+{
+	$startUpPath = dirname(FSOF_ROOT_PATH)."/provider/shell/StartUp.php";
+	if(!file_exists($startUpPath))
+	{
+        echo "{$cmd} server {$name} \033[31;40m [FAIL] \033[0m; no find:{$startUpPath}".PHP_EOL;
+		return false;
+	}
+
+	initByFSOFConfig();;
+	$process = new \swoole_process(function(\swoole_process $worker) use($startUpPath, $cmd, $name)
+	{
+		$worker->exec(PHP_BIN_PATH, array($startUpPath, $name, $cmd));
+	}, false);
+	$process->start();
+	$exeRet = \swoole_process::wait();
+	if($exeRet['code'])
+	{
+		//创建失败
+        echo "{$cmd} server {$name} \033[31;40m [FAILED] \033[0m".PHP_EOL;
+        return false;
+	}
+	else
+	{
+        echo "{$cmd} server {$name}  \033[32;40m [SUCCESS] \033[0m".PHP_EOL;
+        return true;
+	}
+}
+
+function getProviderMasterPid($name)
+{
+	$providerFile = FSOF_PROVIDER_PID_PATH.$name.MASTER_PID_FILE_FORMAT;
+	if (file_exists($providerFile))
+	{
+		$pid = file_get_contents($providerFile);
+		if (!empty($pid))
+		{
+			if (posix_kill(intval($pid), SIG_DFL))
+			{
+				return $pid;
+			}
+		}
+		else
+		{
+			$master_name = "{$name}_master_process";
+			return filterProcess($master_name, PS_CMD_WORK_PROCESS);
+		}
+	}
+	return null;
+}
+
+function getProviderManagerPid($name)
+{
+	$providerFile = FSOF_PROVIDER_PID_PATH.$name.MANAGER_PID_FILE_FORMAT;
+	if (file_exists($providerFile))
+	{
+		$pid = file_get_contents($providerFile);
+		if (!empty($pid))
+		{
+			if (posix_kill(intval($pid), SIG_DFL))
+			{
+				return $pid;
+			}
+		}
+		else
+		{
+			$manager_name = "{$name}_manager_process";
+			return filterProcess($manager_name, PS_CMD_WORK_PROCESS);
+		}
+	}
+	return null;
+}
+
+function checkMasterProcessExist($name)
+{
+	$pid = getProviderMasterPid($name);
+	if (empty($pid))
+	{
+		return false;
+	}
+	else
+	{
+        echo "the pid of {$name} is :".$pid.PHP_EOL;
+		return true;
+	}
+}
+
+function checkProviderInfo($name)
+{
+	$providerDeploy = FSOFConfigManager::isExistProviderDeploy($name);
+	if (empty($providerDeploy))
+	{
+		fwrite(STDERR,"\033[31;40m [ERROR] \033[0m your server {$name} not deploy".PHP_EOL);
+		return false;
+	}
+
+	$phpStart = FSOFConfigManager::isExistProviderFile($name);
+	if(!$phpStart)
+	{
+		fwrite(STDERR,"\033[31;40m [ERROR] \033[0m {$name} root path not exist".PHP_EOL);
+		return false;
+	}
+	return true;
+}
+
+function start( $name, $cmd)
+{
+	$isRun = checkMasterProcessExist($name);
+	if ($isRun)
+	{
+		return PROVIDER_STATE_RUNNING;
+	}
+	else
+	{
+		if(startServ($cmd,$name))
+		{
+			return PROVIDER_STATE_SUCCESS;
+		}
+		else
+		{
+			return PROVIDER_STATE_FAILED;
+		}
+	}
+}
+
+function startProvider($name, $cmd)
+{
+	if (!checkProviderInfo($name))
+	{
+		return false;
+	}
+
+	$ret = start($name, $cmd);
+	if ( PROVIDER_STATE_SUCCESS == $ret)
+	{
+		echo "server {$name} start \033[32;40m [SUCCESS] \033[0m".PHP_EOL;
+	}
+	else if (PROVIDER_STATE_RUNNING == $ret)
+	{
+		echo "{$name} is already running".PHP_EOL;
+	}
+	else
+	{
+		fwrite(STDERR, "server {$name} start \033[31;40m [FAIL] \033[0m".PHP_EOL);
+		return false;
+	}
+	return true;
+}
+
+function restartProvider($name, $cmd)
+{
+	if (!checkProviderInfo($name))
+	{
+		return false;
+	}
+	stopProvider($name);
+	$startCmd = "start";
+	if ("extrestart" == $cmd)
+	{
+		$startCmd = "extstart";
+	}
+	$ret = start($name, $startCmd);
+	if (PROVIDER_STATE_FAILED != $ret)
+	{
+		echo "restart server {$name} \033[32;40m [SUCCESS] \033[0m" . PHP_EOL;
+	}
+	else
+	{
+		fwrite(STDERR, "restart server {$name} \033[31;40m [FAIL] \033[0m" . PHP_EOL);
+		return false;
+	}
+	return true;
+}
+
+function reloadProvider($name)
+{
+	$pid = getProviderMasterPid($name);
+	if (!posix_kill(intval($pid), SIGUSR1))
+	{
+		echo $name."server {$name} reload \033[31;40m [FAIL] \033[0m".PHP_EOL;
+	}
+	else
+	{
+		fwrite(STDERR, "server {$name} reload \033[32;40m [SUCCESS] \033[0m".PHP_EOL);
+	}
+}
+
+function waitProcessEnd($name)
+{
+	/*
+	* 先检测该master进程是否存在,检测时间为10s,不存在则退出,如一直存在,则强制杀掉子进程(发送SIGKILL信号),目的为了manager进程能正常退出, 从zookeeper注销服务
+	* ,等待2s后重新检测,如仍存在,则强制杀除master与manager进程
+	*/
+	$work_name= "{$name}_event_worker_process";
+	$stime = time();
+
+	while(time() - $stime < 10)
+	{
+		$pid = getProviderMasterPid($name);
+		if (empty($pid))
+		{
+			break;
+		}
+		sleep(1);
+	}
+
+	$workPid = trim(filterProcess($work_name, PS_CMD_WORK_PROCESS));
+	if (!empty($workPid))
+	{
+		$pids = explode("\n", $workPid);
+		foreach ($pids as $key => $wPid)
+		{
+			posix_kill(intval($wPid), SIGKILL);
+			usleep(10000);
+		}
+	}
+
+	sleep(1);
+	$pid = getProviderMasterPid($name);
+	if (!empty($pid))
+	{
+		$managerPid = getProviderManagerPid($name);
+		if(!empty($managerPid))
+		{
+			posix_kill(intval($managerPid), SIGKILL);
+		}
+		posix_kill(intval($pid), SIGKILL);
+	}
+}
+
+function stopProvider($name)
+{
+	$masterPid = getProviderMasterPid($name);
+	if (empty($masterPid))
+	{
+		waitProcessEnd($name);
+	}
+	else
+	{
+		if (!posix_kill(intval($masterPid), SIGTERM))
+		{
+			fwrite(STDERR, "end signal to {$name}: {$masterPid} failed" );
+		}
+		waitProcessEnd($name);
+	}
+
+	$masterFile = FSOF_PROVIDER_PID_PATH.$name.MASTER_PID_FILE_FORMAT;
+	$managerFile = FSOF_PROVIDER_PID_PATH.$name.MANAGER_PID_FILE_FORMAT;
+	if (file_exists($masterFile))
+	{
+		unlink($masterFile);
+	}
+	if (file_exists($managerFile))
+	{
+		unlink($managerFile);
+	}
+    echo "stop server {$name} \033[32;40m [SUCCESS] \033[0m".PHP_EOL;
+}
+
+function getProviderStatus($name)
+{
+	echo "######################\033[32;40m {$name} server status\033[0m##################" . PHP_EOL;
+	if(getProviderMasterPid($name))
+	{
+		$psRet = filterProcess($name, FILTER_PROCESS_STATUS);
+		if (empty($psRet))
+		{
+			echo PHP_EOL . "\033[32;40m {$name} is [NO RUNNING] \033[0m-------------" . PHP_EOL;
+		}
+		else
+		{
+			print_r($psRet);
+			echo PHP_EOL . "\033[32;40m {$name} is [RUNNING] \033[0m-------------" . PHP_EOL;
+		}
+	}
+	else
+	{
+		echo PHP_EOL . "\033[32;40m {$name} is [NO RUNNING] \033[0m-------------" . PHP_EOL;
+	}
+	echo "-------------------------------------------------------------------------------------" . PHP_EOL;
+}
+
+function filterProcess($process_name,$type)
+{
+	if(FILTER_PROCESS_STATUS == $type)
+	{
+		$shell_cmd = "ps auxf | grep {$process_name} |  grep -v grep | grep -v app_admin";
+	}
+	elseif(PS_CMD_WORK_PROCESS == $type)
+	{
+		$shell_cmd = "ps auxf | grep -w {$process_name} |  grep -v grep | awk '{print $2}'";
+	}
+	else
+	{
+		return "usage: type(1/2) name";
+	}
+
+	$file = popen($shell_cmd, 'r');
+	if(empty($file))
+	{
+        //echo "$shell_cmd.', return null'" . PHP_EOL;
+		return null;
+	}
+
+	$ret = fread($file,10240);
+	pclose($file);
+
+	$ret = trim(print_r($ret,TRUE));
+    //echo $shell_cmd.",return ".$ret. PHP_EOL;
+	return $ret;
+}
+
+function analyseFSOFConfig()
+{
+	$fsofConfigPath = FSOF_INI_CONFIG_FILE_PATH.DIRECTORY_SEPARATOR.'fsof.ini';
+	if (!file_exists($fsofConfigPath))
+	{
+		fwrite(STDERR,"\033[31;40m [ERROR] \033[0m " . $fsofConfigPath . " can not be loaded");
+		return null;
+	}
+	return parse_ini_file($fsofConfigPath, true);
+}
+
+function initByFSOFConfig()
+{
+	$globalFSOFConfig = analyseFSOFConfig();
+	if(!empty($globalFSOFConfig))
+	{
+		if(isset($globalFSOFConfig['fsof_container_setting']))
+		{
+			$globalConfig = $globalFSOFConfig['fsof_container_setting'];
+		}
+	}
+
+	if(strlen(PHP_BINDIR) > 0)
+	{
+		if(!defined("PHP_BIN_PATH"))
+		{
+			define('PHP_BIN_PATH', PHP_BINDIR.DIRECTORY_SEPARATOR.'php');
+		}
+	}
+	else
+	{
+		if(!defined("PHP_BIN_PATH"))
+		{
+			if (isset($globalConfig['php']))
+			{
+				define('PHP_BIN_PATH',$globalConfig['php']);
+			}
+			else
+			{
+				define('PHP_BIN_PATH','/usr/bin/php');
+			}
+		}
+	}
+
+	// set user
+	if (isset($globalConfig['user']))
+	{
+		$user = $globalConfig['user'];
+	}
+	else
+	{
+		$user = 'root';
+	}
+
+	changeConsoleUser($user);
+}
+
+function changeConsoleUser($user)
+{
+	if (!function_exists('posix_getpwnam'))
+	{
+		trigger_error(__METHOD__.": require posix extension.");
+		return;
+	}
+	$user = posix_getpwnam($user);
+	if($user)
+	{
+		posix_setuid($user['uid']);
+		posix_setgid($user['gid']);
+	}
+}
+
+//用于和守护进程进行通信
+function printInfo()
+{
+	echo "usage: app_admin.php  cmd  ||  app_admin.php  app_name  cmd".PHP_EOL;
+	echo "example: app_admin startall\t\t\t[\033[32;40m启动所有服务\033[0m]".PHP_EOL;
+	echo "         app_admin shutdown\t\t\t[\033[32;40m关闭所有服务\033[0m]".PHP_EOL;
+	echo "         app_admin reloadall\t\t\t[\033[32;40m热更新所有服务\033[0m]".PHP_EOL;
+	echo "         app_admin list\t\t\t\t[\033[32;40m查看服务\033[0m]".PHP_EOL;
+	echo "         app_admin status\t\t\t[\033[32;40m查看所有服务运行状态\033[0m]".PHP_EOL;
+	echo "         app_admin app_name status\t\t[\033[32;40m查看app服务运行状态\033[0m]".PHP_EOL;
+	echo "         app_admin app_name start\t\t[\033[32;40m启动app服务\033[0m]".PHP_EOL;
+	echo "         app_admin app_name restart\t\t[\033[32;40m重启app服务\033[0m]".PHP_EOL;
+	echo "         app_admin app_name reload\t\t[\033[32;40m热更新app服务\033[0m]".PHP_EOL;
+	echo "         app_admin app_name stop\t\t[\033[32;40m停止app服务\033[0m]".PHP_EOL;
+	echo "         app_admin app_name extstart\t\t[\033[32;40m启动扩展的app服务,不注册配置中心\033[0m]".PHP_EOL;
+	echo "         app_admin app_name extrestart\t\t[\033[32;40m重启扩展的app服务,不注册配置中心\033[0m]".PHP_EOL;
+	exit(1);
+}
+
diff --git a/bin/restartall.sh b/bin/restartall.sh
new file mode 100644
index 0000000..ca205fa
--- /dev/null
+++ b/bin/restartall.sh
@@ -0,0 +1,17 @@
+#/bin/bash
+
+FSOF_BIN=`pwd`;
+DIRECTORY_SEPARATOR="/";
+FILE_NAME="servicename_master_process";
+
+#记录启动的服务
+ps -ef| grep master_process| grep -v grep > $FSOF_BIN$DIRECTORY_SEPARATOR$FILE_NAME;
+
+#启动服务进程
+while read LINE
+do
+	SER_NAME=`echo $LINE| awk '{print $NF}'|sed 's/_master_process//g'`;
+	echo "********************Beganing Start" $SER_NAME;
+	php $FSOF_BIN$DIRECTORY_SEPARATOR"app_admin.php" $SER_NAME restart;
+	echo "********************Ending Start" $SER_NAME;
+done < $FSOF_BIN$DIRECTORY_SEPARATOR$FILE_NAME
diff --git a/common/BootStrap.php b/common/BootStrap.php
new file mode 100644
index 0000000..e498469
--- /dev/null
+++ b/common/BootStrap.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common;
+
+//定义common根目录
+$fsof_common_root_path = __DIR__;
+require_once($fsof_common_root_path.DIRECTORY_SEPARATOR.'FrameAutoLoader.php');
+
+// 定义config模块的根路径
+if(!defined('FSOF_CONFIG_ROOT_PATH')) define('FSOF_CONFIG_ROOT_PATH', dirname($fsof_common_root_path));
+
+//fsof.ini文件路径
+$fsofIniConfigFilePath = FSOF_CONFIG_ROOT_PATH.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'global'.DIRECTORY_SEPARATOR.'conf';
+if(!defined('FSOF_INI_CONFIG_FILE_PATH')) define('FSOF_INI_CONFIG_FILE_PATH', $fsofIniConfigFilePath);
+
+//app.deploy文件路径
+$fsofPhpConfigPath = FSOF_CONFIG_ROOT_PATH.DIRECTORY_SEPARATOR.'config';
+if(!defined('FSOF_PHP_CONFIG_ROOT_PATH')) define('FSOF_PHP_CONFIG_ROOT_PATH', $fsofPhpConfigPath);
+
+//注册顶层命名空间到自动载入器
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common', $fsof_common_root_path);
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common\log', $fsof_common_root_path.DIRECTORY_SEPARATOR.'log');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common\url', $fsof_common_root_path.DIRECTORY_SEPARATOR.'url');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common\file', $fsof_common_root_path.DIRECTORY_SEPARATOR.'file');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common\config', $fsof_common_root_path.DIRECTORY_SEPARATOR.'config');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common\context', $fsof_common_root_path.DIRECTORY_SEPARATOR.'context');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common\protocol', $fsof_common_root_path.DIRECTORY_SEPARATOR.'protocol');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common\fuse', $fsof_common_root_path.DIRECTORY_SEPARATOR.'fuse');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\common\report', $fsof_common_root_path.DIRECTORY_SEPARATOR.'report');
+
+spl_autoload_register(__NAMESPACE__.'\FrameAutoLoader::autoload');
+
diff --git a/common/FrameAutoLoader.php b/common/FrameAutoLoader.php
new file mode 100644
index 0000000..9ff2d17
--- /dev/null
+++ b/common/FrameAutoLoader.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common;
+
+class FrameAutoLoader
+{
+    /**
+     * 命名空间的路径
+     */
+    private static $nsPath = Array();
+
+    /**
+     * 自动载入类
+     * @param $class
+     */
+    public static function autoload($class)
+    {    	
+    	$frameRootPathDepth = count(explode('\\', __NAMESPACE__));
+        $root = explode('\\', trim($class, '\\'));
+        $pathDepth = count($root);
+        if($pathDepth > $frameRootPathDepth)
+        {
+        	$key = $className = $class;
+	        if($pathDepth > $frameRootPathDepth + 1)
+	        {
+	        	$root = explode('\\', trim($class, '\\'), $frameRootPathDepth + 2);
+	        	$className = $root[$frameRootPathDepth + 1];
+	        	unset($root[$frameRootPathDepth + 1]);
+	        	$key = implode($root, '\\');
+	        }
+	        else if($pathDepth == $frameRootPathDepth + 1)
+	        {
+	        	$root = explode('\\', trim($class, '\\'), $frameRootPathDepth + 1);
+	        	$className = $root[$frameRootPathDepth];
+	        	unset($root[$frameRootPathDepth]);
+	        	$key = implode($root, '\\');
+	        }
+	        
+        	if(isset(self::$nsPath[$key]))
+	        {
+	        	include_once self::$nsPath[$key] . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $className) . '.php';
+	        }
+        }
+    }
+
+    /**
+     * 设置根命名空间
+     * @param $root
+     * @param $path
+     */
+    public static function setRootNS($root, $path)
+    {
+        self::$nsPath[$root] = $path;
+    }
+}
\ No newline at end of file
diff --git a/common/config/FSOFCommonUtil.php b/common/config/FSOFCommonUtil.php
new file mode 100644
index 0000000..6230ad0
--- /dev/null
+++ b/common/config/FSOFCommonUtil.php
@@ -0,0 +1,75 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common\config;
+
+class FSOFCommonUtil
+{
+	public static function parseWeightInfo($versionWeightList)
+	{
+		$versionLists = array();
+		$versionWeight = explode(",", $versionWeightList);
+		foreach ($versionWeight as $index => $value)
+		{
+			$versionWeight = explode(":" ,$value);
+			if (count($versionWeight) == 1)
+			{
+				$versionLists[$value] = 0;
+			}
+			else
+			{
+				$versionLists[$versionWeight[0]] = $versionWeight[1];
+			}
+		}
+		return $versionLists;
+	}
+
+	public static function getWeightSum($versionLists)
+	{
+		$weightSum = 0;
+		foreach ($versionLists as $key => $value)
+		{
+			$weightSum += $value;
+		}
+		return $weightSum;
+	}
+
+	public static function getVersionByWeight($versionWeightList)
+	{
+		$version = $versionWeightList;
+		$versionLists = self::parseWeightInfo($versionWeightList);
+		$weightSum = self::getWeightSum($versionLists);
+		if ($weightSum > 1)
+		{
+			$startValue = 0;
+			$dstValue = mt_rand(0, $weightSum-1);
+			foreach ($versionLists as $key => $value)
+			{
+				if($dstValue >= $startValue && $dstValue < $value + $startValue)
+				{
+					$version = $key;
+					break;
+				}
+				else
+				{
+					$startValue += $value;
+				}
+			}
+		}
+		return $version;
+	}
+}
diff --git a/common/config/FSOFConfigManager.php b/common/config/FSOFConfigManager.php
new file mode 100644
index 0000000..b7bb728
--- /dev/null
+++ b/common/config/FSOFConfigManager.php
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common\config;
+
+class FSOFConfigManager
+{
+
+	public static function getFSOFIni()
+	{
+		$fsof_config_file = FSOF_INI_CONFIG_FILE_PATH.DIRECTORY_SEPARATOR.'fsof.ini';
+		$fsof_config_data = FSOFConfigUtil::loadConfigFile($fsof_config_file);
+		return 	$fsof_config_data;
+	}
+
+	public static function getDeployFile($name)
+	{
+		$env = self::getCurrentEnvironment();
+		return FSOF_PHP_CONFIG_ROOT_PATH.DIRECTORY_SEPARATOR.'app'.DIRECTORY_SEPARATOR.'conf'.DIRECTORY_SEPARATOR.$env.DIRECTORY_SEPARATOR.'provider'.DIRECTORY_SEPARATOR.$name.'.deploy';
+	}
+	
+	public static function getCurrentEnvironment()
+	{
+		if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN')
+		{
+			$currentEnv = 'dev';
+			return $currentEnv;
+		}
+		$currentEnv = 'pro';
+		$fsof_config_data = self::getFSOFIni();
+		if(isset($fsof_config_data['fsof_setting']['environment']))
+		{
+			$currentEnv = $fsof_config_data['fsof_setting']['environment'];
+		}
+		else
+		{
+            \Logger::getLogger(__CLASS__)->error('fsof.ini is not set environment, default is pro');
+		}
+		return 	$currentEnv;
+	}
+
+	public static function getKeepConnect()
+	{
+		$keep_connect = false;
+		$fsof_config_data = self::getFSOFIni();
+		if(isset($fsof_config_data['fsof_setting']['keep_connect']))
+		{
+			$keep_connect = $fsof_config_data['fsof_setting']['keep_connect'];
+		}
+		return 	$keep_connect;
+	}
+
+	public static function isExistProviderDeploy($appName)
+	{
+		$deployFile = self::getDeployFile($appName);
+		if(file_exists($deployFile))
+		{
+			return $deployFile;
+		}
+
+		\Logger::getLogger(__CLASS__)->error('not deploy '.$appName.":".$deployFile);
+		return null;
+	}
+
+	public static function isExistProviderFile($name)
+	{
+		$appBootFile = self::getProviderAppRoot($name);
+		if (isset($appBootFile) && file_exists($appBootFile) && is_file($appBootFile))
+		{
+			return true;
+		}
+		else
+		{
+            \Logger::getLogger(__CLASS__)->error('not process ' . $name . ":" . $appBootFile);
+		}
+		return false;
+	}
+
+	public static function isProviderAppDeploy($appName)
+	{
+		$deployFile = self::getDeployFile($appName);
+   		if(file_exists($deployFile))
+   		{
+   		    $appBootFile = self::getProviderAppRoot($appName);
+            if(isset($appBootFile) && file_exists($appBootFile) && is_file($appBootFile))
+            {
+                return TRUE;
+            }
+            else
+            {
+                \Logger::getLogger(__CLASS__)->error("{$appName}  bootstrap not exist:".$appBootFile);
+            }
+   		}
+		else
+		{
+            \Logger::getLogger(__CLASS__)->error("{$appName}  deploy file not exist:".$deployFile);
+		}
+   		return FALSE;
+	}
+	
+	public static function getProviderAppDeploy($appName)
+	{
+		$deployFile = self::getDeployFile($appName);
+   		$deployFileData = parse_ini_file($deployFile, TRUE);	
+   		return 	$deployFileData;
+	}
+	
+	public static function getProviderAppRoot($appName)
+	{
+		$deployFile = self::getDeployFile($appName);
+   		if(file_exists($deployFile))
+   		{
+   		    $config = parse_ini_file($deployFile, TRUE);
+   		    if(isset($config['server']['root']))
+   		    {
+    		    $appBootFile = $config['server']['root'];
+                if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') 
+                {
+                	$appBootFile = str_replace('/', '\\', $appBootFile);
+                }
+				if(strpos($appBootFile, DIRECTORY_SEPARATOR) > 0)
+				{
+					//对于相对路径,需要拼接成完整路径
+					$appBootFile = FSOF_PHP_CONFIG_ROOT_PATH.DIRECTORY_SEPARATOR.$appBootFile;
+				}
+                return $appBootFile;
+   		    }
+   		}
+   		return NULL;
+	}
+
+    public static function trimall($str)
+    {
+    	//删除空格,换行符及其它
+        $qian=array(" "," ","\t","\n","\r");
+        $hou=array("","","","","");
+        return str_replace($qian,$hou,$str);
+    }
+
+	public static function isVersion($version)
+	{
+		if(empty($version))
+		{
+			return FALSE;
+		}
+		$match_times = preg_match('/^(dev\.|prod\.|)\d+\.\d+\.\d+/', $version);
+		if($match_times > 0)
+		{
+			return TRUE;
+		}
+		return FALSE;
+	}
+
+    public static function getDeployVersion($rootPath) 
+    {
+        $ret = NULL;
+        $versionFilePath = dirname(dirname($rootPath)).DIRECTORY_SEPARATOR.'version.config';
+        if (file_exists($versionFilePath)) 
+        {
+            $ret = self::trimall(file_get_contents($versionFilePath));
+			if(!self::isVersion($ret))
+			{
+				$ret = NULL;
+                \Logger::getLogger(__CLASS__)->error("version.config: version is error:".$ret);
+			}
+        }
+        return $ret;
+    }
+
+    public static function selectDeployVersion($bootFile, $version)
+    {
+        //插入发布版本信息
+        if(empty($version) || empty($bootFile))
+        {
+            return $bootFile;
+        }
+        $rootPath = explode(DIRECTORY_SEPARATOR, $bootFile);
+        $num = count($rootPath);
+        $tmp = array($num+1);
+        for($i = 0; $i < $num; $i++)
+        {
+            if($i < $num-2)
+            {
+                $tmp[$i] = $rootPath[$i];
+            }
+            else if($i == $num-2)
+            {
+                $tmp[$i] = $version;
+                $tmp[$i + 1] = $rootPath[$i];
+            }
+            else
+            {
+                $tmp[$i + 1] = $rootPath[$i];
+            }
+        }
+        $bootFile = implode(DIRECTORY_SEPARATOR, $tmp);
+        return $bootFile;
+    }
+    
+	public static function getProviderAppList()
+	{
+		//遍历所有的deploy文件,所有appname采用'*'
+		$deployDir = self::getDeployFile('*');
+		$deploylist = glob($deployDir);
+		return 	$deploylist;
+	}
+
+	public static function getRunProviderList()
+	{
+		$pid = FSOF_PROVIDER_PID_PATH.'*.master.pid';
+		$pidList = glob($pid);
+		return $pidList;
+	}
+}
diff --git a/common/config/FSOFConfigUtil.php b/common/config/FSOFConfigUtil.php
new file mode 100644
index 0000000..6aa315d
--- /dev/null
+++ b/common/config/FSOFConfigUtil.php
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common\config;
+
+class FSOFConfigUtil
+{
+    public static function loadConfigFile($configFile)
+    {
+		if (! file_exists($configFile))
+		{
+            \Logger::getLogger(__CLASS__)->error($configFile." can not be loaded");
+			return array();
+		}
+		$config = parse_ini_file($configFile, true);
+        return $config;
+    }
+
+    public static function get($configFile, $key, $default = NULL)
+    {
+    	$config = self::loadConfigFile($configFile);
+        $result = isset($config[$key]) ? $config[$key] : $default;        
+        return $result;
+    }
+
+    public static function getField($configFile, $key, $filed, $default = NULL)
+    {
+    	$config = self::loadConfigFile($configFile);
+        $result = isset($config[$key][$filed]) ? $config[$key][$filed] : $default;
+        return $result;
+    }
+
+	public static function parse_ini_file_multi($file, $process_sections = false, $scanner_mode = INI_SCANNER_NORMAL) 
+	{
+	    $explode_str = '.';
+	    $escape_char = "'";
+	    // load ini file the normal way
+	    $data = parse_ini_file($file, $process_sections, $scanner_mode);
+	    if (!$process_sections) 
+	    {
+	        $data = array($data);
+	    }
+	    foreach ($data as $section_key => $section) 
+	    {
+	        // loop inside the section
+	        foreach ($section as $key => $value) 
+	        {
+	            if (strpos($key, $explode_str)) 
+	            {
+	                if (substr($key, 0, 1) !== $escape_char) 
+	                {
+	                    // key has a dot. Explode on it, then parse each subkeys
+	                    // and set value at the right place thanks to references
+	                    $sub_keys = explode($explode_str, $key);
+	                    $subs =& $data[$section_key];
+	                    foreach ($sub_keys as $sub_key) 
+	                    {
+	                        if (!isset($subs[$sub_key])) 
+	                        {
+	                            $subs[$sub_key] = array();
+	                        }
+	                        $subs =& $subs[$sub_key];
+	                    }
+	                    // set the value at the right place
+	                    $subs = $value;
+	                    // unset the dotted key, we don't need it anymore
+	                    unset($data[$section_key][$key]);
+	                }
+	                else 
+	                {
+	                	// we have escaped the key, so we keep dots as they are
+	                    $new_key = trim($key, $escape_char);
+	                    $data[$section_key][$new_key] = $value;
+	                    unset($data[$section_key][$key]);
+	                }
+	            }
+	        }
+	    }
+	    if (!$process_sections) 
+	    {
+	        $data = $data[0];
+	    }
+	    return $data;
+	}	
+}
\ No newline at end of file
diff --git a/common/config/FSOFConstants.php b/common/config/FSOFConstants.php
new file mode 100644
index 0000000..0b38d0c
--- /dev/null
+++ b/common/config/FSOFConstants.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common\config;
+
+class FSOFConstants
+{
+	//任何服务分组
+	const FSOF_SERVICE_GROUP_ANY = '*';
+    //默认服务分组
+    const FSOF_SERVICE_GROUP_DEFAULT = 'default';
+    //默认服务版本
+    const FSOF_SERVICE_VERSION_DEFAULT = '1.0.0';
+
+	//monitor定时监控时间,暂定5分钟
+	const FSOF_MONITOR_TIMER = 300000;
+
+	//所使用的redis端口号
+	const FSOF_SERVICE_REDIS_PORT =6379;
+}
\ No newline at end of file
diff --git a/common/file/FSOFRedis.php b/common/file/FSOFRedis.php
new file mode 100644
index 0000000..9ec56a1
--- /dev/null
+++ b/common/file/FSOFRedis.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common\file;
+
+use com\fenqile\fsof\common\config\FSOFConstants;
+
+
+class FSOFRedis
+{
+    const REDIS_TIME_OUT = 1;
+
+    private static $_instance;
+        
+    private $m_redis = null;
+
+    private $logger;
+        
+    public static function instance()
+    {
+        if (extension_loaded('redis'))
+        {
+            if (!isset(FSOFRedis::$_instance))
+            {
+                FSOFRedis::$_instance = new FSOFRedis();
+            }
+            return FSOFRedis::$_instance;
+        }
+        else
+        {
+            \Logger::getLogger(__CLASS__)->error("not installed redis extension");
+        }
+        return NULL;
+    }
+    
+    public function  __construct()
+    {
+        $this->logger = \Logger::getLogger(__CLASS__);
+        $this->get_redis();
+    }
+
+    public function get_redis()
+    {
+        if (!isset($this->m_redis))
+        {
+            try
+            {
+                $redis_cli = new \Redis();
+				$ret = $redis_cli->connect("127.0.0.1",FSOFConstants::FSOF_SERVICE_REDIS_PORT,self::REDIS_TIME_OUT);
+				if (!$ret)
+				{
+                    $this->logger->warn("connect redis failed[127.0.0.1:6379]");
+					$ret = $redis_cli->connect("/var/fsof/redis.sock",-1,self::REDIS_TIME_OUT);
+				}
+            }
+            catch (\Exception $e)
+            {
+                $ret = false;
+                $this->logger->error('connect redis excepiton:'.$e->getMessage().', errno:' . $e->getCode());
+                throw new \Exception($e->getMessage());
+            }
+
+            if($ret)
+            {
+                $this->m_redis = $redis_cli;
+            }
+            else
+            {
+                $this->logger->error('connect redis failed:|errno:' . $redis_cli->getLastError());
+                throw new \Exception("连接本地redis异常");
+            }
+        }
+
+        return $this->m_redis;
+    }
+
+    public function getProviderInfo($key)
+    {
+        return $this->getlist($key);
+    }
+
+    public function get($key)
+    {
+        if (!empty($key) && isset($this->m_redis))
+        {
+            return $this->m_redis->get($key);
+        } 
+        else 
+        {
+            return NULL;
+        }
+    }
+
+	public function getlRange($key)
+	{
+		if (!empty($key) && isset($this->m_redis))
+		{
+			return $this->m_redis->lRange($key, 0, -1);
+		}
+		else
+		{
+            $this->logger->warn('not object of redis:'.$key);
+			return NULL;
+		}
+	}
+
+    public function getlist($key)
+    {
+		$ret = NULL;
+        if (!empty($key)) 
+        {
+			try
+			{
+				if(!isset($this->m_redis))
+				{
+					$this->get_redis();
+				}
+				$ret = $this->getlRange($key);
+			}
+			catch (\Exception $e)
+			{
+                $this->logger->warn('redis current connect excepiton'.' |errcode:'.$e->getCode().' |errmsg:'.$e->getMessage());
+				$this->close();
+				//重试一次
+				$this->get_redis();
+				$ret = $this->getlRange($key);
+			}
+        } 
+ 		return $ret;
+    }
+
+    public function set($key, $value)
+    {
+        if (!empty($key) && isset($this->m_redis))
+        {
+            return $this->m_redis->set($key, $value);
+        } 
+        else 
+        {
+            return null;
+        }
+    }
+
+    /**
+     * Description: 关闭redis连接
+     */
+    public function close()
+    {
+        try
+        {
+            if (isset($this->m_redis)) 
+            {
+                $this->m_redis->close();
+                unset($this->m_redis);
+            }
+        } 
+        catch (\Exception $e)
+        {
+			unset($this->m_redis);
+            $this->logger->error('close redis error:'.$e->getMessage(),$e);
+        }
+    }
+
+    public function __destruct()
+    {
+        $this->close();
+    }
+}
diff --git a/common/file/FileSystemUtil.php b/common/file/FileSystemUtil.php
new file mode 100644
index 0000000..5cdef35
--- /dev/null
+++ b/common/file/FileSystemUtil.php
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common\file;
+
+class FileSystemUtil
+{
+    /**
+     * 递归创建目录
+     * @param $dir
+     * @param int $mode
+     * @return bool
+     */
+    public static function makeDir($dir, $mode = 0777)
+    {
+        if (is_dir($dir) || mkdir($dir, $mode, true)) 
+        {
+            return true;
+        }
+        
+        if (!self::makeDir(dirname($dir), $mode)) 
+        {
+            return false;
+        }
+        return mkdir($dir, $mode);
+    }
+
+    /**
+     * 递归获取目录下的文件
+     * @param $dir
+     * @param string $filter
+     * @param array $result
+     * @param bool $deep
+     * @return array
+     */
+    public static function treeDir($dir, $filter = '', &$result = array(), $deep = false)
+    {
+        $files = new \DirectoryIterator($dir);
+        foreach ($files as $file) 
+        {
+            if ($file->isDot()) 
+            {
+                continue;
+            }
+            
+            $filename = $file->getFilename();
+
+            if ($file->isDir()) 
+            {
+                self::treeDir($dir . DIRECTORY_SEPARATOR . $filename, $filter, $result, $deep);
+            } 
+            else 
+            {
+                if(!empty($filter) && !preg_match($filter, $filename))
+                {
+                    continue;
+                }
+                
+                if ($deep) 
+                {
+                    $result[$dir][] = $filename;
+                } 
+                else 
+                {
+                    $result[] = $dir . DIRECTORY_SEPARATOR . $filename;
+                }
+            }
+        }
+        
+        return $result;
+    }
+
+    /**
+     * 递归删除目录
+     * @param $dir
+     * @param $filter
+     * @return bool
+     */
+    public static function deleteDir($dir, $filter = '')
+    {
+        $files = new \DirectoryIterator($dir);
+        foreach ($files as $file) 
+        {
+            if ($file->isDot()) 
+            {
+                continue;
+            }
+            
+            $filename = $file->getFilename();
+            
+            if ($file->isDir()) 
+            {
+                self::deleteDir($dir . DIRECTORY_SEPARATOR . $filename);
+            } 
+            else 
+            {
+            	if (!empty($filter) && !preg_match($filter, $filename)) 
+            	{
+                	continue;
+            	}
+            	
+                unlink($dir . DIRECTORY_SEPARATOR . $filename);
+            }
+        }
+        return rmdir($dir);
+    }
+
+    public static function require_file($path)
+    {
+        $bRet = false;
+        if(is_file($path)) {
+            require_once($path);
+            $bRet = true;
+        }
+
+        return $bRet;
+    }
+}
diff --git a/common/log/FSOFSystemUtil.php b/common/log/FSOFSystemUtil.php
new file mode 100644
index 0000000..652c613
--- /dev/null
+++ b/common/log/FSOFSystemUtil.php
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+namespace com\fenqile\fsof\common\log;
+
+class FSOFSystemUtil
+{
+	private static $localHost = null;
+	private static $defaultHost = '127.0.0.1';
+
+	public static function getLocalIP()
+	{
+		if (!isset(FSOFSystemUtil::$localHost))
+		{
+			if(extension_loaded('swoole'))
+			{
+				$ipList = swoole_get_local_ip();
+				foreach($ipList as $key => $local)
+				{
+                    if ($local != self::$defaultHost)
+                    {
+                        FSOFSystemUtil::$localHost = $local;
+                        break;
+                    }
+				}
+
+				if (empty(FSOFSystemUtil::$localHost))
+				{
+					FSOFSystemUtil::$localHost = self::$defaultHost;
+				}
+			}
+			else
+			{
+				FSOFSystemUtil::$localHost = self::$defaultHost;
+			}
+		}
+		return FSOFSystemUtil::$localHost;
+	}
+
+    public static function getServiceIP()
+    {
+        $result = self::getLocalIP();
+
+		if ($result == self::$defaultHost)
+		{
+            throw new \Exception("本服务器网络地址错误出错");
+		}
+
+        return $result;
+    }
+}
diff --git a/common/protocol/fsof/DubboParser.php b/common/protocol/fsof/DubboParser.php
new file mode 100644
index 0000000..0aee201
--- /dev/null
+++ b/common/protocol/fsof/DubboParser.php
@@ -0,0 +1,305 @@
+<?php
+namespace com\fenqile\fsof\common\protocol\fsof;
+
+/**
+ *
+ * Dubbo网络协议
+ * +------------------------------------------------------------------------------------------+
+ * |                        包头(二进制数据 16bit)   |  包体  |
+ * +-----------------------------------------------------------------------------------------+
+ * | 版本号  |   命令&serialize   | 空白 | 包序号|  长度  |  数据  |
+ * +-----------------------------------------------------------------------------------------+
+ * | magic(2) |  cmd&serialize(1)|(1)    |sn(8) | len(4)  | data(N)|
+ * +-----------------------------------------------------------------------------------------+
+ *
+ * magic:协议包起始标识, 0xdabb
+ * --------------------------------------------------------------------------------------------
+ * cmd:命令类型:FLAG_REQUEST为0x80, FLAG_TWOWAY为0x40, FLAG_EVENT为0x20
+ * serialize:序列化方案编号:与cmd共用一个字节,采用json,对应dubbo中编号为6
+ * --------------------------------------------------------------------------------------------
+ * sn:请求序号,consumer会为每个请求编制一个进程内唯一序号
+ *    ,provider处理完请求后在返回的数据包中会携带该sn号,供consumer判断当前的数据是对应哪个请求
+ * --------------------------------------------------------------------------------------------*
+ * len:数据报文长度
+ * --------------------------------------------------------------------------------------------
+ * data:数据报文,目前采用json进行序列化
+ * --------------------------------------------------------------------------------------------
+ */
+class DubboParser
+{
+    //dubbo协议基本信息
+    const PACKAGE_HEDA_LEN = 16;
+    const MAX_RECV_LEN = 1048576;//1024*1024;
+    const RESPONSE_TCP_SEGMENT_LEN = 1048576;//1*1024*1024;
+
+    //fsof协议ver字段,ver字段既指示协议版本信息,也作为magic使用
+    const DUBBO_PROTOCOL_MAGIC = 0xdabb;
+
+    //serialize 方案编号
+    const DUBBO_PROTOCOL_SERIALIZE_FAST_JSON = 6;     //serialization code
+
+
+    //fsof协议包头cmd字段含义
+    const FLAG_REQUEST = 0x80;           //request
+    const FLAG_TWOWAY = 0x40;            //two_way
+    const FLAG_HEARTBEAT_EVENT = 0x20;  //heart_event
+    const SERIALIZATION_MASK = 0x1f;     //serialization_mask
+
+    const UPPER_MASK = 0xffffffff00000000;
+    const LOWER_MASK = 0x00000000ffffffff;
+
+    const RESPONSE_WITH_EXCEPTION = 0;
+    const RESPONSE_VALUE = 1;
+    const RESPONSE_NULL_VALUE = 2;
+
+    private $logger;
+
+    public function  __construct()
+    {
+        $this->logger = \Logger::getLogger(__CLASS__);
+    }
+
+    public function packRequest(DubboRequest &$request)
+    {
+        $reqData = json_encode($request->getDubboVersion()) . PHP_EOL .
+            json_encode($request->getService()) . PHP_EOL .
+            json_encode($request->getVersion()) . PHP_EOL .
+            json_encode($request->getMethod()) . PHP_EOL ;
+        $typeStr = "";
+        for($i=0;$i < count($request->getTypes());$i++){
+           $typeStr = $typeStr.$request->getTypes()[$i];
+        }
+        $reqData = $reqData.json_encode($typeStr) . PHP_EOL;
+        for ($x = 0; $x < count($request->getParams()); $x++) {
+            $reqData = $reqData . json_encode($request->getParams()[$x]) . PHP_EOL;
+        }
+        $attach = array();
+        $attach['path'] = $request->getService();
+        $attach['interface'] = $request->getService();
+        $attach['group'] = $request->getGroup();
+        $attach['timeout'] = $request->getTimeout();
+        $attach['version'] = $request->getVersion();
+        $request->setAttach($attach);
+        $reqData = $reqData . json_encode($request->getAttach());
+
+        $upper = ($request->getSn() & self::UPPER_MASK) >> 32;
+        $lower = $request->getSn() & self::LOWER_MASK;
+        $flag = (self::FLAG_REQUEST | self::DUBBO_PROTOCOL_SERIALIZE_FAST_JSON);
+        if ($request->isTwoWay()) $flag |= self::FLAG_TWOWAY;
+        if ($request->isHeartbeatEvent()) $flag |= self::FLAG_HEARTBEAT_EVENT;
+        $out = pack("n1C1a1N1N1N1",
+            self::DUBBO_PROTOCOL_MAGIC,
+            $flag,
+            "",
+            $upper,
+            $lower,
+            strlen($reqData));
+        return $out . $reqData;
+    }
+
+
+    public function parseResponseHeader(DubboResponse &$response)
+    {
+        $res_header = substr($response->getFullData(), 0, self::PACKAGE_HEDA_LEN);
+        $format = 'n1magic/C1flag/C1status/N1upper/N1lower/N1len';
+        $_arr = unpack($format, $res_header);
+        $response->setStatus($_arr['status']);
+        $response->setSn($_arr["upper"] << 32 | $_arr["lower"]);
+        $flag = $_arr["flag"];
+        if (($flag & self::FLAG_HEARTBEAT_EVENT) != 0)
+        {
+            $response->setHeartbeatEvent(true);
+        }
+        $response->setSerialization($flag & self::DUBBO_PROTOCOL_SERIALIZE_FAST_JSON);
+        $response->setLen($_arr["len"]);
+        return $response;
+    }
+
+    public function parseResponseBody(DubboResponse &$response)
+    {
+        $_data = substr($response->getFullData(), self::PACKAGE_HEDA_LEN);
+        $response->setResponseBody($_data);
+        $dataArr = array();
+        if ($_data){
+            $dataArr = explode(PHP_EOL,$_data);
+        }
+        if ($response->getStatus() == DubboResponse::OK)
+        {
+            if ($response->isHeartbeatEvent())
+            {
+                $response->setResult(json_decode($dataArr[0], true));
+            } else
+            {
+                switch ($dataArr[0])
+                {
+                    case self::RESPONSE_NULL_VALUE:
+                        break;
+                    case self::RESPONSE_VALUE:
+                        $response->setResult(json_decode($dataArr[1], true));
+                        break;
+                    case self::RESPONSE_WITH_EXCEPTION:
+                        $exception = json_decode($dataArr[1], true);
+                        if(is_array($exception) && array_key_exists('message', $exception)){
+                            throw new \Exception($exception['message']);
+                        }else if(is_string($exception)){
+                            throw new \Exception($exception);
+                        }else{
+                            throw new \Exception("provider occur error");
+                        }
+                        break;
+                    default:
+                        return false;
+                }
+            }
+            return $response;
+        } else {
+            throw new \Exception(json_decode($dataArr[0], true));
+        }
+    }
+
+
+    public function parseRequestHeader(DubboRequest &$request)
+    {
+        $_data = substr($request->getFullData(), 0, self::PACKAGE_HEDA_LEN);
+        $format = 'n1magic/C1flag/C1blank/N1upper/N1lower/N1len';
+        $_arr = unpack($format, $_data);
+        $flag = $_arr['flag'];
+        $request->setTwoWay(($flag & self::FLAG_TWOWAY) != 0);
+        if (($flag & self::FLAG_HEARTBEAT_EVENT) != 0)
+        {
+            $request->setHeartbeatEvent(true);
+        }
+        $request->setSerialization($flag & self::DUBBO_PROTOCOL_SERIALIZE_FAST_JSON);
+        $request->setSn($_arr['upper'] << 32 | $_arr['lower']);
+        $request->setDataLen($_arr['len']);
+        $request->setRequestLen($request->getDataLen() + self::PACKAGE_HEDA_LEN);
+        return $request;
+    }
+
+    public function parseRequestBody(DubboRequest &$request)
+    {
+        if ($request->getSerialization() != self::DUBBO_PROTOCOL_SERIALIZE_FAST_JSON)
+        {
+            $this->logger->error("unknown serialization type :" . $request->getSerialization());
+            return false;
+        }
+        $cliData = substr($request->getFullData(), self::PACKAGE_HEDA_LEN);
+        if ($cliData)
+        {
+            if ($request->isHeartbeatEvent())
+            {
+                //心跳请求,不需要数据回送
+            } else
+            {
+                $dataArr = explode(PHP_EOL, $cliData);
+                $request->setDubboVersion(json_decode($dataArr[0], true));
+                $request->setService(json_decode($dataArr[1], true));
+                $request->setVersion(json_decode($dataArr[2], true));
+                $methodName = json_decode($dataArr[3],true);
+                if ($methodName == "\$invoke")
+                {
+                    //泛化调用
+                    $request->setMethod(json_decode($dataArr[5],true));
+                    $request->setParams(json_decode($dataArr[7],true));
+                    $attach = json_decode($dataArr[8],true);
+                } else
+                {
+                    //非泛化调用
+                    $request->setMethod($methodName);
+                    $paramTypes = json_decode($dataArr[4], true);
+                    if ($paramTypes == "")
+                    {
+                        //调用没有参数的方法
+                        $request->setTypes(NULL);
+                        $request->setParams(NULL);
+                        $attach = json_decode($dataArr[5],true);
+                    } else
+                    {
+                        $typeArr = explode(";", $paramTypes);
+                        $typeArrLen = count($typeArr);
+                        $request->setParamNum($typeArrLen - 1);
+                        $params = array();
+                        for ($i = 0; $i < $typeArrLen - 1; $i++) {
+                            $params[$i] = json_decode($dataArr[5 + $i],true);
+                        }
+                        $request->setParams($params);
+                        $attach = json_decode($dataArr[5 + ($typeArrLen - 1)],true);
+                    }
+                }
+                $request->setAttach($attach);
+                if (array_key_exists('group', $attach))
+                {
+                    $request->setGroup($attach['group']);
+                }
+                return $request;
+            }
+        }
+        return false;
+    }
+
+
+    public function packResponse(DubboResponse &$response)
+    {
+        if ($response->getStatus() != DubboResponse::OK) {
+            $resData = json_encode($response->getErrorMsg()) ;
+        } else {
+            if($response->getErrorMsg() != NULL && $response->getErrorMsg() != ""){
+                $resData = json_encode(self::RESPONSE_WITH_EXCEPTION) . PHP_EOL . json_encode($response->getErrorMsg());
+            }else if ($response->getResult() == NULL) {
+                $resData = json_encode(self::RESPONSE_NULL_VALUE);
+            } else {
+                $resData = json_encode(self::RESPONSE_VALUE) . PHP_EOL . json_encode($response->getResult());
+            }
+        }
+        $resData =  $resData.PHP_EOL;
+        $upper = ($response->getSn() & self::UPPER_MASK) >> 32;
+        $lower = $response->getSn() & self::LOWER_MASK;
+        $flag = self::DUBBO_PROTOCOL_SERIALIZE_FAST_JSON;
+        if ($response->isHeartbeatEvent()) {
+            $flag |= self::FLAG_HEARTBEAT_EVENT;
+        }
+        $out = pack("n1C1C1N1N1N1",
+            self::DUBBO_PROTOCOL_MAGIC,
+            $flag,
+            $response->getStatus(),
+            $upper,
+            $lower,
+            strlen($resData));
+
+        return $out . $resData;
+    }
+
+    public function isNormalResponse(DubboResponse $response)
+    {
+        return !($response->isHeartbeatEvent());
+    }
+
+    public function isNormalRequest(DubboRequest $request)
+    {
+        return !($request->isHeartbeatEvent());
+    }
+
+    public function isOneWayRequest(DubboRequest $request)
+    {
+        return !($request->isTwoWay());
+    }
+
+    public function isHearBeatRequest(DubboRequest $request)
+    {
+        return $request->isHeartbeatEvent();
+    }
+
+    public function isHearBeatResponse(DubboResponse $response)
+    {
+        return $response->isHeartbeatEvent();
+    }
+
+    public static function getReqInQueueTime(DubboRequest $request)
+    {
+        $ret = 0;
+        if (!empty($request->reqInfo)) {
+            $ret = isset($request->reqInfo['inqueue_time']) ? $request->reqInfo['inqueue_time'] : 0;
+        }
+        return $ret;
+    }
+}
\ No newline at end of file
diff --git a/common/protocol/fsof/DubboRequest.php b/common/protocol/fsof/DubboRequest.php
new file mode 100644
index 0000000..cb30cb7
--- /dev/null
+++ b/common/protocol/fsof/DubboRequest.php
@@ -0,0 +1,341 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common\protocol\fsof;
+
+class DubboRequest
+{
+    //包头字段
+    private $twoWay = true;
+    private $heartbeatEvent = false;
+    private $sn;                    //请求序号
+    private $serialization;
+    private $fullData;                   //报文(包含消息头)
+    private $dataLen;    //数据报文长度
+    private $requestLen; //请求报文总长度(即消息头+消息体的长度)
+
+    //包体字段
+    private $dubboVersion = "2.0.0";       //dubbo 版本
+    private $service;                      //服务名称
+    private $version;                      //服务版本
+    private $group;             //服务group
+    private $method;                //方法名
+    private $timeout;             //超时时间(ms)
+    private $types;              //参数类型
+    private $paramNum = 0;        //参数个数
+    private $params = array();    //调用$method时的参数
+    private $attach = array();
+
+    /**
+     * @return boolean
+     */
+    public function isTwoWay()
+    {
+        return $this->twoWay;
+    }
+
+    /**
+     * @param boolean $twoWay
+     */
+    public function setTwoWay($twoWay)
+    {
+        $this->twoWay = $twoWay;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getDataLen()
+    {
+        return $this->dataLen;
+    }
+
+    /**
+     * @param mixed $dataLen
+     */
+    public function setDataLen($dataLen)
+    {
+        $this->dataLen = $dataLen;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getRequestLen()
+    {
+        return $this->requestLen;
+    }
+
+    /**
+     * @param mixed $requestLen
+     */
+    public function setRequestLen($requestLen)
+    {
+        $this->requestLen = $requestLen;
+    }
+
+
+
+    /**
+     * @return boolean
+     */
+    public function isHeartbeatEvent()
+    {
+        return $this->heartbeatEvent;
+    }
+
+    /**
+     * @param boolean $heartbeatEvent
+     */
+    public function setHeartbeatEvent($heartbeatEvent)
+    {
+        $this->heartbeatEvent = $heartbeatEvent;
+    }
+
+
+
+
+    /**
+     * @return mixed
+     */
+    public function getSn()
+    {
+        return $this->sn;
+    }
+
+    /**
+     * @param mixed $sn
+     */
+    public function setSn($sn)
+    {
+        $this->sn = $sn;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getTimeout()
+    {
+        return $this->timeout;
+    }
+
+    /**
+     * @param mixed $timeout
+     */
+    public function setTimeout($timeout)
+    {
+        $this->timeout = $timeout;
+    }
+
+
+
+    /**
+     * @return mixed
+     */
+    public function getFullData()
+    {
+        return $this->fullData;
+    }
+
+    /**
+     * @param mixed $fullData
+     */
+    public function setFullData($fullData)
+    {
+        $this->fullData = $fullData;
+    }
+
+    /**
+     * @return string
+     */
+    public function getDubboVersion()
+    {
+        return $this->dubboVersion;
+    }
+
+    /**
+     * @param string $dubboVersion
+     */
+    public function setDubboVersion($dubboVersion)
+    {
+        $this->dubboVersion = $dubboVersion;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getService()
+    {
+        return $this->service;
+    }
+
+    /**
+     * @param mixed $service
+     */
+    public function setService($service)
+    {
+        $this->service = $service;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getVersion()
+    {
+        return $this->version;
+    }
+
+    /**
+     * @param mixed $version
+     */
+    public function setVersion($version)
+    {
+        $this->version = $version;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getGroup()
+    {
+        return $this->group;
+    }
+
+    /**
+     * @param mixed $group
+     */
+    public function setGroup($group)
+    {
+        $this->group = $group;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getMethod()
+    {
+        return $this->method;
+    }
+
+    /**
+     * @param mixed $method
+     */
+    public function setMethod($method)
+    {
+        $this->method = $method;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getTypes()
+    {
+        return $this->types;
+    }
+
+    /**
+     * @param mixed $types
+     */
+    public function setTypes($types)
+    {
+        $this->types = $types;
+    }
+
+    /**
+     * @return array
+     */
+    public function getParams()
+    {
+        return $this->params;
+    }
+
+    /**
+     * @param array $params
+     */
+    public function setParams($params)
+    {
+        $this->params = $params;
+    }
+
+    /**
+     * @return array
+     */
+    public function getAttach()
+    {
+        return $this->attach;
+    }
+
+    /**
+     * @param array $attach
+     */
+    public function setAttach($attach)
+    {
+        $this->attach = $attach;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getSerialization()
+    {
+        return $this->serialization;
+    }
+
+    /**
+     * @param mixed $serialization
+     */
+    public function setSerialization($serialization)
+    {
+        $this->serialization = $serialization;
+    }
+
+    /**
+     * @return int
+     */
+    public function getParamNum()
+    {
+        return $this->paramNum;
+    }
+
+    /**
+     * @param int $paramNum
+     */
+    public function setParamNum($paramNum)
+    {
+        $this->paramNum = $paramNum;
+    }
+
+
+
+    //用于监控service中各方法的性能
+    public $startTime;            //开始处理请求的时间
+    public $endTime;            //请求处理结束的时间
+
+    public $host;                //记录acc日志中的目标IP
+    public $port;                //记录acc日志中的目标端口
+
+    public $reqInfo = null;            //swoole框架记录的过载信息
+
+    public $environment = "prod";
+
+
+    public function __toString()
+    {
+        $ret = sprintf("%s:%s:%s->%s", $this->service, $this->version, $this->group, $this->method);
+        return $ret;
+    }
+}
\ No newline at end of file
diff --git a/common/protocol/fsof/DubboResponse.php b/common/protocol/fsof/DubboResponse.php
new file mode 100644
index 0000000..9e3554e
--- /dev/null
+++ b/common/protocol/fsof/DubboResponse.php
@@ -0,0 +1,193 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\common\protocol\fsof;
+
+class DubboResponse
+{
+    const OK = 20;
+    const SERVICE_ERROR = 70;      //服务端框架层有异常
+
+    private $fullData;				//返回报文(包含消息头)
+
+    //包头字段
+    private $sn;				//请求序号
+    private $status = self::OK;
+    private $heartbeatEvent = false;
+    private $serialization;
+    private $len;            //数据部分长度
+
+    //包体字段
+    private $responseBody;    //包体数据
+    private $result;           //调用$method的结果
+    private $errorMsg;
+
+    /**
+     * @return mixed
+     */
+    public function getFullData()
+    {
+        return $this->fullData;
+    }
+
+    /**
+     * @param mixed $fullData
+     */
+    public function setFullData($fullData)
+    {
+        $this->fullData = $fullData;
+    }
+
+    /**
+     * @return int
+     */
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getLen()
+    {
+        return $this->len;
+    }
+
+    /**
+     * @param mixed $len
+     */
+    public function setLen($len)
+    {
+        $this->len = $len;
+    }
+
+    /**
+     * @param int $status
+     */
+    public function setStatus($status)
+    {
+        $this->status = $status;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function isHeartbeatEvent()
+    {
+        return $this->heartbeatEvent;
+    }
+
+    /**
+     * @param boolean $heartbeatEvent
+     */
+    public function setHeartbeatEvent($heartbeatEvent)
+    {
+        $this->heartbeatEvent = $heartbeatEvent;
+    }
+
+
+
+
+    /**
+     * @return mixed
+     */
+    public function getErrorMsg()
+    {
+        return $this->errorMsg;
+    }
+
+    /**
+     * @param mixed $errorMsg
+     */
+    public function setErrorMsg($errorMsg)
+    {
+        $this->errorMsg = $errorMsg;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getSn()
+    {
+        return $this->sn;
+    }
+
+    /**
+     * @param mixed $sn
+     */
+    public function setSn($sn)
+    {
+        $this->sn = $sn;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getResult()
+    {
+        return $this->result;
+    }
+
+    /**
+     * @param mixed $result
+     */
+    public function setResult($result)
+    {
+        $this->result = $result;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getSerialization()
+    {
+        return $this->serialization;
+    }
+
+    /**
+     * @param mixed $serialization
+     */
+    public function setSerialization($serialization)
+    {
+        $this->serialization = $serialization;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getResponseBody()
+    {
+        return $this->responseBody;
+    }
+
+    /**
+     * @param mixed $responseBody
+     */
+    public function setResponseBody($responseBody)
+    {
+        $this->responseBody = $responseBody;
+    }
+
+
+
+	public function __toString()
+	{
+		$ret = sprintf("%s->%s",  $this->sn,$this->responseBody);
+		return $ret;
+	}		
+}
\ No newline at end of file
diff --git a/common/url/FSOFUrl.php b/common/url/FSOFUrl.php
new file mode 100644
index 0000000..7b5637a
--- /dev/null
+++ b/common/url/FSOFUrl.php
@@ -0,0 +1,294 @@
+<?php
+namespace com\fenqile\fsof\common\url;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+ 
+class FSOFUrl
+{
+    const URL_SCHEME = 'scheme';
+    const URL_HOST = 'host';
+    const URL_PORT = 'port';
+    const URL_QUERY = 'query';
+    const URL_PATH = 'path';
+    
+    const URL_VERSION = 'version';
+    const URL_GROUP = 'group';
+	const URL_SET = 'set';
+    const URL_SERVICE = 'service';
+
+    const URL_APPLICATION = 'application';
+    const URL_CATEGORY = 'category';
+
+	const URL_WEIGHT = 'weight';
+
+    private $originUrl = NULL;
+    private $encodedUrl = NULL;
+    private $zkPath = NULL;
+
+    private $query = NULL;
+    private $schema = NULL;
+    private $host = NULL;
+    private $port = NULL;
+    private $group = NULL;
+	private $set = NULL;
+    private $service = NULL;
+    private $version = NULL;
+    private $params = NULL;
+	private $weight = NULL;
+
+    private $logger;
+
+    public function __construct($urlPara)
+    {
+        $this->logger = \Logger::getLogger(__CLASS__);
+        if(is_string($urlPara))
+        {
+            if(!$this->initByStr($urlPara))
+            {
+                $this->logger->error('FSOFUrl initByStr failed|urlPara:'.$urlPara);
+                throw new \Exception("传入URL非法, FSOFUrl初始化失败");
+            }
+        }
+        else if(is_array($urlPara))
+        {
+            if(!$this->initByArr($urlPara))
+            {
+                $this->logger->error('FSOFUrl initByArr failed|urlPara:'.json_encode($urlPara));
+                throw new \Exception("传入URL非法, FSOFUrl初始化失败");
+            }
+        }
+        else
+        {
+            throw new \Exception("传入URL非法, FSOFUrl初始化失败");
+        }
+    }
+
+    private function  initByStr($urlPara)
+    {
+        $this->originUrl = $urlPara;
+
+        $ret = $this->parse($this->originUrl);
+        if(!$ret)
+        {
+            return FALSE;
+        }
+
+        return $this->initByArr($ret);
+    }
+
+    private function initByArr($urlPara)
+    {
+        if( !isset($urlPara[self::URL_SCHEME]) ||
+            !isset($urlPara[self::URL_HOST]) ||
+            !isset($urlPara[self::URL_PORT]))
+        {
+            return FALSE;
+        }
+
+        $this->params = $urlPara;
+        $this->schema = $urlPara[self::URL_SCHEME];
+        $this->host =  $urlPara[self::URL_HOST];
+        $this->port =  $urlPara[self::URL_PORT];
+        $getArgs = null;
+
+        if(isset($urlPara[self::URL_QUERY]))
+        {
+            $this->query = $urlPara[self::URL_QUERY];
+            parse_str($this->query,$getArgs);
+            $this->params = array_merge($this->params,$getArgs);
+        }
+
+		if (isset ($getArgs))
+		{
+			if(isset($getArgs[self::URL_VERSION]))
+			{
+				$this->version = $getArgs[self::URL_VERSION];
+			}
+
+			if(isset($getArgs[self::URL_GROUP]))
+			{
+				$this->group = $getArgs[self::URL_GROUP];
+			}
+
+			if (array_key_exists(self::URL_WEIGHT,$getArgs))
+			{
+				$this->weight = intval($getArgs[self::URL_WEIGHT]);
+			}
+			else
+			{
+				$this->weight = null;
+			}
+
+			if(isset($getArgs[self::URL_SET]))
+			{
+				$this->set = $getArgs[self::URL_SET];
+			}
+
+			if(isset($urlPara[self::URL_PATH]))
+			{
+				$this->service = ltrim($urlPara[self::URL_PATH], '/');
+			}
+			else if(isset($getArgs[self::URL_SERVICE]))
+			{
+				$this->service = $getArgs[self::URL_SERVICE];
+			}
+		}
+
+        $this->joinUrlStr();
+
+        return true;
+    }
+
+    private function joinUrlStr()
+    {
+        if(empty($this->originUrl))
+        {
+            $this->originUrl = $this->schema.'://'.$this->host.':'.$this->port.'/'.$this->service.'?'.$this->query;
+            $this->encodedUrl = urlencode($this->originUrl);
+        } 
+        else 
+        {
+            $this->encodedUrl = urlencode($this->originUrl);
+        }
+        
+        return true;
+    }
+
+    public function getOriginUrl()
+    {
+        return $this->originUrl;
+    }
+
+    public function getEncodedUrl()
+    {
+        return $this->encodedUrl;
+    }
+
+    public  function getHost()
+    {
+        return $this->host;
+    }
+
+    public function getPort()
+    {
+        return $this->port;
+    }
+
+	public function getGroup($defaultValue = NULL)
+	{
+		if(empty($this->group))
+		{
+			return $defaultValue;
+		}
+		else
+		{
+			return $this->group;
+		}
+	}
+
+    public function getSet($defaultValue = NULL)
+    {
+        if(empty($this->set))
+        {
+            return $defaultValue;
+        }
+        else
+        {
+            return $this->set;
+        }
+    }
+
+    public function getVersion($defaultValue = NULL)
+    {
+        if(empty($this->version))
+        {
+            return $defaultValue;
+        }
+        else
+        {
+            return $this->version;
+        }
+    }
+
+    public function getService()
+    {
+        return $this->service;
+    }
+
+    public function getZookeeperPath()
+    {
+        $root = '/dubbo';
+        $providers = 'providers';
+        $this->zkPath = $root.'/'.$this->getService().'/'.$providers.'/'.$this->getEncodedUrl();
+        return $this->zkPath;
+    }
+
+    public function getApplication()
+    {
+        return $this->getparam(self::URL_APPLICATION);
+    }
+
+    public function getCategory()
+    {
+        return $this->getparam(self::URL_CATEGORY);
+    }
+
+	public function getDefaultWeight($weight)
+	{
+		if(null === $this->weight)
+		{
+			return $weight;
+		}
+		else
+		{
+			return $this->weight;
+		}
+	}
+
+	public function getWeight()
+	{
+		return $this->weight;
+	}
+
+	public function setWeight($weight)
+	{
+		$this->weight = $weight;
+	}
+
+	public function getParams($key)
+	{
+		return $this->getparam($key);
+	}
+
+    private function parse($url)
+    {
+        return parse_url($url);
+    }
+
+    private function getparam($key)
+    {
+        if(isset($this->params[$key]))
+        {
+            return $this->params[$key];
+        }
+        else
+        {
+            return NULL;
+        }
+    }
+}
\ No newline at end of file
diff --git a/config/app/conf/dev/provider/demo-provider.deploy b/config/app/conf/dev/provider/demo-provider.deploy
new file mode 100644
index 0000000..b1f9ded
--- /dev/null
+++ b/config/app/conf/dev/provider/demo-provider.deploy
@@ -0,0 +1,22 @@
+[server]
+; port
+listen[] = 10000
+
+;app log config file path
+log_cfg_file_path = '/root/fsof_php_core/dubbo-php-framework/demo/demo-provider/config/log4php.xml'
+
+;swoole log path
+swoole_log_path = '/var/fsof/provider/example_swoole.log'
+
+; point to app root path's bootstrap.php
+root = '/root/fsof_php_core/dubbo-php-framework/demo/demo-provider/BootStrap.php'
+
+[setting]
+; worker num
+worker_num = 2
+
+; daemonize
+daemonize = true
+
+;max_request
+max_request = 1
diff --git a/config/app/conf/gray/provider/example.deploy b/config/app/conf/gray/provider/example.deploy
new file mode 100644
index 0000000..a502d5e
--- /dev/null
+++ b/config/app/conf/gray/provider/example.deploy
@@ -0,0 +1,20 @@
+[server]
+; port
+listen[] = 10000
+
+;Provider app log level INFO WARN ERROR
+log_level = INFO
+
+;base service log level INFO WARN ERROR
+bslog_level = INFO
+
+; point to app root path's bootstrap.php 
+root = '../example/provider/src/BootStrap.php'
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[setting]
+; worker num
+worker_num = 2
+
+; daemonize
+daemonize = true
\ No newline at end of file
diff --git a/config/app/conf/pre/provider/example.deploy b/config/app/conf/pre/provider/example.deploy
new file mode 100644
index 0000000..c87f999
--- /dev/null
+++ b/config/app/conf/pre/provider/example.deploy
@@ -0,0 +1,22 @@
+[server]
+; port
+listen[] = 10000
+
+;Provider app log level INFO WARN ERROR
+log_level = INFO
+
+;base service log level INFO WARN ERROR
+bslog_level = INFO
+
+; point to app root path's bootstrap.php 
+root = '../example/provider/src/BootStrap.php'
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[setting]
+; worker num
+worker_num = 2
+
+; daemonize
+daemonize = true
+
+
diff --git a/config/app/conf/pro/provider/example.deploy b/config/app/conf/pro/provider/example.deploy
new file mode 100644
index 0000000..a502d5e
--- /dev/null
+++ b/config/app/conf/pro/provider/example.deploy
@@ -0,0 +1,20 @@
+[server]
+; port
+listen[] = 10000
+
+;Provider app log level INFO WARN ERROR
+log_level = INFO
+
+;base service log level INFO WARN ERROR
+bslog_level = INFO
+
+; point to app root path's bootstrap.php 
+root = '../example/provider/src/BootStrap.php'
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+[setting]
+; worker num
+worker_num = 2
+
+; daemonize
+daemonize = true
\ No newline at end of file
diff --git a/config/global/conf/fsof.ini b/config/global/conf/fsof.ini
new file mode 100644
index 0000000..aa92cfc
--- /dev/null
+++ b/config/global/conf/fsof.ini
@@ -0,0 +1,34 @@
+[fsof_container_setting]
+;php path
+php = '/usr/bin/php'
+
+;app's user
+user = root
+
+[fsof_setting]
+;machine enviroment:[dev|pre|gray|pro]
+environment = dev
+
+;in p2p mode, provider not register to registry
+p2p_mode = false
+
+;zookeeper log switch: 0.close; 1.error; 2.warn; 3.info; 4.debug
+zklog_level = 0
+
+;zookeepr log path
+zklog_path = '/var/fsof/provider/zookeeper.log'
+
+;zookeeper url list
+zk_url_list = http://127.0.0.1:2181
+
+;provider overload mode switch
+overload_mode = true
+
+;if request wait more than waiting_time before processed, we will lost this quest, unit is micro-second 
+waiting_time = 2000
+
+;if overload_number requests trigger overload rule continuous, we will open loss request mode
+overload_number = 5
+
+;how many quest is lost before lost mode is close 
+loss_number = 20
\ No newline at end of file
diff --git a/consumer/FSOFConsumer.php b/consumer/FSOFConsumer.php
new file mode 100644
index 0000000..58f06da
--- /dev/null
+++ b/consumer/FSOFConsumer.php
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\consumer;
+
+use com\fenqile\fsof\consumer\proxy\ProxyFactory;
+
+
+class FSOFConsumer
+{
+    /**
+     * @var  boolean  Has [FSOFConsumer::init] been called?
+     */
+    protected static $_init = FALSE;
+
+    protected static $_initSetting;
+    
+    public static function init(array $settings = NULL)
+    {
+        if (self::isConsumerInit())
+        {
+            // Do not allow execution twice
+            return;
+        }
+        \Logger::getLogger(__CLASS__)->info("consumer cfg:".json_encode($settings, true));
+
+        $consumerRoot = __DIR__;
+		$fsofBootPath = dirname($consumerRoot);
+
+        //加载commom
+        $fsofCommonPath = $fsofBootPath.DIRECTORY_SEPARATOR.'common';
+        require_once($fsofCommonPath.DIRECTORY_SEPARATOR.'BootStrap.php');
+
+        //加载registry
+        $fsofRegistryPath = $fsofBootPath.DIRECTORY_SEPARATOR.'registry';
+        require_once($fsofRegistryPath.DIRECTORY_SEPARATOR.'BootStrap.php');
+
+        //检查输入参数app_src
+        if ((!isset($settings['app_src'])) || (!isset($settings['app_name'])))
+		{
+            throw new \Exception("FSOFConsumer::init传入的app的src路径参数不准确");
+        }        
+        $consumerConfigFile = $settings['app_src'];
+        $consumerConfigFile = rtrim($consumerConfigFile, DIRECTORY_SEPARATOR);
+        $consumerConfigFile = $consumerConfigFile.DIRECTORY_SEPARATOR.'consumer'.DIRECTORY_SEPARATOR.$settings['app_name'].'.consumer';
+        if (file_exists($consumerConfigFile))
+        {
+        	try 
+        	{
+                $consumerConfig = parse_ini_file($consumerConfigFile, true);     
+            } 
+            catch (\Exception $e) 
+            {
+                throw new \Exception("consumer配置文件有误[".$consumerConfigFile."]");
+            }
+        }
+		else
+		{
+			$consumerConfig = array();
+		}
+
+		self::$_initSetting = $settings;
+
+        //注册consumer框架的autoLoader
+        self::registerConsumerFrameAutoLoader($consumerRoot);
+
+        //注册consumer的动态代理工厂
+        ProxyFactory::setConsumerConfig($consumerConfig, $consumerConfigFile, $settings);
+
+        // FSOFConsumer is now initialized
+		self::$_init = TRUE;
+    }
+
+    private static function registerConsumerFrameAutoLoader($consumerRoot)
+    {
+        if (!self::isConsumerInit())
+        {
+            //注册框架顶层命名空间到自动加载器
+            require_once $consumerRoot.DIRECTORY_SEPARATOR.'FrameAutoLoader.php';
+            FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer', $consumerRoot);
+            FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer\app', $consumerRoot.DIRECTORY_SEPARATOR.'app');
+            FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer\fsof', $consumerRoot.DIRECTORY_SEPARATOR.'fsof');
+            FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer\proxy', $consumerRoot.DIRECTORY_SEPARATOR.'proxy');
+            FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer\client', $consumerRoot.DIRECTORY_SEPARATOR.'client');
+            spl_autoload_register(__NAMESPACE__.'\FrameAutoLoader::autoload');
+        }
+    }
+
+    public static function getInitSetting()
+    {
+        return  self::$_initSetting;
+    }
+    
+    public static function isConsumerInit()
+    {
+        return  self::$_init;
+    }
+
+}
\ No newline at end of file
diff --git a/consumer/FrameAutoLoader.php b/consumer/FrameAutoLoader.php
new file mode 100644
index 0000000..c87b096
--- /dev/null
+++ b/consumer/FrameAutoLoader.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\consumer;
+
+class FrameAutoLoader
+{
+    /**
+     * 命名空间的路径
+     */
+    private static $nsPath = Array();
+
+    /**
+     * 自动载入类
+     * @param $class
+     */
+    public static function autoload($class)
+    {
+    	$frameRootPathDepth = count(explode('\\', __NAMESPACE__));
+        $root = explode('\\', trim($class, '\\'));
+        $pathDepth = count($root);
+        if($pathDepth > $frameRootPathDepth)
+        {
+        	$key = $className = $class;
+	        if($pathDepth > $frameRootPathDepth + 1)
+	        {
+	        	$root = explode('\\', trim($class, '\\'), $frameRootPathDepth + 2);
+	        	$className = $root[$frameRootPathDepth + 1];
+	        	unset($root[$frameRootPathDepth + 1]);
+	        	$key = implode($root, '\\');
+	        }
+	        else if($pathDepth == $frameRootPathDepth + 1)
+	        {
+	        	$root = explode('\\', trim($class, '\\'), $frameRootPathDepth + 1);
+	        	$className = $root[$frameRootPathDepth];
+	        	unset($root[$frameRootPathDepth]);
+	        	$key = implode($root, '\\');
+	        }
+	        
+        	if(isset(self::$nsPath[$key]))
+	        {
+	        	include_once self::$nsPath[$key] . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $className) . '.php';
+	        }
+        }
+    }
+
+    /**
+     * 设置根命名空间
+     * @param $root
+     * @param $path
+     */
+    public static function setRootNS($root, $path)
+    {
+        self::$nsPath[$root] = $path;
+    }
+}
\ No newline at end of file
diff --git a/consumer/client/FSOFClient4Linux.php b/consumer/client/FSOFClient4Linux.php
new file mode 100644
index 0000000..8416989
--- /dev/null
+++ b/consumer/client/FSOFClient4Linux.php
@@ -0,0 +1,91 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\consumer\client;
+
+class FSOFClient4Linux extends IFSOFClient
+{
+    private  $logger;
+    public function __construct()
+    {
+        $this->logger = \Logger::getLogger(__CLASS__);
+        if (extension_loaded('swoole'))
+        {
+            try 
+            {
+				$this->client = new \swoole_client(SWOOLE_SOCK_TCP);
+                $this->client->set(array(
+                    'open_length_check' => TRUE,
+                    'package_length_offset' => 12,       //第N个字节是包长度的值
+                    'package_body_offset' => 16,       //第几个字节开始计算长度
+                    'package_length_type' => 'N',
+                    'package_max_length' => 1024 * 1024 * 5, //TCP协议最大长度为2M,暂定5M
+                ));
+            } 
+            catch (\Exception $e) 
+            {
+                $this->logger->error("not installed swoole extension", $e);
+                throw new \Exception("该环境未安装swoole扩展");
+            }
+        }
+        else
+        {
+            $this->logger->error("not installed swoole extension");
+            throw new \Exception("该环境未安装swoole扩展");
+        }
+    }
+
+    public function connect($ipAddr, $port, $ioTimeOut)
+    {
+        try 
+        {
+            return $this->client->connect($ipAddr, $port, $ioTimeOut);
+        } 
+        catch (\Exception $e) 
+        {
+            $this->logger->error("connect FSOF server[".$ipAddr.":".$port ."] failed", $e);
+            return false;
+        }
+    }
+
+    public function send($data, $len)
+    {
+        return $this->client->send($data);
+    }
+
+    public function recv($len = 65535)
+    {
+        return $this->client->recv($len, true);
+    }
+
+    public function close($force = false)
+    {
+        try 
+        {
+            $this->client->close($force);
+        } 
+        catch (\Exception $e) 
+        {
+            $this->logger->error("close exception", $e);
+        }
+    }
+
+    public function getlasterror()
+    {
+        return $this->client->errCode;
+    }
+}
\ No newline at end of file
diff --git a/consumer/client/IFSOFClient.php b/consumer/client/IFSOFClient.php
new file mode 100644
index 0000000..3109dfb
--- /dev/null
+++ b/consumer/client/IFSOFClient.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\consumer\client;
+
+abstract class IFSOFClient
+{
+    protected $client;
+
+    abstract public function connect($ipAddr, $port, $ioTimeOut);
+
+    abstract public function send($data, $len);
+
+    abstract public function recv($len = 65535);
+
+    abstract public function close($force = false);
+
+    abstract public function getlasterror();
+}
\ No newline at end of file
diff --git a/consumer/fsof/FSOFProcessor.php b/consumer/fsof/FSOFProcessor.php
new file mode 100644
index 0000000..1c1cb87
--- /dev/null
+++ b/consumer/fsof/FSOFProcessor.php
@@ -0,0 +1,342 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\consumer\fsof;
+
+use com\fenqile\fsof\common\config\FSOFConstants;
+use com\fenqile\fsof\common\protocol\fsof\DubboParser;
+use com\fenqile\fsof\common\protocol\fsof\DubboRequest;
+use com\fenqile\fsof\common\protocol\fsof\DubboResponse;
+use com\fenqile\fsof\consumer\client\FSOFClient4Linux;
+
+class FSOFProcessor
+{
+    const FSOF_CONNECTION_RESET = 104;
+
+    const FSOF_ETIMEOUT = 110;
+    const FSOF_EINPROGRESS = 115;
+    const FSOF_ECONNREFUSED = 111;
+
+    protected $parser;
+
+    private  $logger;
+
+    public function __construct()
+    {
+        $this->logger = \Logger::getLogger(__CLASS__);
+        $this->parser = new DubboParser();
+    }
+
+    public function executeRequest(DubboRequest $request, $svrAddr, $ioTimeOut, &$providerAddr)
+    {
+        //计算服务端个数
+        $svrNum = count($svrAddr);
+        //连接异常重试次数最多2次
+        $connect_try_times = ($svrNum > 2) ? 2 : $svrNum;
+        $client = NULL;
+        for ($i = 0; $i < $connect_try_times; $i++)
+        {
+            try
+            {
+                //获取路由下标
+                $col = mt_rand(0, $svrNum-1);
+                $svrUrl = $svrAddr[$col];
+                $host = $svrUrl->getHost();
+                $port = $svrUrl->getPort();
+
+                //记录路由信息
+                $providerAddr = $host.':'.$port;
+
+                //透传到服务端字段
+                $request->host = $host;
+                $request->port = $port;
+                $request->setGroup($svrUrl->getGroup(FSOFConstants::FSOF_SERVICE_GROUP_ANY));
+                $request->setVersion( $svrUrl->getVersion(FSOFConstants::FSOF_SERVICE_VERSION_DEFAULT));
+                $request->setTimeout($ioTimeOut * 1000);
+
+                $client = $this->connectProvider($host, $port, $ioTimeOut);
+                if(empty($client))
+                {
+                    //记录连接错误日志
+                    $this->logger->error("connect FSOF server[".$host.":".$port ."] failed");
+                    //删除无用地址信息
+                    $svrAddr[$col] = NULL;
+                    $svrAddr = array_filter($svrAddr);
+                    if(self::FSOF_ECONNREFUSED == $this->lastErrorNo)
+                    {
+                        //连接拒绝
+                        continue;
+                    }
+                    else if(self::FSOF_ETIMEOUT == $this->lastErrorNo || self::FSOF_EINPROGRESS == $this->lastErrorNo)
+                    {
+                        //连接超时
+                        break;
+                    }
+                    else
+                    {
+                        //其他错误
+                        continue;
+                    }
+                }
+                else
+                {
+                    break;
+                }
+            }
+            catch (\Exception $e)
+            {
+                if (!empty($client))
+                {
+                    unset($client);
+                }
+                $this->logger->error($e->getMessage(), $e);
+            }
+        }
+
+        //与服务端进行交互
+        $ret = NULL;
+        if(isset($client))
+        {
+            try
+            {
+                $data = $this->parser->packRequest($request);
+                $dataLen = strlen($data);
+                if(!$client->send($data, $dataLen))
+                {
+                    $client->close(true);
+                    unset($client);
+                    $msg = json_encode($request->__toString(), JSON_UNESCAPED_UNICODE);
+                    if (mb_strlen($msg, 'UTF-8') >= 512)
+                    {
+                        $msg = mb_substr($msg, 0, 512, 'UTF-8').' ...(len:'.strlen($msg).")";
+                    }
+                    $this->logger->error("send date failed:" . $msg);
+                    throw new \Exception("发送请求数据失败");
+                }
+            }
+            catch (\Exception $e)
+            {
+                $client->close(true);
+                unset($client);
+                $msg = json_encode($request->__toString(), JSON_UNESCAPED_UNICODE);
+                if (mb_strlen($msg, 'UTF-8') >= 512)
+                {
+                    $msg = mb_substr($msg, 0, 512, 'UTF-8').' ...(len:'.strlen($msg).")";
+                }
+                $this->logger->error("send date failed:" . $msg, $e);
+                throw new \Exception("发送请求数据失败");
+            }
+
+            try
+            {
+                $ret = $this->recvDataFromProvider($client, $request);
+                $client->close();
+                unset($client);
+            }
+            catch (\Exception $e)
+            {
+                $client->close(true);
+                unset($client);
+                throw $e;
+            }
+        }
+        else
+        {
+            throw new \Exception("与服务器建立连接失败");
+        }
+        return $ret;
+    }
+
+    protected function connectProvider($host, $port, $iotimeout)
+    {
+        try
+        {
+            $start_time = microtime(true);//取到微秒
+
+			$client = new FSOFClient4Linux();
+
+            if ($client->connect($host,$port,$iotimeout))
+            {
+                $this->logger->debug('connect to server['.$host.":".$port."] success,timeout:".$iotimeout);
+            }
+            else
+            {
+                //记录错误码
+                $this->lastErrorNo = $client->getlasterror();
+                $cost_time = (int)((microtime(true) - $start_time) * 1000000);
+                $this->logger->error('connect to server['.$host.":".$port."] failed,timeout:".$iotimeout."|".$cost_time."us".'|errcode:'.$this->lastErrorNo);
+                unset($client);
+            }
+        }
+        catch (\Exception $e)
+        {
+            unset($client);
+            $this->logger->error("Connect provider exception:",$e);
+        }
+
+        if (isset($client))
+        {
+            return $client;
+        }
+        else
+        {
+            return NULL;
+        }
+    }
+
+    protected function recvDataFromProvider($socket, DubboRequest $request)
+    {
+        $fsof_data = $this->Recv($socket, DubboParser::PACKAGE_HEDA_LEN);
+        if (!$fsof_data)
+        {
+            if (0 == $socket->getlasterror())
+            {
+                throw new \Exception("provider端己关闭网络连接");
+            }
+            else
+            {
+                throw new \Exception("接收应答数据超时");
+            }
+        }
+
+        //解析头
+        $response = new DubboResponse();
+        $response->setFullData($fsof_data);
+        $response = $this->parser->parseResponseHeader($response);
+        if (($response) && ($response->getSn() != $request->getSn()))
+        {
+            $this->logger->error("response sn[{$response->getSn()}] != request sn[{$request->getSn()}]");
+            throw new \Exception("请求包中的sn非法");
+        }
+
+        //接收消息体
+        $resData = substr($response->getFullData(), DubboParser::PACKAGE_HEDA_LEN);
+        if ($resData)
+        {
+            $resDataLen = strlen($resData);
+        }
+        else
+        {
+            $resDataLen = 0;
+        }
+
+        if ($resDataLen < $response->getLen())
+        {
+            //取到微秒
+            $start_time = microtime(true);
+            //如果长度超过1M,则分包处理,以1M为单位分包
+            $resv_len = $response->getLen() - $resDataLen;
+            $cur_len = 0;
+            $recv_data = '';
+            do
+            {
+                if (DubboParser::MAX_RECV_LEN > $resv_len)
+                {
+                    $cur_len = $resv_len;
+                }
+                else
+                {
+                    $cur_len = DubboParser::MAX_RECV_LEN;
+                }
+                $tmpdata = $this->Recv($socket, $cur_len);
+                if ($tmpdata)
+                {
+                    $recv_data = $recv_data . $tmpdata;
+                    $resv_len -= $cur_len;
+                }
+                else
+                {
+                    if (0 == $socket->getlasterror())
+                    {
+                        throw new \Exception("provider端己关闭网络连接");
+                    }
+                    else
+                    {
+                        throw new \Exception("接收应答数据超时");
+                    }
+                }
+                //如果超过15秒就当超时处理
+                if ((microtime(true) - $start_time) > 15)
+                {
+                    $this->logger->error("Multi recv {$resv_len} bytes data timeout");
+                    throw new \Exception("接收应答数据超时");
+                }
+            } while ($resv_len > 0);
+
+            $response->setFullData($response->getFullData() . $recv_data);
+        }
+
+        if ($this->parser->parseResponseBody($response))
+        {
+            if(DubboResponse::OK != $response->getStatus())
+            {
+                throw new \Exception($response->getErrorMsg());
+            }
+            else
+            {
+                return $response->getResult();
+            }
+        }
+        else
+        {
+            $this->logger->error("parse response body err:".$response->__toString());
+            throw new \Exception("未知异常");
+        }
+    }
+
+    protected function Recv($socket, $len)
+    {
+        try
+        {
+            $resv_len = $len;
+            $_data = '';
+            $cnt = 20;//最多循环20次,防止provider端挂掉时,consumer陷入死循环
+            do
+            {
+                $cnt--;
+                $tmp_data = $socket->recv($resv_len);
+                if (!$tmp_data)
+                {
+                    $this->logger->warn("socket->recv faile:$resv_len");
+                    break;
+                }
+                $_data = $_data . $tmp_data;
+                $resv_len -= strlen($tmp_data);
+            } while (($resv_len > 0) && ($cnt > 0));
+
+            if ($resv_len > 0)
+            {
+                $this->logger->error("Recv $len data fail!");
+                return FALSE;
+            }
+
+            return $_data;
+        }
+        catch (\Exception $e)
+        {
+            $this->logger->error('recv data exception',$e);
+            if(self::FSOF_CONNECTION_RESET == $e->getCode())
+            {
+                throw new \Exception("未知异常");
+            }
+            else
+            {
+                throw new \Exception("接收应答数据超时");
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/consumer/proxy/Proxy.php b/consumer/proxy/Proxy.php
new file mode 100644
index 0000000..cecadce
--- /dev/null
+++ b/consumer/proxy/Proxy.php
@@ -0,0 +1,144 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\consumer\proxy;
+
+use com\fenqile\fsof\common\protocol\fsof\DubboRequest;
+use com\fenqile\fsof\consumer\fsof\FSOFProcessor;
+
+
+final class Proxy
+{
+    private $appName;
+
+	private $group;
+
+    private $serviceInterface;
+
+    private $serviceAddress = array();
+
+    private $fsofProcessor;
+
+	//默认超时时间为3s
+    private $ioTimeOut = 3;
+
+    private  $logger;
+
+    public static function newProxyInstance($serviceInterfaces,  $appName, $group)
+    {
+        return new Proxy($serviceInterfaces, $appName, $group);
+    }
+
+    public function __construct($serviceInterfaces, $appName, $group)
+    {
+        $this->logger = \Logger::getLogger(__CLASS__);
+        $this->serviceInterface = $serviceInterfaces;
+        $this->appName = $appName;
+		$this->group = $group;
+        $this->fsofProcessor = new FSOFProcessor();
+    }
+
+    public function setIOTimeOut($ioTimeOut)
+    {
+        $this->ioTimeOut = $ioTimeOut;
+    }
+
+    public function setAddress($serviceAddr = array())
+    {
+		//删除旧的地址
+        unset($this->serviceAddress);
+        $this->serviceAddress = $serviceAddr;
+    }
+
+	public function getAddressStr()
+    {
+        $ret = "";
+        foreach ($this->serviceAddress as $index => $url)
+        {
+            $ret .= $url->getHost().':'.$url->getPort().';';
+        }
+        return $ret;
+    }
+    
+    protected function generatePackageSN()
+    {
+        srand((double)microtime() * 1000000);
+        $rand_number = rand();
+        return $rand_number;
+    }
+
+    protected function generateParamType($num)
+    {
+        $types = array();
+        for($i = 0; $i < $num; $i++)
+        {
+            $types[] = 'Ljava/lang/Object;';
+        }
+        return $types;
+    }
+
+    protected function trimParams($params)
+    {
+        if(count($params) == 1 && empty($params[0]))
+        {
+            return null;
+        }
+        return $params;
+    }
+
+    public function __call($name, $args)
+    {
+        $result = NULL;
+		$method = null;
+        $providerAddress = NULL;
+        $request = new DubboRequest();
+		//取到微秒
+        $begin_time = microtime(true);
+        $this->logger->debug("in|consumer_app:{$this->appName}|service:{$this->serviceInterface}|timout:{$this->ioTimeOut}|name:{$name}");
+        try {
+            $request->setSn($this->generatePackageSN());
+            $request->setService($this->serviceInterface);
+            $request->setMethod($args[0]);
+            array_shift($args);
+            $request->setParams($args);
+            $request->setTypes($this->generateParamType(count($request->getParams())));
+            $result = $this->fsofProcessor->executeRequest($request, $this->serviceAddress, $this->ioTimeOut, $providerAddress);
+        }catch (\Exception $e) {
+            $cost_time = (int)((microtime(true) - $begin_time) * 1000000);
+            //记录consumer接口告警日志
+            $this->setAccLog($request, $cost_time, $e->getMessage());
+            throw $e;
+        }
+        $cost_time = (int)((microtime(true) - $begin_time) * 1000000);
+        //记录consumer接口告警日志
+        $this->setAccLog($request, $cost_time, "ok");
+		return $result;
+    }
+
+    protected function setAccLog($request, $costTime, $errMsg='ok')
+    {
+		//时间|服务名|耗时(us)|返回码|应用名|方法名|目标服务group|目标服务version|目标机器ip:port|备注
+		$accLog = sprintf("%s|%d|%d|%s|%s|%s|%s|%s", $request->getService(), $costTime,
+			$this->appName,
+			$request->getMethod(),
+			$request->getGroup(),
+			$request->getVersion(),
+			$request->host . ':' . $request->port,
+			$errMsg);
+        $this->logger->debug($accLog);
+    }
+}
\ No newline at end of file
diff --git a/consumer/proxy/ProxyFactory.php b/consumer/proxy/ProxyFactory.php
new file mode 100644
index 0000000..d1c3c4e
--- /dev/null
+++ b/consumer/proxy/ProxyFactory.php
@@ -0,0 +1,229 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\consumer\proxy;
+
+use com\fenqile\fsof\common\url\FSOFUrl;
+use com\fenqile\fsof\common\log\FSOFSystemUtil;
+use com\fenqile\fsof\common\config\FSOFConstants;
+use com\fenqile\fsof\common\config\FSOFCommonUtil;
+use com\fenqile\fsof\registry\automatic\ConsumerProxy;
+
+
+final class ProxyFactory
+{
+	/**
+	 * @var  App加载的配置文件路径
+	 */
+	protected static $appConfigFile = '';
+
+	/**
+	 * @var  p2p模式开关
+	 */
+	protected static $p2pMode = FALSE;
+
+    /**
+     * @var app所属的group
+     */
+    protected static $appGroup = FSOFConstants::FSOF_SERVICE_GROUP_ANY;
+
+    /**
+     * @var app所属的version
+     */
+    protected static $appVersion = FSOFConstants::FSOF_SERVICE_VERSION_DEFAULT;
+        
+    /**
+     * @var  appname
+     */
+    protected static $appName = 'consumer';
+
+	/**
+	 * @var  instance array
+	 */
+    protected static $serviceInstances = array();
+
+    /**
+	 * @var  *.consumer中配置的service信息
+	 */
+	protected static $serviceConsumers = array();
+
+    private static $logger;
+
+	public static function setConsumerConfig($configData, $consumerConfigFile, $initSettings)
+	{
+        self::$logger = \Logger::getLogger(__CLASS__);
+
+		//App名字
+		self::$appName = $initSettings['app_name'];
+
+		//获取app加载配置文件;输出日志方便问题定位
+		self::$appConfigFile = $consumerConfigFile;
+
+		//是否开启p2p模式, p2p模式下, 将使用[consumer_services]下的信息进行路由
+		if(isset($configData['consumer_config']['p2p_mode']) && $configData['consumer_config']['p2p_mode'])
+		{
+			self::$p2pMode = $configData['consumer_config']['p2p_mode'];
+		}
+
+		if (isset($configData['consumer_config']['group']))
+		{
+			self::$appGroup = $configData['consumer_config']['group'];
+		}
+
+		if(isset($configData['consumer_config']['version']))
+		{
+			self::$appVersion = $configData['consumer_config']['version'];
+		}
+
+		if(isset($configData['consumer_services']))
+		{
+			self::$serviceConsumers = $configData['consumer_services'];
+		}
+	}
+
+    //use automatic registry
+    private static function getInstancByRedis($service, $ioTimeOut, $version, $group)
+	{
+        $ret = NULL;
+        $providerInfo = ConsumerProxy::instance()->getProviders($service, $version, $group);
+        if(!empty($providerInfo))
+        {
+            $cacheKey = $service.':'.$version.':'.$group;
+            if(empty(self::$serviceInstances[$cacheKey]))
+            {
+                $ret = Proxy::newProxyInstance($service,  self::$appName, $group);
+                self::$serviceInstances[$cacheKey] = $ret;
+            }
+            else
+            {
+                $ret = self::$serviceInstances[$cacheKey];
+            }
+
+            //设置io超时时间
+            $ret->setIOTimeOut($ioTimeOut);
+			
+            //设置地址列表
+            $ret->setAddress($providerInfo);
+        }
+        else
+        {
+            self::$logger->error("not find providers form redis for $service:$version:$group");
+        }
+        
+        return $ret;     
+    }
+
+    //use p2p mode
+    private static function getInstanceByP2P($service, $ioTimeOut, $version, $group)
+    {
+        $ret = NULL;
+        if(array_key_exists($service, self::$serviceConsumers))
+        {
+            $serviceProperty = self::$serviceConsumers[$service];
+			if (isset($serviceProperty['url']))
+			{
+				$ret = Proxy::newProxyInstance($service, self::$appName, $group);
+
+				//设置io超时时间
+				$ret->setIOTimeOut($ioTimeOut);
+
+				//设置所用服务的ip地址列表
+				$serviceAddr = explode(",",$serviceProperty['url']);
+				$serviceUrls = array();
+				foreach ($serviceAddr as $index => $addr)
+				{
+					$tmpUrl = $addr.'/'."{$service}?version={$version}&group={$group}";
+					$serviceUrls[] = new FSOFUrl($tmpUrl);
+				}
+				$ret->setAddress($serviceUrls);
+			}
+			else
+			{
+                self::$logger->warn(self::$appName.'.consumer not exist url');
+			}
+        }
+        else 
+        {
+            self::$logger->warn('service not found on p2p|consumer_app:'.self::$appName.'|provider_service:'.$service);
+        }
+        
+        return $ret;         
+    }
+
+    public static function getInstance($consumerInterface, $ioTimeOut = 3)
+    {
+    	$ret = NULL;
+        $route = '';
+        $addressList = 'null';
+
+		//app级组和版本信息
+		$group = self::$appGroup;
+		$versionList = self::$appVersion;
+
+		if (array_key_exists($consumerInterface, self::$serviceConsumers))
+		{
+            $serviceProperty = self::$serviceConsumers[$consumerInterface];
+			if(isset($serviceProperty['group']))
+			{
+				$group = $serviceProperty['group'];
+			}
+			if(isset($serviceProperty['version']))
+			{
+				$versionList = $serviceProperty['version'];
+			}
+		}
+
+		try
+		{
+
+			//依据配置权重选取版本号
+			$version = FSOFCommonUtil::getVersionByWeight($versionList);
+
+			//p2p模式
+			if (self::$p2pMode)
+			{
+				$ret = self::getInstanceByP2P($consumerInterface, $ioTimeOut, $version, $group);
+				$route = 'p2p';
+			}
+
+			if (empty($ret))
+			{
+				//registry 模式
+				$ret = self::getInstancByRedis($consumerInterface, $ioTimeOut, $version, $group);
+				$route = 'auto registry';
+			}
+
+			if (empty($ret))
+			{
+				$errMsg = "current_address:".FSOFSystemUtil::getLocalIP()."|".$consumerInterface;
+                throw new \Exception($errMsg);
+			}
+			else
+			{
+                $addressList = $ret->getAddressStr();
+			}
+            self::$logger->debug('consumer_app:'.self::$appName.'|app_config_file:'.self::$appConfigFile.
+                '|version:'.$version.'|group:'.$group.'|provider_service:'.$consumerInterface.'|route:'.$route.'|addr_list:'.$addressList.'|timeout:'.$ioTimeOut);
+        }
+        catch (\Exception $e)
+        {
+            self::$logger->error('consumer_app:'.self::$appName.'|app_config_file:'.self::$appConfigFile.
+                '|version:'.$version.'|group:'.$group.'|provider_service:'.$consumerInterface.'|errmsg:'. $e->getMessage().'|exceptionmsg:'.$e);
+        }
+    	return $ret;
+    }
+}
\ No newline at end of file
diff --git a/demo/demo-consumer/config/log4php.xml b/demo/demo-consumer/config/log4php.xml
new file mode 100644
index 0000000..7e89f2f
--- /dev/null
+++ b/demo/demo-consumer/config/log4php.xml
@@ -0,0 +1,12 @@
+<configuration xmlns="http://logging.apache.org/log4php/">
+    <appender name="myAppender" class="LoggerAppenderFile">
+        <param name="file" value="/tmp/consumer.log" />
+        <layout class="LoggerLayoutPattern">
+            <param name="conversionPattern" value="[%date{Y-m-d H:i:s,u}][%level][%logger][%line] %message%newline" />
+        </layout>
+    </appender>
+    <root>
+        <level value="DEBUG" />
+        <appender_ref ref="myAppender" />
+    </root>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-consumer/consumer/demo-consumer.consumer b/demo/demo-consumer/consumer/demo-consumer.consumer
new file mode 100644
index 0000000..8e007d8
--- /dev/null
+++ b/demo/demo-consumer/consumer/demo-consumer.consumer
@@ -0,0 +1,10 @@
+[consumer_config]
+p2p_mode = false
+
+[consumer_services]
+
+com.fenqile.example.DemoService[group] = *
+com.fenqile.example.DemoService[version] = 1.0.0
+
+com.fenqile.arch.dubbo.service.DemoPhpService[group] = *
+com.fenqile.arch.dubbo.service.DemoPhpService[version] = 1.0.0
\ No newline at end of file
diff --git a/demo/demo-consumer/server/Consumer.php b/demo/demo-consumer/server/Consumer.php
new file mode 100644
index 0000000..fa895d0
--- /dev/null
+++ b/demo/demo-consumer/server/Consumer.php
@@ -0,0 +1,15 @@
+<?php
+$APP_SRC_PATH = __DIR__;
+$fsofApiPath = dirname(dirname(dirname($APP_SRC_PATH))).DIRECTORY_SEPARATOR.'api'.DIRECTORY_SEPARATOR.'FSOFApi.php';
+require_once($fsofApiPath);
+FSOFApi::configure('demo-consumer', $APP_SRC_PATH);
+
+require_once('log4php/Logger.php');
+Logger::configure(dirname(dirname(__FILE__)).'/config/log4php.xml');
+date_default_timezone_set('PRC');
+
+//php框架调用php提供的服务
+$service = 'com.fenqile.example.DemoService';
+$proxy = FSOFApi::newProxy($service, 3);
+$ret = $proxy->invoke("sayHello","zhangsan");
+echo "ret:$ret".PHP_EOL;
diff --git a/demo/demo-provider/BootStrap.php b/demo/demo-provider/BootStrap.php
new file mode 100644
index 0000000..a38b939
--- /dev/null
+++ b/demo/demo-provider/BootStrap.php
@@ -0,0 +1,24 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * This file must exist and put in the project root directory,
+ * The framework automatically include files and folders at its level.
+ * If you need to include the files of other directories, please include in this file
+ */
+//require_once 'other dirname file';
\ No newline at end of file
diff --git a/demo/demo-provider/config/log4php.xml b/demo/demo-provider/config/log4php.xml
new file mode 100644
index 0000000..4916ea7
--- /dev/null
+++ b/demo/demo-provider/config/log4php.xml
@@ -0,0 +1,12 @@
+<configuration xmlns="http://logging.apache.org/log4php/">
+    <appender name="myAppender" class="LoggerAppenderFile">
+        <param name="file" value="/tmp/provider.log" />
+        <layout class="LoggerLayoutPattern">
+            <param name="conversionPattern" value="[%date{Y-m-d H:i:s,u}][%level][%logger][%line] %message%newline" />
+        </layout>
+    </appender>
+    <root>
+        <level value="INFO" />
+        <appender_ref ref="myAppender" />
+    </root>
+</configuration>
\ No newline at end of file
diff --git a/demo/demo-provider/provider/demo-provider.provider b/demo/demo-provider/provider/demo-provider.provider
new file mode 100644
index 0000000..1ed5f94
--- /dev/null
+++ b/demo/demo-provider/provider/demo-provider.provider
@@ -0,0 +1,9 @@
+[service_properties]
+owner = author
+version = 1.0.0
+group = default
+
+[service_providers]
+com.fenqile.example.DemoService[service] = DemoServiceImpl
+com.fenqile.example.DemoService[version] = 1.0.0
+com.fenqile.example.DemoService[group] = default
\ No newline at end of file
diff --git a/demo/demo-provider/server/DemoServiceImpl.php b/demo/demo-provider/server/DemoServiceImpl.php
new file mode 100644
index 0000000..77930d0
--- /dev/null
+++ b/demo/demo-provider/server/DemoServiceImpl.php
@@ -0,0 +1,18 @@
+<?php
+/**
+ * Version: 1.0.0
+ * Description: 示例程序,模拟server工程下的各个service
+ */
+
+require_once('log4php/Logger.php');
+Logger::configure(dirname(dirname(__FILE__)).'/config/log4php.xml');
+date_default_timezone_set('PRC');
+
+class DemoServiceImpl
+{
+	public function sayHello($name)
+	{
+        \Logger::getLogger(__CLASS__)->info("Hello $name");
+        return "Hello $name";
+	}
+}
diff --git a/provider/FSOFProvider.php b/provider/FSOFProvider.php
new file mode 100644
index 0000000..7eab85a
--- /dev/null
+++ b/provider/FSOFProvider.php
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider;
+
+require_once(FSOF_PROVIDER_ROOT_PATH.DIRECTORY_SEPARATOR.'FrameAutoLoader.php');
+
+//加载commom
+$fsofCommonPath = FSOF_FRAMEWORK_ROOT_PATH.DIRECTORY_SEPARATOR.'common';
+require_once($fsofCommonPath.DIRECTORY_SEPARATOR.'BootStrap.php');
+
+//加载registry
+$fsofRegistryPath = FSOF_FRAMEWORK_ROOT_PATH.DIRECTORY_SEPARATOR.'registry';
+require_once $fsofRegistryPath.DIRECTORY_SEPARATOR.'BootStrap.php';
+
+//注册顶层命名空间到自动载入器
+FrameAutoLoader::setRootNS('com\fenqile\fsof\provider', FSOF_PROVIDER_ROOT_PATH);
+FrameAutoLoader::setRootNS('com\fenqile\fsof\provider\core', FSOF_PROVIDER_ROOT_PATH.DIRECTORY_SEPARATOR.'core');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\provider\fsof', FSOF_PROVIDER_ROOT_PATH.DIRECTORY_SEPARATOR.'fsof');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\provider\shell', FSOF_PROVIDER_ROOT_PATH.DIRECTORY_SEPARATOR.'shell');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\provider\common', FSOF_PROVIDER_ROOT_PATH.DIRECTORY_SEPARATOR.'common');
+FrameAutoLoader::setRootNS('com\fenqile\fsof\provider\monitor', FSOF_PROVIDER_ROOT_PATH.DIRECTORY_SEPARATOR.'monitor');
+//provider启动时初始化consumer
+FrameAutoLoader::setRootNS('com\fenqile\fsof\consumer', FSOF_FRAMEWORK_ROOT_PATH.DIRECTORY_SEPARATOR.'consumer');
+spl_autoload_register(__NAMESPACE__.'\FrameAutoLoader::autoload');
+
+//注册全局异常捕获器
+function exceptionHandler($exception)
+{
+	$exceptionHash = array(
+    	'className' => 'Exception',
+        'message' => $exception->getMessage(),
+        'code' => $exception->getCode(),
+        'file' => $exception->getFile(),
+        'line' => $exception->getLine(),
+        'trace' => array(),
+    );
+
+	$traceItems = $exception->getTrace();
+    foreach ($traceItems as $traceItem) 
+    {
+        $traceHash = array(
+            'file' => isset($traceItem['file']) ? $traceItem['file'] : 'null',
+            'line' => isset($traceItem['line']) ? $traceItem['line'] : 'null',
+            'function' => isset($traceItem['function']) ? $traceItem['function'] : 'null',
+            'args' => array(),
+        );
+
+        if (!empty($traceItem['class'])) 
+        {
+            $traceHash['class'] = $traceItem['class'];
+        }
+
+        if (!empty($traceItem['type'])) 
+        {
+            $traceHash['type'] = $traceItem['type'];
+        }
+
+        if (!empty($traceItem['args'])) 
+        {
+            foreach ($traceItem['args'] as $argsItem) 
+            {
+                $traceHash['args'][] = \var_export($argsItem, true);
+            }
+        }
+
+        $exceptionHash['trace'][] = $traceHash;
+    }
+
+    \Logger::getLogger(__CLASS__)->error(print_r($exceptionHash, true));
+}
+set_exception_handler(__NAMESPACE__ . '\exceptionHandler');
\ No newline at end of file
diff --git a/provider/FrameAutoLoader.php b/provider/FrameAutoLoader.php
new file mode 100644
index 0000000..b5c5c48
--- /dev/null
+++ b/provider/FrameAutoLoader.php
@@ -0,0 +1,70 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider;
+
+class FrameAutoLoader
+{
+    /**
+     * 命名空间的路径
+     */
+    private static $nsPath = Array();
+
+    /**
+     * 自动载入类
+     * @param $class
+     */
+    public static function autoload($class)
+    {
+    	$frameRootPathDepth = count(explode('\\', __NAMESPACE__));
+        $root = explode('\\', trim($class, '\\'));
+        $pathDepth = count($root);
+        if($pathDepth > $frameRootPathDepth)
+        {
+        	$key = $className = $class;
+	        if($pathDepth > $frameRootPathDepth + 1)
+	        {
+	        	$root = explode('\\', trim($class, '\\'), $frameRootPathDepth + 2);
+	        	$className = $root[$frameRootPathDepth + 1];
+	        	unset($root[$frameRootPathDepth + 1]);
+	        	$key = implode($root, '\\');
+	        }
+	        else if($pathDepth == $frameRootPathDepth + 1)
+	        {
+	        	$root = explode('\\', trim($class, '\\'), $frameRootPathDepth + 1);
+	        	$className = $root[$frameRootPathDepth];
+	        	unset($root[$frameRootPathDepth]);
+	        	$key = implode($root, '\\');
+	        }
+	        
+        	if(isset(self::$nsPath[$key]))
+	        {
+	        	include_once self::$nsPath[$key] . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $className) . '.php';
+	        }
+        }
+    }
+
+    /**
+     * 设置根命名空间
+     * @param $root
+     * @param $path
+     */
+    public static function setRootNS($root, $path)
+    {
+        self::$nsPath[$root] = $path;
+    }
+}
\ No newline at end of file
diff --git a/provider/common/Console.php b/provider/common/Console.php
new file mode 100644
index 0000000..841f6fe
--- /dev/null
+++ b/provider/common/Console.php
@@ -0,0 +1,56 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider\common;
+
+class Console
+{
+    /**
+     * 改变进程的用户ID
+     * @param $user
+     */
+    public static function changeUser($user)
+    {
+		if (!function_exists('posix_getpwnam'))
+		{
+			trigger_error(__METHOD__.": require posix extension.");
+			return;
+		}
+        $user = posix_getpwnam($user);
+        if($user)
+        {
+            posix_setuid($user['uid']);
+            posix_setgid($user['gid']);
+        }
+    }
+
+    public static function setProcessName($name)
+    {
+        if (function_exists('cli_set_process_title'))
+        {
+            cli_set_process_title($name);
+        }
+        else if(function_exists('swoole_set_process_name'))
+        {
+            swoole_set_process_name($name);
+        }
+        else
+        {
+            trigger_error(__METHOD__." failed. require cli_set_process_title or swoole_set_process_name.");
+        }
+    }
+}
\ No newline at end of file
diff --git a/provider/core/app/AppAutoLoader.php b/provider/core/app/AppAutoLoader.php
new file mode 100644
index 0000000..14a983a
--- /dev/null
+++ b/provider/core/app/AppAutoLoader.php
@@ -0,0 +1,129 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider\core\app;
+
+class AppAutoLoader 
+{
+	private static $root_path = array();
+	private static $class_autoload_path = array();
+
+    /**
+     * [set_include_path 完成根目录下目录的扫描,支持多层目录嵌套]
+     * @param [type] $dir [路径]
+     * @return array
+     */
+	private static function set_include_path($dir)
+	{
+		$include_paths = array();
+		$include_paths[] = $dir;
+		
+		//读取所有的文件夹目录
+		$arr = scandir($dir);		
+		$len = count($arr);
+		for ($i=0; $i < $len; $i++) 
+		{
+			//.和..去掉
+		    if (('.' == $arr[$i]) ||  ('..' == $arr[$i]))
+            {
+                continue;
+            }
+			if(is_dir($dir.DIRECTORY_SEPARATOR.$arr[$i]))
+			{
+				$include_paths =  array_merge($include_paths, self::set_include_path($dir.DIRECTORY_SEPARATOR.$arr[$i]));
+			}
+		}
+		
+		return array_unique($include_paths);
+	}
+
+	/**
+	 * [auto_load]
+	 * @param  [type] $className [文件名]
+	 * @return [type]            [description]
+	 */
+	public static function auto_load($className)
+	{
+		$newClassName = str_replace('\\', DIRECTORY_SEPARATOR, trim($className, '\\'));
+		foreach (self::$class_autoload_path as $key => $path) 
+		{
+			$class_file = $path.DIRECTORY_SEPARATOR.$newClassName.".php";
+			if (is_file($class_file)) 
+			{
+				require_once($class_file);
+				break;
+			}
+		}
+	}
+
+	/**
+	 * [setRoot 设置root根目录,可以同时添加多个]
+	 * @param array $root [array]
+	 */
+	public static function setRoot($rootArr = array())
+	{
+		if(is_array($rootArr))
+		{
+			self::$root_path = array_merge(self::$root_path, $rootArr);
+			
+			foreach (self::$root_path as $key => $value) 
+			{
+				self::$class_autoload_path = array_merge(self::$class_autoload_path,self::set_include_path($value));
+			}
+		}
+	}
+
+	/**
+	 * [addRoot 添加root节点,可以多节点实现auto_load]
+	 * @param [type] $root [description]
+	 */
+	public static function addRoot($root)
+	{
+        \Logger::getLogger(__CLASS__)->debug('addRoot() in '.$root);
+		if(isset($root))
+		{
+			self::$root_path[] = $root;
+			foreach (self::$root_path as $key => $value)
+			{
+				self::$class_autoload_path = array_merge(self::$class_autoload_path,self::set_include_path($value));
+			}
+		}
+        \Logger::getLogger(__CLASS__)->debug('addRoot() out '.print_r(self::$class_autoload_path, true));
+	}
+
+	/**
+	 * [getFatherPath 获取父级目录路径]
+	 * @param  [type]  $path [description]
+	 * @param  integer $num  [父级的级数,默认是当前目录的上一级目录]
+	 * @return [type]        [路径字符串]
+	 */
+	public static function getFatherPath($path, $num = 1)
+	{
+		if (empty($path)) 
+		{
+			return "";
+		}
+		
+		for ($i = 0; $i < $num; $i++) 
+		{
+			$path = substr($path,0,strrpos($path ,DIRECTORY_SEPARATOR));
+		}
+		return $path;
+	}
+}
+
+spl_autoload_register(array(__NAMESPACE__ . '\AppAutoLoader','auto_load'));
\ No newline at end of file
diff --git a/provider/core/app/AppContext.php b/provider/core/app/AppContext.php
new file mode 100644
index 0000000..12f3e3b
--- /dev/null
+++ b/provider/core/app/AppContext.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider\core\app;
+
+
+final class AppContext
+{
+    private $instances = array();
+
+    private $stateless = FALSE;//默认所有服务都是有状态的,每次使用都重新new
+    
+    private $server;
+    
+    public function setStateless($stateless, $server)
+    {
+    	$this->stateless = $stateless;
+    	$this->server = $server;	
+    }
+    
+    public function isStateless()
+    {
+        return $this->stateless;
+    }
+    
+    public function getInstance($className, $params = null)
+    {
+		if($this->stateless)
+		{
+            \Logger::getLogger(__CLASS__)->debug("get stateless instance for $className");
+	        if (isset($this->instances[$className])) 
+	        {
+	            return $this->instances[$className];
+	        }
+	        
+	        if (!class_exists($className,true)) 
+	        {
+	            throw new \Exception("no class {$className}");
+	        }
+	        
+	        if (empty($params)) 
+	        {
+	            $this->instances[$className] = new $className();
+	        } 
+	        else 
+	        {
+	            $this->instances[$className] = new $className($params);
+	        }
+	        
+	        return $this->instances[$className];
+        }
+        else
+        {
+            \Logger::getLogger(__CLASS__)->debug("get new instance for $className");
+        	if (!class_exists($className,true)) 
+	        {
+	            throw new \Exception("no class {$className}");
+	        }
+	        
+        	if (empty($params)) 
+	        {
+	            return new $className();
+	        } 
+	        else 
+	        {
+	            return new $className($params);
+	        } 
+	    }
+    }
+}
\ No newline at end of file
diff --git a/provider/core/app/AppLauncher.php b/provider/core/app/AppLauncher.php
new file mode 100644
index 0000000..f2e7257
--- /dev/null
+++ b/provider/core/app/AppLauncher.php
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider\core\app;
+
+use com\fenqile\fsof\provider\fsof\FSOFProtocol;
+
+//加载Provider框架代码
+require_once(FSOF_PROVIDER_ROOT_PATH.DIRECTORY_SEPARATOR.'FSOFProvider.php');
+
+class AppLauncher
+{    
+    public static function  createApplication($appBootLoader)
+    {
+    	/**
+    	 * 执行app的初始化操作,所有初始化逻辑都在$appBootLoader中定义
+    	 * 先加载app的初始化文件,这样app的自定义autoload机制优先级高于AppLauncher
+      	**/
+    	require_once $appBootLoader;
+    	
+    	//autoload 用户的所有代码
+    	$appRoot = AppAutoLoader::getFatherPath($appBootLoader, 1);
+        AppAutoLoader::addRoot($appRoot);
+        return new FSOFProtocol();
+    }
+}
\ No newline at end of file
diff --git a/provider/core/protocol/BaseProtocol.php b/provider/core/protocol/BaseProtocol.php
new file mode 100644
index 0000000..56168eb
--- /dev/null
+++ b/provider/core/protocol/BaseProtocol.php
@@ -0,0 +1,116 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider\core\protocol;
+
+use com\fenqile\fsof\common\config\FSOFConstants;
+
+abstract class BaseProtocol implements IProtocol
+{
+	protected  $server;
+	protected  $swoole_server;
+	
+	function __construct()
+	{
+        $this->init();
+	}
+
+    abstract public function init();
+        
+    public function setServer($server) 
+    {
+        $this->server = $server;
+    }
+    
+    public function getAppConfig()
+    {
+    	return $this->server->getAppConfig();
+    }
+
+	public function getAppName()
+	{
+		return $this->server->getAppName();
+	}
+
+    public function getAppRunTimeEnv()
+    {
+    	return $this->server->getAppRunTimeEnv();
+    }
+    
+    public function onStart($server, $workerId)
+    {
+    	$this->swoole_server = $server;
+    	
+    	//监控app重加载时间
+        $this->server->getAppMonitor()->onAppReload();
+        
+        //当worker_id为0时添加定时器,驱动app监控信息上报
+//		if($workerId == 0)
+//		{
+//			$this->swoole_server->addtimer(FSOFConstants::FSOF_MONITOR_TIMER);	//5分钟监控一次数据5*60*1000
+//		}
+
+        \Logger::getLogger(__CLASS__)->debug("protocol onStart():{$workerId}");
+    }
+    
+    public function onConnect($server, $fd, $fromId)
+    {
+
+    }
+    
+    public function onReceive($server,$clientId, $fromId, $data, $reqInfo = null)
+    {
+    	
+    }
+
+    public function onClose($server, $fd, $fromId)
+    {
+
+    }
+    
+    public function onShutdown($serv, $workerId)
+    {
+    	
+    }
+
+ 	public function onTask($serv, $taskId, $fromId, $data)
+ 	{
+ 		
+ 	}
+ 	
+    public function onFinish($serv, $taskId, $data)
+    {
+    	
+    }
+    
+    public function onTimer($serv, $interval)
+    {
+        switch( $interval ) 
+        {
+            case FSOFConstants::FSOF_MONITOR_TIMER:
+            {
+            	$this->server->getAppMonitor()->uploadMonitorData();
+                break;
+            }
+        }
+    }
+    
+    public function onRequest($request, $response)
+    {
+    	
+    }
+}
\ No newline at end of file
diff --git a/provider/core/protocol/BufferedProtocol.php b/provider/core/protocol/BufferedProtocol.php
new file mode 100644
index 0000000..12fd7b5
--- /dev/null
+++ b/provider/core/protocol/BufferedProtocol.php
@@ -0,0 +1,64 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider\core\protocol;
+
+
+abstract class BufferedProtocol extends BaseProtocol
+{
+    protected $requests;
+
+   	const STATUS_FINISH = 1; //完成,进入处理流程
+    const STATUS_WAIT   = 2; //等待数据
+    const STATUS_ERROR  = 3; //错误,丢弃此包
+    
+    public function onReceive($server, $clientId, $fromId, $data, $reqInfo = null)
+    {
+    	// 检查buffer
+        $ret = $this->checkBuffer($clientId, $data);
+        \Logger::getLogger(__CLASS__)->debug("ret = ${ret}");
+
+        switch($ret)
+        {
+            case self::STATUS_ERROR:
+            	unset($this->requests[$clientId]);
+                return true;           // 错误的请求
+            case self::STATUS_WAIT:
+                return true;          //数据不完整,继续等待
+            default:
+                break;                 // 完整数据
+        }
+
+        $request = $this->requests[$clientId];
+		if (!empty($reqInfo))
+		{
+			$request->reqInfo = $reqInfo;
+		}
+        $this->server->setRequest($request);
+        $this->onOneRequest($clientId, $request);
+        unset($this->requests[$clientId]);
+    }
+
+    abstract public function checkBuffer($client_id, $data);
+
+    abstract public function onOneRequest($client_id, $request);
+    
+    public function onClose($server, $fd, $fromId)
+    {
+        unset($this->requests[$fd]);
+    }
+}
\ No newline at end of file
diff --git a/provider/core/protocol/IProtocol.php b/provider/core/protocol/IProtocol.php
new file mode 100644
index 0000000..187f1bf
--- /dev/null
+++ b/provider/core/protocol/IProtocol.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+namespace com\fenqile\fsof\provider\core\protocol;
+
+interface IProtocol
+{
+	function setServer($server);
+    function getAppConfig();
+    function onStart($server, $workerId);
+    function onConnect($server, $client_id, $from_id);
+    function onReceive($server,$client_id, $from_id, $data, $reqInfo = null);
+    function onClose($server, $client_id, $from_id);
+    function onShutdown($server, $worker_id);
+    function onTask($serv, $task_id, $from_id, $data);
+    function onFinish($serv, $task_id, $data);
+    function onTimer($serv, $interval);
+    function onRequest($request, $response);
+}
\ No newline at end of file
diff --git a/provider/core/server/BaseServer.php b/provider/core/server/BaseServer.php
new file mode 100644
index 0000000..e66c04e
--- /dev/null
+++ b/provider/core/server/BaseServer.php
@@ -0,0 +1,812 @@
... 2974 lines suppressed ...