FOSSology  3.2.0rc1
Open Source License Compliance by Open Source Software
wc_agent.c
Go to the documentation of this file.
1 /*****************************************************************
2  wc_agent: the word count agent
3  Copyright (C) 2007-2011 Hewlett-Packard Development Company, L.P.
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License
7  version 2 as published by the Free Software Foundation.
8 
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License along
15  with this program; if not, write to the Free Software Foundation, Inc.,
16  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 
18  ***************************************************************/
19 
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include <signal.h>
42 #include <libgen.h>
43 
44 #include "libfossology.h"
45 
46 #ifdef COMMIT_HASH
47 char BuildVersion[]="Build version: " COMMIT_HASH ".\n";
48 #endif
49 
50 #define MAXCMD 2048
51 
52 /* for the DB */
53 void *pgConn = NULL;
54 
55 /* input for this system */
56 long GlobalPfileFk=-1;
57 char GlobalPfile[MAXCMD];
67 int IsFile(long mode)
68 {
75  if (((mode & 1<<18) + (mode & 0040000) == 0) && ((mode & 1<<28) == 0) && ((mode & 1<<29) != 0)) return 1;
76  else return 0;
77 }
78 
91 int ProcessData(long PfileFk, char *Pfile)
92 {
93  char *RepFile;
94  char Cmd[MAXCMD];
95  char SQL[MAXCMD];
96  long Bytes,Words,Lines;
97  FILE *Fin;
98  PGresult *result;
99 
100  /* Get the path to the actual file */
101  RepFile = fo_RepMkPath("files",Pfile);
102  if (!RepFile)
103  {
104  LOG_FATAL("pfile %ld Word count unable to open file.\n",GlobalPfileFk);
105  printf("LOG pfile %ld Word count unable to open file: pfile_fk=%ld pfile=%s\n",GlobalPfileFk,GlobalPfileFk,GlobalPfile);
106  PQfinish(pgConn);
107  exit(-1);
108  }
109 
110  /* Create the command to run */
111  memset(Cmd,'\0',MAXCMD);
112  snprintf(Cmd,MAXCMD,"/usr/bin/wc '%s' 2>/dev/null",RepFile);
113 
114  /* Run the command and read the results */
115  Fin = popen(Cmd,"r");
116  if (!Fin)
117  {
118  LOG_FATAL("pfile %ld Word count unable to count words.\n",GlobalPfileFk);
119  printf("LOG pfile %ld Word count unable to run command: %s\n",GlobalPfileFk,Cmd);
120  PQfinish(pgConn);
121  exit(-1);
122  }
123 
124  /* Read the results */
125  fscanf(Fin,"%ld %ld %ld",&Lines,&Words,&Bytes);
126 
127  /* Store the results */
128  if (!pgConn)
129  {
130  printf("%s: Bytes=%ld Words=%ld Lines=%ld\n",Pfile,Bytes,Words,Lines);
131  }
132  else
133  {
134  /* Store results in the database */
135  memset(Cmd,'\0',MAXCMD);
136  snprintf(Cmd,MAXCMD,"INSERT INTO agent_wc (pfile_fk,wc_words,wc_lines) VALUES (%ld,%ld,%ld);",
137  PfileFk,Words,Lines);
138  result = PQexec(pgConn, SQL);
139  if (fo_checkPQcommand(pgConn, result, SQL, __FILE__, __LINE__))
140  {
141  LOG_FATAL("pfile %ld Database insert failed.\n",GlobalPfileFk);
142  printf("LOG pfile %ld Database insert failed: %s\n",GlobalPfileFk,SQL);
143  PQfinish(pgConn);
144  exit(-1);
145  }
146  PQclear(result);
147  }
148 
149  /* Clean up */
150  pclose(Fin);
151  if(RepFile)
152  {
153  free(RepFile);
154  RepFile = NULL;
155  }
156  return(0);
157 } /* ProcessData() */
158 
166 void Usage(char *Name)
167 {
168  printf("Usage: %s [options]\n",Name);
169  printf(" -i :: Initialize the DB connection then exit (nothing downloaded)\n");
170  printf(" -c :: Specify the directory for the system configuration.\n");
171  printf(" -C :: Run from command line.\n");
172 } /* Usage() */
173 
178 int main(int argc, char *argv[])
179 {
180  int c;
181  int InitFlag=0; /* is the system just going to initialize? */
182  int CmdlineFlag = 0; /* run from command line flag, 1 yes, 0 not */
183  char *Parm = NULL;
184  char *agent_desc = "File character, line, word count.";
185  int pfile_count = 0;
186  int Agent_pk = 0;
187  int ars_pk = 0;
188  char *COMMIT_HASH;
189  char *VERSION;
190  char agent_rev[MAXCMD];
191 
192  int upload_pk = 0; // the upload primary key
193  char *AgentARSName = "wc_agent_ars";
194  int rv;
195  PGresult *result;
196  char sqlbuf[MAXCMD];
197  char *DBConfFile = NULL; /* use default Db.conf */
198  char *ErrorBuf;
199 
200 
201  /* initialize the scheduler connection */
202  fo_scheduler_connect(&argc, argv);
203 
204  /* Process command-line */
205  while((c = getopt(argc,argv,"iCc:")) != -1)
206  {
207  switch(c)
208  {
209  case 'i':
210  InitFlag=1;
211  break;
212  case 'c': break; /* handled by fo_scheduler_connect() */
213  case 'C':
214  CmdlineFlag = 1;
215  break;
216  default:
217  Usage(argv[0]);
218  exit(-1);
219  }
220  }
221 
222  /* Init */
223  pgConn = fo_dbconnect(DBConfFile, &ErrorBuf);
224  if (!pgConn )
225  {
226  LOG_FATAL("Unable to connect to database\n");
227  exit(-1);
228  }
229 
230  COMMIT_HASH = fo_sysconfig("wc_agent", "COMMIT_HASH");
231  VERSION = fo_sysconfig("wc_agent", "VERSION");
232  sprintf(agent_rev, "%s.%s", VERSION, COMMIT_HASH);
233 
234  Agent_pk = fo_GetAgentKey(pgConn , basename(argv[0]), 0, agent_rev, agent_desc);
235 
236  /* When initializing the DB, don't do anything else */
237  if (InitFlag)
238  {
239  PQfinish(pgConn);
240  return(0);
241  }
242 
243  /* Run from scheduler! */
244  if (0 == CmdlineFlag)
245  {
246  while(fo_scheduler_next())
247  {
248  Parm = fo_scheduler_current();
249  if (Parm[0] != '\0')
250  {
251 
253  /* 1 parameter: upload_pk */
254  upload_pk = atoi(Parm);
255  /* does ars table exist?
256  * If not, create it.
257  */
258  rv = fo_tableExists(pgConn, AgentARSName);
259  if (!rv)
260  {
261  rv = fo_CreateARSTable(pgConn, AgentARSName);
262  if (!rv) return(0);
263  }
264 
265  /* check ars table if this is duplicate request*/
266  memset(sqlbuf, 0, sizeof(sqlbuf));
267  snprintf(sqlbuf, sizeof(sqlbuf),
268  "select ars_pk from wc_agent_ars,agent \
269  where agent_pk=agent_fk and ars_success=true \
270  and upload_fk='%d' and agent_fk='%d'",
271  upload_pk, Agent_pk);
272  result = PQexec(pgConn, sqlbuf);
273  if (fo_checkPQresult(pgConn, result, sqlbuf, __FILE__, __LINE__))
274  {
275  PQfinish(pgConn);
276  exit(-1);
277  }
278  if (PQntuples(result) > 0)
279  {
280  PQclear(result);
281  LOG_WARNING("Ignoring requested wc_agent analysis of upload %d - Results are already in database.\n",upload_pk);
282  continue;
283  }
284  PQclear(result);
285  /* Record analysis start in wc_agent_ars, the wc_agent audit trail. */
286  ars_pk = fo_WriteARS(pgConn, ars_pk, upload_pk, Agent_pk, AgentARSName, 0, 0);
287 
288  /* get all pfile ids on a upload record */
289  memset(sqlbuf, 0, sizeof(sqlbuf));
290  snprintf(sqlbuf, sizeof(sqlbuf), "SELECT DISTINCT(pfile_pk) as pfile_id,"
291  " pfile_sha1 || '.' || pfile_md5 || '.' || pfile_size AS pfile_path,"
292  " ufile_mode FROM uploadtree, pfile"
293  " WHERE uploadtree.pfile_fk = pfile.pfile_pk"
294  " AND pfile.pfile_pk not in(SELECT pfile_fk from agent_wc)"
295  " AND upload_fk = '%d' LIMIT 5000;", upload_pk);
296  result = PQexec(pgConn, sqlbuf);
297  if (fo_checkPQresult(pgConn, result, sqlbuf, __FILE__, __LINE__))
298  {
299  PQfinish(pgConn);
300  exit(-1);
301  }
302  pfile_count = PQntuples(result);
303  int i;
304  long ufile_mode = 0;
305  for(i=0; i < pfile_count; i++)
306  {
307  ufile_mode = atoi(PQgetvalue(result, i, 2));
308  if (IsFile(ufile_mode))
309  {
310  GlobalPfileFk = atoi(PQgetvalue(result, i, 0));
311  strncpy(GlobalPfile, PQgetvalue(result, i, 1), sizeof(GlobalPfile));
312  if (ProcessData(GlobalPfileFk,GlobalPfile) != 0)
313  {
314  LOG_FATAL("pfile %ld Word count failed.\n",GlobalPfileFk);
315  printf("LOG pfile %ld Word count failed: pfile_fk=%ld pfile=%s\n",GlobalPfileFk,GlobalPfileFk,GlobalPfile);
316  PQfinish(pgConn);
317  PQclear(result);
318  exit(-1);
319  }
320  }
321  }
322  PQclear(result);
323  }
324  }
325  } /* if run from scheduler */
326 
327  /* Clean up */
328  PQfinish(pgConn);
330  return(0);
331 } /* main() */
332 
333 
char * DBConfFile
DB conf file location.
Definition: testRun.c:33
int fo_checkPQresult(PGconn *pgConn, PGresult *result, char *sql, char *FileID, int LineNumb)
Check the result status of a postgres SELECT.
Definition: libfossdb.c:181
char BuildVersion[]
Definition: buckets.c:79
int ProcessData(long PfileFk, char *Pfile)
This function does the work.
Definition: wc_agent.c:91
char GlobalPfile[MAXCMD]
Definition: wc_agent.c:57
int IsFile(long mode)
Check if the pfile_id is a file.
Definition: wc_agent.c:67
char * Pfile
Pfile name (SHA1.MD5.Size)
void * pgConn
Database connection.
Definition: wc_agent.c:53
char * fo_scheduler_current()
Get the last read string from the scheduler.
void fo_scheduler_disconnect(int retcode)
Disconnect the scheduler connection.
void fo_scheduler_connect(int *argc, char **argv, PGconn **db_conn)
Establish a connection between an agent and the scheduler.
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:215
char SQL[256]
SQL query to execute.
Definition: adj2nest.c:90
int Agent_pk
agent identifier
Definition: finder.c:30
The main FOSSology C library.
int main(int argc, char *argv[])
main function
Definition: wc_agent.c:178
char * fo_RepMkPath(const char *Type, char *Filename)
Given a filename, construct the full path to the file.
Definition: libfossrepo.c:364
FUNCTION int fo_CreateARSTable(PGconn *pgConn, const char *tableName)
Create ars table if it doesn&#39;t already exist.
Definition: libfossagent.c:284
int fo_tableExists(PGconn *pgConn, const char *tableName)
Check if table exists. Note, this assumes the database name is &#39;fossology&#39;.
Definition: libfossdb.c:243
FUNCTION int fo_GetAgentKey(PGconn *pgConn, const char *agent_name, long Upload_pk, const char *rev, const char *agent_desc)
Get the latest enabled agent key (agent_pk) from the database.
Definition: libfossagent.c:172
char * fo_scheduler_next()
Get the next data to process from the scheduler.
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:228
void Usage(char *Name)
Say how to run this program.
Definition: wc_agent.c:166
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...
const char * upload_pk
Definition: sqlstatements.h:93
char * fo_sysconfig(const char *sectionname, const char *variablename)
gets a system configuration variable from the configuration data.
PGconn * fo_dbconnect(char *DBConfFile, char **ErrorBuf)
Connect to a database. The default is Db.conf.
Definition: libfossdb.c:40