]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/tsync/terrasync.cxx
Remove using std:: from the metar header, remove HTTP support, add very basic unit...
[simgear.git] / simgear / scene / tsync / terrasync.cxx
index d242dec6a3102a2a9ed88b37ec4c10234f91938a..0f99d4e508c739aaeafa5f64362539a21c7d274e 100644 (file)
@@ -86,6 +86,7 @@
 #endif
 
 using namespace simgear;
+using namespace std;
 
 const char* rsync_cmd = 
         "rsync --verbose --archive --delete --perms --owner --group";
@@ -93,8 +94,37 @@ const char* rsync_cmd =
 const char* svn_options =
         "checkout -q";
 
+namespace UpdateInterval
+{
+    // interval in seconds to allow an update to repeat after a successful update (=daily)
+    static const double SuccessfulAttempt = 24*60*60;
+    // interval in seconds to allow another update after a failed attempt (10 minutes)
+    static const double FailedAttempt     = 10*60;
+};
+
 typedef map<string,time_t> CompletedTiles;
 
+///////////////////////////////////////////////////////////////////////////////
+// helper functions ///////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+string stripPath(string path)
+{
+    // svn doesn't like trailing white-spaces or path separators - strip them!
+    path = simgear::strutils::strip(path);
+    int slen = path.length();
+    while ((slen>0)&&
+            ((path[slen-1]=='/')||(path[slen-1]=='\\')))
+    {
+        slen--;
+    }
+    return path.substr(0,slen);
+}
+
+bool hasWhitespace(string path)
+{
+    return path.find(' ')!=string::npos;
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 // WaitingTile ////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
@@ -125,10 +155,10 @@ public:
    bool hasNewTiles() { return !_freshTiles.empty();}
    WaitingTile getNewTile() { return _freshTiles.pop_front();}
 
-   void   setSvnServer(string server)       { _svn_server   = simgear::strutils::strip(server);}
+   void   setSvnServer(string server)       { _svn_server   = stripPath(server);}
    void   setExtSvnUtility(string svn_util) { _svn_command  = simgear::strutils::strip(svn_util);}
    void   setRsyncServer(string server)     { _rsync_server = simgear::strutils::strip(server);}
-   void   setLocalDir(string dir)           { _local_dir    = simgear::strutils::strip(dir);}
+   void   setLocalDir(string dir)           { _local_dir    = stripPath(dir);}
    string getLocalDir()                     { return _local_dir;}
    void   setUseSvn(bool use_svn)           { _use_svn = use_svn;}
 
@@ -259,6 +289,7 @@ bool SGTerraSync::SvnThread::start()
         _stalled = true;
         return false;
     }
+
 #ifdef HAVE_SVN_CLIENT_H
     _use_svn |= _use_built_in;
 #endif
@@ -271,7 +302,6 @@ bool SGTerraSync::SvnThread::start()
         _stalled = true;
         return false;
     }
