public function testAllInOne()
 {
     // ²âÊÔ´òÓ¡µ½ÆÁÄ»
     BigpipeLog::debug('[%s:%u][%s][debug]', __FILE__, __LINE__, __FUNCTION__);
     BigpipeLog::trace('[%s:%u][%s][trace]', __FILE__, __LINE__, __FUNCTION__);
     BigpipeLog::notice('[%s:%u][%s][notice]', __FILE__, __LINE__, __FUNCTION__);
     BigpipeLog::monitor('[%s:%u][%s][monitor]', __FILE__, __LINE__, __FUNCTION__);
     BigpipeLog::warning('[%s:%u][%s][warning]', __FILE__, __LINE__, __FUNCTION__);
     BigpipeLog::fatal('[%s:%u][%s][fatal]', __FILE__, __LINE__, __FUNCTION__);
     // ²âÊÔ²»Êä³ö´òÓ¡ÐÅÏ¢log configure
     $conf = new BigpipeLogConf();
     $conf->severity = BigpipeLogSeverity::FATAL;
     $conf->disable_ostream = true;
     $fatal_log = sprintf('[%s:%u][%s][fatal message]', __FILE__, __LINE__, __FUNCTION__);
     $warning_Log = sprintf('[%s:%u][%s][warning]', __FILE__, __LINE__, __FUNCTION__);
     $this->assertTrue(BigpipeLog::init($conf));
     BigpipeLog::fatal('%s', $fatal_log);
     $msg = BigpipeLog::get_last_error_message();
     BigpipeLog::warning('%s', $warning_Log);
     $this->assertEquals($msg, BigpipeLog::get_last_error_message());
     $new_fatal_log = sprintf('[%s:%u][%s][fatal new message]', __FILE__, __LINE__, __FUNCTION__);
     $this->assertTrue($msg == BigpipeLog::get_last_error_message());
     // ²âÊÔclose
     BigpipeLog::close();
 }
 /**
  * 生成unique id
  * @return string unique id
  */
 public static function get_session_id($pipe_name)
 {
     $hostip = '127.0.0.0';
     // default host ip
     ##$host = gethostname(); // can not be used before php 5.3
     $host = php_uname('n');
     if (false === $host) {
         BigpipeLog::warning('[%s:%u][%s][no host name. use default value: %s]', __FILE__, __LINE__, __FUNCTION__, $hostip);
     } else {
         $hostip = gethostbyname($host);
         if (false === $hostip) {
             BigpipeLog::warning('[%s:%u][%s][no ip on host use default local ip: 127.0.0.0][host name:%s]', __FILE__, __LINE__, __FUNCTION__, $host);
         }
     }
     // session格式为
     // hostip + 精确得到1天半的时间戳 + pid + pipe_name
     $timestamp = time() >> 17;
     // 精确到1天半的时间戳
     $uid = sprintf('%s-%u-%u-%s', $hostip, $timestamp, getmypid(), $pipe_name);
     return $uid;
 }
 private function _load_meta($meta_conf)
 {
     // 检查必须的配置项
     if (false === isset($meta_conf['meta_host']) || false === isset($meta_conf['root_path']) || false === isset($meta_conf['zk_recv_timeout'])) {
         BigpipeLog::fatal('[queue client configure][missing mandatory meta configure]');
         return false;
     }
     $this->meta = $meta_conf;
     return true;
 }
