Advertisement
Guest User

Untitled

a guest
Oct 15th, 2019
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.96 KB | None | 0 0
  1. #include "util.h"
  2. #include <pthread.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <dirent.h>
  8. #include <stdbool.h>
  9.  
  10.  
  11. int dnslookup(const char* hostname, char* firstIPstr, int maxSize){
  12.  
  13. /* Local vars */
  14. struct addrinfo* headresult = NULL;
  15. struct addrinfo* result = NULL;
  16. struct sockaddr_in* ipv4sock = NULL;
  17. struct in_addr* ipv4addr = NULL;
  18. char ipv4str[INET_ADDRSTRLEN];
  19. char ipstr[INET6_ADDRSTRLEN];
  20. int addrError = 0;
  21.  
  22. /* DEBUG: Print Hostname*/
  23. #ifdef UTIL_DEBUG
  24. fprintf(stderr, "%s\n", hostname);
  25. #endif
  26.  
  27. /* Lookup Hostname */
  28. addrError = getaddrinfo(hostname, NULL, NULL, &headresult);
  29. if(addrError){
  30. fprintf(stderr, "Error looking up Address: %s\n",
  31. gai_strerror(addrError));
  32. return UTIL_FAILURE;
  33. }
  34. /* Loop Through result Linked List */
  35. for(result=headresult; result != NULL; result = result->ai_next){
  36. /* Extract IP Address and Convert to String */
  37. if(result->ai_addr->sa_family == AF_INET){
  38. /* IPv4 Address Handling */
  39. ipv4sock = (struct sockaddr_in*)(result->ai_addr);
  40. ipv4addr = &(ipv4sock->sin_addr);
  41. if(!inet_ntop(result->ai_family, ipv4addr,
  42. ipv4str, sizeof(ipv4str))){
  43. perror("Error Converting IP to String");
  44. return UTIL_FAILURE;
  45. }
  46. #ifdef UTIL_DEBUG
  47. fprintf(stdout, "%s\n", ipv4str);
  48. #endif
  49. strncpy(ipstr, ipv4str, sizeof(ipstr));
  50. ipstr[sizeof(ipstr)-1] = '\0';
  51. }
  52. else if(result->ai_addr->sa_family == AF_INET6){
  53. /* IPv6 Handling */
  54. #ifdef UTIL_DEBUG
  55. fprintf(stdout, "IPv6 Address: Not Handled\n");
  56. #endif
  57. strncpy(ipstr, "UNHANDELED", sizeof(ipstr));
  58. ipstr[sizeof(ipstr)-1] = '\0';
  59. }
  60. else{
  61. /* Unhandlded Protocol Handling */
  62. #ifdef UTIL_DEBUG
  63. fprintf(stdout, "Unknown Protocol: Not Handled\n");
  64. #endif
  65. strncpy(ipstr, "UNHANDELED", sizeof(ipstr));
  66. ipstr[sizeof(ipstr)-1] = '\0';
  67. }
  68. /* Save First IP Address */
  69. if(result==headresult){
  70. strncpy(firstIPstr, ipstr, maxSize);
  71. firstIPstr[maxSize-1] = '\0';
  72. }
  73. }
  74.  
  75. /* Cleanup */
  76. freeaddrinfo(headresult);
  77.  
  78. return UTIL_SUCCESS;
  79. }
  80.  
  81. //Global mutex declaration and initialization
  82. pthread_mutex_t inputLock;
  83. pthread_mutex_t writeToBuffer;
  84. pthread_mutex_t writeCountLock;
  85. pthread_mutex_t writetoFile;
  86. pthread_mutex_t chooseFromBuff;
  87. pthread_mutex_t reqLogblock;
  88.  
  89.  
  90. typedef struct eti {
  91. //Input stuff
  92. char inputFiles[10][25];
  93. int inputfileNum;
  94. int inputcounter;
  95.  
  96. //Reading
  97. char sharedArray[10][1025];
  98. int buffCount;
  99. bool buffOccupied[10];
  100.  
  101. //Important stuff
  102. bool writeFinished;
  103. bool flushed;
  104. int readCount;
  105.  
  106. //Files
  107. FILE *ofp;
  108. FILE *reqLog;
  109. } EssentialThreadInformation;
  110.  
  111.  
  112. void reqDestruction(int serviced, void *tstruct){
  113. EssentialThreadInformation *godstruct = (struct EssentialThreadInformation*) tstruct;
  114.  
  115. char output[100];
  116. snprintf(output, 100, "Thread %d serviced %d files\n", pthread_self(), serviced);
  117. fputs(output, godstruct->reqLog);
  118. }
  119.  
  120.  
  121. void *requesterThread(void *tstruct){
  122.  
  123. EssentialThreadInformation *godstruct = (struct EssentialThreadInformation*) tstruct;
  124.  
  125. char data[1025];
  126. FILE *fd;
  127. int j;
  128. int serviced = 0;
  129.  
  130. while (godstruct->inputcounter < godstruct->inputfileNum) {
  131.  
  132.  
  133. //Requester choosing its input file
  134. pthread_mutex_lock(&inputLock);
  135.  
  136. if (godstruct->inputcounter >= godstruct->inputfileNum) {
  137. printf("Spare thread aborted.\n");
  138. pthread_mutex_unlock(&inputLock);
  139.  
  140. pthread_mutex_lock(&reqLogblock);
  141. reqDestruction(serviced, godstruct);
  142. pthread_mutex_unlock(&reqLogblock);
  143.  
  144. return 0;
  145. }
  146.  
  147. fd = fopen(godstruct->inputFiles[godstruct->inputcounter], "r");
  148. serviced++;
  149. godstruct->inputcounter++;
  150.  
  151. pthread_mutex_unlock(&inputLock);
  152.  
  153.  
  154.  
  155. while(fgets(data, 1025, fd)){
  156.  
  157. //Do nothing when the buffer is full
  158. while (godstruct->buffCount == 10) {
  159. //nothing
  160. }
  161.  
  162. //Only one thread can write to the buffer at the same time
  163. pthread_mutex_lock(&writeToBuffer);
  164.  
  165. if (godstruct->buffCount < 10) {
  166. for (j = 0; j < 10; j++) {
  167. if (godstruct->buffOccupied[j] == false) {
  168. break;
  169. }
  170. }
  171. strcpy(godstruct->sharedArray[j],data);
  172. godstruct->buffOccupied[j] = true;
  173. godstruct->buffCount++;
  174. }
  175. //Unlock writing
  176. pthread_mutex_unlock(&writeToBuffer);
  177. }
  178.  
  179. fclose(fd);
  180. }
  181.  
  182. pthread_mutex_lock(&reqLogblock);
  183. reqDestruction(serviced, godstruct);
  184. pthread_mutex_unlock(&reqLogblock);
  185.  
  186. return 0;
  187. }
  188.  
  189.  
  190. void *resolverThread(void *tstruct){
  191.  
  192. EssentialThreadInformation *godstruct = (struct EssentialThreadInformation*) tstruct;
  193. char data[1025];
  194. char ip[1025];
  195. int j;
  196. int len;
  197.  
  198. while (!godstruct->writeFinished) {
  199.  
  200. //Do nothing while there isn't anything in the buffer
  201. while(godstruct->buffCount == 0) {
  202. //Do nothing
  203. if (godstruct->writeFinished) {
  204. break;
  205. }
  206. }
  207. if (godstruct->writeFinished) {
  208. break;
  209. }
  210.  
  211. pthread_mutex_lock(&writeCountLock);
  212. godstruct->readCount++;
  213. if (godstruct->readCount == 1) {
  214. pthread_mutex_lock(&writeToBuffer);
  215. }
  216. pthread_mutex_unlock(&writeCountLock);
  217.  
  218.  
  219. //Only one thread can choose a buffer location at once
  220. pthread_mutex_lock(&chooseFromBuff);
  221. if (godstruct->buffCount > 0) {
  222. for (j = 0; j < 10; j++) {
  223. if (godstruct->buffOccupied[j] == true) {
  224. break;
  225. }
  226. }
  227.  
  228. godstruct->buffOccupied[j] = false;
  229. godstruct->buffCount--;
  230. strcpy(data, godstruct->sharedArray[j]);
  231. }
  232. pthread_mutex_unlock(&chooseFromBuff);
  233.  
  234. //DNS LOOKUP
  235. len = strlen(data);
  236. data[len - 1] = '\0';
  237.  
  238. if(dnslookup(data, ip, 1025) == 0) {
  239. strcat(data, ",");
  240. strcat(data, ip);
  241. strcat(data, "\n");
  242. }
  243. else {
  244. strcat(data, ",\n");
  245. }
  246.  
  247.  
  248. //Only one thread can write to the output file at once.
  249. pthread_mutex_lock(&writetoFile);
  250. fputs(data, godstruct->ofp);
  251. pthread_mutex_unlock(&writetoFile);
  252.  
  253.  
  254. pthread_mutex_lock(&writeCountLock);
  255. godstruct->readCount--;
  256. if (godstruct->readCount == 0) {
  257. pthread_mutex_unlock(&writeToBuffer);
  258. }
  259. pthread_mutex_unlock(&writeCountLock);
  260. }
  261.  
  262.  
  263.  
  264. //Final flush
  265. pthread_mutex_lock(&chooseFromBuff);
  266. if (!godstruct->flushed) {
  267. for (j = 0; j < 10; j++) {
  268. if (godstruct->buffOccupied[j] == true) {
  269. strcpy(data, godstruct->sharedArray[j]);
  270. len = strlen(data);
  271. data[len - 1] = '\0';
  272.  
  273. if(dnslookup(data, ip, 1025) == 0) {
  274. strcat(data, ",");
  275. strcat(data, ip);
  276. strcat(data, "\n");
  277. }
  278. else {
  279. strcat(data, ",\n");
  280. }
  281. fputs(data, godstruct->ofp);
  282. }
  283. }
  284. godstruct->flushed = true;
  285. }
  286. pthread_mutex_unlock(&chooseFromBuff);
  287.  
  288. return 0;
  289. }
  290.  
  291.  
  292. int main(int argc, char * argv[]) {
  293.  
  294. EssentialThreadInformation *godstruct = malloc(sizeof(EssentialThreadInformation));
  295. int i = 0;
  296.  
  297.  
  298. //THE GREAT SETTING OF THE VARIABLES
  299. godstruct->inputfileNum = 0;
  300. godstruct->inputcounter = 0;
  301. godstruct->buffCount = 0;
  302. for (i = 0; i < 10; i++) {
  303. godstruct->buffOccupied[i] = false;
  304. }
  305. godstruct->writeFinished = false;
  306. godstruct->flushed = false;
  307. godstruct->readCount = 0;
  308.  
  309.  
  310. godstruct->ofp = fopen(argv[4], "w");
  311. godstruct->reqLog = fopen(argv[3], "w");
  312. int numRequesterThreads = atoi(argv[1]);
  313. int numResolverThreads = atoi(argv[2]);
  314.  
  315. //Get input folder directory
  316. i = 0;
  317. char fileNames[25];
  318. DIR *dir;
  319. struct dirent *dirstruct;
  320.  
  321.  
  322. dir = opendir(argv[5]);
  323. if (dir) {
  324. while ((dirstruct = readdir(dir)) != NULL) {
  325. if(strcmp(dirstruct->d_name, ".") && strcmp(dirstruct->d_name, "..")) {
  326. strcpy(godstruct->inputFiles[i], argv[5]);
  327. strcat(godstruct->inputFiles[i], "/");
  328. strcat(godstruct->inputFiles[i], dirstruct->d_name);
  329. i++;
  330. }
  331. }
  332. godstruct->inputfileNum = i;
  333. closedir(dir);
  334. }
  335. else {
  336. printf("Input directory doesn't exist\n");
  337. return 0;
  338. }
  339.  
  340.  
  341. //Writers
  342. pthread_t writethread[10];
  343. pthread_mutex_init(&inputLock, NULL);
  344. pthread_mutex_init(&writeToBuffer, NULL);
  345. pthread_mutex_init(&reqLogblock, NULL);
  346.  
  347.  
  348. //Create threads
  349. for(i = 0; i < numRequesterThreads; i++) {
  350. pthread_create(&writethread[i], NULL, requesterThread, (void *)godstruct);
  351. }
  352.  
  353.  
  354.  
  355. pthread_mutex_init(&writeCountLock, NULL);
  356. pthread_mutex_init(&writeToBuffer, NULL);
  357. pthread_mutex_init(&chooseFromBuff, NULL);
  358.  
  359.  
  360. //Readers
  361. pthread_t readthread[10];
  362.  
  363.  
  364.  
  365. //Create threads
  366. for(i = 0; i < numResolverThreads; i++) {
  367. pthread_create(&readthread[i], NULL, resolverThread, (void *)godstruct);
  368. }
  369.  
  370.  
  371. //Wait for threads
  372. for (i = 0; i < numRequesterThreads; i++) {
  373. pthread_join(writethread[i], NULL);
  374. }
  375. godstruct->writeFinished = true;
  376.  
  377.  
  378. for (i = 0; i < numResolverThreads; i++) {
  379. pthread_join(readthread[i], NULL);
  380. }
  381.  
  382.  
  383.  
  384. fclose(godstruct->ofp);
  385. fclose(godstruct->reqLog);
  386.  
  387. pthread_mutex_destroy(&inputLock);
  388. pthread_mutex_destroy(&writeToBuffer);
  389. pthread_mutex_destroy(&writeCountLock);
  390. pthread_mutex_destroy(&writetoFile);
  391. pthread_mutex_destroy(&chooseFromBuff);
  392.  
  393. return 0;
  394. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement