7 #include "ReuserDatabaseHandler.hpp"
17 #include <unicode/unistr.h>
20 #include "libfossagent.h"
42 constexpr
int DT_WIP = 0;
43 constexpr
int DT_TO_BE_DISCUSSED = 3;
44 constexpr
int DT_IRRELEVANT = 4;
45 constexpr
int DT_IDENTIFIED = 5;
46 constexpr
int DT_DO_NOT_USE = 6;
47 constexpr
int DT_NON_FUNCTIONAL = 7;
54 case DT_IDENTIFIED:
return 5;
55 case DT_DO_NOT_USE:
return 4;
56 case DT_NON_FUNCTIONAL:
return 3;
57 case DT_IRRELEVANT:
return 2;
58 case DT_TO_BE_DISCUSSED:
return 1;
65 if (
s.empty())
return false;
67 if (!((c >=
'a' && c <=
'z') || (c >=
'A' && c <=
'Z') ||
68 (c >=
'0' && c <=
'9') || c ==
'_'))
74 const std::string& input)
76 icu::UnicodeString us = icu::UnicodeString::fromUTF8(input);
77 icu::UnicodeString result;
78 for (int32_t i = 0; i < us.length(); ++i)
80 UChar32 cp = us.char32At(i);
82 bool isControl = (cp <= 0x08)
85 || (cp >= 0x0E && cp <= 0x1F)
86 || (cp >= 0x7F && cp <= 0x9F);
91 result.toUTF8String(out);
95 std::string ReuserDatabaseHandler::shellEscape(
const std::string&
s)
99 r += (c ==
'\'') ? std::string(
"'\\''") : std::string(1, c);
104 int ReuserDatabaseHandler::diffLineCount(
const std::string& a,
105 const std::string& b)
107 if (a.empty() || b.empty())
return -1;
111 std::string cmd =
"diff -- " + shellEscape(a) +
" " + shellEscape(b)
113 FILE* pipe = popen(cmd.c_str(),
"r");
114 if (!pipe)
return -1;
118 while (fgets(buf,
sizeof(buf), pipe))
121 int status = pclose(pipe);
123 if (WIFEXITED(status) && WEXITSTATUS(status) == 2)
133 if (!pfileName)
return {};
136 if (!filePath)
return {};
137 std::string result(filePath);
150 bool needsUploadFilter =
151 (table ==
"uploadtree" || table ==
"uploadtree_a");
156 "SELECT uploadtree_pk, upload_fk, lft, rgt"
157 " FROM %s WHERE parent IS NULL AND upload_fk=%d",
158 table.c_str(), uploadId)
160 "SELECT uploadtree_pk, upload_fk, lft, rgt"
161 " FROM %s WHERE parent IS NULL",
164 if (!result || result.getRowCount() == 0)
return false;
166 auto row = result.getRow(0);
167 out.uploadtree_pk = std::stoi(row[0]);
168 out.uploadTreeTableName = table;
169 out.upload_fk = std::stoi(row[1]);
170 out.lft = std::stoi(row[2]);
171 out.rgt = std::stoi(row[3]);
178 int uploadId,
int groupId)
180 std::vector<ReuseTriple> result;
184 "reuserGetReusedUploads",
185 "SELECT reused_upload_fk, reused_group_fk, reuse_mode"
187 " WHERE upload_fk=$1 AND group_fk=$2"
188 " ORDER BY date_added DESC",
195 result.push_back({std::stoi(row[0]), std::stoi(row[1]),
202 int uploadId,
int groupId)
204 std::map<int, int> result;
209 bool needsUploadFilter =
210 (table ==
"uploadtree" || table ==
"uploadtree_a");
213 bool applyGlobal =
true;
216 "reuserGetGlobalDecision",
219 "SELECT (ri_globaldecision != 0) FROM report_info WHERE upload_fk=$1",
226 std::string joinCond =
228 ?
"(ut.pfile_fk = cd.pfile_fk AND cd.scope = 1)"
229 " OR (ut.uploadtree_pk = cd.uploadtree_fk"
230 " AND cd.scope = 0 AND cd.group_fk = " + std::to_string(groupId) +
")"
231 :
"(ut.uploadtree_pk = cd.uploadtree_fk"
232 " AND cd.group_fk = " + std::to_string(groupId) +
")";
234 std::string uploadFilter =
236 ?
" AND ut.upload_fk = " + std::to_string(uploadId)
243 " SELECT DISTINCT ON(ut.uploadtree_pk)"
244 " cd.clearing_decision_pk AS id,"
245 " cd.pfile_fk AS pfile_id,"
246 " cd.decision_type AS dec_type"
247 " FROM clearing_decision cd"
248 " INNER JOIN %s ut ON (%s)%s"
249 " WHERE cd.decision_type != 0"
250 " ORDER BY ut.uploadtree_pk, cd.scope ASC,"
251 " cd.clearing_decision_pk DESC"
254 " SELECT id, pfile_id, dec_type"
256 " ORDER BY pfile_id, id DESC"
258 " SELECT id, pfile_id, dec_type FROM per_pfile",
259 table.c_str(), joinCond.c_str(), uploadFilter.c_str());
261 std::map<int, int> resultTypes;
266 int decId = std::stoi(row[0]);
267 int pfileId = std::stoi(row[1]);
268 int decType = std::stoi(row[2]);
270 auto it = result.find(pfileId);
271 if (it == result.end()) {
272 result[pfileId] = decId;
273 resultTypes[pfileId] = decType;
276 LOG_NOTICE(
"Reuser: conflicting decisions for pfile %d,"
277 " applying stronger decision type %d over %d.",
278 pfileId, decType, resultTypes[pfileId]);
279 result[pfileId] = decId;
280 resultTypes[pfileId] = decType;
287 std::map<int, std::vector<int>>
289 int uploadId,
const std::vector<int>& pfileIds)
291 std::map<int, std::vector<int>> result;
292 if (pfileIds.empty())
return result;
299 for (
size_t i = 0; i < pfileIds.size(); ++i)
301 if (i > 0) arr +=
",";
302 arr += std::to_string(pfileIds[i]);
305 bool needsUploadFilter =
306 (table ==
"uploadtree" || table ==
"uploadtree_a");
311 "SELECT uploadtree_pk, pfile_fk FROM %s"
312 " WHERE upload_fk=%d AND pfile_fk=ANY('{%s}'::int[])",
313 table.c_str(), uploadId, arr.c_str())
315 "SELECT uploadtree_pk, pfile_fk FROM %s"
316 " WHERE pfile_fk=ANY('{%s}'::int[])",
317 table.c_str(), arr.c_str());
322 int pk = std::stoi(row[0]);
323 int pfileId = std::stoi(row[1]);
324 if (pk > 0 && pfileId > 0)
325 result[pfileId].push_back(pk);
333 int uploadId,
int uploadTreeId,
int userId,
int groupId,
334 int licenseId,
bool removed,
int type,
335 const std::string& reportInfo,
const std::string& comment,
336 const std::string& ack,
int jobId)
342 const char* removedStr = removed ?
"t" :
"f";
349 table =
"uploadtree";
352 "INSERT INTO clearing_decision"
353 " (uploadtree_fk, pfile_fk, user_fk, group_fk, decision_type, scope)"
355 " (SELECT pfile_fk FROM %s WHERE uploadtree_pk=%d),"
357 uploadTreeId, table.c_str(), uploadTreeId, userId, groupId);
361 "reuserInsertClearingEvent",
362 "INSERT INTO clearing_event"
363 " (uploadtree_fk, user_fk, group_fk, type_fk, rf_fk,"
364 " removed, reportinfo, comment, acknowledgement)"
365 " VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)"
366 " RETURNING clearing_event_pk",
367 int,
int,
int,
int,
int,
char*,
char*,
char*,
char*),
368 uploadTreeId, userId, groupId, type, licenseId,
369 removedStr, safeReport.c_str(), safeComment.c_str(), safeAck.c_str());
372 return std::stoi(qr.
getRow(0)[0]);
378 "reuserInsertClearingEventWithJob",
379 "INSERT INTO clearing_event"
380 " (uploadtree_fk, user_fk, group_fk, type_fk, rf_fk,"
381 " removed, reportinfo, comment, acknowledgement, job_fk)"
382 " VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)"
383 " RETURNING clearing_event_pk",
384 int,
int,
int,
int,
int,
char*,
char*,
char*,
char*,
int),
385 uploadTreeId, userId, groupId, type, licenseId,
386 removedStr, safeReport.c_str(), safeComment.c_str(), safeAck.c_str(),
390 return std::stoi(qr.
getRow(0)[0]);
395 int uploadId,
int uploadTreeId,
int userId,
int groupId,
396 int decType,
int scope,
const std::vector<int>& eventIds)
398 if (eventIds.empty())
return 0;
400 if (!
begin())
return 0;
405 "reuserRemoveWipDecision",
406 "DELETE FROM clearing_decision"
407 " WHERE uploadtree_fk=$1 AND group_fk=$2 AND decision_type=0",
409 uploadTreeId, groupId);
411 if (!rRem) {
rollback();
return 0; }
415 table =
"uploadtree";
418 "INSERT INTO clearing_decision"
419 " (uploadtree_fk, pfile_fk, user_fk, group_fk, decision_type, scope)"
421 " (SELECT pfile_fk FROM %s WHERE uploadtree_pk=%d),"
423 " RETURNING clearing_decision_pk",
424 uploadTreeId, table.c_str(), uploadTreeId, userId, groupId, decType, scope);
427 int decisionPk = std::stoi(rIns.
getRow(0)[0]);
434 "reuserInsertClearingDecisionEvent",
435 "INSERT INTO clearing_decision_event"
436 " (clearing_decision_fk, clearing_event_fk) VALUES($1,$2)",
439 for (
int evPk : eventIds)
443 LOG_WARNING(
"Reuser: failed to link clearing_event %d to"
444 " clearing_decision %d, continuing.", evPk, decisionPk);
452 int uploadId,
int newItemUploadTreePk,
int userId,
int groupId,
453 int originalDecisionPk)
458 "reuserGetDecisionMeta",
459 "SELECT decision_type, scope FROM clearing_decision"
460 " WHERE clearing_decision_pk=$1",
465 int decType = std::stoi(rMeta.
getRow(0)[0]);
466 int scope = std::stoi(rMeta.
getRow(0)[1]);
471 "reuserGetEventsForDecision",
472 "SELECT ce.rf_fk, ce.removed,"
473 " ce.reportinfo, ce.comment, ce.acknowledgement"
474 " FROM clearing_event ce"
475 " INNER JOIN clearing_decision_event cde"
476 " ON cde.clearing_event_fk = ce.clearing_event_pk"
477 " WHERE cde.clearing_decision_fk=$1"
478 " ORDER BY ce.clearing_event_pk ASC",
482 if (!rEvents)
return 0;
485 std::vector<int> newEventIds;
489 auto row = rEvents.
getRow(i);
490 int rfFk = std::stoi(row[0]);
491 bool isRemoved = (row[1] ==
"t" || row[1] ==
"true");
496 rfFk, isRemoved, evType,
497 row[2], row[3], row[4],
jobId);
499 newEventIds.push_back(evPk);
502 if (newEventIds.empty())
return 0;
504 decType, scope, newEventIds);
510 int arsId,
bool success)
513 "reuser_ars",
nullptr, success ? 1 : 0);
519 int uploadId,
int reusedUploadId,
520 int groupId,
int reusedGroupId,
int userId)
523 if (reusedMap.empty())
return true;
528 std::vector<int> toImport;
529 for (
const auto& kv : reusedMap)
530 if (currentMap.find(kv.first) == currentMap.end())
531 toImport.push_back(kv.first);
533 if (toImport.empty())
return true;
535 constexpr
size_t chunkSize = 100;
536 for (
size_t i = 0; i < toImport.size(); i += chunkSize)
538 size_t end =
std::min(i + chunkSize, toImport.size());
539 std::vector<int> chunk(toImport.begin() + i, toImport.begin() + end);
542 for (
const auto& entry : pkMap)
544 int originalDecision = reusedMap.at(entry.first);
545 for (
int uploadtreePk : entry.second)
548 uploadId, uploadtreePk, userId, groupId, originalDecision);
558 int uploadId,
int reusedUploadId,
559 int groupId,
int reusedGroupId,
int userId)
562 if (reusedMap.empty())
return true;
566 std::vector<int> toImport;
567 for (
const auto& kv : reusedMap)
568 if (currentMap.find(kv.first) == currentMap.end())
569 toImport.push_back(kv.first);
571 if (toImport.empty())
return true;
578 bool reusedNeedsFilter = (tableReused ==
"uploadtree" || tableReused ==
"uploadtree_a");
579 bool targetNeedsFilter = (tableTarget ==
"uploadtree" || tableTarget ==
"uploadtree_a");
581 std::string reusedFilter = reusedNeedsFilter
582 ?
" AND ur.upload_fk=" + std::to_string(reusedUploadId) :
"";
583 std::string targetFilter = targetNeedsFilter
584 ?
" AND ut.upload_fk=" + std::to_string(uploadId) :
"";
586 for (
int pfileFk : toImport)
588 int originalDecision = reusedMap.at(pfileFk);
591 if (reusedPath.empty())
continue;
595 "SELECT ut.uploadtree_pk, ut.pfile_fk"
597 " WHERE ur.pfile_fk=%d%s"
598 " AND ut.ufile_name=ur.ufile_name%s",
599 tableReused.c_str(), tableTarget.c_str(),
600 pfileFk, reusedFilter.c_str(),
601 targetFilter.c_str());
606 int newItemPk = std::stoi(row[0]);
607 int newPfileFk = std::stoi(row[1]);
608 if (newItemPk <= 0 || newPfileFk <= 0)
continue;
611 if (newPath.empty())
continue;
613 int diffCount = diffLineCount(reusedPath, newPath);
614 if (diffCount < 0)
return false;
618 uploadId, newItemPk, userId, groupId, originalDecision);
628 int uploadId,
int groupId,
int reusedUploadId,
int reusedGroupId)
632 "reuserGetReusedMainLicenses",
633 "SELECT rf_fk FROM upload_clearing_license"
634 " WHERE upload_fk=$1 AND group_fk=$2",
636 reusedUploadId, reusedGroupId);
638 std::set<int> reusedSet;
640 reusedSet.insert(std::stoi(r1.
getRow(i)[0]));
642 if (reusedSet.empty())
return true;
646 "reuserGetTargetMainLicenses",
647 "SELECT rf_fk FROM upload_clearing_license"
648 " WHERE upload_fk=$1 AND group_fk=$2",
652 std::set<int> existingSet;
654 existingSet.insert(std::stoi(r2.
getRow(i)[0]));
656 for (
int rf : reusedSet)
658 if (existingSet.count(rf))
continue;
661 "reuserInsertMainLicense",
662 "INSERT INTO upload_clearing_license (upload_fk, group_fk, rf_fk)"
663 " VALUES ($1,$2,$3)",
665 uploadId, groupId, rf);
666 if (!rIns)
return false;
672 int uploadId,
int reusedUploadId)
677 "reuserConfSettingsCheck",
678 "SELECT 1 FROM report_info WHERE upload_fk=$1 LIMIT 1",
682 if (!rCheck || rCheck.
getRowCount() == 0)
return true;
684 if (!
begin())
return false;
689 "reuserConfSettingsDelete",
690 "DELETE FROM report_info WHERE upload_fk=$1",
694 if (!rDel) {
rollback();
return false; }
699 "SELECT string_agg(quote_ident(column_name), ',')"
700 " FROM information_schema.columns"
701 " WHERE table_schema = current_schema()"
702 " AND table_name = 'report_info'"
703 " AND column_name != 'ri_pk'"
704 " AND column_name != 'upload_fk'");
707 std::string cols = rCols.
getRow(0)[0];
708 if (cols.empty()) {
rollback();
return false; }
712 "INSERT INTO report_info(upload_fk, %s)"
713 " SELECT %d, %s FROM report_info WHERE upload_fk=%d",
714 cols.c_str(), uploadId, cols.c_str(), reusedUploadId);
716 if (!rCopy) {
rollback();
return false; }
723 int uploadId,
int reusedUploadId,
int userId)
725 const std::string agentName =
"copyright";
730 "reuserCopyrightTargetAgentId",
731 "SELECT agent_pk AS agent_id FROM agent"
732 " LEFT JOIN copyright_ars ON agent_fk=agent_pk"
733 " WHERE agent_name=$2 AND agent_enabled"
734 " AND upload_fk=$1 AND ars_success"
735 " ORDER BY agent_pk DESC LIMIT 1",
737 uploadId, agentName.c_str());
739 if (!rAgentT || rAgentT.
getRowCount() == 0)
return true;
740 int targetAgentId = std::stoi(rAgentT.
getRow(0)[0]);
744 "reuserCopyrightReusedAgentId",
745 "SELECT agent_pk AS agent_id FROM agent"
746 " LEFT JOIN copyright_ars ON agent_fk=agent_pk"
747 " WHERE agent_name=$2 AND agent_enabled"
748 " AND upload_fk=$1 AND ars_success"
749 " ORDER BY agent_pk DESC LIMIT 1",
751 reusedUploadId, agentName.c_str());
753 if (!rAgentR || rAgentR.
getRowCount() == 0)
return true;
754 int reusedAgentId = std::stoi(rAgentR.
getRow(0)[0]);
760 bool needsUploadFilter = (table ==
"uploadtree" || table ==
"uploadtree_a");
761 std::string uploadFilter = needsUploadFilter
762 ?
" AND UT.upload_fk = " + std::to_string(uploadId) :
"";
765 "SELECT DISTINCT ON (C.copyright_pk, UT.uploadtree_pk)"
766 " C.copyright_pk, UT.uploadtree_pk, UT.upload_fk,"
767 " (CASE WHEN (CE.content IS NULL OR CE.content = '')"
768 " THEN C.content ELSE CE.content END) AS content,"
769 " (CASE WHEN (CE.hash IS NULL OR CE.hash = '')"
770 " THEN C.hash ELSE CE.hash END) AS hash"
772 " INNER JOIN %s UT ON C.pfile_fk = UT.pfile_fk%s"
773 " LEFT JOIN copyright_event CE"
774 " ON CE.copyright_fk = C.copyright_pk"
775 " AND CE.upload_fk = %d"
776 " AND CE.uploadtree_fk = UT.uploadtree_pk"
777 " WHERE C.content IS NOT NULL AND C.content <> ''"
778 " AND (CE.is_enabled IS NULL OR CE.is_enabled = 'true')"
779 " AND C.agent_fk = %d"
780 " ORDER BY C.copyright_pk, UT.uploadtree_pk, content DESC",
781 table.c_str(), uploadFilter.c_str(), uploadId, targetAgentId);
785 using Row3 = std::array<int, 3>;
786 std::map<std::string, std::vector<Row3>> allMap;
789 auto row = rAll.
getRow(i);
790 std::string hash = row[4];
792 allMap[hash].push_back(Row3{std::stoi(row[0]), std::stoi(row[1]),
795 if (allMap.empty())
return true;
801 "reuserGetReusedCopyrightEvents",
802 "SELECT C.copyright_pk, CE.is_enabled, C.hash,"
803 " CE.content AS contentedited"
804 " FROM copyright_event CE"
805 " INNER JOIN copyright C ON C.copyright_pk = CE.copyright_fk"
806 " WHERE CE.upload_fk=$1 AND CE.scope=$3 AND C.agent_fk=$2",
808 reusedUploadId, reusedAgentId, 1 );
812 auto rRow = rReused.
getRow(i);
813 std::string hash = rRow[2];
814 if (hash.empty())
continue;
816 auto it = allMap.find(hash);
817 if (it == allMap.end() || it->second.empty())
continue;
819 Row3 entry = it->second.back();
820 it->second.pop_back();
821 int copyrightPk = entry[0];
822 int uploadtreePk = entry[1];
823 int uploadFk = entry[2];
825 const std::string& contentEdited = rRow[3];
830 "reuserCopyrightEventExists",
832 " SELECT 1 FROM copyright_event"
833 " WHERE copyright_fk=$1 AND upload_fk=$2 AND uploadtree_fk=$3"
836 copyrightPk, uploadFk, uploadtreePk);
838 bool eventExists = rExists && rExists.
getRowCount() > 0
839 && std::stoi(rExists.
getRow(0)[0]) != 0;
850 "reuserCopyrightEventDisableUpdate",
851 "UPDATE copyright_event SET scope=$4, is_enabled=false"
852 " WHERE upload_fk=$1 AND copyright_fk=$2 AND uploadtree_fk=$3",
854 uploadFk, copyrightPk, uploadtreePk, 1)
857 "reuserCopyrightEventDisableInsert",
858 "INSERT INTO copyright_event"
859 " (upload_fk, copyright_fk, uploadtree_fk, is_enabled, scope)"
860 " VALUES($1,$2,$3,'f',$4)",
862 uploadFk, copyrightPk, uploadtreePk, 1);
864 LOG_WARNING(
"Reuser: failed to disable copyright_event"
865 " (copyright_fk=%d, uploadtree_fk=%d), continuing.",
866 copyrightPk, uploadtreePk);
874 "reuserCopyrightEventUpdateContent",
875 "UPDATE copyright_event SET upload_fk=$1, content=$4,"
877 " WHERE copyright_fk=$2 AND uploadtree_fk=$3",
878 int,
int,
int,
char*),
879 uploadFk, copyrightPk, uploadtreePk, contentEdited.c_str())
882 "reuserCopyrightEventInsertContent",
883 "INSERT INTO copyright_event"
884 " (upload_fk, uploadtree_fk, copyright_fk,"
885 " is_enabled, content, hash)"
886 " VALUES($1,$3,$2,'true',$4,md5($4))",
887 int,
int,
int,
char*),
888 uploadFk, copyrightPk, uploadtreePk, contentEdited.c_str());
890 LOG_WARNING(
"Reuser: failed to update copyright_event content"
891 " (copyright_fk=%d, uploadtree_fk=%d), continuing.",
892 copyrightPk, uploadtreePk);
Database handler for the reuser agent.
virtual bool processUploadReuse(int uploadId, int reusedUploadId, int groupId, int reusedGroupId, int userId)
virtual bool getParentItemBounds(int uploadId, ItemTreeBounds &out)
Fetch the parent item bounds for a given upload.
virtual int createCopyOfClearingDecision(int uploadId, int newItemUploadTreePk, int userId, int groupId, int originalDecisionPk)
Copy an existing clearing decision to a new uploadtree item.
virtual int createDecisionFromEvents(int uploadId, int uploadTreeId, int userId, int groupId, int decType, int scope, const std::vector< int > &eventIds)
Create a clearing_decision linked to eventIds.
virtual bool reuseMainLicense(int uploadId, int groupId, int reusedUploadId, int reusedGroupId)
virtual ReuserDatabaseHandler spawn() const
virtual std::map< int, int > getClearingDecisionMapByPfile(int uploadId, int groupId)
Build a pfile_fk to clearing_decision_pk map for uploadId.
static int getDecisionTypePriority(int decisionType)
Priority for decision types during reuse conflict resolution.
virtual bool processEnhancedUploadReuse(int uploadId, int reusedUploadId, int groupId, int reusedGroupId, int userId)
static bool isValidIdentifier(const std::string &s)
Validate that s contains only characters safe for SQL identifiers.
std::string getRepoPathOfPfile(int pfileId)
virtual int insertClearingEvent(int uploadId, int uploadTreeId, int userId, int groupId, int licenseId, bool removed, int type, const std::string &reportInfo, const std::string &comment, const std::string &ack, int jobId)
Insert a new clearing event and return its primary key (0 on error).
static std::string replaceUnicodeControlChars(const std::string &input)
Strip Unicode control characters (C0, C1, DEL) from input.
virtual bool reuseCopyrights(int uploadId, int reusedUploadId, int userId)
virtual int writeArsRecord(int agentId, int uploadId, int arsId=0, bool success=false)
Write (insert or update) an ARS record.
virtual std::vector< ReuseTriple > getReusedUploads(int uploadId, int groupId)
Return the list of uploads that should be reused for uploadId.
virtual bool reuseConfSettings(int uploadId, int reusedUploadId)
virtual std::map< int, std::vector< int > > getUploadTreePksForPfiles(int uploadId, const std::vector< int > &pfileIds)
For a set of pfile ids, return a map pfile_fk to [uploadtree_pk].
Database handler for agents.
std::string queryUploadTreeTableName(int uploadId)
Get the upload tree table name for a given upload id.
bool commit() const
COMMIT a transaction block in DB.
bool begin() const
BEGIN a transaction block in DB.
char * getPFileNameForFileId(unsigned long pfileId) const
Get the file name of a give pfile id.
DbManager dbManager
DbManager to use.
bool rollback() const
ROLLBACK a transaction block in DB.
QueryResult execPrepared(fo_dbManager_PreparedStatement *stmt,...) const
Execute a prepared statement with new parameters.
QueryResult queryPrintf(const char *queryFormat,...) const
Execute a query in printf format.
PGconn * getConnection() const
fo_dbManager * getStruct_dbManager() const
std::vector< std::string > getRow(int i) const
int s
The socket that the CLI will use to communicate.
FUNCTION int min(int user_perm, int permExternal)
Get the minimum permission level required.
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.
char * fo_RepMkPath(const char *Type, char *Filename)
Given a filename, construct the full path to the file.
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.
int fo_scheduler_jobId()
Gets the id of the job that the agent is running.
fo_dbManager * dbManager
fo_dbManager object
fo namespace holds the FOSSology library functions.
bool stringToBool(const char *string)
Bounds of an item within an uploadtree table.