// File: /workspace/github_c_makefile_star2_O0/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 %rbp
movq %rsp, %rbp
subq $0x40, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
cmpq $0x0, -0x10(%rbp)
jne 0x2be8
movq $0x0, -0x8(%rbp)
jmp 0x327a
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x11d0
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x2c00
jmp 0x2c1f
leaq 0x2546(%rip), %rdi      # 0x514d
leaq 0x2436(%rip), %rsi      # 0x5044
movl $0x289, %edx            # imm = 0x289
leaq 0x271e(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x10(%rbp), %rax
cmpl $0x40, 0x8(%rax)
jae 0x2c2b
jmp 0x2c4a
leaq 0x24ff(%rip), %rdi      # 0x5131
leaq 0x240b(%rip), %rsi      # 0x5044
movl $0x28c, %edx            # imm = 0x28C
leaq 0x26f3(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x10(%rbp), %rdi
addq $0x18, %rdi
movq -0x10(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rax
movl %eax, %ecx
leaq -0x24(%rbp), %r8
callq 0x1460
movl %eax, -0x28(%rbp)
cmpl $0x0, -0x28(%rbp)
jne 0x3089
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
cmpl -0x24(%rbp), %eax
jbe 0x2cc9
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x2c9d
jmp 0x2cbc
leaq 0x24a9(%rip), %rdi      # 0x514d
leaq 0x2399(%rip), %rsi      # 0x5044
movl $0x298, %edx            # imm = 0x298
leaq 0x2681(%rip), %rcx      # 0x5338
callq 0x10a0
movq $0x0, -0x8(%rbp)
jmp 0x327a
movq -0x20(%rbp), %rax
movslq -0x24(%rbp), %rcx
cmpq %rcx, %rax
jbe 0x2f73
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
movslq -0x24(%rbp), %rax
subq %rax, %rdx
callq 0x2bc0
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
je 0x2f2f
movq -0x38(%rbp), %rax
cmpl $0x0, 0xb0(%rax)
jle 0x2d6a
leaq 0x4427(%rip), %rax      # 0x7140
cmpl $0x0, (%rax)
je 0x2d6a
movq -0x38(%rbp), %rdi
addq $0x80, %rdi
callq 0x1070
movq -0x38(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x2d46
jmp 0x2d65
leaq 0x2400(%rip), %rdi      # 0x514d
leaq 0x22f0(%rip), %rsi      # 0x5044
movl $0x2a7, %edx            # imm = 0x2A7
leaq 0x25d8(%rip), %rcx      # 0x5338
callq 0x10a0
jmp 0x2e42
movq -0x38(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x2e07
movq -0x38(%rbp), %rax
cmpl $0x0, 0xc(%rax)
jne 0x2e07
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
cmpq -0x38(%rbp), %rax
jne 0x2d97
jmp 0x2db6
leaq 0x25de(%rip), %rdi      # 0x537c
leaq 0x229f(%rip), %rsi      # 0x5044
movl $0x2b2, %edx            # imm = 0x2B2
leaq 0x2587(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x38(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x38(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x2ddd
jmp 0x2dfc
leaq 0x2369(%rip), %rdi      # 0x514d
leaq 0x2259(%rip), %rsi      # 0x5044
movl $0x2b6, %edx            # imm = 0x2B6
leaq 0x2541(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x38(%rbp), %rdi
callq 0x1030
jmp 0x2e40
movq -0x38(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x2e1f
jmp 0x2e3e
leaq 0x2327(%rip), %rdi      # 0x514d
leaq 0x2217(%rip), %rsi      # 0x5044
movl $0x2bf, %edx            # imm = 0x2BF
leaq 0x24ff(%rip), %rcx      # 0x5338
callq 0x10a0
jmp 0x2e40
jmp 0x2e42
movq -0x10(%rbp), %rax
cmpq 0x42c3(%rip), %rax      # 0x7110
jne 0x2f22
movq -0x10(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x2f22
movq -0x10(%rbp), %rax
cmpl $0x0, 0xc(%rax)
jne 0x2f22
movq -0x10(%rbp), %rax
cmpl $0x0, 0xb0(%rax)
jle 0x2ed2
leaq 0x42bc(%rip), %rax      # 0x7140
cmpl $0x0, (%rax)
je 0x2ed2
movq -0x10(%rbp), %rdi
addq $0x80, %rdi
callq 0x1070
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x2eb1
jmp 0x2ed0
leaq 0x2295(%rip), %rdi      # 0x514d
leaq 0x2185(%rip), %rsi      # 0x5044
movl $0x2ce, %edx            # imm = 0x2CE
leaq 0x246d(%rip), %rcx      # 0x5338
callq 0x10a0
jmp 0x2f20
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, 0x4230(%rip)      # 0x7110
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x2ef8
jmp 0x2f17
leaq 0x224e(%rip), %rdi      # 0x514d
leaq 0x213e(%rip), %rsi      # 0x5044
movl $0x2d6, %edx            # imm = 0x2D6
leaq 0x2426(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x10(%rbp), %rdi
callq 0x1030
jmp 0x2f22
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x327a
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x2f47
jmp 0x2f66
leaq 0x21ff(%rip), %rdi      # 0x514d
leaq 0x20ef(%rip), %rsi      # 0x5044
movl $0x2e3, %edx            # imm = 0x2E3
leaq 0x23d7(%rip), %rcx      # 0x5338
callq 0x10a0
movq $0x0, -0x8(%rbp)
jmp 0x327a
movq -0x20(%rbp), %rax
movslq -0x24(%rbp), %rcx
cmpq %rcx, %rax
jne 0x2f82
jmp 0x2fa1
leaq 0x21cc(%rip), %rdi      # 0x5155
leaq 0x20b4(%rip), %rsi      # 0x5044
movl $0x2ea, %edx            # imm = 0x2EA
leaq 0x239c(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x10(%rbp), %rax
cmpl $0x0, 0xc(%rax)
je 0x3045
movq -0x10(%rbp), %rax
movl $0x0, 0xc(%rax)
movq -0x10(%rbp), %rax
cmpq 0x414b(%rip), %rax      # 0x7110
jne 0x3038
movq -0x10(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x3038
movq -0x10(%rbp), %rax
cmpl $0x0, 0xc(%rax)
jne 0x3038
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, 0x4126(%rip)      # 0x7110
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x3002
jmp 0x3021
leaq 0x2144(%rip), %rdi      # 0x514d
leaq 0x2034(%rip), %rsi      # 0x5044
movl $0x2fa, %edx            # imm = 0x2FA
leaq 0x231c(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x10(%rbp), %rdi
callq 0x1030
movl $0x100100, %eax         # imm = 0x100100
movq %rax, -0x8(%rbp)
jmp 0x327a
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x327a
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x305d
jmp 0x307c
leaq 0x20e9(%rip), %rdi      # 0x514d
leaq 0x1fd9(%rip), %rsi      # 0x5044
movl $0x30e, %edx            # imm = 0x30E
leaq 0x22c1(%rip), %rcx      # 0x5338
callq 0x10a0
movq $0x0, -0x8(%rbp)
jmp 0x327a
cmpl $0x0, -0x28(%rbp)
jge 0x323b
movq -0x10(%rbp), %rax
movq (%rax), %rdi
movq -0x18(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x2bc0
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
je 0x31fa
movq -0x40(%rbp), %rax
cmpl $0x0, 0xb0(%rax)
jle 0x311b
leaq 0x4076(%rip), %rax      # 0x7140
cmpl $0x0, (%rax)
je 0x311b
movq -0x40(%rbp), %rdi
addq $0x80, %rdi
callq 0x1070
movq -0x40(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x30f7
jmp 0x3116
leaq 0x204f(%rip), %rdi      # 0x514d
leaq 0x1f3f(%rip), %rsi      # 0x5044
movl $0x320, %edx            # imm = 0x320
leaq 0x2227(%rip), %rcx      # 0x5338
callq 0x10a0
jmp 0x31ed
movq -0x40(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x31b2
movq -0x40(%rbp), %rax
cmpl $0x0, 0xc(%rax)
jne 0x31b2
movq -0x10(%rbp), %rax
movq (%rax), %rax
cmpq -0x40(%rbp), %rax
jne 0x3143
jmp 0x3162
leaq 0x224a(%rip), %rdi      # 0x5394
leaq 0x1ef3(%rip), %rsi      # 0x5044
movl $0x329, %edx            # imm = 0x329
leaq 0x21db(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x40(%rbp), %rax
movq (%rax), %rcx
movq -0x10(%rbp), %rax
movq %rcx, (%rax)
movq -0x40(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x3188
jmp 0x31a7
leaq 0x1fbe(%rip), %rdi      # 0x514d
leaq 0x1eae(%rip), %rsi      # 0x5044
movl $0x32c, %edx            # imm = 0x32C
leaq 0x2196(%rip), %rcx      # 0x5338
callq 0x10a0
movq -0x40(%rbp), %rdi
callq 0x1030
jmp 0x31eb
movq -0x40(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x31ca
jmp 0x31e9
leaq 0x1f7c(%rip), %rdi      # 0x514d
leaq 0x1e6c(%rip), %rsi      # 0x5044
movl $0x334, %edx            # imm = 0x334
leaq 0x2154(%rip), %rcx      # 0x5338
callq 0x10a0
jmp 0x31eb
jmp 0x31ed
movq -0x10(%rbp), %rax
movq %rax, -0x8(%rbp)
jmp 0x327a
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x3212
jmp 0x3231
leaq 0x1f34(%rip), %rdi      # 0x514d
leaq 0x1e24(%rip), %rsi      # 0x5044
movl $0x33d, %edx            # imm = 0x33D
leaq 0x210c(%rip), %rcx      # 0x5338
callq 0x10a0
movq $0x0, -0x8(%rbp)
jmp 0x327a
movq -0x10(%rbp), %rdi
addq $0x58, %rdi
callq 0x1110
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
jne 0x3253
jmp 0x3272
leaq 0x1ef3(%rip), %rdi      # 0x514d
leaq 0x1de3(%rip), %rsi      # 0x5044
movl $0x345, %edx            # imm = 0x345
leaq 0x20cb(%rip), %rcx      # 0x5338
callq 0x10a0
movq $0x0, -0x8(%rbp)
movq -0x8(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)