FOSSology  4.7.1
Open Source License Compliance by Open Source Software
process.c
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2013 Hewlett-Packard Development Company, L.P.
3  SPDX-FileCopyrightText: © 2014-2015, 2019 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
12 #include "maintagent.h"
13 
14 /********** Globals *************/
15 PGconn* pgConn = NULL;
17 
26 PGresult * PQexecCheck(int exitNumber, char *SQL, char *file, const int line)
27 {
28  PGresult *result;
29  result = PQexec(pgConn, SQL);
30  if (fo_checkPQcommand(pgConn, result, SQL, file, line)) {
31  PQclear(result);
32  exitNow(exitNumber);
33  }
34  return result;
35 }
36 
42 FUNCTION void PQexecCheckClear(int exitNumber, char *SQL, char *file, const int line)
43 {
44  PGresult *result;
45  result = PQexecCheck(exitNumber, SQL, file, line);
46  PQclear(result);
47 }
48 
53 FUNCTION void vacAnalyze()
54 {
55  long startTime, endTime;
56  char SQL_vacuum[64];
57  char SQL_analyze[64];
58  strncpy(SQL_analyze, "ANALYZE", sizeof(SQL_analyze));
59 
60  /* Determine server major version and use VACUUM FULL for Postgres 17+ */
61  int serverVersion =
62  PQserverVersion(pgConn); /* returns ver as int, e.g., 170000 */
63  int serverMajor = 0;
64  if (serverVersion > 0)
65  {
66  serverMajor = serverVersion / 10000;
67  }
68  if (serverMajor >= 17)
69  {
70  snprintf(SQL_vacuum, sizeof(SQL_vacuum), "VACUUM FULL");
71  }
72  else
73  {
74  snprintf(SQL_vacuum, sizeof(SQL_vacuum), "VACUUM");
75  }
76 
77  /* If very verbose (-vvvv) is requested, add VERBOSE to the commands */
78  if (agent_verbose >= 4)
79  {
80  strncat(SQL_vacuum, " VERBOSE",
81  sizeof(SQL_vacuum) - strlen(SQL_vacuum) - 1);
82  strncat(SQL_analyze, " VERBOSE",
83  sizeof(SQL_analyze) - strlen(SQL_analyze) - 1);
84  }
85 
86  startTime = (long) time(0);
87  double _start = now_monotonic_seconds();
88  log_action_start("vacAnalyze (2 Queries)");
89 
90  /* Prepare descriptions for logs */
91  char desc_vac[80];
92  char desc_analyze[80];
93  snprintf(desc_vac, sizeof(desc_vac), "vacAnalyze: 1/2 - VACUUM");
94  if (serverMajor >= 17)
95  {
96  strncat(desc_vac, " FULL", sizeof(desc_vac) - strlen(desc_vac) - 1);
97  }
98  if (agent_verbose >= 4)
99  {
100  strncat(desc_vac, " VERBOSE", sizeof(desc_vac) - strlen(desc_vac) - 1);
101  }
102  snprintf(desc_analyze, sizeof(desc_analyze), "vacAnalyze: 2/2 - ANALYZE");
103  if (agent_verbose >= 4)
104  {
105  strncat(desc_analyze, " VERBOSE",
106  sizeof(desc_analyze) - strlen(desc_analyze) - 1);
107  }
108 
109  /* Vacuum */
110  PQexecCheckClear(-110, SQL_vacuum, __FILE__, __LINE__);
111  log_action_end(desc_vac, _start);
112 
113  /* Analyze */
114  PQexecCheckClear(-111, SQL_analyze, __FILE__, __LINE__);
115  log_action_end(desc_analyze, _start);
116 
117  endTime = (long) time(0);
118  printf("Vacuum/Analyze took %ld seconds\n", endTime - startTime);
119 
120  log_action_end("vacAnalyze", _start);
121 
123  1); // Tell the scheduler that we are alive and update item count
124  return; // success
125 }
126 
132 FUNCTION void validateFolders()
133 {
134  PGresult* result; // the result of the database access
135  char *countTuples;
136 
137  char *invalidUploadRefs = "DELETE FROM foldercontents WHERE foldercontents_mode = 2 AND child_id NOT IN (SELECT upload_pk FROM upload)";
138  char *invalidUploadtreeRefs = "DELETE FROM foldercontents WHERE foldercontents_mode = 4 AND child_id NOT IN (SELECT uploadtree_pk FROM uploadtree)";
139  char *unRefFolders = "DELETE FROM folder WHERE folder_pk \
140  NOT IN (SELECT child_id FROM foldercontents WHERE foldercontents_mode = 1) AND folder_pk != '1'";
141  long startTime, endTime;
142 
143  startTime = (long)time(0);
144 
145  double _start = now_monotonic_seconds();
146  log_action_start("validateFolders");
147 
148  /* Remove folder contents with invalid upload references */
149  result = PQexecCheck(-120, invalidUploadRefs, __FILE__, __LINE__);
150  countTuples = PQcmdTuples(result);
151  PQclear(result);
152  printf("%s Invalid folder upload References\n", countTuples);
153 
154  /* Remove folder contents with invalid uploadtree references */
155  result = PQexecCheck(-121, invalidUploadtreeRefs, __FILE__, __LINE__);
156  countTuples = PQcmdTuples(result);
157  PQclear(result);
158  printf("%s Invalid folder uploadtree References\n", countTuples);
159 
160  /* Remove unreferenced folders */
161  result = PQexecCheck(-122, unRefFolders, __FILE__, __LINE__);
162  countTuples = PQcmdTuples(result);
163  PQclear(result);
164  printf("%s unreferenced folders\n", countTuples);
165 
166  endTime = (long)time(0);
167  printf("Validate folders took %ld seconds\n", endTime-startTime);
168 
169  log_action_end("validateFolders", _start);
170 
171  fo_scheduler_heart(1); // Tell the scheduler that we are alive and update item count
172  return; // success
173 }
174 
190 FUNCTION void verifyFilePerms(int fix)
191 {
192 /*
193  long StartTime, EndTime;
194  char *RepoPath;
195 
196  StartTime = (long)time(0);
197 
198  RepoPath = fo_sysconfig("FOSSOLOGY", "path");
199  if (stat(RepoPath, &statbuf) == -1)
200  {
201  }
202 
203  EndTime = (long)time(0);
204  printf("Verify File Permissions took %ld seconds\n", EndTime-StartTime);
205 */
206  LOG_NOTICE("Verify file permissions is not implemented yet");
207 
208  fo_scheduler_heart(1); // Tell the scheduler that we are alive and update item count
209  return; // success
210 }
211 
217 FUNCTION void removeUploads()
218 {
219  PGresult* result; // the result of the database access
220  char *countTuples;
221  long startTime, endTime;
222 
223  char SQLBuf[MAXSQL];
224  char tempTable[64];
225 
226  double _start = now_monotonic_seconds();
227  log_action_start("removeUploads (4 Queries)");
228 
229  startTime = (long)time(0);
230 
231  /* Create a session-local temp table and populate it with candidate upload ids */
232  snprintf(tempTable, sizeof(tempTable), "tmp_ids_%d", getpid());
233 
234  snprintf(SQLBuf, MAXSQL, "CREATE TEMP TABLE %s(id bigint);", tempTable);
235  PQexecCheckClear(-130, SQLBuf, __FILE__, __LINE__);
236  log_action_end("removeUploads: 1/4 - temp table creation", _start);
237 
238  /* Insert first set: upload_fk from uploadtree where parent IS NULL and
239  * pfile_fk IS NULL */
240  snprintf(SQLBuf, MAXSQL,
241  "INSERT INTO %s (id) SELECT upload_fk FROM uploadtree WHERE parent "
242  "IS NULL AND pfile_fk IS NULL;",
243  tempTable);
244  PQexecCheckClear(-131, SQLBuf, __FILE__, __LINE__);
245  log_action_end("removeUploads: 2/4 - first set insertion", _start);
246 
247  /* Insert second set: uploads not referenced by uploadtree (and other
248  * predicates) */
249  snprintf(SQLBuf, MAXSQL,
250  "INSERT INTO %s (id) SELECT upload_pk FROM upload WHERE upload_pk "
251  "NOT IN (SELECT upload_fk FROM uploadtree) AND (expire_action IS "
252  "NULL OR expire_action != 'd') AND pfile_fk IS NOT NULL;",
253  tempTable);
254  PQexecCheckClear(-132, SQLBuf, __FILE__, __LINE__);
255  log_action_end("removeUploads: 3/4 - second set insertion", _start);
256 
257  /* Now delete via join using the temp table to avoid client-side IN lists */
258  snprintf(SQLBuf, MAXSQL,
259  "DELETE FROM upload USING %s WHERE upload.upload_pk = %s.id;",
260  tempTable, tempTable);
261  result = PQexecCheck(-133, SQLBuf, __FILE__, __LINE__);
262  countTuples = PQcmdTuples(result);
263  PQclear(result);
264  log_action_end("removeUploads: 4/4 - deletion", _start);
265 
266  endTime = (long)time(0);
267  printf("%s Uploads with no pfiles (%ld seconds)\n", countTuples, endTime-startTime);
268 
269  log_action_end("removeUploads (4 Queries)", _start);
270 
271  /* Drop the session-local temp table created earlier */
272  snprintf(SQLBuf, MAXSQL, "DROP TABLE IF EXISTS %s;", tempTable);
273  PQexecCheckClear(-134, SQLBuf, __FILE__, __LINE__);
274 
276  1); // Tell the scheduler that we are alive and update item count
277  return; // success
278 }
279 
284 FUNCTION void removeTemps()
285 {
286  PGresult* result;
287  int row;
288  int countTuples;
289  int droppedCount = 0;
290  char SQLBuf[MAXSQL];
291  long startTime, endTime;
292 
293  double _start = now_monotonic_seconds();
294  log_action_start("removeTemps");
295 
296  char* SQL =
297  "SELECT table_name FROM information_schema.tables WHERE table_type = 'BASE TABLE' "
298  "AND table_schema = 'public' AND (table_name ~ '^metaanalysis_[[:digit:]]+$' "
299  "OR table_name LIKE 'delup_%');";
300 
301  startTime = (long)time(0);
302 
303  result = PQexec(pgConn, SQL);
304  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__)) exitNow(-140);
305  countTuples = PQntuples(result);
306  /* Loop through the temp table names, dropping the tables */
307  for (row = 0; row < countTuples; row++) {
308  snprintf(SQLBuf, MAXSQL, "DROP TABLE %s", PQgetvalue(result, row, 0));
309  PQexecCheckClear(-141, SQLBuf, __FILE__, __LINE__);
310  droppedCount++;
311  }
312  PQclear(result);
313 
314  endTime = (long)time(0);
315  printf("%d Orphaned temp tables were dropped (%ld seconds)\n", droppedCount, endTime-startTime);
316 
317  log_action_end("removeTemps", _start);
318 
319  fo_scheduler_heart(1); // Tell the scheduler that we are alive and update item count
320  return; // success
321 }
322 
328 FUNCTION void processExpired()
329 {
330 /*
331  PGresult* result; // the result of the database access
332  int numrows; // generic return value
333  long StartTime, EndTime;
334 
335  StartTime = (long)time(0);
336 
337  EndTime = (long)time(0);
338  printf("Process expired uploads took %ld seconds\n", EndTime-StartTime);
339 */
340  LOG_NOTICE("Process expired uploads is not implemented yet");
341 
342  fo_scheduler_heart(1); // Tell the scheduler that we are alive and update item count
343  return; // success
344 }
345 
353 FUNCTION void removeOrphanedFiles()
354 {
355  long StartTime, EndTime;
356  double _start = now_monotonic_seconds();
357  log_action_start("removeOrphanedFiles");
358 
359  char* repoPath;
360  char filesPath[myBUFSIZ];
361 
362  StartTime = (long)time(0);
363 
364  repoPath = fo_sysconfig("FOSSOLOGY", "path");
365  strncpy(filesPath, repoPath, myBUFSIZ - 1);
366  strncat(filesPath, "/localhost/files", myBUFSIZ - 1);
367 
368  if (access(filesPath, R_OK | W_OK) != 0)
369  {
370  LOG_ERROR("Files path is not readable/writeable: '%s'", filesPath);
371  }
372  else
373  {
374  recurseDir("files", filesPath, 3);
375  }
376 
377  EndTime = (long)time(0);
378  printf("Remove orphaned files from the repository took %ld seconds\n",
379  EndTime - StartTime);
380 
381  log_action_end("removeOrphanedFiles", _start);
382 
383  return; // success
384 }
385 
393 FUNCTION void deleteOrphanGold()
394 {
395  long StartTime, EndTime;
396  double _start = now_monotonic_seconds();
397  log_action_start("deleteOrphanGold");
398 
399  char* repoPath;
400  char goldPath[myBUFSIZ];
401 
402  StartTime = (long)time(0);
403 
404  repoPath = fo_sysconfig("FOSSOLOGY", "path");
405  strncpy(goldPath, repoPath, myBUFSIZ - 1);
406  strncat(goldPath, "/localhost/gold", myBUFSIZ - 1);
407 
408  if (access(goldPath, R_OK | W_OK) != 0)
409  {
410  LOG_ERROR("Gold path is not readable/writeable: '%s'", goldPath);
411  }
412  else
413  {
414  recurseDir("gold", goldPath, 3);
415  }
416 
417  EndTime = (long)time(0);
418  printf("Remove orphaned gold files from the repository took %ld seconds\n",
419  EndTime - StartTime);
420 
421  log_action_end("deleteOrphanGold", _start);
422 
423  return; // success
424 }
425 
431 {
432  long startTime, endTime;
433  double _start = now_monotonic_seconds();
434  log_action_start("normalizeUploadPriorities (3 Queries)");
435 
436  char* SQL1 =
437  "CREATE TEMPORARY TABLE tmp_upload_prio(ordprio serial, uploadid int, groupid int)";
438  char* SQL2 =
439  "INSERT INTO tmp_upload_prio (uploadid, groupid) "
440  "(SELECT upload_fk uploadid, group_fk groupid FROM upload_clearing ORDER BY priority ASC);";
441  char* SQL3 =
442  "UPDATE upload_clearing "
443  "SET priority = ordprio FROM tmp_upload_prio "
444  "WHERE uploadid=upload_fk AND group_fk=groupid;";
445 
446  startTime = (long)time(0);
447 
448  PQexecCheckClear(-180, SQL1, __FILE__, __LINE__);
449  log_action_end("normalizeUploadPriorities: 1/3", _start);
450 
451  PQexecCheckClear(-181, SQL2, __FILE__, __LINE__);
452  log_action_end("normalizeUploadPriorities: 2/3", _start);
453 
454  PQexecCheckClear(-182, SQL3, __FILE__, __LINE__);
455  log_action_end("normalizeUploadPriorities: 3/3", _start);
456 
457  endTime = (long)time(0);
458  printf("Normalized upload priorities (%ld seconds)\n", endTime-startTime);
459 
460  log_action_end("normalizeUploadPriorities (3 Queries)", _start);
461 
462  fo_scheduler_heart(1); // Tell the scheduler that we are alive and update item count
463  return; // success
464 }
465 
470 FUNCTION void reIndexAllTables()
471 {
472  PGresult* result; // the result of the database access
473  char SQLBuf[MAXSQL];
474  long startTime, endTime;
475  double _start = now_monotonic_seconds();
476  log_action_start("reIndexAllTables");
477 
478  char* SQL =
479  "SELECT table_catalog FROM information_schema.tables WHERE table_type = "
480  "'BASE TABLE' AND table_schema = 'public' AND table_name LIKE"
481  "'upload%' LIMIT 1";
482 
483  startTime = (long)time(0);
484 
485  result = PQexec(pgConn, SQL);
486  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__)) exitNow(-190);
487 
488  memset(SQLBuf,'\0',sizeof(SQLBuf));
489  snprintf(SQLBuf,sizeof(SQLBuf),"REINDEX DATABASE %s;", PQgetvalue(result, 0, 0));
490  PQclear(result);
491  PQexecCheckClear(-191, SQLBuf, __FILE__, __LINE__);
492 
493  endTime = (long)time(0);
494  printf("Time taken for reindexing the database : %ld seconds\n", endTime-startTime);
495 
496  log_action_end("reIndexAllTables", _start);
497 
498  fo_scheduler_heart(1); // Tell the scheduler that we are alive and update item count
499  return; // success
500 }
501 
506 FUNCTION void removeOrphanedRows()
507 {
508  PGresult* result; // the result of the database access
509  char *countTuples;
510  long startTime, endTime;
511  double _start = now_monotonic_seconds();
512  log_action_start("removeOrphanedRows (6 Queries)");
513 
514  char* SQL1 =
515  "DELETE FROM uploadtree UT "
516  " WHERE NOT EXISTS ( "
517  " SELECT 1 "
518  " FROM upload U "
519  " WHERE UT.upload_fk = U.upload_pk "
520  " );";
521 
522  char* SQL2 =
523  "DELETE FROM clearing_decision AS CD "
524  " WHERE NOT EXISTS ( "
525  " SELECT 1 "
526  " FROM uploadtree UT "
527  " WHERE CD.uploadtree_fk = UT.uploadtree_pk "
528  " ) AND CD.scope = '0';";
529 
530  char* SQL3 =
531  "DELETE FROM clearing_event CE "
532  " WHERE NOT EXISTS ( "
533  " SELECT 1 "
534  " FROM uploadtree UT "
535  " WHERE CE.uploadtree_fk = UT.uploadtree_pk "
536  " ) AND NOT EXISTS ( "
537  " SELECT 1 "
538  " FROM clearing_decision CD"
539  " WHERE CD.uploadtree_fk = CE.uploadtree_fk "
540  " AND CD.scope = '1'"
541  " );";
542 
543  char* SQL4 =
544  "DELETE FROM clearing_decision_event CDE"
545  " WHERE NOT EXISTS ( "
546  " SELECT 1 "
547  " FROM clearing_event CE "
548  " WHERE CE.clearing_event_pk = CDE.clearing_event_fk "
549  " );";
550 
551  char* SQL5 =
552  "DELETE FROM obligation_map OM "
553  " WHERE NOT EXISTS ( "
554  " SELECT 1 "
555  " FROM license_ref LR "
556  " WHERE OM.rf_fk = LR.rf_pk "
557  " );";
558 
559  char* SQL6 =
560  "DELETE FROM obligation_candidate_map OCM "
561  " WHERE NOT EXISTS ( "
562  " SELECT 1 "
563  " FROM license_ref LR "
564  " WHERE OCM.rf_fk = LR.rf_pk "
565  " );";
566 
567  startTime = (long)time(0);
568 
569  result = PQexecCheck(-200, SQL1, __FILE__, __LINE__);
570  countTuples = PQcmdTuples(result);
571  PQclear(result);
572  printf("%s Orphaned records have been removed from uploadtree table\n", countTuples);
574  log_action_end("removeOrphanedRows: 1/6 - uploadtree", _start);
575 
576  result = PQexecCheck(-201, SQL2, __FILE__, __LINE__);
577  countTuples = PQcmdTuples(result);
578  PQclear(result);
579  printf("%s Orphaned records have been removed from clearing_decision table\n", countTuples);
581  log_action_end("removeOrphanedRows: 2/6 - clearing_decision", _start);
582 
583  result = PQexecCheck(-202, SQL3, __FILE__, __LINE__);
584  countTuples = PQcmdTuples(result);
585  PQclear(result);
586  printf("%s Orphaned records have been removed from clearing_event table\n", countTuples);
588  log_action_end("removeOrphanedRows: 3/6 - clearing_event", _start);
589 
590  result = PQexecCheck(-203, SQL4, __FILE__, __LINE__);
591  countTuples = PQcmdTuples(result);
592  PQclear(result);
593  printf("%s Orphaned records have been removed from clearing_decision_event table\n", countTuples);
595  log_action_end("removeOrphanedRows: 4/6 - clearing_decision_event", _start);
596 
597  result = PQexecCheck(-204, SQL5, __FILE__, __LINE__);
598  countTuples = PQcmdTuples(result);
599  PQclear(result);
600  printf("%s Orphaned records have been removed from obligation_map table\n", countTuples);
602  log_action_end("removeOrphanedRows: 5/6 - obligation_map", _start);
603 
604  result = PQexecCheck(-205, SQL6, __FILE__, __LINE__);
605  countTuples = PQcmdTuples(result);
606  PQclear(result);
607  printf("%s Orphaned records have been removed from obligation_candidate_map table\n", countTuples);
608  fo_scheduler_heart(1); // Tell the scheduler that we are alive and update item count
609  log_action_end("removeOrphanedRows: 6/6 - obligation_candidate_map", _start);
610 
611  endTime = (long)time(0);
612 
613  printf("Time taken for removing orphaned rows from database : %ld seconds\n", endTime-startTime);
614 
615  log_action_end("removeOrphanedRows (6 Queries)", _start);
616 
617  return; // success
618 }
619 
620 
625 FUNCTION void removeOrphanedLogFiles()
626 {
627  PGresult* result;
628  PGresult* updateResult;
629  int row;
630  int countTuples;
631  int removedCount = 0;
632  int jobQueueId;
633  char* logPath;
634  long startTime, endTime;
635  fo_dbManager_PreparedStatement* updateStatement;
636  struct stat statbuf;
637 
638  double _start = now_monotonic_seconds();
639  log_action_start("removeOrphanedLogFiles");
640 
641  char* SQL =
642  "SELECT jq_pk, jq_log FROM job ja "
643  "INNER JOIN job jb ON ja.job_upload_fk = jb.job_upload_fk "
644  "INNER JOIN jobqueue jq ON jb.job_pk = jq.jq_job_fk "
645  "WHERE ja.job_name = 'Delete' AND jq_log IS NOT NULL "
646  "AND jq_log != 'removed';";
647 
648  startTime = (long)time(0);
649 
650  result = PQexec(pgConn, SQL);
651  if (fo_checkPQresult(pgConn, result, SQL, __FILE__, __LINE__))
652  {
653  exitNow(-140);
654  }
655  countTuples = PQntuples(result);
656 
657  updateStatement = fo_dbManager_PrepareStamement(dbManager,
658  "updateRemovedLogFromJobqueue",
659  "UPDATE jobqueue SET jq_log = 'removed' WHERE jq_pk = $1;", int);
660  /* Loop through the logs found and delete them. Also update the database */
661  for (row = 0; row < countTuples; row++)
662  {
663  fo_dbManager_begin(dbManager);
664  jobQueueId = atoi(PQgetvalue(result, row, 0));
665  logPath = PQgetvalue(result, row, 1);
666  if (stat(logPath, &statbuf) == -1)
667  {
668  LOG_NOTICE("Log file '%s' does not exists", logPath);
669  }
670  else
671  {
672  remove(logPath);
673  LOG_VERBOSE2("Removed file '%s'", logPath);
674  }
675  updateResult = fo_dbManager_ExecPrepared(updateStatement, jobQueueId);
676  if (updateResult)
677  {
678  PQclear(updateResult);
679  removedCount++;
680  }
681  else
682  {
683  LOG_ERROR("Unable to update the value of jobqueue.jq_log to 'removed' "
684  "for jq_pk = %d", jobQueueId);
685  }
686  fo_dbManager_commit(dbManager);
687  }
688  PQclear(result);
689 
690  endTime = (long)time(0);
691  printf("%d / %d Orphaned log files were removed "
692  "(%ld seconds)\n", removedCount, countTuples, endTime - startTime);
693 
694  log_action_end("removeOrphanedLogFiles", _start);
695 
696  fo_scheduler_heart(1); // Tell the scheduler that we are alive and update item count
697  return; // success
698 }
699 
704 FUNCTION void removeExpiredTokens(long int retentionPeriod)
705 {
706  PGresult* result; // the result of the database access
707  char *countTuples;
708  long startTime, endTime;
709  char SQL[1024];
710  time_t current_time = time(0);
711  time_t shifted_time = current_time - (retentionPeriod*24*60*60);
712  struct tm time_structure = *localtime(&shifted_time);
713 
714  double _start = now_monotonic_seconds();
715  log_action_start("removeExpiredTokens");
716 
717  snprintf(SQL, sizeof(SQL),
718  "DELETE FROM personal_access_tokens WHERE (active = 'FALSE' OR expire_on < '%d-%02d-%02d') AND client_id IS NULL",
719  time_structure.tm_year + 1900,
720  time_structure.tm_mon + 1,
721  time_structure.tm_mday
722  );
723 
724  startTime = (long)time(0);
725 
726  result = PQexecCheck(-220, SQL, __FILE__, __LINE__);
727  countTuples = PQcmdTuples(result);
728  PQclear(result);
729  printf("%s Expired personal access tokens have been removed from personal_access_tokens table\n", countTuples);
731 
732  endTime = (long)time(0);
733 
734  printf("Time taken for removing expired personal access tokens from database : %ld seconds\n", endTime-startTime);
735 
736  log_action_end("removeExpiredTokens", _start);
737 
738  return; // success
739 }
740 
748 FUNCTION void deleteOldGold(char* date)
749 {
750  PGresult* result; // the result of the database access
751  int numrows = 0; // generic return value
752  long StartTime, EndTime;
753  int countTuples, row, remval;
754  int day, month, year; // Date validation
755  char* filepath;
756  char sql[MAXSQL];
757 
758  day = month = year = -1;
759  sscanf(date, "%4d-%2d-%2d", &year, &month, &day);
760  if (((year < 1900) || (year > 9999)) || ((month < 1) || (month > 12)) ||
761  ((day < 1) || (day > 31)))
762  {
763  LOG_FATAL("Invalid date! Require yyyy-mm-dd, '%s' given.", date);
764  exitNow(-144);
765  }
766 
767  double _start = now_monotonic_seconds();
768  log_action_start("deleteOldGold");
769 
770  snprintf(sql, MAXSQL,
771  "SELECT DISTINCT ON(pfile_pk) "
772  "CONCAT(LOWER(pfile_sha1), '.', LOWER(pfile_md5), '.', pfile_size) "
773  "AS filename FROM upload INNER JOIN pfile ON pfile_pk = pfile_fk "
774  "WHERE upload_ts < '%s' AND pfile_fk NOT IN ("
775  "SELECT pfile_fk FROM upload WHERE upload_ts > '%s' "
776  "AND pfile_fk IS NOT NULL);",
777  date, date);
778 
779  StartTime = (long)time(0);
780 
781  result = PQexec(pgConn, sql);
782  if (fo_checkPQresult(pgConn, result, sql, __FILE__, __LINE__))
783  {
784  exitNow(-145);
785  }
786  countTuples = PQntuples(result);
787  if (agent_verbose)
788  {
789  LOG_DEBUG("Read %d rows from DB.", countTuples);
790  }
791  /* Loop through the pfiles and remove them from repository */
792  for (row = 0; row < countTuples; row++)
793  {
794  filepath = fo_RepMkPath("gold", PQgetvalue(result, row, 0));
795  remval = remove(filepath);
796  if (remval < 0)
797  {
798  if (errno != ENOENT)
799  {
800  // Removal failed and error != file not exist
801  LOG_WARNING("Unable to remove '%s' file.", filepath);
802  }
803  }
804  else
805  {
806  numrows++;
807  }
808  free(filepath);
809  }
810  PQclear(result);
811 
812  EndTime = (long)time(0);
813  printf("Removed %d old gold files from the repository, took %ld seconds\n",
814  numrows, EndTime - StartTime);
815 
816  log_action_end("deleteOldGold", _start);
817 
819  1); // Tell the scheduler that we are alive and update item count
820  return; // success
821 }
822 
823 /*
824  * @brief Delete all log files older than given date in olderThan param
825  *
826  * -# Use find to list all files in a temporary location.
827  * -# Use the number of lines in the file to get the total no of files.
828  * -# Feed the file to xargs and call rm to remove them.
829  * -# Close the fd and unlink the temporary file.
830  * @param olderThan Delete logs older than this date (YYYY-MM-DD)
831  */
832 FUNCTION void removeOldLogFiles(const char* olderThan)
833 {
834  time_t current_time = time(0);
835  time_t shifted_time;
836  time_t ellapsed_time;
837  struct tm ti = {0};
838  char cmd[myBUFSIZ];
839  unsigned int numfiles = 0;
840  long StartTime, EndTime;
841  char ch;
842  FILE* tempFile;
843  int retval;
844 
845  double _start = now_monotonic_seconds();
846  log_action_start("removeOldLogFiles");
847  StartTime = (long)time(0);
848  if (sscanf(olderThan, "%d-%d-%d", &ti.tm_year, &ti.tm_mon, &ti.tm_mday) != 3)
849  {
850  LOG_FATAL("Unable to parse date '%s' in YYYY-MM-DD format.", olderThan);
851  exitNow(-148);
852  }
853  ti.tm_year -= 1900;
854  ti.tm_mon -= 1;
855  shifted_time = mktime(&ti);
856  ellapsed_time = (current_time - shifted_time) / 60 / 60 / 24 - 1;
857 
858  char file_template[] = "/tmp/foss-XXXXXX";
859  int fd = mkstemp(file_template);
860 
861  snprintf(cmd, myBUFSIZ, "/usr/bin/find %s/logs -type f -mtime +%ld -fprint %s",
862  fo_sysconfig("FOSSOLOGY", "path"), ellapsed_time, file_template);
863  retval = system(cmd); // Find and print files in temp location
864  if (!WIFEXITED(retval))
865  { // find fail
866  LOG_FATAL("Unable run find for logs files.");
867  unlink(file_template);
868  exitNow(-148);
869  }
870  tempFile = fdopen(fd, "r");
871  if (tempFile == NULL)
872  {
873  LOG_FATAL("Unable to open temp file.");
874  unlink(file_template);
875  exitNow(-148);
876  }
877  while ((ch = fgetc(tempFile)) != EOF)
878  {
879  if (ch == '\n')
880  {
881  numfiles++;
882  }
883  }
884 
885  snprintf(cmd, myBUFSIZ, "/usr/bin/xargs --arg-file=%s /bin/rm -f", file_template);
886  retval = system(cmd);
887  if (!WIFEXITED(retval))
888  { // xargs fail
889  LOG_FATAL("Unable delete log files with xargs.");
890  fclose(tempFile);
891  unlink(file_template);
892  exitNow(-148);
893  }
894  fclose(tempFile);
895  unlink(file_template);
896 
897  EndTime = (long)time(0);
898 
899  printf("Removed %d log files.\n", numfiles);
900 
901  printf(
902  "Removing log files older than '%s' from the repository took %ld "
903  "seconds\n",
904  olderThan, EndTime - StartTime);
905 
906  log_action_end("removeOldLogFiles", _start);
907 
909  return;
910 }
char SQL[256]
SQL query to execute.
Definition: adj2nest.c:78
void exitNow(int exitVal)
Exit function. This does all cleanup and should be used instead of calling exit() or main() return.
Definition: util.c:1177
PGconn * pgConn
Database connection.
Definition: adj2nest.c:86
int fo_checkPQresult(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres SELECT.
Definition: libfossdb.c:170
int fo_checkPQcommand(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres commands (not select) If an error occured, write the error to s...
Definition: libfossdb.c:204
char * fo_RepMkPath(const char *Type, char *Filename)
Given a filename, construct the full path to the file.
Definition: libfossrepo.c:352
void fo_scheduler_heart(int i)
This function must be called by agents to let the scheduler know they are alive and how many items th...
char * fo_sysconfig(const char *sectionname, const char *variablename)
gets a system configuration variable from the configuration data.
int agent_verbose
Common verbose flags for the agents, this is used so that the scheduler can change the verbose level ...
FUNCTION void removeOrphanedRows()
remove orphaned rows from fossology database
Definition: process.c:506
FUNCTION void verifyFilePerms(int fix)
Verify and optionally fix file permissions.
Definition: process.c:190
FUNCTION void deleteOldGold(char *date)
Delete gold files which are older than specified date.
Definition: process.c:748
FUNCTION void removeTemps()
Remove orphaned temp tables from deprecated pkgmettagetta and old delagent.
Definition: process.c:284
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
PGresult * PQexecCheck(int exitNumber, char *SQL, char *file, const int line)
simple wrapper which includes PQexec and fo_checkPQcommand
Definition: process.c:26
FUNCTION void reIndexAllTables()
reindex of all indexes in fossology database
Definition: process.c:470
FUNCTION void removeOldLogFiles(const char *olderThan)
Definition: process.c:832
FUNCTION void removeUploads()
Remove Uploads with no pfiles.
Definition: process.c:217
FUNCTION void removeOrphanedLogFiles()
Definition: process.c:625
FUNCTION void PQexecCheckClear(int exitNumber, char *SQL, char *file, const int line)
Execute SQL query and create the result and clear the result.
Definition: process.c:42
FUNCTION void processExpired()
Process expired uploads (slow)
Definition: process.c:328
FUNCTION void removeExpiredTokens(long int retentionPeriod)
remove expired personal access tokens from fossology database
Definition: process.c:704
FUNCTION void validateFolders()
Validate folder and foldercontents tables.
Definition: process.c:132
FUNCTION void removeOrphanedFiles()
Remove orphaned files from the repository (slow) Loop through each file in the repository and make su...
Definition: process.c:353
FUNCTION void vacAnalyze()
Do database vacuum and analyze.
Definition: process.c:53
FUNCTION void deleteOrphanGold()
Delete orphaned gold files from the repository.
Definition: process.c:393
FUNCTION void normalizeUploadPriorities()
Normalize priority of Uploads.
Definition: process.c:430
FUNCTION void recurseDir(const char *type, char *path, int level)
Recursively read directory till level is 0.
Definition: utils.c:131
PGresult * fo_dbManager_ExecPrepared(fo_dbManager_PreparedStatement *preparedStatement,...)
Execute a prepared statement.
Definition: standalone.c:37