// File: /workspace/github_c_makefile_star2_O2/stevenmherring[P]DNS/fine-trie.c
// Function: delete
struct trie_node *
      _delete (struct trie_node *node, const char *string,
        size_t strlen) {
          int keylen, cmp;
          int rc;
          // First things first, check if we are NULL

          if (node == NULL) return NULL;


          // lock the node here,
          rc = pthread_mutex_lock(&(node->lock));
          assert(rc == 0);


          assert(node->strlen < 64);

          // See if this key is a substring of the string passed in
          cmp = compare_keys (node->key, node->strlen, string, strlen, &keylen);
          if (cmp == 0) {
            // Yes, either quit, or recur on the children

            // If this key is longer than our search string, the key isn't here
            if (node->strlen > keylen)
            {
              // unlock node
              rc = pthread_mutex_unlock(&(node->lock));
              assert(rc == 0);

              return NULL;
            }
            else if (strlen > keylen)
            {
              // found wont be unlocked by this method
              struct trie_node *found =  _delete(node->children, string, strlen - keylen);

              if (found)
              {
                if(found->waiting > 0 && allow_squatting)
                {
                  pthread_cond_broadcast(&(found->c));
                  rc = pthread_mutex_unlock(&(found->lock));
                  assert(rc == 0);

                }
                else
                {
                  /* If the node doesn't have children, delete it.
                  * Otherwise, keep it around to find the kids */
                  if (found->children == NULL && found->ip4_address == 0)
                  {
                    // shouldnt need to lock found->next because as long as parent is locked,
                    // nothing bad should be able to happen to it (check what insert does)
                    assert(node->children == found);
                    node->children = found->next;
                    // unlock found
                    rc = pthread_mutex_unlock(&(found->lock));
                    assert(rc == 0);


                    free(found);

                  }
                  else
                  {
                    rc = pthread_mutex_unlock(&(found->lock));
                    assert(rc == 0);

                  }
                }

                // unlock found

                // TODO get root lock
                /* Delete the root node if we empty the tree */
                if (node == root && node->children == NULL && node->ip4_address == 0)
                {
                  if(node->waiting > 0 && allow_squatting)
                  {
                    pthread_cond_broadcast(&(node->c));
                    rc = pthread_mutex_unlock(&(node->lock));
                    assert(rc == 0);

                  }
                  else
                  {
                    root = node->next;

                    rc = pthread_mutex_unlock(&(node->lock));
                    assert(rc == 0);


                    free(node);
                  }
                }

                // dont unlock node, we are still doing operations on it
                return node; /* Recursively delete needless interior nodes */
              }
              else
              {
                rc = pthread_mutex_unlock(&(node->lock));
                assert(rc == 0);

                return NULL;
              }
            }
            else
            {
              assert (strlen == keylen);

              /* We found it! Clear the ip4 address and return. */
              if (node->ip4_address)
              {
                node->ip4_address = 0;

                //TODO lock root
                /* Delete the root node if we empty the tree */
                if (node == root && node->children == NULL && node->ip4_address == 0)
                {

                  root = node->next;


                  rc = pthread_mutex_unlock(&(node->lock));
                  assert(rc == 0);


                  // dont free if waiting > 0

                  free(node);
                  return (struct trie_node *) 0x100100; /* XXX: Don't use this pointer for anything except
                  * comparison with NULL, since the memory is freed.
                  * Return a "poison" pointer that will probably
                  * segfault if used.
                  */
                }

                // dont return node, still doing stuff
                return node;
              }
              else
              {
                /* Just an interior node with no value */
                rc = pthread_mutex_unlock(&(node->lock));
                assert(rc == 0);

                return NULL;
              }
            }
          }
          else if (cmp < 0) {
            // No, look right (the node's key is "less" than  the search key)

            // found should be locked
            struct trie_node *found = _delete(node->next, string, strlen);

            if (found)
            {
              if(found->waiting > 0 && allow_squatting)
              {
                pthread_cond_broadcast(&(found->c));
                rc = pthread_mutex_unlock(&(found->lock));
                assert(rc == 0);

              }
              else
              {
                /* If the node doesn't have children, delete it.
                * Otherwise, keep it around to find the kids */
                if (found->children == NULL && found->ip4_address == 0)
                {
                  assert(node->next == found);
                  node->next = found->next;
                  rc = pthread_mutex_unlock(&(found->lock));
                  assert(rc == 0);


                  free(found);
                }
                else
                {
                  rc = pthread_mutex_unlock(&(found->lock));
                  assert(rc == 0);

                }
              }

              return node; /* Recursively delete needless interior nodes */
            }

            rc = pthread_mutex_unlock(&(node->lock));
            assert(rc == 0);

            return NULL;
          }
          else
          {
            // Quit early
            rc = pthread_mutex_unlock(&(node->lock));
            assert(rc == 0);

            return NULL;
          }

        }

