// File: /workspace/github_c_makefile_star2_O1/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 0x28b3
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
leaq 0x58(%rdi), %r14
movq %r14, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x29e9
movl 0x8(%rbx), %esi
cmpl $0x40, %esi
jae 0x2a08
leaq 0x18(%rbx), %rdi
leaq 0x4(%rsp), %r8
movq %r12, %rdx
movl %r15d, %ecx
callq 0x13fa
testl %eax, %eax
je 0x2667
js 0x26a4
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x28b3
leaq 0x1abe(%rip), %rdi      # 0x410d
leaq 0x19ae(%rip), %rsi      # 0x4004
leaq 0x1c81(%rip), %rcx      # 0x42de
movl $0x345, %edx            # imm = 0x345
callq 0x10b0
movslq 0x4(%rsp), %rax
cmpl %eax, 0x8(%rbx)
jbe 0x271a
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x28b3
leaq 0x1a81(%rip), %rdi      # 0x410d
leaq 0x1971(%rip), %rsi      # 0x4004
leaq 0x1c44(%rip), %rcx      # 0x42de
movl $0x298, %edx            # imm = 0x298
callq 0x10b0
movq (%rbx), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x25e4
testq %rax, %rax
je 0x2808
movq %rax, %r15
cmpl $0x0, 0xb0(%rax)
jle 0x2837
leaq 0x4a6e(%rip), %rax      # 0x7140
cmpl $0x0, (%rax)
je 0x2837
leaq 0x80(%r15), %rdi
callq 0x1070
addq $0x58, %r15
movq %r15, %rdi
callq 0x1110
testl %eax, %eax
je 0x28b5
leaq 0x1a0b(%rip), %rdi      # 0x410d
leaq 0x18fb(%rip), %rsi      # 0x4004
leaq 0x1bce(%rip), %rcx      # 0x42de
movl $0x320, %edx            # imm = 0x320
callq 0x10b0
subq %rax, %r15
jbe 0x2798
movq 0x10(%rbx), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x25e4
testq %rax, %rax
je 0x2878
movq %rax, %r15
cmpl $0x0, 0xb0(%rax)
leaq 0x49f8(%rip), %r12      # 0x7140
jle 0x28c4
cmpl $0x0, (%r12)
je 0x28c4
leaq 0x80(%r15), %rdi
callq 0x1070
addq $0x58, %r15
movq %r15, %rdi
callq 0x1110
testl %eax, %eax
je 0x28ea
leaq 0x198d(%rip), %rdi      # 0x410d
leaq 0x187d(%rip), %rsi      # 0x4004
leaq 0x1b50(%rip), %rcx      # 0x42de
movl $0x2a7, %edx            # imm = 0x2A7
callq 0x10b0
jne 0x2a27
cmpl $0x0, 0xc(%rbx)
je 0x28a3
movl $0x0, 0xc(%rbx)
cmpq %rbx, 0x495a(%rip)      # 0x7110
jne 0x28b5
cmpq $0x0, 0x10(%rbx)
jne 0x28b5
movq (%rbx), %rax
movq %rax, 0x493f(%rip)      # 0x7110
movq %r14, %rdi
callq 0x1110
movq %rbx, %r15
movl $0x100100, %ebx         # imm = 0x100100
testl %eax, %eax
je 0x2972
leaq 0x191d(%rip), %rdi      # 0x410d
leaq 0x180d(%rip), %rsi      # 0x4004
leaq 0x1ae0(%rip), %rcx      # 0x42de
movl $0x2fa, %edx            # imm = 0x2FA
callq 0x10b0
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x28b3
leaq 0x18ee(%rip), %rdi      # 0x410d
leaq 0x17de(%rip), %rsi      # 0x4004
leaq 0x1ab1(%rip), %rcx      # 0x42de
movl $0x33d, %edx            # imm = 0x33D
callq 0x10b0
cmpq $0x0, 0x10(%r15)
jne 0x2849
cmpl $0x0, 0xc(%r15)
je 0x294f
addq $0x58, %r15
movq %r15, %rdi
callq 0x1110
testl %eax, %eax
je 0x28b5
leaq 0x18ad(%rip), %rdi      # 0x410d
leaq 0x179d(%rip), %rsi      # 0x4004
leaq 0x1a70(%rip), %rcx      # 0x42de
movl $0x334, %edx            # imm = 0x334
callq 0x10b0
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x28b3
leaq 0x1882(%rip), %rdi      # 0x410d
leaq 0x1772(%rip), %rsi      # 0x4004
leaq 0x1a45(%rip), %rcx      # 0x42de
movl $0x2e3, %edx            # imm = 0x2E3
callq 0x10b0
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2a46
xorl %ebx, %ebx
movq %rbx, %rax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r14
popq %r15
retq
cmpq $0x0, 0x10(%r15)
jne 0x28d6
cmpl $0x0, 0xc(%r15)
je 0x297f
addq $0x58, %r15
movq %r15, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2a65
cmpq %rbx, 0x481f(%rip)      # 0x7110
jne 0x28b5
cmpq $0x0, 0x10(%rbx)
jne 0x28b5
cmpl $0x0, 0xc(%rbx)
jne 0x28b5
cmpl $0x0, 0xb0(%rbx)
jle 0x29b1
cmpl $0x0, (%r12)
je 0x29b1
leaq 0x80(%rbx), %rdi
callq 0x1070
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x28b5
leaq 0x17d6(%rip), %rdi      # 0x410d
leaq 0x16c6(%rip), %rsi      # 0x4004
leaq 0x1999(%rip), %rcx      # 0x42de
movl $0x2ce, %edx            # imm = 0x2CE
callq 0x10b0
cmpq %r15, (%rbx)
jne 0x2a84
movq (%r15), %rax
movq %rax, (%rbx)
movq %r15, %rdi
addq $0x58, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2aa3
movq %r15, %rdi
callq 0x1030
jmp 0x28b5
cmpq %r15, 0x10(%rbx)
jne 0x2ac2
movq (%r15), %rax
movq %rax, 0x10(%rbx)
movq %r15, %rdi
addq $0x58, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2ae1
movq %r15, %rdi
callq 0x1030
jmp 0x28ea
movq (%rbx), %rax
movq %rax, 0x4755(%rip)      # 0x7110
movq %r14, %rdi
callq 0x1110
movq %rbx, %r15
testl %eax, %eax
je 0x2972
leaq 0x173c(%rip), %rdi      # 0x410d
leaq 0x162c(%rip), %rsi      # 0x4004
leaq 0x18ff(%rip), %rcx      # 0x42de
movl $0x2d6, %edx            # imm = 0x2D6
callq 0x10b0
leaq 0x171d(%rip), %rdi      # 0x410d
leaq 0x160d(%rip), %rsi      # 0x4004
leaq 0x18e0(%rip), %rcx      # 0x42de
movl $0x289, %edx            # imm = 0x289
callq 0x10b0
leaq 0x16e2(%rip), %rdi      # 0x40f1
leaq 0x15ee(%rip), %rsi      # 0x4004
leaq 0x18c1(%rip), %rcx      # 0x42de
movl $0x28c, %edx            # imm = 0x28C
callq 0x10b0
leaq 0x16e7(%rip), %rdi      # 0x4115
leaq 0x15cf(%rip), %rsi      # 0x4004
leaq 0x18a2(%rip), %rcx      # 0x42de
movl $0x2ea, %edx            # imm = 0x2EA
callq 0x10b0
leaq 0x16c0(%rip), %rdi      # 0x410d
leaq 0x15b0(%rip), %rsi      # 0x4004
leaq 0x1883(%rip), %rcx      # 0x42de
movl $0x30e, %edx            # imm = 0x30E
callq 0x10b0
leaq 0x16a1(%rip), %rdi      # 0x410d
leaq 0x1591(%rip), %rsi      # 0x4004
leaq 0x1864(%rip), %rcx      # 0x42de
movl $0x2bf, %edx            # imm = 0x2BF
callq 0x10b0
leaq 0x18af(%rip), %rdi      # 0x433a
leaq 0x1572(%rip), %rsi      # 0x4004
leaq 0x1845(%rip), %rcx      # 0x42de
movl $0x329, %edx            # imm = 0x329
callq 0x10b0
leaq 0x1663(%rip), %rdi      # 0x410d
leaq 0x1553(%rip), %rsi      # 0x4004
leaq 0x1826(%rip), %rcx      # 0x42de
movl $0x32c, %edx            # imm = 0x32C
callq 0x10b0
leaq 0x1859(%rip), %rdi      # 0x4322
leaq 0x1534(%rip), %rsi      # 0x4004
leaq 0x1807(%rip), %rcx      # 0x42de
movl $0x2b2, %edx            # imm = 0x2B2
callq 0x10b0
leaq 0x1625(%rip), %rdi      # 0x410d
leaq 0x1515(%rip), %rsi      # 0x4004
leaq 0x17e8(%rip), %rcx      # 0x42de
movl $0x2b6, %edx            # imm = 0x2B6
callq 0x10b0