PIPS
workspace.c
Go to the documentation of this file.
1 /*
2 
3  $Id: workspace.c 23065 2016-03-02 09:05:50Z coelho $
4 
5  Copyright 1989-2016 MINES ParisTech
6 
7  This file is part of PIPS.
8 
9  PIPS is free software: you can redistribute it and/or modify it
10  under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  any later version.
13 
14  PIPS is distributed in the hope that it will be useful, but WITHOUT ANY
15  WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  FITNESS FOR A PARTICULAR PURPOSE.
17 
18  See the GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with PIPS. If not, see <http://www.gnu.org/licenses/>.
22 
23 */
24 #ifdef HAVE_CONFIG_H
25  #include "pips_config.h"
26 #endif
27 /*
28  * Workspace management.
29  *
30  * Basically, a workspace is the object that manages a database.
31  * The database will be stored into that workspace.
32  * Just to say it is a directory, with a name.
33  */
34 
35 #include "private.h"
36 #include "pipsdbm_private.h"
37 
38 
39 /******************************************************************** UTILS */
40 
41 /* the workspace name must be composed of the following characters.
42  */
43 #define WORKSPACE_NAME_CHARS \
44  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"
45 
46 bool workspace_name_p(const char* name)
47 {
48  return strlen(name)==strspn(name, WORKSPACE_NAME_CHARS);
49 }
50 
51 
52 /************************************************************ THE WORKSPACE */
53 
54 /* the workspace has a name.
55  *
56  * {set,reset,get}_workspace
57  */
58 static string current_workspace_name = NULL;
59 
60 static void db_set_current_workspace_name(const char* name)
61 {
63  pips_internal_error("current workspace %s not closed",
65  pips_assert("valid workspace name", workspace_name_p(name));
67 }
68 
70 {
71  pips_assert("some current workspace", current_workspace_name);
73 }
74 
76 {
78 }
79 
80 /* the function is used to check that there is some current workspace...
81  */
83 {
85 }
86 // FI: I would like to export MD_DATABASE via pipsdbm-local.h
87 // for use in workspace-util
88 #define MD_DATABASE "database"
89 
90 /* returns an allocated string. */
91 string db_get_workspace_directory_name(const char* name)
92 {
93  return strdup(concatenate("./", name, "." MD_DATABASE, NULL));
94 }
95 
97 {
98  string ws_name = db_get_current_workspace_name();
99  pips_assert("some current workspace", ws_name);
100  return db_get_workspace_directory_name(ws_name);
101 }
102 
103 /************************************************************* LOGICAL TIME */
104 
105 static int logical_time = 1; /* 0 means not set... */
106 
108 {
109  return logical_time++;
110 }
111 
113 {
114  return logical_time;
115 }
116 
117 static void db_set_logical_time(int time)
118 {
119  pips_assert("positive time set", time>=1);
120  logical_time = time;
121 }
122 
123 static void db_reset_logical_time(void)
124 {
125  logical_time = 0;
126 }
127 
128 /***************************************************************** META DATA */
129 
130 // "Warnings" should be defined here... but for cycle between libraries?
131 
132 #define METADATA "Metadata"
133 
134 #define DATABASE_STATUS "STATUS"
135 #define DATABASE_SYMBOLS "SYMBOLS"
136 #define DATABASE_MISC "MISC"
137 #define DATABASE_NEWGEN "NEWGEN" /* newgen type translation data... */
138 
140 {
142 }
143 
144 static string meta_data_db_file_name(string data)
145 {
146  string dir_name = db_get_meta_data_directory(),
147  res = strdup(concatenate(dir_name, "/" MD_DATABASE ".", data, NULL));
148  free(dir_name); return res;
149 }
150 
151 /* reset all meta data on failures.
152  */
153 static void reset_meta_data(void)
154 {
157  /* what about db_symbols? */
159 }
160 
161 /* save (and maybe free) metadata.
162  * @return whether sucessful.
163  */
164 static bool save_meta_data(bool do_free)
165 {
166  string file_name;
167  FILE * file;
168 
169  pips_debug(2, "saving database status\n");
171  file = safe_fopen(file_name, "w");
172  db_save_pips_database(file);
173  safe_fclose(file, file_name);
174  free(file_name);
175 
176  if (do_free) db_close_pips_database();
177 
178  pips_debug(2, "saving database symbols\n");
180  file = safe_fopen(file_name, "w");
182  safe_fclose(file, file_name);
183  free(file_name);
184 
185  if (do_free) gen_free_tabulated(db_symbol_domain);
186 
187  pips_debug(2, "saving database misc data\n");
189  file = safe_fopen(file_name, "w");
190  fprintf(file, "%d\n%s\n",
192  safe_fclose(file, file_name);
193  free(file_name);
194 
195  pips_debug(2, "saving newgen type translation data\n");
198  free(file_name);
199 
200  pips_debug(2, "done\n");
201 
202  return true;
203 }
204 
205 #define ONERROR(cond, what) \
206  if (cond) { what; return false; }
207 
208 /* load metadata from workspace.
209  * @return whether successful.
210  */
211 static bool load_meta_data(void)
212 {
213  string file_name, ws_name;
214  FILE * file;
215  int time;
216  bool ok;
217 
218  pips_debug(2, "loading newgen type translation data\n");
222  else
223  pips_user_warning("no newgen type translation file...");
224  free(file_name);
225 
226  pips_debug(2, "loading database misc data\n");
228  file = check_fopen(file_name, "r");
229  ONERROR(!file,/* nope */)
230  ONERROR(fscanf(file, "%d\n", &time)!=1,
231  pips_internal_error("fscanf failed"))
232  db_set_logical_time(time);
233  ws_name = safe_readline(file);
235  pips_user_warning("Workspace %s has been moved to %s\n",
236  ws_name, db_get_current_workspace_name());
237  free(ws_name);
238  safe_fclose(file, file_name);
239  free(file_name);
240 
241  pips_debug(2, "loading database symbols\n");
243  file = check_fopen(file_name, "r");
244  ONERROR(!file,/* nope */)
246 
247  safe_fclose(file, file_name);
248  free(file_name);
249 
250  pips_debug(2, "loading database status\n");
252  file = check_fopen(file_name, "r");
253  ONERROR(!file,/* nope */)
254  ok = db_open_pips_database(file);
255  ONERROR(!ok, pips_user_error("Could not read database content!"))
256  safe_fclose(file, file_name);
257  free(file_name);
258 
259  pips_debug(2, "done\n");
260 
261  return true;
262 }
263 
264 /**************************************************************** MANAGEMENT */
265 
266 bool workspace_exists_p(const char* name)
267 {
269  bool result = directory_exists_p(full_name);
270  free(full_name);
271  return result;
272 }
273 
274 bool workspace_ok_p(const char* name)
275 {
277  bool result = file_readable_p(full_name);
278  free(full_name);
279  return result;
280 }
281 
282 bool db_create_workspace(const char* name)
283 {
284  bool ok;
285  string dir_name;
287 
288  dir_name = db_get_workspace_directory_name(name);
289 
290  pips_debug(1, "workspace %s in directory %s\n", name, dir_name);
291 
292  if ((ok = purge_directory(dir_name)))
293  {
294  if ((ok = create_directory(dir_name)))
295  {
298  }
299  else
300  {
301  pips_user_warning("could not create directory %s\n", dir_name);
302  }
303  }
304  else
305  {
306  pips_user_warning("could not remove old directory %s\n", dir_name);
307  }
308 
309  free(dir_name);
310  pips_debug(1, "done\n");
311 
312  debug_off();
313  return ok;
314 }
315 
316 /* stores all resources of module oname.
317  */
318 static void db_close_module(string what, string oname, bool do_free)
319 {
320  // the download order is retrieved from the methods...
321  int nr = dbll_number_of_resources(), i;
322 
323  if (!same_string_p(oname, "")) /* log if necessary. */
324  user_log(" %s module %s.\n", what, oname);
325 
326  for (i=0; i<nr; i++)
327  {
329  (dbll_get_ith_resource_name(i), oname, do_free);
330  }
331 }
332 
333 static void db_save_workspace(string what, bool do_free)
334 {
335  gen_array_t a;
336 
337  user_log("%s all modules.\n", what);
338  a = db_get_module_list();
339  GEN_ARRAY_FOREACH(string, module, a)
340  db_close_module(what, module, do_free);
342 
343  user_log("%s program.\n", what);
344  db_close_module(what, "", do_free); /* ENTITIES are saved here... */
345 
346  user_log("%s workspace.\n", what);
347  save_meta_data(do_free);
348 }
349 
351 {
353  pips_debug(1, "Checkpointing workspace %s\n",
355 
356  db_save_workspace("Saving", false);
357 
358  /* load ENTITIES (since no one ask for them as they should...)
359  */
360  if (db_resource_p(DBR_ENTITIES, ""))
361  (void) db_get_memory_resource(DBR_ENTITIES, "", true);
362 
363  ifdebug(1) dump_all_db_resource_status(stderr, "db_checkpoint_workspace");
364  debug_off();
365 }
366 
367 bool db_close_workspace(bool is_quit)
368 {
370  pips_debug(1, "Closing workspace %s\n", db_get_current_workspace_name());
371 
372  db_save_workspace("Closing", /* free? */ !is_quit);
374 
375  pips_debug(1, "done\n");
376  debug_off();
377  return true;
378 }
379 
380 bool db_open_workspace(const char* name)
381 {
382  bool ok = true;
383  string dir_name;
385  pips_debug(1, "Opening workspace %s\n", name);
386 
387  dir_name = db_get_workspace_directory_name(name);
388  if (directory_exists_p(dir_name))
389  {
391  ok = load_meta_data();
392 
393  if (!ok) /* failure! */
394  {
395  reset_meta_data();
396  pips_user_warning("Cannot load workspace metadata for %s.\n",
397  name);
398  }
399 
400  /* load ENTITIES (since no one ask for them as they should;-) */
401  if (ok && db_resource_p(DBR_ENTITIES, "")) {
402  (void) db_get_memory_resource(DBR_ENTITIES, "", true);
403  /* should touch them somehow to force latter saving? */
404  }
405  }
406  else ok = false;
407 
408  pips_debug(1, "done (%d)\n", ok);
409  debug_off();
410  free(dir_name);
411  return ok;
412 }
void user_log(const char *format,...)
Definition: message.c:234
void read_tabulated_db_symbol(FILE *f)
void write_tabulated_db_symbol(FILE *f)
void dump_all_db_resource_status(FILE *file, string where)
Definition: database.c:198
bool db_resource_p(const char *rname, const char *oname)
true if exists and in loaded or stored state.
Definition: database.c:524
void db_save_pips_database(FILE *fd)
Definition: database.c:137
bool db_open_pips_database(FILE *fd)
Definition: database.c:119
void db_create_pips_database(void)
exported interface is minimal.
Definition: database.c:109
void db_reset_pips_database_if_necessary(void)
Definition: database.c:155
void db_save_and_free_memory_resource_if_any(const char *rname, const char *oname, bool do_free)
Definition: database.c:1013
void db_close_pips_database(void)
Definition: database.c:150
void gen_array_full_free(gen_array_t a)
Definition: array.c:77
bool create_directory(char *name)
Definition: file.c:435
FILE * safe_fopen(const char *filename, const char *what)
Definition: file.c:67
bool file_exists_p(const char *name)
Definition: file.c:321
int safe_fclose(FILE *stream, const char *filename)
Definition: file.c:77
bool file_readable_p(char *name)
Definition: file.c:428
bool directory_exists_p(const char *name)
Definition: file.c:314
char * safe_readline(FILE *file)
returns the allocated line read, whatever its length.
Definition: file.c:497
FILE * check_fopen(const char *file, const char *mode)
file.c
Definition: file.c:56
bool purge_directory(char *name)
Definition: file.c:453
void gen_type_translation_write(string filename)
Definition: genClib.c:2195
int gen_free_tabulated(int domain)
free tabulated elements of this domain.
Definition: genClib.c:1461
void gen_type_translation_read(string filename)
set current type translation table according to file
Definition: genClib.c:2189
void free(void *)
string db_get_memory_resource(const char *rname, const char *oname, bool pure)
Return the pointer to the resource, whatever it is.
Definition: database.c:755
gen_array_t db_get_module_list(void)
Get an array of all the modules (functions, procedures and compilation units) of a workspace.
Definition: database.c:1266
#define full_name(dir, name)
Definition: compile.c:414
int dbll_number_of_resources(void)
Definition: lowlevel.c:108
string db_get_directory_name_for_module(const char *name)
returns the allocated and mkdir'ed directory for module name
Definition: lowlevel.c:150
string dbll_get_ith_resource_name(int i)
Definition: lowlevel.c:113
#define debug_on(env)
Definition: misc-local.h:157
#define pips_debug
these macros use the GNU extensions that allow variadic macros, including with an empty list.
Definition: misc-local.h:145
#define pips_user_warning
Definition: misc-local.h:146
#define pips_assert(what, predicate)
common macros, two flavors depending on NDEBUG
Definition: misc-local.h:172
#define pips_internal_error
Definition: misc-local.h:149
#define debug_off()
Definition: misc-local.h:160
#define pips_user_error
Definition: misc-local.h:147
#define GEN_ARRAY_FOREACH(type, s, array)
Definition: newgen_array.h:50
string concatenate(const char *,...)
Return the concatenation of the given strings.
Definition: string.c:183
#define same_string_p(s1, s2)
static char * module
Definition: pips.c:74
#define PIPSDBM_DEBUG_LEVEL
Definition: pipsdbm-local.h:27
#define db_symbol_domain
newgen_db_status_domain_defined
int fprintf()
test sc_min : ce test s'appelle par : programme fichier1.data fichier2.data ...
char * strdup()
#define ifdebug(n)
Definition: sg.c:47
static bool ok
static string file_name
#define METADATA
Definition: workspace.c:132
bool db_close_workspace(bool is_quit)
Definition: workspace.c:367
static void db_reset_logical_time(void)
Definition: workspace.c:123
bool db_open_workspace(const char *name)
Definition: workspace.c:380
static bool load_meta_data(void)
load metadata from workspace.
Definition: workspace.c:211
int db_inc_logical_time(void)
0 means not set...
Definition: workspace.c:107
static int logical_time
Definition: workspace.c:105
static void db_reset_current_workspace_name(void)
Definition: workspace.c:69
#define DATABASE_STATUS
Definition: workspace.c:134
bool workspace_exists_p(const char *name)
Definition: workspace.c:266
static void reset_meta_data(void)
reset all meta data on failures.
Definition: workspace.c:153
#define MD_DATABASE
Definition: workspace.c:88
#define DATABASE_SYMBOLS
Definition: workspace.c:135
static bool save_meta_data(bool do_free)
save (and maybe free) metadata.
Definition: workspace.c:164
static void db_set_current_workspace_name(const char *name)
Definition: workspace.c:60
static void db_close_module(string what, string oname, bool do_free)
stores all resources of module oname.
Definition: workspace.c:318
int db_get_logical_time(void)
Definition: workspace.c:112
string db_get_current_workspace_directory(void)
Definition: workspace.c:96
static void db_save_workspace(string what, bool do_free)
Definition: workspace.c:333
#define DATABASE_MISC
Definition: workspace.c:136
string db_get_meta_data_directory()
The syntax of a property list.
Definition: workspace.c:139
bool workspace_name_p(const char *name)
workspace.c
Definition: workspace.c:46
void db_checkpoint_workspace(void)
Definition: workspace.c:350
static string current_workspace_name
the workspace has a name.
Definition: workspace.c:58
static void db_set_logical_time(int time)
Definition: workspace.c:117
bool workspace_ok_p(const char *name)
Definition: workspace.c:274
#define ONERROR(cond, what)
Definition: workspace.c:205
static void db_reset_current_workspace_name_if_necessary(void)
Definition: workspace.c:75
string db_get_current_workspace_name(void)
the function is used to check that there is some current workspace...
Definition: workspace.c:82
#define WORKSPACE_NAME_CHARS
the workspace name must be composed of the following characters.
Definition: workspace.c:43
#define DATABASE_NEWGEN
Definition: workspace.c:137
string db_get_workspace_directory_name(const char *name)
returns an allocated string.
Definition: workspace.c:91
static string meta_data_db_file_name(string data)
Definition: workspace.c:144
bool db_create_workspace(const char *name)
Definition: workspace.c:282