/** Zadanie: program ma 1 parameter: ./a.out -n - pouzivejte getopt() Ukol: V adresari vzit regularni soubory - nad kazdym souborem spustit vlakno - (predate mu nejak jmeno souboru) - vlakno zjisti velikost souboru a updatuje citac velikosti reg.souboru toho adresare.(f) cislo N - v jednu chvili muze bezet max. N vlaken, jakmile jedno skonci, spustim dalsi. - spravna synch. citac, max. N vlaken - osetrovat chyby (nad etc) 13:45- 16:15 - vystup - cislo + njekay debugging vhodny */ // for fdopendir #ifndef __USE_GNU # define __USE_GNU #endif #ifndef _ATFILE_SOURCE # define _ATFILE_SOURCE #endif #include #include #include #include #include #include #include // threads #include // readdir... #include #include // stat, fstatat, ... #include void usage(char* argv0) { fprintf(stderr, "usage: %s -n \n", argv0); exit(1); } int ACT_THRS = 0; pthread_cond_t cond = PTHREAD_COND_INITIALIZER; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; off_t ALLSIZE = 0; void * adderthr(void *val) { struct stat* fileinfo = (struct stat*) val; // zamkneme pthread_mutex_lock(&mutex); printf("AKTUALNY POCET VLAKIEN: %d sucet: %d = %d + %d\n", ACT_THRS, ALLSIZE, ALLSIZE, fileinfo->st_size); // pricitame velkost suboru ALLSIZE += fileinfo->st_size; --ACT_THRS; // vlakno vykonalo pricitanie, signalizacia pre vypustenie dalsieho vlakna pthread_cond_signal(&cond); // odomkneme pthread_mutex_unlock(&mutex); // poll(NULL, 0, 95); return val; } void secti(char* dirname, int N) { DIR *d; int dirfd; struct dirent *de; struct stat* fileinfo; void * thr_retval; int i; int threadnr = 0; int threadsize = 10; // cisla vsetkych threadov pre joinovanie pthread_t* threads; if ((threads = malloc(threadsize * sizeof(pthread_t))) == NULL) errx(1, "chyba naalokovania tabulky threadov"); if ((dirfd = open(dirname, O_RDONLY)) < 0) errx(1, "Chyba otvorenia zlozky dirdf - %s", dirname); // perror(dirname); if ((d = fdopendir(dirfd)) == NULL) errx(1, "Chyba otvorenia zlozky fdopendir - %s", dirname); // Rozlisenie medzi koncom zlozky a chybou errno = 0; while ((de = readdir(d))) { // ked je to regularny subor if ((fileinfo = malloc(sizeof(struct stat))) == NULL) perror("malloc"); // nenasleduje symlinky if (fstatat(dirfd, de->d_name, fileinfo, AT_SYMLINK_NOFOLLOW) == -1) perror("fstatat"); if (de->d_type == DT_REG) { // if (S_ISREG(fileinfo->st_mode)) { pthread_mutex_lock(&mutex); printf("spracovanie suboru %s\n", de->d_name); // uspi a caka kym skoncia vlakna while (ACT_THRS == N) { pthread_cond_wait(&cond, &mutex); } if (threadnr == threadsize) { // realloc threadsize = threadsize * 2; if ((threads = realloc(threads, threadsize * sizeof(pthread_t))) == NULL) perror("realloc"); } ++ACT_THRS; pthread_create(&threads[threadnr++], NULL, adderthr, (void *) fileinfo); // zobudi vlakna // if (ACT_THRS < N) // pthread_cond_signal(&cond); pthread_mutex_unlock(&mutex); } else { printf("neregularny subor: %s\n", de->d_name); free(fileinfo); } } // join all threads for (i = 0; i != threadnr; ++i) { pthread_join(threads[i], &thr_retval); // uvolnenie zdrojov fileinfo = (struct stat*) thr_retval; free(fileinfo); } free(threads); if (errno != 0) warn("%s", dirname); printf("HOTOVO: vysledok: %ld", (long int)ALLSIZE); // directory closed by close // closedir(d); if (close(dirfd) == -1) perror("close"); } int main(int argc, char* argv[]) { int N = 10; // default number of threads char *dirname; int opt; char *argv0 = argv[0]; // opterr = 0; if (argc < 2) usage(argv0); printf("first param (command): %s\n", argv[1]); argv++; argc--; while ((opt = getopt(argc, argv, "n:")) != -1) { switch (opt) { case 'n': printf("option -c set to '%s'\n", optarg); N = atoi(optarg); break; case '?': usage(argv0); break; } } printf("option arguments done\n"); /* optind is the 1st non-option argument */ argv = argv + optind; if (argv[0] != NULL) { printf("dirname:"); dirname = argv[0]; printf(" %s\n", dirname); } else { printf("no filenames entered\n"); usage(argv0); } secti(dirname, N); return (EXIT_SUCCESS); }