winlin

for #319, support signal to persistence config

@@ -46,6 +46,7 @@ using namespace std; @@ -46,6 +46,7 @@ using namespace std;
46 #include <srs_kernel_file.hpp> 46 #include <srs_kernel_file.hpp>
47 #include <srs_app_utility.hpp> 47 #include <srs_app_utility.hpp>
48 #include <srs_core_performance.hpp> 48 #include <srs_core_performance.hpp>
  49 +#include <srs_kernel_file.hpp>
49 50
50 using namespace _srs_internal; 51 using namespace _srs_internal;
51 52
@@ -240,6 +241,97 @@ int SrsConfDirective::parse(SrsConfigBuffer* buffer) @@ -240,6 +241,97 @@ int SrsConfDirective::parse(SrsConfigBuffer* buffer)
240 return parse_conf(buffer, parse_file); 241 return parse_conf(buffer, parse_file);
241 } 242 }
242 243
  244 +int SrsConfDirective::persistence(SrsFileWriter* writer, int level)
  245 +{
  246 + int ret = ERROR_SUCCESS;
  247 +
  248 + static char SPACE = SRS_CONSTS_SP;
  249 + static char SEMICOLON = SRS_CONSTS_SE;
  250 + static char LF = SRS_CONSTS_LF;
  251 + static char LB = SRS_CONSTS_LB;
  252 + static char RB = SRS_CONSTS_RB;
  253 + static const char* INDENT = " ";
  254 +
  255 + // for level0 directive, only contains sub directives.
  256 + if (level > 0) {
  257 + // indent by (level - 1) * 4 space.
  258 + for (int i = 0; i < level - 1; i++) {
  259 + if ((ret = writer->write((char*)INDENT, 4, NULL)) != ERROR_SUCCESS) {
  260 + return ret;
  261 + }
  262 + }
  263 +
  264 + // directive name.
  265 + if ((ret = writer->write((char*)name.c_str(), (int)name.length(), NULL)) != ERROR_SUCCESS) {
  266 + return ret;
  267 + }
  268 + if (!args.empty() && (ret = writer->write((char*)&SPACE, 1, NULL)) != ERROR_SUCCESS) {
  269 + return ret;
  270 + }
  271 +
  272 + // directive args.
  273 + for (int i = 0; i < (int)args.size(); i++) {
  274 + std::string& arg = args.at(i);
  275 + if ((ret = writer->write((char*)arg.c_str(), (int)arg.length(), NULL)) != ERROR_SUCCESS) {
  276 + return ret;
  277 + }
  278 + if (i < (int)args.size() - 1 && (ret = writer->write((char*)&SPACE, 1, NULL)) != ERROR_SUCCESS) {
  279 + return ret;
  280 + }
  281 + }
  282 +
  283 + // native directive, without sub directives.
  284 + if (directives.empty()) {
  285 + if ((ret = writer->write((char*)&SEMICOLON, 1, NULL)) != ERROR_SUCCESS) {
  286 + return ret;
  287 + }
  288 + }
  289 + }
  290 +
  291 + // persistence all sub directives.
  292 + if (level > 0) {
  293 + if (!directives.empty()) {
  294 + if ((ret = writer->write((char*)&SPACE, 1, NULL)) != ERROR_SUCCESS) {
  295 + return ret;
  296 + }
  297 + if ((ret = writer->write((char*)&LB, 1, NULL)) != ERROR_SUCCESS) {
  298 + return ret;
  299 + }
  300 + }
  301 +
  302 + if ((ret = writer->write((char*)&LF, 1, NULL)) != ERROR_SUCCESS) {
  303 + return ret;
  304 + }
  305 + }
  306 +
  307 + for (int i = 0; i < (int)directives.size(); i++) {
  308 + SrsConfDirective* dir = directives.at(i);
  309 + if ((ret = dir->persistence(writer, level + 1)) != ERROR_SUCCESS) {
  310 + return ret;
  311 + }
  312 + }
  313 +
  314 + if (level > 0 && !directives.empty()) {
  315 + // indent by (level - 1) * 4 space.
  316 + for (int i = 0; i < level - 1; i++) {
  317 + if ((ret = writer->write((char*)INDENT, 4, NULL)) != ERROR_SUCCESS) {
  318 + return ret;
  319 + }
  320 + }
  321 +
  322 + if ((ret = writer->write((char*)&RB, 1, NULL)) != ERROR_SUCCESS) {
  323 + return ret;
  324 + }
  325 +
  326 + if ((ret = writer->write((char*)&LF, 1, NULL)) != ERROR_SUCCESS) {
  327 + return ret;
  328 + }
  329 + }
  330 +
  331 +
  332 + return ret;
  333 +}
  334 +