function run_tuning_sub($seq, $pid, $sp, $max_count)
{
    // 初始化log配置
    $log_conf = new BigpipeLogConf();
    $log_conf->file = sprintf('subscribe-%u-%u.php', $seq, $pid);
    if (BigpipeLog::init($log_conf)) {
        //echo "[Success] [open subscribe log]\n\n";
        //print_r($log_conf);
        //echo '\n';
    } else {
        echo '[Failure] [open subscribe log]\\n';
        print_r($log_conf);
        echo '\\n';
    }
    // subscriber的configure
    $conf = new BigpipeConf();
    $conf_dir = './conf';
    $conf_file = './for-tuning.conf';
    if (false === bigpipe_load_file($conf_dir, $conf_file, $conf)) {
        echo "[failure][when load configure]\n";
        return;
    }
    // 订阅参数
    $pipe_name = 'pipe2';
    $pipelet_id = $pid;
    //
    $start_point = $sp;
    $token = 'token';
    $peek_time_ms = 200;
    $suffix_str = sprintf('-%u-%u', $seq, $pid);
    $file_sub_succ = fopen('./sub_succ-' . $suffix_str . '.csv', 'w+');
    $file_sub_wait = fopen('./sub_wait-' . $suffix_str . '.csv', 'w+');
    $file_sub_fail = fopen('./sub_fail-' . $suffix_str . '.csv', 'w+');
    $sub = new BigpipeSubscriber();
    if ($sub->init($pipe_name, $token, $pipelet_id, $start_point, $conf)) {
        echo '[Success][init subscriber]\\n';
        $count = 0;
        $failure = 0;
        $success = 0;
        $wait_cnt = 0;
        $run_time_str = null;
        $total_start = BigpipeUtilities::get_time_us();
        while ($success < $max_count && $wait_cnt < $max_count && $failure < $max_count) {
            $pret = $sub->peek($peek_time_ms);
            if (BigpipeErrorCode::READABLE == $pret) {
                $msg = $sub->receive();
                if (false === $msg) {
                    $failure++;
                } else {
                    if (true === $msg->is_last_msg) {
                        $end_time = BigpipeUtilities::get_time_us();
                        if (0 == strncmp('timestamp:', $msg->content, 10)) {
                            $t_str = substr($msg->content, 10);
                            $run_time_str = sprintf("%u,%u,%s,%u\n", $pipelet_id, $msg->msg_id, $t_str, $end_time);
                            fwrite($file_sub_succ, $run_time_str);
                        }
                    }
                    $success++;
                }
            } else {
                if (BigpipeErrorCode::UNREADABLE == $pret) {
                    $wait_cnt++;
                } else {
                    $failure++;
                }
            }
            $count++;
        }
        $total_end = BigpipeUtilities::get_time_us();
        printf("[Leave][seq:%u][count:%u][succ:%u][fail:%u][wait:%u]\n\n", $seq, $count, $success, $failure, $wait_cnt);
        $avg = (double) ($total_end - $total_start) / (double) (1000 * $count);
        printf("[Subscriber][seq:%u][avg_time:%f(ms)]\n", $seq, $avg);
    } else {
        echo '[Failure][init subscribe]\\n';
    }
    $sub->uninit();
    BigpipeLog::close();
}
 /**
  * 从zk中读取一个node并,反序列化node value数组
  * @return mixed value of a node. <p>
  *         return value converted into associative arrays on success. <p>
  *         return false on failure
  */
 public function deserialize($buff)
 {
     // unpack head
     $this->_content = $buff;
     $head_arr = unpack("C1ver/C1len/S1flags/L1bdlen", $this->_content);
     $this->_version = $head_arr['ver'];
     $this->_length = $head_arr['len'];
     $this->_flags = $head_arr['flags'];
     $this->_body_len = $head_arr['bdlen'];
     $obj = json_decode(substr($this->_content, $this->_length), true);
     if (null === $obj) {
         BigpipeLog::warning("[%s:%u][%s][fail to decode meta node][ver:%d][flags:%u][len:%u]", __FILE__, __LINE__, __FUNCTION__, $this->_version, $this->_flags, $this->_body_len);
         $obj = false;
     } else {
         BigpipeLog::notice("[%s:%u][%s][meta node header][ver:%d][flags:%u][len:%u]", __FILE__, __LINE__, __FUNCTION__, $this->_version, $this->_flags, $this->_body_len);
     }
     return $obj;
 }
 public static function get_private_method(&$obj, $method_name)
 {
     $ret = version_compare(PHP_VERSION, '5.3.0', '>=') ? true : false;
     if (true === $ret) {
         // 使用5.3.0的功能
         $method = new ReflectionMethod($obj, $method_name);
         $method->setAccessible(true);
         // >=php5.3可用
         return $method;
     } else {
         BigpipeLog::warning('unsported function in PHP < 5.3.0');
     }
     return $ret;
 }
 /**
  * 向终端发送CONNECT命令
  */
 private function _stomp_connect()
 {
     // 发送CONNECT
     $cmd = new BStompConnectFrame();
     $cmd->role = $this->role;
     $cmd->session_id = $this->session_id;
     $cmd->topic_name = $this->topic_name;
     if (!$this->send($cmd)) {
         BigpipeLog::warning("[stomp connect error]");
         return false;
     }
     // 接收CONNECTED
     $res_body = $this->receive();
     if (null === $res_body) {
         BigpipeLog::warning("[stomp receive connected error]");
         return false;
     }
     // parse CONNECTED
     $ack = new BStompConnectedFrame();
     if (!$ack->load($res_body)) {
         BigpipeLog::warning('[stomp parse connected frame error][cmd_type:' . $ack->command_type . '][msg:' . $ack->last_error_message() . ']');
         return false;
     }
     // 更新session id和session message id
     $this->session_id = $ack->session_id;
     $this->session_message_id = $ack->session_message_id + 1;
     return true;
 }
            echo "[expected:{$max_msg_count}][actual:{$msg_count}]\n";
            continue;
            // 打包失败,退出
        }
        // 当消息添加完后,使用publisher的send接口,发布数据
        // send成功,返回的pub_result中包含了pipelet_id和pipelet_msg_id
        // pipelet_msg_id唯一标识了本个数据包在pipelet中的位置
        // send失败,用户可以选择继续send,这时send接口内部会更新状态,尝试重新发布
        $pub_result = $pub->send($msg_package);
        if (false === $pub_result) {
            echo "[fail to publish message package][count:{$count}]\n";
            break;
            // 出错便停止
        } else {
            // write result to file
            $session = TestUtilities::get_private_var($pub, '_session');
            $ret_str = sprintf("%d,%u,%u,%u,%s\n", $pub_result->error_no, $pub_result->pipelet_id, $pub_result->pipelet_msg_id, $pub_result->session_msg_id, $session);
            fwrite($pub_file, $ret_str);
            $succeed++;
        }
        echo "[Publisher][count:{$count}][success:{$succeed}]====\n";
        // 当发布结束后,使用uninit强制清空发布状态
        $pub->uninit();
    } else {
        echo "[Failure][init publisher]\n";
    }
    $count++;
}
// end of while
BigpipeLog::close();
 public function execute()
 {
     $minute_partition = parent::$arrAppConf['minute_partition'];
     $bigpipeLogConf = new BigpipeLogConf();
     $bigpipeLogConf->file = 'subscribe.php';
     if (BigpipeLog::init($bigpipeLogConf)) {
         echo "[Success] [open subscribe log]\n";
         //			print_r($bigpipeLogConf);
     } else {
         echo '[Failure] [open subscribe log]\\n';
         print_r($bigpipeLogConf);
         echo "\n";
     }
     $conf = new BigpipeConf();
     $conf_dir = ETL_CONF . parent::$app;
     $conf_file = './php-api.conf';
     if (false === bigpipe_load_file($conf_dir, $conf_file, $conf)) {
         echo "[failure][when load configure]\n";
         exit;
     }
     $pipeName = parent::$arrAppConf['pipe_name'];
     $pipelet = parent::$pipelet;
     $token = parent::$arrAppConf['token'];
     $peekTimeMs = parent::$arrAppConf['peek_time_ms'];
     $messageIdFile = ETL_DATA . parent::$app . "/message_pipelet_" . parent::$pipelet . ".flag";
     $startPoint = file_get_contents($messageIdFile);
     if ($startPoint == false) {
         $startPoint = -1;
     } else {
         if (trim($startPoint) != "-2") {
             $startPoint = intval(trim($startPoint)) + 1;
         }
     }
     $sub = new BigpipeSubscriber();
     if ($sub->init($pipeName, $token, $pipelet, $startPoint, $conf)) {
         $lastPartition = 0;
         while (true) {
             $pret = $sub->peek($peekTimeMs);
             if (BigpipeErrorCode::READABLE == $pret) {
                 $msg = $sub->receive();
                 if (false == $msg) {
                     echo "[Receive][error]\n";
                     continue;
                 } else {
                     //						echo $msg->msg_id . "\t" . $msg->seq_id. "\n" ;
                     $arrMsgContent = mc_pack_pack2array($msg->content);
                     //cut
                     $arrContent = cut($arrMsgContent['body']);
                     //map
                     $objEvent = new Event();
                     foreach (parent::$arrMap as $map) {
                         $arrParams = array();
                         foreach ($map['in'] as $in) {
                             $arrParams['in'][$in] = $arrContent[$in];
                         }
                         foreach ($map['out'] as $out) {
                             $arrParams['out'][$out] = null;
                         }
                         $hook_func_callback = $map['hook'];
                         $res = call_user_func($hook_func_callback, &$arrParams);
                         if ($res === true) {
                             foreach ($arrParams['out'] as $key => $value) {
                                 $objEvent->arrEvent[$key] = $value;
                             }
                             foreach ($arrParams['in'] as $key => $value) {
                                 unset($arrContent[$key]);
                             }
                         }
                     }
                     $objEvent->arrEvent['event_loginfo'] = common_loginfo($arrContent);
                     //write to data
                     $date = sprintf("%s%s%s", $objEvent->arrEvent['event_year'], $objEvent->arrEvent['event_month'], $objEvent->arrEvent['event_dayofmonth']);
                     list($hour, $minute, $second) = explode(":", $objEvent->arrEvent['event_time'], 3);
                     $partition = $date . $hour . sprintf("%02d", intval($minute / parent::$arrAppConf['minute_partition']) * parent::$arrAppConf['minute_partition']);
                     $dataFile = ETL_DATA . parent::$app . "/" . parent::$app . "_" . parent::$pipelet . "_{$partition}";
                     $strEvent = "";
                     foreach ($objEvent->arrEvent as $item) {
                         $item = str_replace("", "", $item);
                         $item = str_replace("\n", "", $item);
                         if ($strEvent == "") {
                             $strEvent .= $item;
                         } else {
                             $strEvent .= "" . $item;
                         }
                     }
                     $strEvent .= "\n";
                     file_put_contents($dataFile, $strEvent, FILE_APPEND | LOCK_EX);
                     $fpMessageId = fopen($messageIdFile, "w");
                     fwrite($fpMessageId, $msg->msg_id);
                     fclose($fpMessageId);
                 }
             } else {
                 if (BigpipeErrorCode::UNREADABLE == $pret) {
                     sleep(30);
                 } else {
                     echo "[Peek][Error][ret:{$pret}]\n";
                 }
             }
         }
     } else {
         echo '[Failure][init subscribe]\\n';
     }
     $sub->uninit();
     BigpipeLog::close();
 }
 /**
  * Uninitialize the meta on meta agent
  * @param $meta_name : string of meta name
  * @return void type
  */
 private function _uninit_meta($meta_name)
 {
     if (null == $this->meta_name) {
         return;
         // 不需要释放meta
     }
     // create uninit_meta_command
     $cmd = new UninitMetaFrame();
     $cmd->meta_name = $this->meta_name;
     // send
     $res_body = $this->_request($cmd);
     if (null === $res_body) {
         $this->meta_name = null;
         BigpipeLog::warning('[uninit_meta error][%s][%s]', $this->last_error_message, $cmd->last_error_message());
         $this->last_error_message = "_uninit_meta no ack";
         return;
     }
     // parse ack
     $ack = new UninitMetaAckFrame();
     if (!$ack->load($res_body)) {
         $this->last_error_message = '_uninit_meta error ack';
         $this->meta_name = null;
         BigpipeLog::warning('[%s:%u][%s][ack error][%s][%s]', __FILE__, __LINE__, __FUNCTION__, $this->last_error_message, $cmd->last_error_message());
         return;
     }
     $this->meta_name = null;
 }
 /**
  * List the children of the given path, i.e. the name of the directories
  * within the current node, if any
  * @param string $path the path to the node
  * @return array the subpaths within the given node
  */
 public function get_children($path)
 {
     if (false === $this->_inited) {
         BigpipeLog::warning("[%s:%u][%s][uninited]", __FILE__, __LINE__, __FUNCTION__);
         return false;
     }
     if (strlen($path) > 1 && preg_match('@/$@', $path)) {
         // remove trailing /
         $path = substr($path, 0, -1);
     }
     return $this->_zk->getChildren($path);
 }
 /**
  * Check if there is a frame to read
  * @param $timeo: 用户指定的超时等待值,如果无指定则读取配置(单位:毫秒)
  * @return number
  */
 public function is_readable($timeo_ms)
 {
     if (empty($timeo_ms) || $timeo_ms <= 0) {
         // 参数错误
         BigpipeLog::warning("[is_readable][invalid parameter]");
         return BigpipeErrorCode::INVALID_PARAM;
     }
     $timeo_s = floor($timeo_ms / 1000);
     $timeo_us = $timeo_ms % 1000 * 1000;
     $ret = $this->_socket->is_readable($timeo_s, $timeo_us);
     if (c_socket::ERROR == $ret) {
         $msg = $this->_socket->__get('socket_error');
         BigpipeLog::warning("[peek to read error][{$msg}]");
         $ret = BigpipeErrorCode::ERROR_CONNECTION;
     } else {
         if (c_socket::TIMEOUT == $ret) {
             BigpipeLog::warning("[peek to read time out]");
             $ret = BigpipeErrorCode::TIMEOUT;
         } else {
             $ret = BigpipeErrorCode::READABLE;
         }
     }
     return $ret;
 }
 /**
  * 更新meta信息, 记录重试次数
  * @return boolean
  */
 private function _failover()
 {
     if ($this->_fo_count >= $this->_max_fo_cnt) {
         // 重置failover
         BigpipeLog::fatal("[_failover][can not do more][max_cnt:%d]", $this->_max_fo_cnt);
         $this->_fo_sleep_time = 0;
         $this->_fo_count = 0;
         return false;
     }
     if (0 == $this->_fo_sleep_time) {
         // php中只有微秒级的usleep和秒级的sleep
         // 目前只有当start时才会进入这个分支。
         // 这时我们会跳过failover
         $this->_fo_sleep_time = BigpipeCommonDefine::INIT_FO_SLEEP_TIME * 1000;
     } else {
         usleep($this->_fo_sleep_time);
     }
     // usleep($this->_fo_sleep_time);
     $this->_fo_count++;
     $this->_fo_sleep_time *= 2;
     // increase failover sleep time
     if ($this->_fo_sleep_time > BigpipeCommonDefine::MAX_FO_SLEEP_TIME) {
         // failover sleep time不能无限制增长
         $this->_fo_sleep_time = BigpipeCommonDefine::MAX_FO_SLEEP_TIME;
     }
     // 通过meta跟新stripe
     $broker = $this->_update_meta();
     if (false === $broker) {
         BigpipeLog::fatal("[_failover][can not update meta from meta agent]");
         return false;
     }
     // 连接broker
     $pub_dest = array("socket_address" => $broker['ip'], "socket_port" => $broker['port'], "socket_timeout" => $this->_conn_timeo);
     $this->_stomp_adapter->set_destination($pub_dest);
     $this->_stomp_adapter->role = BStompRoleType::PUBLISHER;
     $this->_stomp_adapter->topic_name = $broker['stripe'];
     $this->_stomp_adapter->session_id = $this->_session_id;
     // 发布时session不变
     if ($this->_stomp_adapter->connect()) {
         BigpipeLog::debug("[Success][connected on broker][ip:%s][port:%u]", $broker['ip'], $broker['port']);
         BigpipeLog::debug('[session message id][%u]', $this->_stomp_adapter->session_message_id);
         $this->_broker = $broker;
         return true;
     }
     return false;
     // 连接失败
 }
 /**
  * 从read buffer读取一个message package
  * @return false on failure or BigpageMessage on success
  */
 private function _receive()
 {
     $obj = false;
     do {
         $res_body = $this->_stomp_adapter->receive();
         if (null === $res_body) {
             continue;
             // 直接重订阅
         }
         // 接收成功,读取数据
         $msg = new BStompMessageFrame();
         if (!$msg->load($res_body)) {
             // message包问题
             BigpipeLog::warning('[%s:%u][%s][receive msg error][%s]', __FILE__, __LINE__, __FUNCTION__, $msg->last_error_message());
             continue;
         }
         // 读取msg包
         if (-1 != $this->_pipelet_msg_id && $msg->topic_message_id < $this->_pipelet_msg_id) {
             BigpipeLog::warning('[%s:%u][%s][received different start point error][recv: %u][req: %u]', __FILE__, __LINE__, __FUNCTION__, $msg->topic_message_id, $this->_pipelet_msg_id);
             continue;
         }
         $msg_body = $msg->message_body;
         if (empty($msg_body) || false === $msg_body) {
             continue;
             // 接收message失败,failover
         }
         // message 接收成功,返回ack
         if (BStompClientAckType::AUTO == $this->_client_ack_type) {
             // 发送ack包
             $ack = new BStompAckFrame();
             $ack->receipt_id = $msg->receipt_id;
             $ack->topic_message_id = $msg->topic_message_id;
             $ack->destination = $msg->destination;
             $ack->ack_type = BStompIdAckType::TOPIC_ID;
             if (!$this->_stomp_adapter->send($ack)) {
                 // message接收成功,但是ack发送失败,可以不用理会
                 // 因为下次receive时,会进入failover
                 BigpipeLog::warning('[%s:%u][%s][fail to ack message]', __FILE__, __LINE__, __FUNCTION__);
             }
         }
         // 处理message
         if ($this->_enable_checksum) {
             $sign = creat_sign_mds64($msg_body);
             if ($sign[2] != $msg->cur_checksum) {
                 // checksum校验失败, 进入failover
                 BigpipeLog::warning('[%s:%u][%s][message package checksum error][orig:%u][curr:%u][name:%s][msg_id:%u]', __FILE__, __LINE__, __FUNCTION__, $msg->cur_checksum, $sign[2], $this->_get_stripe_name(), $msg->topic_message_id);
                 continue;
             }
         }
         if (!$this->_package->load($msg_body, $msg->topic_message_id)) {
             // 接收的包有问题, 进入failover
             BigpipeLog::warning('[%s:%u][%s][message package error][name:%s][msg_id:%u]', __FILE__, __LINE__, __FUNCTION__, $this->_get_stripe_name(), $msg->topic_message_id);
             continue;
         }
         $obj = $this->_package->pop();
         // 必须能成功取一条message
         if (false === $obj) {
             // 包中的内容有问,进入failover
             BigpipeLog::warning('[%s:%u][%s][empty message package][name:%s][msg_id:%u]', __FILE__, __LINE__, __FUNCTION__, $this->_get_stripe_name(), $msg->topic_message_id);
             continue;
         }
         $this->_active();
         // 设置活跃状态
         $this->_pipelet_msg_id = $msg->topic_message_id + 1;
         if ($this->_get_end_pos() < $this->_pipelet_msg_id) {
             // 已接收到stripe末尾,更换新stripe
             // 主动更新订阅, 如果更新失败也没关系,下次receive时可以处理
             // 这里进入flush_subscribe不需要sleep
             $this->_fo_sleep_time = 0;
             if ($this->_flush_subscribe()) {
                 $this->_active();
                 //
             }
         }
         break;
         // 成功收到message 跳出循环
     } while ($this->_flush_subscribe());
     return $obj;
 }