-
     if ((!_use_svn)&&(_rsync_server==""))
     {
         SG_LOG(SG_TERRAIN,SG_ALERT,
@@ -358,20 +388,19 @@ bool SGTerraSync::SvnThread::syncTreeInternal(const char* dir)
         return false;
     }
 
-    char command[512];
-    char dest_base_dir[512];
-    snprintf( command, 512,
-        "%s/%s", _svn_server.c_str(), dir);
-    snprintf( dest_base_dir, 512,
-        "%s/%s", _local_dir.c_str(), dir);
+    ostringstream command;
+    command << _svn_server << "/" << dir;
+
+    ostringstream dest_base_dir;
+    dest_base_dir << _local_dir << "/" << dir;
 
     apr_pool_t *subpool = svn_pool_create(_svn_pool);
 
     svn_error_t *err = NULL;
 #if (SVN_VER_MINOR >= 5)
     err = svn_client_checkout3(NULL,
-            command,
-            dest_base_dir,
+            command.str().c_str(),
+            dest_base_dir.str().c_str(),
             _svn_rev_peg,
             _svn_rev,
             svn_depth_infinity,
@@ -382,8 +411,8 @@ bool SGTerraSync::SvnThread::syncTreeInternal(const char* dir)
 #else
     // version 1.4 API
     err = svn_client_checkout2(NULL,
-            command,
-            dest_base_dir,
+            command.str().c_str(),
+            dest_base_dir.str().c_str(),
             _svn_rev_peg,
             _svn_rev,
             1, // recurse=true - same as svn_depth_infinity for checkout3 above
@@ -407,7 +436,7 @@ bool SGTerraSync::SvnThread::syncTreeInternal(const char* dir)
                     err->message << " (code " << err->apr_err << ").");
             svn_error_clear(err);
             // try to clean up
-            err = svn_client_cleanup(dest_base_dir,
+            err = svn_client_cleanup(dest_base_dir.str().c_str(),
                     _svn_ctx,subpool);
             if (!err)
             {
@@ -427,22 +456,37 @@ bool SGTerraSync::SvnThread::syncTreeInternal(const char* dir)
 
 bool SGTerraSync::SvnThread::syncTreeExternal(const char* dir)
 {
-    int rc;
-    char command[512];
+    ostringstream buf;
+    SGPath localPath( _local_dir );
+    localPath.append( dir );
+
     if (_use_svn)
     {
-        snprintf( command, 512,
-            "\"%s\" %s %s/%s \"%s/%s\"", _svn_command.c_str(), svn_options,
-            _svn_server.c_str(), dir,
-            _local_dir.c_str(), dir );
+        buf << "\"" << _svn_command << "\" "
+            << svn_options << " "
+            << "\"" << _svn_server << "/" << dir << "\" "
+            << "\"" << localPath.str_native() << "\"";
     } else {
-        snprintf( command, 512,
-            "%s %s/%s/ \"%s/%s/\"", rsync_cmd,
-            _rsync_server.c_str(), dir,
-            _local_dir.c_str(), dir );
+        buf << rsync_cmd << " "
+            << "\"" << _rsync_server << "/" << dir << "/\" "
+            << "\"" << localPath.str_native() << "/\"";
     }
+
+    string command;
+#ifdef SG_WINDOWS
+        // windows command line parsing is just lovely...
+        // to allow white spaces, the system call needs this:
+        // ""C:\Program Files\something.exe" somearg "some other arg""
+        // Note: whitespace strings quoted by a pair of "" _and_ the 
+        //       entire string needs to be wrapped by "" too.
+        // The svn url needs forward slashes (/) as a path separator while
+        // the local path needs windows-native backslash as a path separator.
+    command = "\"" + buf.str() + "\"";
+#else
+    command = buf.str();
+#endif
     SG_LOG(SG_TERRAIN,SG_DEBUG, "sync command '" << command << "'");
-    rc = system( command );
+    int rc = system( command.c_str() );
     if (rc)
     {
         SG_LOG(SG_TERRAIN,SG_ALERT,
@@ -466,7 +510,7 @@ void SGTerraSync::SvnThread::run()
             _completedTiles.find( next._dir );
         time_t now = time(0);
         if ((ii == _completedTiles.end())||
-            ((ii->second + 60*60*24) < now ))
+            (ii->second < now ))
         {
             bool isNewDirectory = false;
 
@@ -475,6 +519,7 @@ void SGTerraSync::SvnThread::run()
             {
                 _consecutive_errors++;
                 _fail_count++;
+                _completedTiles[ next._dir ] = now + UpdateInterval::FailedAttempt;
             }
             else
             {
@@ -494,9 +539,9 @@ void SGTerraSync::SvnThread::run()
                         _is_dirty = true;
                     }
                 }
+                _completedTiles[ next._dir ] = now + UpdateInterval::SuccessfulAttempt;
             }
             _busy = false;
-            _completedTiles[ next._dir ] = now;
         }
 
         if (_consecutive_errors >= 5)
@@ -525,16 +570,18 @@ int SGTerraSync::SvnThread::svnClientSetup(void)
     //  not supported under msvc 7.1 ( code inside svn_cmdline_init )
     if (svn_cmdline_init("terrasync", 0) != EXIT_SUCCESS)
         return EXIT_FAILURE;
+
+    // revert locale setting
+    setlocale(LC_ALL,"C");
 #else
+    /* svn_cmdline_init configures the locale. Setup environment to ensure the
+     * default "C" locale remains active, since fgfs isn't locale aware - especially
+     * requires "." as decimal point in strings containing floating point varibales. */
+    setenv("LC_ALL", "C", 1);
+
     if (svn_cmdline_init("terrasync", stderr) != EXIT_SUCCESS)
         return EXIT_FAILURE;
 #endif
-    /* Oh no! svn_cmdline_init configures the locale - affecting numeric output
-     * formats (i.e. sprintf("%f", ...)). fgfs relies on "C" locale in many places
-     * (including assumptions on required sprintf buffer sizes). Things go horribly
-     * wrong when the locale is changed to anything else but "C". Might be enough to
-     * revert LC_NUMERIC locale - but we'll do a complete revert for now...*/
-    setlocale(LC_ALL,"C");
 
     apr_pool_t *pool;
     apr_pool_create(&pool, NULL);
@@ -755,20 +802,16 @@ void SGTerraSync::setTileCache(TileCache* tile_cache)
 
 void SGTerraSync::syncAirportsModels()
 {
-    char synced_other;
-    for ( synced_other = 'K'; synced_other <= 'Z'; synced_other++ )
-    {
-        char dir[512];
-        snprintf( dir, 512, "Airports/%c", synced_other );
-        WaitingTile w(dir,false);
-        _svnThread->request( w );
-    }
-    for ( synced_other = 'A'; synced_other <= 'J'; synced_other++ )
+    static const char bounds[] = "KZAJ";
+    for( unsigned i = 0; i < sizeof(bounds)/sizeof(bounds[0])/2; i+= 2 ) 
     {
-        char dir[512];
-        snprintf( dir, 512, "Airports/%c", synced_other );
-        WaitingTile w(dir,false);
-        _svnThread->request( w );
+        for ( char synced_other = bounds[i]; synced_other <= bounds[i+1]; synced_other++ )
+        {
+            ostringstream dir;
+            dir << "Airports/" << synced_other;
+            WaitingTile w(dir.str(),false);
+            _svnThread->request( w );
+        }
     }
     WaitingTile w("Models",false);
     _svnThread->request( w );
@@ -811,12 +854,11 @@ void SGTerraSync::syncArea( int lat, int lon )
     bool refresh=true;
     for (const char** tree = &terrainobjects[0]; *tree; tree++)
     {
-        char dir[512];
-        snprintf( dir, 512, "%s/%c%03d%c%02d/%c%03d%c%02d",
-            *tree,
-            EW, abs(baselon), NS, abs(baselat),
-            EW, abs(lon), NS, abs(lat) );
-        WaitingTile w(dir,refresh);
+        ostringstream dir;
+        dir << *tree << "/" << setfill('0')
+            << EW << setw(3) << abs(baselon) << NS << setw(2) << abs(baselat) << "/"
+            << EW << setw(3) << abs(lon)     << NS << setw(2) << abs(lat);
+        WaitingTile w(dir.str(),refresh);
         _svnThread->request( w );
         refresh=false;
     }