Dynamic file loading in Linux

Source: Internet
Author: User
# Ifndef _ watcher_h _ # DEFINE _ watcher_h _ # include <sys/time. h> # include <sys/STAT. h> # include <string> // We often want to know if a file was just now created or updated (then we // may reload the file to get latest data ). filewatcher does boilerplate part // For you as below. // example: // watcher FW; // FW. create ("path_of_file_to_be_watched ");//.... // If (FW. is_timestamp_updated ()> 0) {//> 0 means that The file is created or updated //...... // FW. update_timestamp (); // update recorded timestamp //} // you may call is_timestamp_updated () multiple times to know Latest status // of the file before calling update_timestamp (), or you may combine callto // the two functions by: // If (FW. check_and_update_timestamp ()> 0 ){//.... //} class watcher {public: static const time_t non_exist_ts = (time_t )- 1; // must be negative static const int skew =-2; // file exceptions from the future: the file timestamp is abnormal or the file static const int deleted =-1 copied from the server with a faster time; // must be zero static const int unchanged = 0; // must be positive static const int updated = 1; static const int created = 2; // default constructor explicit watcher (): _ chk_ts (non_exist_ts), _ last_ts (non_exist_ts) // The explicit here has no practical significance. You can delete {} // create this watcher on a file // Returns: //-1 file_path is null // 0 success int create (const char * file_path) {If (null = file_path) {fatal ("file_path is null"); Return-1;} file_path _ = file_path; // post-underline... Okay... Struct stat tmp_st; int ret = Stat (file_path _. c_str (), & tmp_st); // to store the previous state if (Ret <0) {warn ("% s does not exist", file_path _. c_str (); _ chk_ts = non_exist_ts; _ last_ts = non_exist_ts;} else {_ chk_ts = tmp_st.st_mtime; _ last_ts = tmp_st.st_mtime;} return 0 ;} // check if watched file was created/modified/deleted. recorded timestamp // is not changed so it's safe to call this function Multipl E times, you // won't miss an update. // returns: // updated the file is modified or created since last call to this // function // unchanged the file is not modified or still not existing since last // call to this function // deleted the file was deleted since last call to this function // skew the file exists but the timestamp steps back // note: this method only checks, to tell file_reader_t O forget the change // (because you already processed the file), you must call // update_timestamp (). you may call check_and_update_timestamp () to // combine two CILS. // Note: if the file is updated too frequently (<500 ms), this method may/return unchanged due to precision of Stat (2 ); if the file is // being updated too frequently for a period of time, this method // shocould eventually return Several updates; if the file is being // updated and deleted too frequently, the update events are // probably undetectable. fortunately, this is unseen in our app. int is_timestamp_updated () {struct stat tmp_st; const int ret = Stat (file_path _. c_str (), & tmp_st); If (Ret <0) {_ chk_ts = non_exist_ts; If (non_exist_ts! = _ Last_ts) {return deleted;} else {return unchanged ;}} else {_ chk_ts = tmp_st.st_mtime; If (non_exist_ts! = _ Last_ts) {If (_ chk_ts> _ last_ts) {return updated;} else if (_ chk_ts = _ last_ts) {return unchanged;} else {return skew ;}} else {return created ;}}// change recorded time void update_timestamp () {_ last_ts = _ chk_ts;} // combine is_timestamp_updated () and update_timestamp () int reset () {const int ret = is_timestamp_updated (); update_timestamp (); return ret;} // get path of the watched file const char * filepath () const {return file_path _. c_str ();} PRIVATE: STD: String file_path _; time_t _ chk_ts; time_t _ last_ts ;}; typedef watcher watcher_t; # endif

· The code is relatively simple as it is determined based on various timestamp situations.

So with the Monitoring Program, if I need to dynamically load the file when updating the file, what should I do? To load a file, you need to update the stored data, which may be used during dynamic loading.

The solution is thread-based monitoring. When two buffers are used, the client can only access one of them at any time, and the access to which one is determined by the loader. When the file is updated, update the data to the unused buffer to ensure normal access to the old data. When the update is complete and the old data is no longer called, the interface that notifies the customer of data transmission uses new data, clears the previous buffer, and sets this buffer to unused, waiting for the next update.

