18 #include "string_operations.h"
19 #include "highlight.h"
22 static GHashTable* phraseByCpId = NULL;
24 int phrase_onAllMatches(
MonkState* state,
const File* file,
const GArray* matches);
30 char* parseDelimiters(
const char* input) {
31 if (input == NULL || strlen(input) == 0) {
32 return g_strdup(
" ,\t\n\r\f");
35 GString* result = g_string_new(
" ,\t\n\r\f");
37 gchar** tokens = g_strsplit(input,
",", -1);
39 for (
int i = 0; tokens[i] != NULL; i++) {
40 gchar* token = g_strstrip(tokens[i]);
42 if (strlen(token) > 0) {
43 for (
int j = 0; token[j] !=
'\0'; j++) {
45 if (strchr(result->str, c) == NULL) {
46 g_string_append_c(result, c);
55 const char* essentialDelims =
" ,\t\n\r\f";
56 for (
const char* p = essentialDelims; *p !=
'\0'; p++) {
57 if (strchr(result->str, *p) == NULL)
58 g_string_append_c(result, *p);
61 return g_string_free(result, FALSE);
65 Licenses* buildLicenseIndexFromPhrases(GArray* phrases,
const char* delimiters) {
66 GArray* licenseArray = g_array_new(FALSE, FALSE,
sizeof(
License));
70 g_hash_table_destroy(phraseByCpId);
72 phraseByCpId = g_hash_table_new(g_direct_hash, g_direct_equal);
74 for (guint i = 0; i < phrases->len; i++) {
78 if (!phrase->licenseMappings || phrase->licenseMappings->len == 0) {
84 license.shortname = g_strdup_printf(
"phrase_%ld", phrase->cpId);
85 license.tokens = tokenize(phrase->text, delimiters);
87 g_array_append_val(licenseArray,
license);
90 g_hash_table_insert(phraseByCpId, GSIZE_TO_POINTER(phrase->cpId), phrase);
93 return buildLicenseIndexes(licenseArray, MIN_ADJACENT_MATCHES, MAX_LEADING_DIFF);
97 int saveKotobaHighlights(
MonkState* state,
const File* file,
const GArray* matches,
98 long clearingEventId,
long phraseId) {
99 for (guint j = 0; j < matches->len; j++) {
103 if (
match->type != MATCH_TYPE_FULL)
108 DiffPoint highlight = getFullHighlightFor(file->tokens,
109 highlightTokens->start,
110 highlightTokens->length);
114 fo_dbManager_PrepareStamement(
116 "saveKotobaHighlight",
117 "INSERT INTO highlight_kotoba(clearing_event_fk, cp_fk, start, len) VALUES($1,$2,$3,$4)",
118 long,
long,
size_t,
size_t
126 if (!highlightResult) {
130 PQclear(highlightResult);
137 int phrase_onAllMatches(
MonkState* state,
const File* file,
const GArray* matches) {
138 int haveAFullMatch = 0;
139 for (guint j = 0; j < matches->len; j++) {
141 if (
match->type == MATCH_TYPE_FULL) {
152 if (!fo_dbManager_begin(state->dbManager))
155 for (guint j = 0; j < matches->len; j++) {
157 if (
match->type != MATCH_TYPE_FULL)
160 Phrase* phrase = g_hash_table_lookup(phraseByCpId, GSIZE_TO_POINTER(
match->license->refId));
164 for (guint k = 0; k < phrase->licenseMappings->len; k++) {
170 (phrase->comments ? phrase->comments :
"");
173 (phrase->acknowledgement ? phrase->acknowledgement :
"");
176 fo_dbManager_PrepareStamement(
180 long,
int,
int,
int,
int,
long,
int,
char*,
char*,
char*,
int
186 BULK_DECISION_TYPE_KOTOBA,
196 fo_dbManager_rollback(state->dbManager);
200 long clearingEventId = -1;
201 if (PQntuples(result) == 1)
202 clearingEventId = atol(PQgetvalue(result, 0, 0));
205 if (clearingEventId <= 0)
209 if (!saveKotobaHighlights(state, file, matches, clearingEventId, phrase->cpId)) {
210 fo_dbManager_rollback(state->dbManager);
217 return fo_dbManager_commit(state->dbManager);
221 int processUploadWithPhrases(
MonkState* state,
int uploadId) {
226 GArray* phrases = queryActiveCustomPhrases(state->dbManager);
227 if (!phrases || phrases->len == 0) {
229 phrases_free(phrases);
233 char* configDelimiters = NULL;
234 PGresult* delimitersResult = fo_dbManager_Exec_printf(state->dbManager,
235 "SELECT conf_value FROM sysconfig WHERE variablename='KotobaDelimiters'");
236 if (delimitersResult && PQntuples(delimitersResult) > 0 && !PQgetisnull(delimitersResult, 0, 0))
237 configDelimiters = g_strdup(PQgetvalue(delimitersResult, 0, 0));
238 if (delimitersResult)
239 PQclear(delimitersResult);
241 char* delimiters = parseDelimiters(configDelimiters);
242 g_free(configDelimiters);
246 gchar* insertSql = g_strdup_printf(
247 "INSERT INTO clearing_event(uploadtree_fk, user_fk, group_fk, job_fk, type_fk, rf_fk, removed, comment, reportinfo, acknowledgement) "
248 "SELECT uploadtree_pk, $2, $3, $4, $5, $6, $7, $8, $9, $10 "
249 "FROM %s WHERE upload_fk = $11 AND pfile_fk = $1 "
250 "RETURNING clearing_event_pk",
251 uploadTreeTableName);
254 for (guint i = 0; i < phrases->len; i++) {
257 p->stmtName = g_strdup_printf(
"phrase_decision.%s.%ld", uploadTreeTableName, p->cpId);
259 g_free(uploadTreeTableName);
262 .uploadId = uploadId,
267 .delimiters = delimiters,
268 .uploadTreeTableName = NULL,
269 .insertSql = insertSql
274 Licenses* licenses = buildLicenseIndexFromPhrases(phrases, args.delimiters);
276 phrases_free(phrases);
277 g_free(args.delimiters);
278 g_free(args.insertSql);
284 licenses_free(licenses);
285 phrases_free(phrases);
286 g_free(args.delimiters);
287 g_free(args.insertSql);
291 if (PQntuples(fileIdResult) == 0) {
292 PQclear(fileIdResult);
293 licenses_free(licenses);
294 phrases_free(phrases);
295 g_free(args.delimiters);
296 g_free(args.insertSql);
302 int resultsCount = PQntuples(fileIdResult);
304 #ifdef MONK_MULTI_THREAD
308 MonkState threadLocalStateStore = *state;
309 MonkState* threadLocalState = &threadLocalStateStore;
310 threadLocalState->ptr = &args;
312 threadLocalState->dbManager = fo_dbManager_fork(state->dbManager);
313 if (threadLocalState->dbManager) {
314 #ifdef MONK_MULTI_THREAD
315 #pragma omp for schedule(dynamic)
317 for (
int i = 0; i < resultsCount; i++) {
321 long fileId = atol(PQgetvalue(fileIdResult, i, 0));
324 &phraseCallbacks, args.delimiters)) {
331 fo_dbManager_finish(threadLocalState->dbManager);
337 PQclear(fileIdResult);
338 licenses_free(licenses);
339 phrases_free(phrases);
340 g_free(args.delimiters);
341 g_free(args.insertSql);
347 int main(
int argc,
char** argv) {
355 state->scanMode = MODE_BULK;
360 int uploadId = atoi(schedulerCurrent);
362 if (uploadId == 0)
continue;
364 int arsId =
fo_WriteARS(fo_dbManager_getWrappedConnection(state->dbManager),
365 0, uploadId, state->agentId, AGENT_ARS, NULL, 0);
370 if (!processUploadWithPhrases(state, uploadId))
373 fo_WriteARS(fo_dbManager_getWrappedConnection(state->dbManager),
374 arsId, uploadId, state->agentId, AGENT_ARS, NULL, 1);
381 g_hash_table_destroy(phraseByCpId);
385 scheduler_disconnect(state, 0);
int queryAgentId(DbManager &dbManager)
Query and register the agent id. Bails on failure.
void bail(int exitval)
Disconnect scheduler and exit.
void matchPFileWithLicenses(CopyrightState const &state, int agentId, unsigned long pFileId, CopyrightDatabaseHandler &databaseHandler, int uploadId, const string &uploadTreeTableName)
Get the file contents, scan for statements and save findings to database.
char * getUploadTreeTableName(fo_dbManager *dbManager, int uploadId)
Get the upload tree table name for a given upload.
PGresult * queryFileIdsForUpload(fo_dbManager *dbManager, int uploadId, bool ignoreFilesWithMimeType)
Get all file IDs (pfile_fk) for a given upload.
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.
The main FOSSology C library.
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...
int jobId
The id of the job.
void fo_scheduler_connect_dbMan(int *argc, char **argv, fo_dbManager **dbManager)
Make a connection from an agent to the scheduler and create a DB manager as well.
int fo_scheduler_userID()
Gets the id of the user that created the job that the agent is running.
char * fo_scheduler_current()
Get the last read string from the scheduler.
int fo_scheduler_jobId()
Gets the id of the job that the agent is running.
char * fo_scheduler_next()
Get the next data to process from the scheduler.
int fo_scheduler_groupID()
Gets the id of the group that created the job that the agent is running.
if(!preg_match("/\s$projectGroup\s/", $groups) &&(posix_getgid() !=$gInfo[ 'gid']))
get monk license list of one specified uploadtree_id
PGresult * fo_dbManager_ExecPrepared(fo_dbManager_PreparedStatement *preparedStatement,...)
Execute a prepared statement.
License mapping entry with per-mapping report metadata.
int removing
0 = add license, 1 = remove license
char * acknowledgement
nullable
long rfPk
rf_pk from license_ref table
char * reportinfo
nullable
Structure to hold a custom phrase and its mapped licenses.
Store the results of a regex match.