// File: /workspace/github_cpp_makefile_star2_O2/supragya[P]DirectorySync/DirectorySync.cpp
// Function: filewatcher(char*, char*, int)
void filewatcher(char *dirname, char *intermediate, int sock) {

    std::cout << "#### Began thread [FILEWATCHER]"<<std::endl;


    // Initialise FileWatcher
    int fd, wd;
    char workCMD[WORKCMDLEN];

    strcpy(workCMD, dirname);
    if(strlen(intermediate) > 0)
        strcat(workCMD, "/");
    strcat(workCMD, intermediate);

    fd = inotify_init();
    if ( fd < 0 ) {
        std::cout<<"[FW: inotify] Could not initialise inotify, quitting"<<std::endl;
        exit(1);
    }
    wd = inotify_add_watch(fd, workCMD, IN_CREATE | IN_MODIFY | IN_DELETE);
    if (wd == -1){
        std::cout<<"[FW: inotify] Could not add watch to ["<<workCMD<<"], quitting\n";
        exit(1);
    }
    else
        std::cout<<"[FW: inotify] Started watching ["<<workCMD<<"]"<<std::endl;


    // Actual FileWatch system
    char *FWINBuffer[INOTIFYBUFLEN];
    int length;
    while(1) {
        int i = 0;
        length = read(fd, FWINBuffer, INOTIFYBUFLEN);
        if (length < 0)
            std::cout << "[FILEWATCHER] Read Error \n";
        while (i < length) {
            struct inotify_event *event = (struct inotify_event *) &FWINBuffer[i];
            if (event->len) {
                if (event->mask & IN_CREATE) {
                    if (event->mask & IN_ISDIR) {
                        strcpy(workCMD, intermediate);
                        if(strlen(intermediate) > 0)
                            strcat(workCMD, "/");
                        strcat(workCMD, event->name);
                        std::cout << "[FW: inotify]\tCreated\tDIR\t" << workCMD << std::endl;
                        message *message_packet = FormMessage(workCMD, CREATE, DIRECTORY, 0);
                        if (!Transactions.is_recorded(*message_packet)) {
                            int sent = send(sock, message_packet, sizeof(message), 0);
                            std::cout << "[FW: inotify]\tSent request to create [" << event->name << "] Directory"
                                      << std::endl;

                            char *newintermediate = (char *)malloc(sizeof(char)*MAXFILENAMELEN);
                            strcpy(newintermediate, workCMD);
                            std::thread currentfilewatcher(filewatcher, dirname, intermediate, sock);
                            std::thread newfilewatcher(filewatcher, dirname, newintermediate, sock);
                            currentfilewatcher.join();
                            newfilewatcher.join();

                        } else {
                            std::cout << "[FW: inotify]\tDirectory [" << event->name
                                      << "]  created due to incoming request, skip request send" << std::endl;
                        }

                        free(message_packet);
                    }
                    else {
                        strcpy(workCMD, intermediate);
                        if(strlen(intermediate) > 0)
                            strcat(workCMD, "/");
                        strcat(workCMD, event->name);
                        std::cout << "[FW: inotify]\tCreated\tFIL\t" << workCMD << std::endl;
                        message *message_packet = FormMessage(workCMD, CREATE, _FILE, 0);

                        if (!Transactions.is_recorded(*message_packet)) {
                            int sent = send(sock, message_packet, sizeof(message), 0);
                            std::cout << "[FW: inotify]\tSent request to create [" << workCMD << "] file"
                                      << std::endl;
                        } else {
                            std::cout << "[FW: inotify]\tFile [" << event->name
                                      << "]  created due to incoming request, skip request send" << std::endl;
                        }

                        free(message_packet);
                    }
                }
                else if (event->mask & IN_MODIFY) {
                    if(!(event->mask & IN_ISDIR)){


                        FileAccess.lock();
                        strcpy(workCMD, dirname);
                        strcat(workCMD, "/");
                        strcat(workCMD, intermediate);
                        if(strlen(intermediate) > 0)
                            strcat(workCMD, "/");
                        strcat(workCMD, event->name);
                        std::ifstream file(workCMD, std::ios::binary);
                        file.seekg(0, file.end);
                        std::cout << "[FW: inotify]\tModified\tFIL\t" << workCMD << std::endl;
                        unsigned int filesize = file.tellg();
                        file.close();
                        FileAccess.unlock();
                        strcpy(workCMD, intermediate);
                        if(strlen(intermediate) > 0)
                            strcat(workCMD, "/");
                        strcat(workCMD, event->name);
                        message *message_packet = FormMessage(workCMD, MODIFY, _FILE, filesize);

                        if(!Transactions.is_recorded(*message_packet)){
                            int sent = send(sock, message_packet, sizeof(message), 0);

                            FileAccess.lock();
                            strcpy(workCMD, dirname);
                            strcat(workCMD, "/");
                            strcat(workCMD, intermediate);
                            if(strlen(intermediate) > 0)
                                strcat(workCMD, "/");
                            strcat(workCMD, event->name);
                            std::cout << "[FW: inotify]\tSent request to modify [" << workCMD << "] filesize = "<< filesize
                                      << std::endl;
                            file.open(workCMD, std::ios::binary);
                            file.seekg(0, file.beg);
                            char *filedata = (char*)malloc(filesize);
                            file.read(filedata, filesize);
                            FileAccess.unlock();
                            send(sock, filedata, filesize, 0);
                            free(filedata);

                        }else{
                            std::cout << "[FW: inotify]\tFile [" << workCMD
                                      << "]  modified due to incoming request, skip request send" << std::endl;
                        }
                    }
                }
                else if (event->mask & IN_DELETE) {
                    if (event->mask & IN_ISDIR) {
                        strcpy(workCMD, intermediate);
                        if(strlen(intermediate) > 0)
                            strcat(workCMD, "/");
                        strcat(workCMD, event->name);
                        std::cout << "[FW: inotify]\tDeleted\tDIR\t" << workCMD << std::endl;
                        message *message_packet = FormMessage(workCMD, DELETE, DIRECTORY, 0);
                        if (!Transactions.is_recorded(*message_packet)) {
                            int sent = send(sock, message_packet, sizeof(message), 0);
                            std::cout << "[FW: inotify]\tSent request to delete [" << workCMD << "] Directory"
                                      << std::endl;
                        } else {
                            std::cout << "[FW: inotify]\tDirectory [" << event->name
                                      << "]  deleted due to incoming request, skip request send" << std::endl;
                        }

                        free(message_packet);
                    }
                    else {
                        strcpy(workCMD, intermediate);
                        if(strlen(intermediate) > 0)
                            strcat(workCMD, "/");
                        strcat(workCMD, event->name);
                        std::cout << "[FW: inotify]\tDeleted\tFIL\t" << workCMD << std::endl;
                        message *message_packet = FormMessage(workCMD, DELETE, _FILE, 0);

                        if (!Transactions.is_recorded(*message_packet)) {
                            int sent = send(sock, message_packet, sizeof(message), 0);
                            std::cout << "[FW: inotify]\tSent request to delete [" << workCMD << "] file"
                                      << std::endl;
                        } else {
                            std::cout << "[FW: inotify]\tFile [" << event->name
                                      << "]  delete due to incoming request, skip request send" << std::endl;
                        }

                        free(message_packet);
                    }
                }
            }
            i += EVENT_SIZE + event->len;
        }
    }

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x4c98, %rsp           # imm = 0x4C98
movq %rsi, %rbx
movq %rdi, %r14
movq %rdi, -0x50(%rbp)
movq %rsi, -0x40(%rbp)
movl %edx, -0x2c(%rbp)
movq 0x44b8(%rip), %rdi      # 0x6fd0
leaq 0x1c43(%rip), %rsi      # 0x4762
callq 0x2180
movq %rax, %rdi
callq 0x20c0
leaq -0x2980(%rbp), %rdi
movq %r14, %rsi
callq 0x2160
cmpb $0x0, (%rbx)
je 0x2b56
leaq -0x2980(%rbp), %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
leaq -0x2980(%rbp), %rdi
movq %rbx, %rsi
callq 0x22c0
callq 0x22e0
testl %eax, %eax
jns 0x2b8b
movq 0x445b(%rip), %rdi      # 0x6fd0
leaq 0x1c06(%rip), %rsi      # 0x4782
callq 0x2180
movq %rax, %rdi
callq 0x20c0
jmp 0x2bd9
movl %eax, %ebx
leaq -0x2980(%rbp), %r12
movl %eax, %edi
movq %r12, %rsi
movl $0x302, %edx            # imm = 0x302
callq 0x20e0
cmpl $-0x1, %eax
jne 0x2be1
movq 0x4421(%rip), %rdi      # 0x6fd0
leaq 0x1c01(%rip), %rsi      # 0x47b7
callq 0x2180
leaq -0x2980(%rbp), %rsi
movq %rax, %rdi
callq 0x2180
leaq 0x1c0d(%rip), %rsi      # 0x47de
movq %rax, %rdi
callq 0x2180
pushq $0x1
popq %rdi
callq 0x21d0
movl %ebx, -0x54(%rbp)
movq 0x43e5(%rip), %rdi      # 0x6fd0
leaq 0x1bf9(%rip), %rsi      # 0x47eb
callq 0x2180
movq %rax, %rdi
movq %r12, %rsi
callq 0x2180
leaq 0x1b77(%rip), %rsi      # 0x4780
movq %rax, %rdi
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movl $0x3e8, %edx            # imm = 0x3E8
movl -0x54(%rbp), %edi
leaq -0x48c0(%rbp), %rsi
callq 0x2230
movq %rax, %rbx
testl %ebx, %ebx
jns 0x2c47
movq 0x4395(%rip), %rdi      # 0x6fd0
leaq 0x1bca(%rip), %rsi      # 0x480c
callq 0x2180
xorl %r13d, %r13d
movq %rbx, -0x38(%rbp)
cmpl %ebx, %r13d
jge 0x2c19
movslq %r13d, %rax
leaq -0x48c0(,%rax,8), %r14
addq %rbp, %r14
cmpl $0x0, 0xc(%r14)
je 0x3365
movl 0x4(%r14), %r15d
btl $0x8, %r15d
jb 0x2d58
testb $0x2, %r15b
jne 0x2e5c
btl $0x9, %r15d
jae 0x3365
movq -0x40(%rbp), %rbx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x2160
btl $0x1e, %r15d
movb (%rbx), %al
jb 0x317b
testb %al, %al
je 0x2cc2
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
leaq 0x10(%r14), %rbx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x22c0
movq 0x42f8(%rip), %rdi      # 0x6fd0
leaq 0x1d1d(%rip), %rsi      # 0x49fc
callq 0x2180
movq %rax, %rdi
movq %r12, %rsi
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movq %r12, %rdi
pushq $0x2
popq %rsi
pushq $0x1
popq %rdx
xorl %ecx, %ecx
callq 0x35ea
movq %rax, %r12
movl $0x80, %ecx
movq %rsp, %rdi
movq %rax, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x4491(%rip), %rdi      # 0x71b0
callq 0x396e
leaq 0x1bbc(%rip), %rsi      # 0x48e7
leaq 0x1ce5(%rip), %r15      # 0x4a17
testb %al, %al
jne 0x2e25
movl -0x2c(%rbp), %edi
movl $0x400, %edx            # imm = 0x400
movq %r12, %rsi
xorl %ecx, %ecx
callq 0x20d0
leaq 0x1c4c(%rip), %rsi      # 0x499f
jmp 0x2e17
movq -0x40(%rbp), %rbx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x2160
btl $0x1e, %r15d
movb (%rbx), %al
jb 0x2fe1
testb %al, %al
je 0x2d8a
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
leaq 0x10(%r14), %rbx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x22c0
movq 0x4230(%rip), %rdi      # 0x6fd0
leaq 0x1b1e(%rip), %rsi      # 0x48c5
callq 0x2180
movq %rax, %rdi
movq %r12, %rsi
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movq %r12, %rdi
pushq $0x3
popq %rsi
pushq $0x1
popq %rdx
xorl %ecx, %ecx
callq 0x35ea
movq %rax, %r12
movl $0x80, %ecx
movq %rsp, %rdi
movq %rax, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x43c9(%rip), %rdi      # 0x71b0
callq 0x396e
leaq 0x1af4(%rip), %rsi      # 0x48e7
leaq 0x1a95(%rip), %r15      # 0x488f
testb %al, %al
jne 0x2e25
movl -0x2c(%rbp), %edi
movl $0x400, %edx            # imm = 0x400
movq %r12, %rsi
xorl %ecx, %ecx
callq 0x20d0
leaq 0x1a2b(%rip), %rsi      # 0x4842
leaq -0x2980(%rbp), %rbx
leaq 0x1abb(%rip), %r15      # 0x48e0
movq 0x41a4(%rip), %rdi      # 0x6fd0
callq 0x2180
movq %rax, %rdi
movq %rbx, %rsi
callq 0x2180
movq %rax, %rdi
movq %r15, %rsi
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movq %r12, %rdi
callq 0x21c0
jmp 0x335a
btl $0x1e, %r15d
jb 0x3365
leaq 0x1d3d2(%rip), %rdi     # 0x20240
callq 0x394e
movq -0x50(%rbp), %rsi
movq %r12, %rdi
callq 0x2160
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
movq -0x40(%rbp), %rbx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x22c0
cmpb $0x0, (%rbx)
je 0x2eb7
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
leaq 0x10(%r14), %rsi
movq %r12, %rdi
movq %rsi, -0x48(%rbp)
callq 0x22c0
leaq -0x270(%rbp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
pushq $0x4
popq %rdx
callq 0x22f0
movq %rbx, %rdi
xorl %esi, %esi
pushq $0x2
popq %rdx
callq 0x2210
movq 0x40e0(%rip), %rdi      # 0x6fd0
leaq 0x1a05(%rip), %rsi      # 0x48fc
callq 0x2180
movq %rax, %rdi
leaq -0x2980(%rbp), %rsi
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movq %rbx, %rdi
callq 0x22a0
movq %rbx, %rdi
movq %rax, %rbx
callq 0x2040
leaq 0x1d313(%rip), %rdi     # 0x20240
callq 0x2120
movq -0x40(%rbp), %r15
leaq -0x2980(%rbp), %r12
movq %r12, %rdi
movq %r15, %rsi
callq 0x2160
cmpb $0x0, (%r15)
je 0x2f60
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
movq %r12, %rdi
movq -0x48(%rbp), %rsi
callq 0x22c0
movl %ebx, %ebx
movq %r12, %rdi
pushq $0x1
popq %rdx
movl %edx, %esi
movq %rbx, %rcx
callq 0x35ea
movq %rax, %r15
movl $0x80, %ecx
movq %rsp, %rdi
movq %rax, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x421a(%rip), %rdi      # 0x71b0
callq 0x396e
testb %al, %al
je 0x3234
movq 0x4026(%rip), %rdi      # 0x6fd0
leaq 0x1936(%rip), %rsi      # 0x48e7
callq 0x2180
movq %rax, %rdi
leaq -0x2980(%rbp), %rsi
callq 0x2180
movq %rax, %rdi
leaq 0x197e(%rip), %rsi      # 0x494d
callq 0x2180
movq %rax, %rdi
callq 0x20c0
jmp 0x334e
testb %al, %al
je 0x2ff7
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
movq %r12, %r15
leaq 0x10(%r14), %r12
movq %r15, %rdi
movq %r12, %rsi
callq 0x22c0
movq 0x3fc0(%rip), %rdi      # 0x6fd0
leaq 0x1810(%rip), %rsi      # 0x4827
callq 0x2180
movq %rax, %rdi
movq %r15, %rsi
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movq %r15, %rdi
pushq $0x3
popq %rsi
pushq $0x2
popq %rdx
xorl %ecx, %ecx
callq 0x35ea
movq %rax, %rbx
movl $0x80, %ecx
movq %rsp, %rdi
movq %rax, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x4159(%rip), %rdi      # 0x71b0
callq 0x396e
testb %al, %al
movq %rbx, -0x48(%rbp)
je 0x30a1
movq 0x3f65(%rip), %rdi      # 0x6fd0
leaq 0x1803(%rip), %rsi      # 0x4875
callq 0x2180
movq %rax, %rdi
movq %r12, %rsi
callq 0x2180
movq %rax, %rdi
leaq 0x1803(%rip), %rsi      # 0x488f
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movq %r15, %r12
jmp 0x3169
movl -0x2c(%rbp), %edi
movl $0x400, %edx            # imm = 0x400
movq %rbx, %rsi
xorl %ecx, %ecx
callq 0x20d0
movq 0x3f16(%rip), %rdi      # 0x6fd0
leaq 0x1781(%rip), %rsi      # 0x4842
callq 0x2180
movq %rax, %rdi
movq %r12, %rsi
callq 0x2180
movq %rax, %rdi
leaq 0x178e(%rip), %rsi      # 0x4869
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movl $0x3e8, %edi            # imm = 0x3E8
callq 0x2200
movq %rax, -0x270(%rbp)
movq %rax, %rdi
movq %r15, %rsi
callq 0x2160
leaq -0x68(%rbp), %rbx
movq %rbx, %rdi
leaq -0x626(%rip), %r12      # 0x2aec
movq %r12, %rsi
leaq -0x50(%rbp), %rdx
leaq -0x40(%rbp), %rcx
leaq -0x2c(%rbp), %r8
callq 0x38ba
leaq -0x60(%rbp), %rdi
movq %r12, %rsi
leaq -0x50(%rbp), %rdx
leaq -0x270(%rbp), %rcx
leaq -0x2c(%rbp), %r8
callq 0x38ba
movq %r15, %r12
movq %rbx, %rdi
callq 0x2270
leaq -0x60(%rbp), %rbx
movq %rbx, %rdi
callq 0x2270
movq %rbx, %rdi
callq 0x38aa
leaq -0x68(%rbp), %rdi
callq 0x38aa
movq -0x38(%rbp), %rbx
movq -0x48(%rbp), %rdi
callq 0x21c0
jmp 0x3365
testb %al, %al
je 0x3191
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
leaq 0x10(%r14), %rbx
movq %r12, %rdi
movq %rbx, %rsi
callq 0x22c0
movq 0x3e29(%rip), %rdi      # 0x6fd0
leaq 0x17d6(%rip), %rsi      # 0x4984
callq 0x2180
movq %rax, %rdi
movq %r12, %rsi
callq 0x2180
movq %rax, %rdi
callq 0x20c0
movq %r12, %rdi
pushq $0x2
popq %rdx
movl %edx, %esi
xorl %ecx, %ecx
callq 0x35ea
movq %rax, %r12
movl $0x80, %ecx
movq %rsp, %rdi
movq %rax, %rsi
rep  movsq (%rsi), %es:(%rdi)
leaq 0x3fc3(%rip), %rdi      # 0x71b0
callq 0x396e
leaq 0x167c(%rip), %rsi      # 0x4875
leaq 0x17c6(%rip), %r15      # 0x49c6
testb %al, %al
jne 0x2e25
movl -0x2c(%rbp), %edi
movl $0x400, %edx            # imm = 0x400
movq %r12, %rsi
xorl %ecx, %ecx
callq 0x20d0
leaq 0x177e(%rip), %rsi      # 0x499f
leaq -0x2980(%rbp), %rbx
leaq 0x163a(%rip), %r15      # 0x4869
jmp 0x2e25
movl -0x2c(%rbp), %edi
movl $0x400, %edx            # imm = 0x400
movq %r15, %rsi
xorl %ecx, %ecx
callq 0x20d0
leaq 0x1cff3(%rip), %rdi     # 0x20240
callq 0x394e
movq -0x50(%rbp), %rsi
movq %r12, %rdi
callq 0x2160
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
movq -0x40(%rbp), %r15
movq %r12, %rdi
movq %r15, %rsi
callq 0x22c0
cmpb $0x0, (%r15)
je 0x3297
movq %r12, %rdi
callq 0x20a0
movw $0x2f, -0x2980(%rbp,%rax)
movq %r12, %rdi
movq -0x48(%rbp), %rsi
callq 0x22c0
movq 0x3d26(%rip), %rdi      # 0x6fd0
leaq 0x1667(%rip), %rsi      # 0x4918
callq 0x2180
movq %rax, %rdi
leaq -0x2980(%rbp), %rsi
callq 0x2180
movq %rax, %rdi
leaq 0x1670(%rip), %rsi      # 0x493f
callq 0x2180
movq %rax, %rdi
movq %rbx, %rsi
callq 0x2110
movq %rax, %rdi
callq 0x20c0
leaq -0x270(%rbp), %rdi
leaq -0x2980(%rbp), %rsi
pushq $0x4
popq %rdx
callq 0x20f0
leaq -0x270(%rbp), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2210
movq %rbx, %rdi
callq 0x2200
movq %rax, %r12
leaq -0x270(%rbp), %rdi
movq %rax, %rsi
movq %rbx, %rdx
callq 0x21e0
leaq 0x1cf0f(%rip), %rdi     # 0x20240
callq 0x2120
movl -0x2c(%rbp), %edi
movq %r12, %rsi
movq %rbx, %rdx
xorl %ecx, %ecx
callq 0x20d0
movq %r12, %rdi
callq 0x21c0
leaq -0x270(%rbp), %rdi
callq 0x2060
leaq -0x2980(%rbp), %r12
movq -0x38(%rbp), %rbx
movl 0xc(%r14), %eax
addl %eax, %r13d
addl $0x10, %r13d
jmp 0x2c4e
movq %rax, %rbx
jmp 0x338c
jmp 0x339b
jmp 0x339b
jmp 0x339b
movq %rax, %rbx
leaq -0x60(%rbp), %rdi
callq 0x38aa
leaq -0x68(%rbp), %rdi
callq 0x38aa
jmp 0x33aa
jmp 0x339b
jmp 0x339b
movq %rax, %rbx
leaq -0x270(%rbp), %rdi
callq 0x2060
movq %rbx, %rdi
callq 0x22b0