function run_tuning_pub($seq, $pid, $max_cnt, $one_msg)
{
    // 初始化log配置
    $log_conf = new BigpipeLogConf();
    $log_conf->file = sprintf('publisher-%u-%u.log', $seq, $pid);
    if (BigpipeLog::init($log_conf)) {
        //echo '[Success] [open meta agent log]\n';
        //print_r($log_conf);
        //echo '\n';
    } else {
        echo "[Failure] [open meta agent log]\n";
        print_r($log_conf);
        echo "\n";
        return;
    }
    // subscriber的configure
    $conf = new BigpipeConf();
    $conf_dir = './conf';
    $conf_file = './for-tuning.conf';
    if (false === bigpipe_load_file($conf_dir, $conf_file, $conf)) {
        echo "[failure][when load configure]\n";
        return;
    }
    // 发布参数
    $pipe_name = 'pipe2';
    //$pipelet_id = 1; // 加1在哪里做好呢?
    $token = 'token';
    $partitioner = new TestPubPartitioner($pid);
    // 生成一个1K左右的包
    $max_msg_count = 12;
    // 500k
    $msg = null;
    $the_one = sprintf("[case:%u]\n", $seq);
    $uid = BigpipeUtilities::get_uid();
    $msg_package = new BigpipeMessagePackage();
    $msg_count = 0;
    while ($msg_count++ < $max_msg_count) {
        $msg = sprintf("[php-api-test][bigpipe_comlog_pvt_mm][uid:%s][package:%u][seq:%u]\n", $uid, 0, $msg_count);
        if (true === $one_msg) {
            $the_one .= $msg;
        } else {
            if (!$msg_package->push($msg)) {
                echo "[fail to pack message]{$msg}\n";
                break;
                // 退出
            }
        }
    }
    // end of add message to package
    if (true == $one_msg) {
        if (!$msg_package->push($the_one)) {
            echo "[fail to pack message]{$the_one}\n";
            return;
            // 退出
        }
    }
    // 定义测试中发包条数
    $max_package_count = $max_cnt;
    echo "\n\n[Publish {$max_package_count} packages]\n\n";
    $pub_file_name = sprintf('./pub-timer-%u-%u.csv', $seq, $pid);
    $pub_file = fopen($pub_file_name, 'w+');
    $pub = new BigpipePublisher();
    $stat = array(0 => 0, 1 => 0, 2 => 0);
    if ($pub->init($pipe_name, $token, $partitioner, $conf)) {
        echo "[Success][init publisher]\n\n";
        $count = 0;
        $succeed = 0;
        $total_start = BigpipeUtilities::get_time_us();
        $is_first = true;
        printf("[case:%u][start:%u]\n\n", $seq, $total_start);
        while ($count < $max_package_count) {
            $count++;
            //$max_msg_count = rand(1, $max_package_message_count);
            //echo "[Pack $max_msg_count messages to package <$count>]\n";
            // if ($msg_count != $max_msg_count + 1)
            // {
            //     echo "[expected:$max_msg_count][actual:$msg_count]\n";
            //     continue; // 打包失败,退出
            // }
            $start_time = BigpipeUtilities::get_time_us();
            $msg_package->push(sprintf('timestamp:%u', $start_time));
            // 加入时间戳
            $pub_result = $pub->send($msg_package);
            $end_time = BigpipeUtilities::get_time_us();
            if (false === $pub_result) {
                //echo "[fail to publish message package][count:$count]\n";
                //break; // 出错便停止
            } else {
                // write result to file
                //$ret_str = sprintf("%d,%u,%u,%u\n",
                //                   $pub_result->error_no,
                //                   $pub_result->pipelet_id,
                //                   $pub_result->pipelet_msg_id,
                //                   $pub_result->session_msg_id);
                //fwrite($pub_file, $ret_str);
                if (true == $is_first) {
                    printf('[%u][%u]\\n', $pub_result->pipelet_id, $pub_result->pipelet_msg_id);
                    $is_first = false;
                }
                $succeed++;
            }
            $msg_package->pop();
            // 弹出时间戳
            $t = (double) ($end_time - $start_time) / 1000;
            $t_str = sprintf("%u\n", $t);
            fwrite($pub_file, $t_str);
        }
        $total_end = BigpipeUtilities::get_time_us();
        echo "[Publisher][seq:{$seq}][count:{$count}][success:{$succeed}]====\n";
        $avg = (double) ($total_end - $total_start) / (double) (1000 * $max_package_count);
        printf("\n[Publisher][case:%u][avg_time:%f(ms)]\n", $seq, $avg);
    } else {
        echo '[Failure][init publisher]\\n';
    }
    $pub->uninit();
    BigpipeLog::close();
}
 /**
  * 将message package 写入buffer<p>
  * @param binary $buff: 传入一个buffer的引用
  * @return true on success or false on failure
  */
 public function store(&$buff)
 {
     if ($this->is_empty()) {
         BigpipeLog::warning('[store error][empty message package]');
         return false;
     }
     $buff .= pack("L1", $this->_count);
     $buff .= $this->_data;
     return true;
 }
 /**
  * 从config array中读取配置<p>
  * 不支持嵌套config array, 既config中嵌套config array
  * @param array $conf_arr
  * @return true on success or false on failure
  */
 protected static function _array_to_object($conf_arr, &$elem)
 {
     try {
         $obj = new ReflectionClass($elem);
         $fields = $obj->getProperties();
         foreach ($fields as $fld) {
             if (isset($conf_arr[$fld->name])) {
                 $val = $conf_arr[$fld->name];
                 if (true === is_array($val)) {
                     // 不允许用本函数给配置项赋一个array
                     BigpipeLog::warning('[%s:%u][%s][can set an array to the config element][name:%s]', __FILE__, __LINE__, __FUNCTION__, $fld->name);
                     return false;
                 } else {
                     $fld->setValue($elem, $val);
                 }
             } else {
                 // 检查是否有默认配置
                 $val = $fld->getValue($elem);
                 if (null === $val) {
                     // 配置没有默认值,必须在配置文件里给出
                     BigpipeLog::warning('[%s:%u][%s][missing configure item][name:%s]', __FILE__, __LINE__, __FUNCTION__, $fld->name);
                     return false;
                 }
             }
             // end of check defulat value
         }
         // end of traverse each fields of 'this' object
     } catch (Exception $e) {
         BigpipeLog::warning('[%s:%u][%s][fail to load configure][error message:%s]', __FILE__, __LINE__, __FUNCTION__, $e->getMessage());
         return false;
     }
     return true;
 }
 /**
  * 打印日志
  * @param BigpipeLogSeverity $severity
  * @param array $args
  */
 private static function log($severity, $args)
 {
     if (self::$_severity < $severity) {
         // 跳过低级别
         return;
     }
     $log_str = null;
     $num_args = count($args);
     if (1 < $num_args) {
         $format = array_shift($args);
         $log_str = vsprintf($format, $args);
     } else {
         if (1 == $num_args) {
             $log_str = vsprintf('%s', $args[0]);
         } else {
             $log_str = "[empty log args]";
         }
     }
     // [严重性][时间]
     $out_str = sprintf("[%s]%s\n", BigpipeLogSeverity::to_string($severity), $log_str);
     self::$_last_error_message = $out_str;
     //         else
     //         {
     //             fwrite(self::$_logfile, $out_str);
     //         }
 }
 /**
  *  从传入buff中读取command type
  * @param binary string $buff:传入协议流
  * @return int32_t command type on success or UNKNOWN_TYPE on failure
  */
 public static function get_command_type($buff)
 {
     if (2 > strlen($buff)) {
         BigpipeLog::warning('[fail to get command type]');
         return MetaAgentFrameType::UNKNOWN_TYPE;
     }
     $ai = unpack("l1int", $buff);
     $type = $ai["int"];
     return $type;
 }
 *
 * Copyright (c) 2009 Baidu.com, Inc. All Rights Reserved
 *
 **************************************************************************/