# Ifndef _ reloader_h # DEFINE _ reloader_h # include <stdio. h> # include <time. h> # include <stdint. h> # include <sys/STAT. h> # include <string. h ># include <New> template <bool> class static_assert; Template <> class static_assert <true> {}; // @ brief dual buffer management class // @ note T must implement the int load (const char * cp_dir, const char * cp_fname) function, otherwise, the compilation fails. // @ note if there is an init requirement, You can provide an int T: Init () function during the construction. // @ note when the above two functions return <0, indicates Failed // @ note recommended design: the file does not exist or the content is empty. It is also considered as a successful template <class T> class reloader_t {public: typedef t content_type; // @ Param init_func, if it is passed in, reload will call init_func // @ note init_func for the new object must be a static function reloader_t (const char * cp_path, const char * cp_fname, INT (content_type :: * init_func) () = NULL );~ Reloader_t (); // @ return-1, the file does not exist; 0, no reload; 1, you can reload int need_reload () const; // @ brief dual buffer switching // @ return-1, reload failed; 1, reload success int reload (); // obtain the currently available buffer pointer content_type * get_content (); // obtain the currently available buffer pointer const content_type * get_content () const; time_t get_file_modtime () const {return _ TM;} time_t get_file_loadtime () const {return _ last_update_tm;} protected: Time _ T _ TM; time_t _ last_update_tm; uint8_t _ using_no; // two buffer pointers content_type * _ p_content [2]; // The actual buffer, avoid frequent request for memory char _ mem during reload [2 * sizeof (content_type)]; char _ path [512]; char _ fname [512]; // personalized init function int (content_type: * _ init_func) (); // The following function ensures that the return value of T: load must be int typedef char small_t; struct big_t {char C [2] ;}; static small_t _ is_int (INT); Template <Class V> static big_t _ is_int (V); Te Mplate <class RT, class linoleic> static RT _ get_load_ret_type (RT (linoleic: *) (const char *, const char *));}; template <class T> reloader_t <t>: reloader_t (const char * cp_path, const char * cp_fname, INT (T: * init_func )()): _ TM (0), _ last_update_tm (0), _ using_no (1), _ init_func (init_func) {// the return value of the static check load must be int static_assert <sizeof (small_t) = sizeof (_ is_int (_ get_load_ret_type (& T: load)> (); If (cp_path = N Ull) {cp_path = ". /";} If (cp_fname = NULL) {cp_fname =" reload_file ";} snprintf (_ path, sizeof (_ path)," % s ", cp_path ); snprintf (_ fname, sizeof (_ fname), "% s", cp_fname); _ p_content [0] = NULL; _ p_content [1] = NULL; memset (& _ MEM, 0, sizeof (_ MEm);} template <class T> reloader_t <t> ::~ Reloader_t () {If (_ p_content [0]! = NULL) {_ p_content [0]-> ~ T (); _ p_content [0] = NULL;} If (_ p_content [1]! = NULL) {_ p_content [1]-> ~ T (); _ p_content [1] = NULL ;}} template <class T> int reloader_t <t >:: need_reload () const {char fpath [sizeof (_ path) + sizeof (_ fname) + 1] = ""; snprintf (fpath, sizeof (fpath), "% S/% s", _ path, _ fname ); struct stat curr_stat; // record the status of the current State file if (STAT (fpath, & curr_stat )! = 0) | (curr_stat.st_mode & s_ifreg) = 0) {return-1;} If (curr_stat.st_mtime <= _ TM) {// The current data is returned 0 ;} return 1;} template <class T> int reloader_t <t >:: reload () {If (_ using_no! = 0 & _ using_no! = 1) {return-1;} // sleep for 1 second, ensure that all threads no longer use this resource // The peripheral ensures sleep (1); struct stat curr_stat; char fpath [sizeof (_ path) + sizeof (_ fname) + 1] = ""; snprintf (fpath, sizeof (fpath), "% S/% s ", _ path, _ fname); // record the status of the current State file if (STAT (fpath, & curr_stat )! = 0) | (curr_stat.st_mode & s_ifreg) = 0) {warn ("Get File: % s status failed", fpath); Return-1 ;} // ensure that the buffer number used is 1 or 0 int reload_no = 1-_ using_no; If (_ p_content [reload_no]! = NULL) {_ p_content [reload_no]-> ~ T (); _ p_content [reload_no] = NULL;} _ p_content [reload_no] = new (& _ mem [reload_no * sizeof (t)]) T (); // init if (_ init_func! = NULL) {int init_ret = (_ p_content [reload_no]-> * _ init_func) (); If (init_ret <0) {fatal ("init failed. init RET: % d ", init_ret); goto reload_failed ;}{ int load_ret = _ p_content [reload_no]-> load (_ path, _ fname ); if (load_ret <0) {fatal ("Load file: % S/% s failed. load RET: % d ", _ path, _ fname, load_ret); goto reload_failed; }}_ TM = curr_stat.st_mtime; _ last_update_tm = Time (null); _ using_no = reloa D_no; Info ("reload [% s] success and shift to data [% d]", fpath, _ using_no); return 1; reload_failed: If (_ p_content [reload_no]! = NULL) {_ p_content [reload_no]-> ~ T (); _ p_content [reload_no] = NULL;} return-1;} template <class T> T * reloader_t <t >:: get_content () {If (_ TM = 0 | (_ using_no! = 1 & _ using_no! = 0) {return NULL;} return _ p_content [_ using_no];} template <class T> const T * reloader_t <t >:: get_content () const {return get_content () ;}# endif

