FOSSology  4.4.0
Open Source License Compliance by Open Source Software
scheduler.c
1 /*
2  Author: Daniele Fognini
3  SPDX-FileCopyrightText: © 2013-2014 Siemens AG
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
8 #include "scheduler.h"
9 
10 #include "common.h"
11 #include "database.h"
12 
13 MatchCallbacks schedulerCallbacks =
14  { .onNo = sched_onNoMatch,
15  .onFull = sched_onFullMatch,
16  .onDiff = sched_onDiffMatch,
17  .onBeginOutput = sched_noop,
18  .onBetweenIndividualOutputs = sched_noop,
19  .onEndOutput = sched_noop,
20  .ignore = sched_ignore
21  };
22 
23 int processUploadId(MonkState* state, int uploadId, const Licenses* licenses) {
24  PGresult* fileIdResult = queryFileIdsForUpload(state->dbManager, uploadId, state->ignoreFilesWithMimeType);
25 
26  if (!fileIdResult)
27  return 0;
28 
29  if (PQntuples(fileIdResult) == 0) {
30  PQclear(fileIdResult);
32  return 1;
33  }
34 
35  int threadError = 0;
36 #ifdef MONK_MULTI_THREAD
37  #pragma omp parallel
38 #endif
39  {
40  MonkState threadLocalStateStore = *state;
41  MonkState* threadLocalState = &threadLocalStateStore;
42 
43  threadLocalState->dbManager = fo_dbManager_fork(state->dbManager);
44  if (threadLocalState->dbManager) {
45  int count = PQntuples(fileIdResult);
46 #ifdef MONK_MULTI_THREAD
47  #pragma omp for schedule(dynamic)
48 #endif
49  for (int i = 0; i < count; i++) {
50  if (threadError)
51  continue;
52 
53  long pFileId = atol(PQgetvalue(fileIdResult, i, 0));
54 
55  if ((pFileId <= 0) || hasAlreadyResultsFor(threadLocalState->dbManager, threadLocalState->agentId, pFileId))
56  {
58  continue;
59  }
60 
61  if (matchPFileWithLicenses(threadLocalState, pFileId, licenses, &schedulerCallbacks, DELIMITERS)) {
63  } else {
65  threadError = 1;
66  }
67  }
68  fo_dbManager_finish(threadLocalState->dbManager);
69  } else {
70  threadError = 1;
71  }
72  }
73  PQclear(fileIdResult);
74 
75  return !threadError;
76 }
77 
78 int handleSchedulerMode(MonkState* state, const Licenses* licenses) {
79  /* scheduler mode */
80  state->scanMode = MODE_SCHEDULER;
81  queryAgentId(state, AGENT_NAME, AGENT_DESC);
82 
83  while (fo_scheduler_next() != NULL) {
84  int uploadId = atoi(fo_scheduler_current());
85 
86  if (uploadId == 0) continue;
87 
88  int arsId = fo_WriteARS(fo_dbManager_getWrappedConnection(state->dbManager),
89  0, uploadId, state->agentId, AGENT_ARS, NULL, 0);
90 
91  if (arsId<=0)
92  bail(state, 1);
93 
94  if (!processUploadId(state, uploadId, licenses))
95  bail(state, 2);
96 
97  fo_WriteARS(fo_dbManager_getWrappedConnection(state->dbManager),
98  arsId, uploadId, state->agentId, AGENT_ARS, NULL, 1);
99  }
101 
102  return 1;
103 }
104 
105 int sched_onNoMatch(MonkState* state, const File* file) {
106  return saveNoResultToDb(state->dbManager, state->agentId, file->id);
107 }
108 
109 int sched_onFullMatch(MonkState* state, const File* file, const License* license, const DiffMatchInfo* matchInfo) {
110  fo_dbManager* dbManager = state->dbManager;
111  const int agentId = state->agentId;
112  const long fileId = file->id;
113 
114 #ifdef DEBUG
115  printf("found full match between (pFile=%ld) and \"%s\" (rf_pk=%ld)\n", file->id, license->shortname, license->refId);
116 #endif //DEBUG
117 
118  fo_dbManager_begin(dbManager);
119 
120  int success = 0;
121  long licenseFileId = saveToDb(dbManager, agentId, license->refId, fileId, 100);
122  if (licenseFileId > 0) {
123  success = saveDiffHighlightToDb(dbManager, matchInfo, licenseFileId);
124  }
125 
126  if (success) {
127  fo_dbManager_commit(dbManager);
128  } else {
129  fo_dbManager_rollback(dbManager);
130  }
131  return success;
132 }
133 
134 int sched_onDiffMatch(MonkState* state, const File* file, const License* license, const DiffResult* diffResult) {
135  fo_dbManager* dbManager = state->dbManager;
136  const int agentId = state->agentId;
137  const long fileId = file->id;
138 
139  unsigned short matchPercent = diffResult->percentual;
140 
141 #ifdef DEBUG
142  printf("found diff match between (pFile=%ld) and \"%s\" (rf_pk=%ld); ", file->id, license->shortname, license->refId);
143  printf("%u%%; ", diffResult->percentual);
144 
145  char * formattedMatchArray = formatMatchArray(diffResult->matchedInfo);
146  printf("diffs: {%s}\n", formattedMatchArray);
147  free(formattedMatchArray);
148 #endif //DEBUG
149 
150  fo_dbManager_begin(dbManager);
151 
152  int success = 0;
153  long licenseFileId = saveToDb(dbManager, agentId, license->refId, fileId, matchPercent);
154  if (licenseFileId > 0) {
155  success = saveDiffHighlightsToDb(dbManager, diffResult->matchedInfo, licenseFileId);
156  }
157 
158  if (success) {
159  fo_dbManager_commit(dbManager);
160  } else {
161  fo_dbManager_rollback(dbManager);
162  }
163 
164  return success;
165 }
166 
167 /* check if we have other results for this file.
168  * We do it now to minimize races with a concurrent scan of this file:
169  * the same file could be inside more than upload
170  */
171 int sched_ignore(MonkState* state, const File* file)
172 {
173  return hasAlreadyResultsFor(state->dbManager, state->agentId, file->id);
174 }
175 
176 #pragma GCC diagnostic push
177 #pragma GCC diagnostic ignored "-Wunused-parameter"
178 int sched_noop(MonkState* state) {
179  return 1;
180 }
181 #pragma GCC diagnostic pop
void matchPFileWithLicenses(CopyrightState const &state, int agentId, unsigned long pFileId, CopyrightDatabaseHandler &databaseHandler)
Get the file contents, scan for statements and save findings to database.
int queryAgentId(PGconn *dbConn)
Get agent id, exit if agent id is incorrect.
bool processUploadId(const CopyrightState &state, int agentId, int uploadId, CopyrightDatabaseHandler &databaseHandler, bool ignoreFilesWithMimeType)
Process a given upload id, scan from statements and add to database.
void bail(int exitval)
Disconnect with scheduler returning an error code and exit.
PGresult * queryFileIdsForUpload(fo_dbManager *dbManager, int uploadId, bool ignoreFilesWithMimeType)
Get all file IDs (pfile_fk) for a given upload.
Definition: libfossagent.c:61
FUNCTION int fo_WriteARS(PGconn *pgConn, int ars_pk, int upload_pk, int agent_pk, const char *tableName, const char *ars_status, int ars_success)
Write ars record.
Definition: libfossagent.c:214
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_scheduler_current()
Get the last read string from the scheduler.
char * fo_scheduler_next()
Get the next data to process from the scheduler.
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
Header file for the scheduler.
Definition: monk.h:61
Definition: monk.h:55
Definition: monk.h:67
Definition: monk.h:44
Definition: nomos.h:426