// Assembly:
pushq %r15
pushq %r14
pushq %r12
pushq %rbx
pushq %rax
testq %rdi, %rdi
je 0x282e
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
leaq 0x58(%rdi), %r14
movq %r14, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x2964
movl 0x8(%rbx), %esi
cmpl $0x40, %esi
jae 0x2983
leaq 0x18(%rbx), %rdi
leaq 0x4(%rsp), %r8
movq %r12, %rdx
movl %r15d, %ecx
callq 0x13dd
testl %eax, %eax
je 0x25e5
js 0x2622
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x282e
leaq 0x1b40(%rip), %rdi      # 0x410d
leaq 0x1a30(%rip), %rsi      # 0x4004
leaq 0x1d03(%rip), %rcx      # 0x42de
movl $0x345, %edx            # imm = 0x345
callq 0x10b0
movslq 0x4(%rsp), %rax
cmpl %eax, 0x8(%rbx)
jbe 0x2698
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x282e
leaq 0x1b03(%rip), %rdi      # 0x410d
leaq 0x19f3(%rip), %rsi      # 0x4004
leaq 0x1cc6(%rip), %rcx      # 0x42de
movl $0x298, %edx            # imm = 0x298
callq 0x10b0
movq (%rbx), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x2562
testq %rax, %rax
je 0x2783
movq %rax, %r15
cmpl $0x0, 0xb0(%rax)
jle 0x27b2
leaq 0x4af0(%rip), %rax      # 0x7140
cmpl $0x0, (%rax)
je 0x27b2
leaq 0x80(%r15), %rdi
callq 0x1070
addq $0x58, %r15
movq %r15, %rdi
callq 0x1110
testl %eax, %eax
je 0x2830
leaq 0x1a8d(%rip), %rdi      # 0x410d
leaq 0x197d(%rip), %rsi      # 0x4004
leaq 0x1c50(%rip), %rcx      # 0x42de
movl $0x320, %edx            # imm = 0x320
callq 0x10b0
subq %rax, %r15
jbe 0x2716
movq 0x10(%rbx), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x2562
testq %rax, %rax
je 0x27f3
movq %rax, %r15
cmpl $0x0, 0xb0(%rax)
leaq 0x4a7a(%rip), %r12      # 0x7140
jle 0x283f
cmpl $0x0, (%r12)
je 0x283f
leaq 0x80(%r15), %rdi
callq 0x1070
addq $0x58, %r15
movq %r15, %rdi
callq 0x1110
testl %eax, %eax
je 0x2865
leaq 0x1a0f(%rip), %rdi      # 0x410d
leaq 0x18ff(%rip), %rsi      # 0x4004
leaq 0x1bd2(%rip), %rcx      # 0x42de
movl $0x2a7, %edx            # imm = 0x2A7
callq 0x10b0
jne 0x29a2
cmpl $0x0, 0xc(%rbx)
je 0x281e
andl $0x0, 0xc(%rbx)
cmpq %rbx, 0x49df(%rip)      # 0x7110
jne 0x2830
cmpq $0x0, 0x10(%rbx)
jne 0x2830
movq (%rbx), %rax
movq %rax, 0x49c4(%rip)      # 0x7110
movq %r14, %rdi
callq 0x1110
movq %rbx, %r15
movl $0x100100, %ebx         # imm = 0x100100
testl %eax, %eax
je 0x28ed
leaq 0x19a2(%rip), %rdi      # 0x410d
leaq 0x1892(%rip), %rsi      # 0x4004
leaq 0x1b65(%rip), %rcx      # 0x42de
movl $0x2fa, %edx            # imm = 0x2FA
callq 0x10b0
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x282e
leaq 0x1973(%rip), %rdi      # 0x410d
leaq 0x1863(%rip), %rsi      # 0x4004
leaq 0x1b36(%rip), %rcx      # 0x42de
movl $0x33d, %edx            # imm = 0x33D
callq 0x10b0
cmpq $0x0, 0x10(%r15)
jne 0x27c4
cmpl $0x0, 0xc(%r15)
je 0x28ca
addq $0x58, %r15
movq %r15, %rdi
callq 0x1110
testl %eax, %eax
je 0x2830
leaq 0x1932(%rip), %rdi      # 0x410d
leaq 0x1822(%rip), %rsi      # 0x4004
leaq 0x1af5(%rip), %rcx      # 0x42de
movl $0x334, %edx            # imm = 0x334
callq 0x10b0
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x282e
leaq 0x1907(%rip), %rdi      # 0x410d
leaq 0x17f7(%rip), %rsi      # 0x4004
leaq 0x1aca(%rip), %rcx      # 0x42de
movl $0x2e3, %edx            # imm = 0x2E3
callq 0x10b0
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
jne 0x29c1
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
cmpq $0x0, 0x10(%r15)
jne 0x2851
cmpl $0x0, 0xc(%r15)
je 0x28fa
addq $0x58, %r15
movq %r15, %rdi
callq 0x1110
testl %eax, %eax
jne 0x29e0
cmpq %rbx, 0x48a4(%rip)      # 0x7110
jne 0x2830
cmpq $0x0, 0x10(%rbx)
jne 0x2830
cmpl $0x0, 0xc(%rbx)
jne 0x2830
cmpl $0x0, 0xb0(%rbx)
jle 0x292c
cmpl $0x0, (%r12)
je 0x292c
leaq 0x80(%rbx), %rdi
callq 0x1070
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x2830
leaq 0x185b(%rip), %rdi      # 0x410d
leaq 0x174b(%rip), %rsi      # 0x4004
leaq 0x1a1e(%rip), %rcx      # 0x42de
movl $0x2ce, %edx            # imm = 0x2CE
callq 0x10b0
cmpq %r15, (%rbx)
jne 0x29ff
movq (%r15), %rax
movq %rax, (%rbx)
movq %r15, %rdi
addq $0x58, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2a1e
movq %r15, %rdi
callq 0x1030
jmp 0x2830
cmpq %r15, 0x10(%rbx)
jne 0x2a3d
movq (%r15), %rax
movq %rax, 0x10(%rbx)
movq %r15, %rdi
addq $0x58, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2a5c
movq %r15, %rdi
callq 0x1030
jmp 0x2865
movq (%rbx), %rax
movq %rax, 0x47da(%rip)      # 0x7110
movq %r14, %rdi
callq 0x1110
movq %rbx, %r15
testl %eax, %eax
je 0x28ed
leaq 0x17c1(%rip), %rdi      # 0x410d
leaq 0x16b1(%rip), %rsi      # 0x4004
leaq 0x1984(%rip), %rcx      # 0x42de
movl $0x2d6, %edx            # imm = 0x2D6
callq 0x10b0
leaq 0x17a2(%rip), %rdi      # 0x410d
leaq 0x1692(%rip), %rsi      # 0x4004
leaq 0x1965(%rip), %rcx      # 0x42de
movl $0x289, %edx            # imm = 0x289
callq 0x10b0
leaq 0x1767(%rip), %rdi      # 0x40f1
leaq 0x1673(%rip), %rsi      # 0x4004
leaq 0x1946(%rip), %rcx      # 0x42de
movl $0x28c, %edx            # imm = 0x28C
callq 0x10b0
leaq 0x176c(%rip), %rdi      # 0x4115
leaq 0x1654(%rip), %rsi      # 0x4004
leaq 0x1927(%rip), %rcx      # 0x42de
movl $0x2ea, %edx            # imm = 0x2EA
callq 0x10b0
leaq 0x1745(%rip), %rdi      # 0x410d
leaq 0x1635(%rip), %rsi      # 0x4004
leaq 0x1908(%rip), %rcx      # 0x42de
movl $0x30e, %edx            # imm = 0x30E
callq 0x10b0
leaq 0x1726(%rip), %rdi      # 0x410d
leaq 0x1616(%rip), %rsi      # 0x4004
leaq 0x18e9(%rip), %rcx      # 0x42de
movl $0x2bf, %edx            # imm = 0x2BF
callq 0x10b0
leaq 0x1934(%rip), %rdi      # 0x433a
leaq 0x15f7(%rip), %rsi      # 0x4004
leaq 0x18ca(%rip), %rcx      # 0x42de
movl $0x329, %edx            # imm = 0x329
callq 0x10b0
leaq 0x16e8(%rip), %rdi      # 0x410d
leaq 0x15d8(%rip), %rsi      # 0x4004
leaq 0x18ab(%rip), %rcx      # 0x42de
movl $0x32c, %edx            # imm = 0x32C
callq 0x10b0
leaq 0x18de(%rip), %rdi      # 0x4322
leaq 0x15b9(%rip), %rsi      # 0x4004
leaq 0x188c(%rip), %rcx      # 0x42de
movl $0x2b2, %edx            # imm = 0x2B2
callq 0x10b0
leaq 0x16aa(%rip), %rdi      # 0x410d
leaq 0x159a(%rip), %rsi      # 0x4004
leaq 0x186d(%rip), %rcx      # 0x42de
movl $0x2b6, %edx            # imm = 0x2B6
callq 0x10b0