This class also realizes the judgment of the file status, but I personally think that this function should still be independent and adopt a combination of methods for processing, so that reloader has a watcher object is a good choice.

Finally, add the thread to solve the problem:

# Ifndef _ hit_reload_h # DEFINE _ hit_reload_h # include <pthread. h> # include "watcher. H "static const char word_reload_file [] = ". /CONF/reloadword "; Class thread {/* {*/thread (const thread &); void operator = (const thread &); pthread_t _ thread; public: thread (): _ thread (0), _ Status (true), _ start (false) {} virtual ~ Thread () {} // start the thread function int start () {int ret = 0; If (_ start = false) {ret = pthread_create (& _ thread, null, thread: func, this); If (Ret! = 0) {fatal ("create thread failed. "); _ Status = false;} else {_ start = true;} return ret;} // get the thread status bool valid () const {return _ status ;} // obtain the thread handle pthread_t & get () {return _ thread;} const pthread_t & get () const {return _ thread;} // wait for the thread end function int join () {If (_ Status = true & _ start = true) {return pthread_join (_ thread, null) ;}return-1 ;} virtual void * Run () = 0; protected: bool _ status; boo L _ start; static void * func (void * ARGs) {thread * p_thread = static_cast <thread *> (ARGs); Return p_thread-> Run ();}}; /* }}*/class reloadthread: Public thread {/* {*/public: Template <class T> void reloadcheck (watcher * watcher, reloader_t <t> * Mgr, const char * file) {/* {*/bool all_reloaded = false; int ret = watcher-> check_and_update_timestamp (); if (Ret> 0) {all_reloaded = true; If (MGR! = NULL) {If (MGR-> reload () <0) {printf ("reload % s config failed", file); all_reloaded = false ;}}} else if (Ret <0) {printf ("watcher status not valid"); // check status failed, reload failed all_reloaded = false ;} else {// update all_reloaded = false not detected;} If (all_reloaded) {printf ("% s is reloaded! ", File) ;}}/ * }}*/void * Run () {watcher watcher_word; watcher_word.create (" word_filter_file "); While (true) {sleep (g_conf.isleeptime ); // reload word. confreloadcheck <wordfilter> (& watcher_word, g_data.word_filter_mgr, g_conf.word_filter_file);} return NULL ;};/* }}} */# endif/* VIM: set Ts = 4 Sw = 4 NOET :*/

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.