/**
 * @file: TestBigpipeStompAdapter.php
 * @brief: 测试TestBigpipeStompAdapter
 **/
require_once dirname(__FILE__) . '/../frame/MetaAgentAdapter.class.php';
require_once dirname(__FILE__) . '/../frame/BigpipeStompAdapter.class.php';
require_once dirname(__FILE__) . '/../frame/bigpipe_configures.inc.php';
require_once dirname(__FILE__) . '/../frame/BigpipeLog.class.php';
require_once dirname(__FILE__) . '/../frame/bigpipe_utilities.inc.php';
// 初始化log配置
$log_conf = new BigpipeLogConf();
if (BigpipeLog::init($log_conf)) {
    echo '[Success] [open meta agent log]\\n';
    print_r($log_conf);
    echo '\\n';
} else {
    echo '[Failure] [open meta agent log]\\n';
    print_r($log_conf);
    echo '\\n';
}
// 准备meta agent
$meta_conf = new BigpipeMetaConf();
$meta_conf->meta_host = '10.218.32.11:2181,10.218.32.20:2181,10.218.32.21:2181,10.218.32.22:2181,10.218.32.23:2181';
$meta_conf->root_path = '/bigpipe_pvt_cluster3';
$agent_conf = new MetaAgentConf();
$agent_conf->meta = $meta_conf->to_array();
$agent_conf->agents = array(array("socket_address" => "10.46.46.54", "socket_port" => 8021, "socket_timeout" => 300));
 /**
  * 检查路径下的node是否存在,如不存在打印错误日志
  * @param string $node_path : node path in meta
  * @return true on success or false on failure
  */
 private function _exists($node_path)
 {
     if (false === $this->_zk->exists($node_path)) {
         BigpipeLog::warning("[invalid meta node][%s]", $node_path);
         return false;
     }
     return true;
 }