243 // see: ngx_conf_parse 335 // see: ngx_conf_parse
244 int SrsConfDirective::parse_conf(SrsConfigBuffer* buffer, SrsDirectiveType type) 336 int SrsConfDirective::parse_conf(SrsConfigBuffer* buffer, SrsDirectiveType type)
245 { 337 {
@@ -1424,7 +1516,31 @@ int SrsConfig::parse_options(int argc, char** argv) @@ -1424,7 +1516,31 @@ int SrsConfig::parse_options(int argc, char** argv)
1424 int SrsConfig::persistence() 1516 int SrsConfig::persistence()
1425 { 1517 {
1426 int ret = ERROR_SUCCESS; 1518 int ret = ERROR_SUCCESS;
1427 - // TODO: FIXME: implements it. 1519 +
  1520 + // write to a tmp file, then mv to the config.
  1521 + std::string path = config_file + ".tmp";
  1522 +
  1523 + // open the tmp file for persistence
  1524 + SrsFileWriter fw;
  1525 + if ((ret = fw.open(path)) != ERROR_SUCCESS) {
  1526 + return ret;
  1527 + }
  1528 +
  1529 + // persistence root directive to writer.
  1530 + if ((ret = root->persistence(&fw, 0)) != ERROR_SUCCESS) {
  1531 + ::unlink(path.c_str());
  1532 + return ret;
  1533 + }
  1534 +
  1535 + // rename the config file.
  1536 + if (::rename(path.c_str(), config_file.c_str()) < 0) {
  1537 + ::unlink(path.c_str());
  1538 +
  1539 + ret = ERROR_SYSTEM_CONFIG_PERSISTENCE;
  1540 + srs_error("rename config from %s to %s failed. ret=%d", path.c_str(), config_file.c_str(), ret);
  1541 + return ret;
  1542 + }
  1543 +
1428 return ret; 1544 return ret;
1429 } 1545 }
1430 1546
@@ -34,6 +34,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -34,6 +34,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 34
35 #include <srs_app_reload.hpp> 35 #include <srs_app_reload.hpp>
36 36
  37 +class SrsFileWriter;
  38 +
37 namespace _srs_internal 39 namespace _srs_internal
38 { 40 {
39 class SrsConfigBuffer; 41 class SrsConfigBuffer;
@@ -136,6 +138,11 @@ public: @@ -136,6 +138,11 @@ public:
136 * parse config directive from file buffer. 138 * parse config directive from file buffer.
137 */ 139 */
138 virtual int parse(_srs_internal::SrsConfigBuffer* buffer); 140 virtual int parse(_srs_internal::SrsConfigBuffer* buffer);
  141 + /**
  142 + * persistence the directive to writer.
  143 + * @param level, the root is level0, all its directives are level1, and so on.
  144 + */
  145 + virtual int persistence(SrsFileWriter* writer, int level);
139 // private parse. 146 // private parse.
140 private: 147 private:
141 /** 148 /**
@@ -194,6 +194,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -194,6 +194,14 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
194 #define SRS_CONSTS_CR '\r' // 0x0D 194 #define SRS_CONSTS_CR '\r' // 0x0D
195 // LF = <US-ASCII LF, linefeed (10)> 195 // LF = <US-ASCII LF, linefeed (10)>
196 #define SRS_CONSTS_LF '\n' // 0x0A 196 #define SRS_CONSTS_LF '\n' // 0x0A
  197 +// SP = <US-ASCII SP, space>
  198 +#define SRS_CONSTS_SP ' ' // 0x20
  199 +// SE = <US-ASCII SE, semicolon>
  200 +#define SRS_CONSTS_SE ';' // 0x3b
  201 +// LB = <US-ASCII SE, left-brace>
  202 +#define SRS_CONSTS_LB '{' // 0x7b
  203 +// RB = <US-ASCII SE, right-brace>
  204 +#define SRS_CONSTS_RB '}' // 0x7d
197 205
198 /////////////////////////////////////////////////////////// 206 ///////////////////////////////////////////////////////////
199 // HTTP consts values 207 // HTTP consts values
@@ -97,6 +97,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -97,6 +97,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
97 #define ERROR_SYSTEM_DIR_EXISTS 1056 97 #define ERROR_SYSTEM_DIR_EXISTS 1056
98 #define ERROR_SYSTEM_CREATE_DIR 1057 98 #define ERROR_SYSTEM_CREATE_DIR 1057
99 #define ERROR_SYSTEM_KILL 1058 99 #define ERROR_SYSTEM_KILL 1058
  100 +#define ERROR_SYSTEM_CONFIG_PERSISTENCE 1059
100 101
101 /////////////////////////////////////////////////////// 102 ///////////////////////////////////////////////////////
102 // RTMP protocol error. 103 // RTMP protocol error.