source: synfigstudio/trunk/fuentes/src/gui/autorecover.cpp @ 481

Last change on this file since 481 was 481, checked in by jrpelegrina, 4 years ago

First release to xenial

File size: 7.6 KB
Line 
1/* === S Y N F I G ========================================================= */
2/*!     \file autorecover.cpp
3**      \brief Template File
4**
5**      $Id$
6**
7**      \legal
8**      Copyright (c) 2002-2005 Robert B. Quattlebaum Jr., Adrian Bentley
9**      Copyright (c) 2008 Chris Moore
10**
11**      This package is free software; you can redistribute it and/or
12**      modify it under the terms of the GNU General Public License as
13**      published by the Free Software Foundation; either version 2 of
14**      the License, or (at your option) any later version.
15**
16**      This package is distributed in the hope that it will be useful,
17**      but WITHOUT ANY WARRANTY; without even the implied warranty of
18**      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19**      General Public License for more details.
20**      \endlegal
21*/
22/* ========================================================================= */
23
24/* === H E A D E R S ======================================================= */
25
26#ifdef USING_PCH
27#       include "pch.h"
28#else
29#ifdef HAVE_CONFIG_H
30#       include <config.h>
31#endif
32
33#include "autorecover.h"
34
35#ifdef __OpenBSD__
36#include <errno.h>
37#elif defined(HAVE_SYS_ERRNO_H)
38#include <sys/errno.h>
39#endif
40//#include <unistd.h>
41#include "app.h"
42#include <synfig/savecanvas.h>
43#include <synfig/loadcanvas.h>
44#include <synfigapp/main.h>
45#include <fstream>
46#include <iostream>
47#include "instance.h"
48
49#include <glibmm/miscutils.h>
50#include <glibmm/main.h>
51
52#ifdef HAVE_SYS_STAT_H
53#include <sys/stat.h>
54#endif
55
56#ifdef HAVE_SYS_TIME_H
57#include <sys/time.h>
58#endif
59
60#ifdef HAVE_SYS_WAIT_H
61#include <sys/wait.h>
62#endif
63
64#ifdef HAVE_SYS_RESOURCE_H
65#include <sys/resource.h>
66#endif
67
68#ifdef HAVE_UNISTD_H
69#include <unistd.h>
70#endif
71
72#include "general.h"
73
74#endif
75
76/* === U S I N G =========================================================== */
77
78using namespace std;
79using namespace etl;
80using namespace synfig;
81using namespace studio;
82
83/* === M A C R O S ========================================================= */
84
85#ifdef _WIN32
86#define mkdir(x,y) mkdir(x)
87#endif
88
89/* === G L O B A L S ======================================================= */
90
91/* === P R O C E D U R E S ================================================= */
92
93/* === M E T H O D S ======================================================= */
94
95AutoRecover::AutoRecover()
96{
97        // Three Minutes
98        set_timeout(3*60*1000);
99
100        if(mkdir(get_shadow_directory().c_str(),ACCESSPERMS)<0)
101        {
102                if(errno!=EEXIST)
103                        synfig::error("UNABLE TO CREATE \"%s\"",get_shadow_directory().c_str());
104        }
105        else
106        {
107                synfig::info("Created directory \"%s\"",get_shadow_directory().c_str());
108        }
109}
110
111AutoRecover::~AutoRecover()
112{
113}
114
115synfig::String
116AutoRecover::get_shadow_directory()
117{
118        return Glib::build_filename(synfigapp::Main::get_user_app_directory(),"tmp");
119}
120
121int
122AutoRecover::pid()
123{
124//      return getpid();
125        return 0;
126}
127
128void
129AutoRecover::set_timeout(int milliseconds)
130{
131        timeout=milliseconds;
132        auto_backup_connect.disconnect();
133        if(timeout && !getenv("SYNFIG_DISABLE_AUTO_SAVE"))
134                auto_backup_connect=Glib::signal_timeout().connect(sigc::ptr_fun(&AutoRecover::auto_backup),timeout);
135}
136
137synfig::String
138AutoRecover::get_shadow_file_name(const synfig::String& filename)
139{
140        unsigned int hash1(0xdeadbeef);
141        unsigned int hash2(0x83502529);
142        char* str_hash1(reinterpret_cast<char*>(&hash1));
143        char* str_hash2(reinterpret_cast<char*>(&hash2));
144
145        // First we need to hash up the directory
146        {
147                String pool(dirname(filename));
148
149                while(pool.size()>4)
150                {
151                        str_hash1[0]^=pool[1];str_hash1[1]^=pool[2];str_hash1[2]^=pool[3];str_hash1[3]^=pool[0];
152                        str_hash2[3]+=pool[0];str_hash2[2]+=pool[1];str_hash2[1]+=pool[2];str_hash2[0]+=pool[3];
153                        swap(hash1,hash2);
154                        pool=String(pool,4,pool.size());
155                }
156                while(pool.size())
157                {
158                        str_hash1[0]^=pool[0];
159                        str_hash1[2]^=pool[0];
160                        str_hash2[1]^=pool[0];
161                        str_hash2[3]^=pool[0];
162                        swap(hash1,hash2);
163                        pool=String(pool,1,pool.size());
164                }
165        }
166        hash1^=hash2;
167
168        return Glib::build_filename(get_shadow_directory(),strprintf("%08X-%s",hash1,basename(filename).c_str()));
169
170//      return dirname(filename) + ETL_DIRECTORY_SEPARATOR + ".shadow_" + basename(filename);
171}
172
173bool
174AutoRecover::cleanup_pid(int pid)
175{
176#ifdef HAVE_FORK
177        int status=0;
178        if(waitpid(pid,&status,WNOHANG)==-1)
179        {
180                synfig::info("PID %d isn't a zombie yet",pid);
181                return true;
182        }
183        if(WEXITSTATUS(status)!=0)
184        {
185                synfig::error("Autobackup seems to have failed! (PID=%d)",pid);
186        }
187//      else
188//              synfig::info("PID=%d has been cleaned up",pid);
189#endif
190        return false;
191}
192
193bool
194AutoRecover::auto_backup()
195{
196        int pid(0);
197
198#ifdef HAVE_FORK
199#undef HAVE_FORK
200#endif
201
202#ifdef HAVE_FORK
203        pid=fork();
204#endif
205
206        if(pid<=0)
207        {
208#ifdef HAVE_SETPRIORITY
209                // make us low priority so that we don't
210                // cause the machine to slow down too much
211                setpriority(PRIO_PROCESS,0,15);
212#endif
213
214                try
215                {
216                        std::list< etl::handle<Instance> >::iterator iter;
217
218                        std::string filename=App::get_config_file("autorecovery");
219                        std::ofstream file(filename.c_str());
220
221                        //int savedcount = 0;
222
223                        for(iter=App::instance_list.begin();iter!=App::instance_list.end();++iter)
224                        {
225                                // If this file hasn't even been changed
226                                // since it was last saved, then don't bother
227                                // backing it up.
228                                if((*iter)->get_action_count()==0)
229                                        continue;
230
231                                Canvas::Handle canvas((*iter)->get_canvas());
232
233                                // todo: literal "container:project.sifz"
234                                FileSystem::Handle file_system = canvas->get_identifier().file_system;
235                                if (file_system && (*iter)->get_container())
236                                {
237                                        if (save_canvas(file_system->get_identifier("#project.sifz"), canvas, false))
238                                        {
239                                                if ((*iter)->get_container()->save_temporary())
240                                                {
241                                                        file << (*iter)->get_container()->get_temporary_filename_base().c_str() << endl;
242                                                        file << canvas->get_file_name().c_str() << endl;
243                                                        //savedcount++;
244                                                }
245                                        }
246                                }
247                        }
248
249                        //if(savecount)
250                        //      synfig::info("AutoRecover::auto_backup(): %d Files backed up.",savecount);
251                }
252                catch(...)
253                {
254                        synfig::error("AutoRecover::auto_backup(): UNKNOWN EXCEPTION THROWN.");
255                        synfig::error("AutoRecover::auto_backup(): FILES NOT BACKED UP.");
256                }
257
258#ifdef HAVE_FORK
259                if(pid==0)
260                {
261                        _exit(0);
262                }
263#endif
264        }
265
266#ifdef HAVE_FORK
267        Glib::signal_timeout().connect(
268                sigc::bind(
269                        sigc::ptr_fun(&AutoRecover::cleanup_pid),
270                        pid
271                ),
272                60*1000
273        );
274#endif
275
276        // Also go ahead and save the settings
277        App::save_settings();
278
279        return true;
280}
281
282bool
283AutoRecover::recovery_needed()const
284{
285        std::string filename=App::get_config_file("autorecovery");
286        std::ifstream file(filename.c_str());
287        if(!file)
288                return false;
289
290        while(file)
291        {
292                std::string filename;
293                getline(file,filename);
294                if(!filename.empty())
295                        return true;
296        }
297
298        return false;
299}
300
301bool
302AutoRecover::recover(int& number_recovered)
303{
304        std::string filename=App::get_config_file("autorecovery");
305        std::ifstream file(filename.c_str());
306        number_recovered = 0;
307        if(!file)
308                return false;
309        bool success=true;
310
311        while(file)
312        {
313                std::string container_filename_base;
314                std::string canvas_filename;
315
316                getline(file,container_filename_base);
317                if (!file || container_filename_base.empty())
318                        continue;
319
320                getline(file,canvas_filename);
321                if(canvas_filename.empty())
322                        continue;
323
324                // Open the file
325                if(App::open_from_temporary_container_as(container_filename_base,canvas_filename))
326                {
327                        // Correct the file name
328                        App::instance_list.back()->set_file_name(canvas_filename);
329
330                        // This file isn't saved! mark it as such
331                        App::instance_list.back()->inc_action_count();
332
333                        number_recovered++;
334                }
335                else
336                        success=false;
337        }
338
339        return success;
340}
341
342void
343AutoRecover::normal_shutdown()
344{
345        // Turn off the timer
346        auto_backup_connect.disconnect();
347
348        std::string filename=App::get_config_file("autorecovery");
349        remove(filename.c_str());
350}
351
352void
353AutoRecover::clear_backup(synfig::Canvas::Handle canvas)
354{
355        if(canvas)
356                remove(get_shadow_file_name(canvas->get_file_name()).c_str());
357}
Note: See TracBrowser for help on using the repository browser.