// File: /workspace/github_c_makefile_star2_O1/stevenmherring[P]DNS/fine-trie.c
// Function: insert
int _insert (const char *string, size_t strlen, int32_t ip4_address,
    struct trie_node *node, struct trie_node *parent, struct trie_node *left)
    {
      int rc;

      // assert that this thread has a lock on both parent or left
      // whichever is not null

      // First things first, check if we are NULL
      assert (node != NULL);


      // get a lock on node
      rc = pthread_mutex_lock(&(node->lock));
      assert(rc == 0);


      int cmp, keylen;


      assert (node->strlen < 64);
      assert (node->strlen > 0);
      assert (strlen > 0);

      // Take the minimum of the two lengths
      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, we need to insert
        // "above" this node
        if (node->strlen > keylen)
        {
          struct trie_node *new_node;

          assert(keylen == strlen);
          assert((!parent) || parent->children == node);

          new_node = new_leaf (string, strlen, ip4_address);

          rc = pthread_mutex_lock(&(new_node->lock));
          assert(rc == 0);


          node->strlen -= keylen;
          new_node->children = node;

          assert ((!parent) || (!left));

          // should already have a lock on the parent or left node
          if (parent)
          {
            parent->children = new_node;
          }
          else if (left) {
            left->next = new_node;
          }
          else if ((!parent) || (!left)) {
            root = new_node;

          }

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


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


          return 1;
        }
        else if (strlen > keylen)
        {
          if (node->children == NULL)
          {
            struct trie_node *new_node = new_leaf (string, strlen - keylen, ip4_address);

            rc = pthread_mutex_lock(&(new_node->lock));
            assert(rc == 0);

            node->children = new_node;

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

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

            return 1;
          }
          else
          {
            // Recur on children list, store "parent" (loosely defined)
            int rv = _insert(string, strlen - keylen, ip4_address, node->children, node, NULL);

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

            return rv;
          }
        }
        else
        {
          assert (strlen == keylen);
          if (node->ip4_address == 0)
          {
            node->ip4_address = ip4_address;

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

            return 1;
          }
          else
          {
            // unlock node
            rc = pthread_mutex_unlock(&(node->lock));
            assert(rc == 0);

            return 0;
          }
        }
      } else
      {
        /* Is there any common substring? */
        int i, cmp2, keylen2, overlap = 0;
        for (i = 1; i < keylen; i++) {
          cmp2 = compare_keys (&node->key[i], node->strlen - i,
            &string[i], strlen - i, &keylen2);
            assert (keylen2 > 0);
            if (cmp2 == 0)
            {
              overlap = 1;
              break;
            }
          }

          if (overlap) {
            // Insert a common parent, recur
            struct trie_node *new_node = new_leaf (&string[i], strlen - i, 0);

            // lock new node
            rc = pthread_mutex_lock(&(new_node->lock));
            assert(rc == 0);


            int diff = node->strlen - i;
            assert ((node->strlen - diff) > 0);
            node->strlen -= diff;
            new_node->children = node;
            assert ((!parent) || (!left));

            // TODO get root lock
            if (node == root)
            {
              new_node->next = node->next;
              node->next = NULL;
              root = new_node;
            }
            else if (parent)
            {
              assert(parent->children == node);
              new_node->next = NULL;
              parent->children = new_node;
            }
            else if (left)
            {
              new_node->next = node->next;
              node->next = NULL;
              left->next = new_node;
            }
            else if ((!parent) && (!left)) {
              // TODO get root lock
              root = new_node;
            }

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



            int rv = _insert(string, i, ip4_address, node, new_node, NULL);

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


            return rv;

          }
          else if (cmp < 0)
          {
            if (node->next == NULL) {
              // Insert here
              struct trie_node *new_node = new_leaf (string, strlen, ip4_address);

              rc = pthread_mutex_lock(&(new_node->lock));
              assert(rc == 0);


              node->next = new_node;

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


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

              return 1;
            }
            else
            {
              // No, recur right (the node's key is "greater" than  the search key)
              // by convention node should be locked and node->next will be locked inside the method
              int rv = _insert(string, strlen, ip4_address, node->next, NULL, node);
              rc = pthread_mutex_unlock(&(node->lock));
              assert(rc == 0);
              return rv;
            }
          }
          else
          {
            // Insert here
            struct trie_node *new_node = new_leaf (string, strlen, ip4_address);
            rc = pthread_mutex_lock(&(new_node->lock));
            assert(rc == 0);
            new_node->next = node;
            // TODO get root lock
            if (node == root)
            {
              root = new_node;
            }
            else if (parent && parent->children == node)
            {
              parent->children = new_node;
            }

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

          }

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

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %r9, 0x30(%rsp)
movq %rdi, 0x8(%rsp)
testq %rcx, %rcx
je 0x222d
movq %r8, %r15
movq %rcx, %r14
movl %edx, %ebx
movq %rsi, %rbp
leaq 0x58(%rcx), %r12
movq %r12, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x224c
movl 0x8(%r14), %esi
cmpl $0x40, %esi
jae 0x226b
testl %esi, %esi
je 0x228a
movq %r15, 0x20(%rsp)
testq %rbp, %rbp
je 0x22a9
leaq 0x18(%r14), %r13
leaq 0x10(%rsp), %r8
movq %r13, %rdi
movq 0x8(%rsp), %rdx
movl %ebp, %ecx
callq 0x13fa
testl %eax, %eax
je 0x1de8
movl %eax, 0x28(%rsp)
movl %ebx, 0x14(%rsp)
movq %r12, 0x18(%rsp)
cmpl $0x2, 0x10(%rsp)
jl 0x1d7f
movl $0x1, %ebx
leaq 0x2c(%rsp), %r12
leaq (%rbx,%r13), %rdi
movl 0x8(%r14), %esi
subl %ebx, %esi
movq 0x8(%rsp), %rax
leaq (%rax,%rbx), %r15
movl %ebp, %ecx
subl %ebx, %ecx
movq %r15, %rdx
movq %r12, %r8
callq 0x13fa
cmpl $0x0, 0x2c(%rsp)
jle 0x220e
testl %eax, %eax
je 0x1f74
incq %rbx
movslq 0x10(%rsp), %rax
cmpq %rax, %rbx
jl 0x1d3d
cmpl $0x0, 0x28(%rsp)
js 0x1f1b
movq 0x8(%rsp), %rdi
movq %rbp, %rsi
movl 0x14(%rsp), %edx
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
movq 0x18(%rsp), %r12
jne 0x22c8
movq %r14, (%r15)
cmpq %r14, 0x534f(%rip)      # 0x7110
movq 0x20(%rsp), %rax
je 0x1ffa
testq %rax, %rax
je 0x2004
cmpq %r14, 0x10(%rax)
jne 0x2004
addq $0x10, %rax
jmp 0x2001
movslq 0x10(%rsp), %rax
cmpl %eax, 0x8(%r14)
jbe 0x1ebf
cmpq %rax, %rbp
jne 0x2306
movq 0x20(%rsp), %r13
testq %r13, %r13
je 0x1e14
cmpq %r14, 0x10(%r13)
jne 0x23fe
movq 0x8(%rsp), %rdi
movq %rbp, %rsi
movl %ebx, %edx
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x2325
testq %r13, %r13
sete %al
movl 0x10(%rsp), %ecx
subl %ecx, 0x8(%r14)
movq %r14, 0x10(%r15)
movq 0x30(%rsp), %rdx
testq %rdx, %rdx
sete %cl
orb %al, %cl
je 0x2344
leaq 0x10(%r13), %rax
testq %rdx, %rdx
leaq 0x52a3(%rip), %rcx      # 0x7110
cmovneq %rdx, %rcx
testq %r13, %r13
cmovneq %rax, %rcx
movq %r15, (%rcx)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2363
movq %r12, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x214f
leaq 0x2266(%rip), %rdi      # 0x410d
leaq 0x2156(%rip), %rsi      # 0x4004
leaq 0x232f(%rip), %rcx      # 0x41e4
movl $0x1a1, %edx            # imm = 0x1A1
callq 0x10b0
subq %rax, %rbp
jbe 0x2048
movq 0x10(%r14), %rcx
testq %rcx, %rcx
je 0x2160
movq 0x8(%rsp), %rdi
movq %rbp, %rsi
movl %ebx, %edx
movq %r14, %r8
xorl %r9d, %r9d
callq 0x1c9c
movl %eax, %ebx
movq %r12, %rdi
callq 0x1110
testl %eax, %eax
je 0x214f
leaq 0x220a(%rip), %rdi      # 0x410d
leaq 0x20fa(%rip), %rsi      # 0x4004
leaq 0x22d3(%rip), %rcx      # 0x41e4
movl $0x1bf, %edx            # imm = 0x1BF
callq 0x10b0
movq (%r14), %rcx
testq %rcx, %rcx
movq 0x18(%rsp), %r12
movl 0x14(%rsp), %edx
je 0x208a
movq 0x8(%rsp), %rdi
movq %rbp, %rsi
xorl %r8d, %r8d
movq %r14, %r9
callq 0x1c9c
movl %eax, %ebx
movq %r12, %rdi
callq 0x1110
testl %eax, %eax
je 0x214f
leaq 0x21b1(%rip), %rdi      # 0x410d
leaq 0x20a1(%rip), %rsi      # 0x4004
leaq 0x227a(%rip), %rcx      # 0x41e4
movl $0x23a, %edx            # imm = 0x23A
callq 0x10b0
subq %rbx, %rbp
movq %r15, %rdi
movq %rbp, %rsi
xorl %edx, %edx
callq 0x12dc
movq %rax, %rbp
leaq 0x58(%rax), %r12
movq %r12, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x2382
movl %ebx, 0x8(%r14)
movq %r14, 0x10(%rbp)
movq 0x20(%rsp), %rdx
testq %rdx, %rdx
sete %al
movq 0x30(%rsp), %rsi
testq %rsi, %rsi
sete %cl
orb %al, %cl
movq 0x18(%rsp), %rdi
je 0x23a1
cmpq %r14, 0x5143(%rip)      # 0x7110
movl 0x14(%rsp), %r15d
je 0x20f1
testq %rdx, %rdx
je 0x20fa
cmpq %r14, 0x10(%rdx)
jne 0x247a
addq $0x10, %rdx
movq %rbp, %rax
movq %rdx, %rsi
jmp 0x210d
leaq 0x510f(%rip), %rax      # 0x7110
movq %r15, (%rax)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x22e7
movq %r12, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x214f
leaq 0x20dd(%rip), %rdi      # 0x410d
leaq 0x1fcd(%rip), %rsi      # 0x4004
leaq 0x21a6(%rip), %rcx      # 0x41e4
movl $0x255, %edx            # imm = 0x255
callq 0x10b0
jne 0x241d
cmpl $0x0, 0xc(%r14)
je 0x21ca
movq %r12, %rdi
callq 0x1110
xorl %ebx, %ebx
testl %eax, %eax
je 0x214f
leaq 0x209b(%rip), %rdi      # 0x410d
leaq 0x1f8b(%rip), %rsi      # 0x4004
leaq 0x2164(%rip), %rcx      # 0x41e4
movl $0x1d5, %edx            # imm = 0x1D5
callq 0x10b0
movq 0x8(%rsp), %rdi
movq %rbp, %rsi
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x243c
movq %r15, (%r14)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x245b
movq %r12, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x214f
leaq 0x2034(%rip), %rdi      # 0x410d
leaq 0x1f24(%rip), %rsi      # 0x4004
leaq 0x20fd(%rip), %rcx      # 0x41e4
movl $0x230, %edx            # imm = 0x230
callq 0x10b0
leaq 0x5018(%rip), %rsi      # 0x7110
jmp 0x2103
testq %rsi, %rsi
je 0x2202
movq (%r14), %rax
movq %rax, (%rbp)
movq %r14, %rax
movq $0x0, (%rax)
movq %rbp, (%rsi)
callq 0x1110
testl %eax, %eax
jne 0x23c0
movq 0x8(%rsp), %rdi
movq %rbx, %rsi
movl %r15d, %edx
movq %r14, %rcx
movq %rbp, %r8
xorl %r9d, %r9d
callq 0x1c9c
movl %eax, %ebx
movq %r12, %rdi
callq 0x1110
testl %eax, %eax
jne 0x23df
movl %ebx, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rsp), %rdi
movq %rbp, %rsi
movl %ebx, %edx
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x2499
movq %r15, 0x10(%r14)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x24b8
movq %r12, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x214f
leaq 0x1f5b(%rip), %rdi      # 0x410d
leaq 0x1e4b(%rip), %rsi      # 0x4004
leaq 0x2024(%rip), %rcx      # 0x41e4
movl $0x1b5, %edx            # imm = 0x1B5
callq 0x10b0
movl %ebx, 0xc(%r14)
movq %r12, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x214f
leaq 0x1f23(%rip), %rdi      # 0x410d
leaq 0x1e13(%rip), %rsi      # 0x4004
leaq 0x1fec(%rip), %rcx      # 0x41e4
movl $0x1cd, %edx            # imm = 0x1CD
callq 0x10b0
leaq 0x4f07(%rip), %rsi      # 0x7110
jmp 0x2114
leaq 0x2093(%rip), %rdi      # 0x42a8
leaq 0x1de8(%rip), %rsi      # 0x4004
leaq 0x1fc1(%rip), %rcx      # 0x41e4
movl $0x1e1, %edx            # imm = 0x1E1
callq 0x10b0
leaq 0x1e76(%rip), %rdi      # 0x40aa
leaq 0x1dc9(%rip), %rsi      # 0x4004
leaq 0x1fa2(%rip), %rcx      # 0x41e4
movl $0x167, %edx            # imm = 0x167
callq 0x10b0
leaq 0x1eba(%rip), %rdi      # 0x410d
leaq 0x1daa(%rip), %rsi      # 0x4004
leaq 0x1f83(%rip), %rcx      # 0x41e4
movl $0x16c, %edx            # imm = 0x16C
callq 0x10b0
leaq 0x1e7f(%rip), %rdi      # 0x40f1
leaq 0x1d8b(%rip), %rsi      # 0x4004
leaq 0x1f64(%rip), %rcx      # 0x41e4
movl $0x172, %edx            # imm = 0x172
callq 0x10b0
leaq 0x1fba(%rip), %rdi      # 0x424b
leaq 0x1d6c(%rip), %rsi      # 0x4004
leaq 0x1f45(%rip), %rcx      # 0x41e4
movl $0x173, %edx            # imm = 0x173
callq 0x10b0
leaq 0x1fa1(%rip), %rdi      # 0x4251
leaq 0x1d4d(%rip), %rsi      # 0x4004
leaq 0x1f26(%rip), %rcx      # 0x41e4
movl $0x174, %edx            # imm = 0x174
callq 0x10b0
leaq 0x1e3e(%rip), %rdi      # 0x410d
leaq 0x1d2e(%rip), %rsi      # 0x4004
leaq 0x1f07(%rip), %rcx      # 0x41e4
movl $0x243, %edx            # imm = 0x243
callq 0x10b0
leaq 0x1e1f(%rip), %rdi      # 0x410d
leaq 0x1d0f(%rip), %rsi      # 0x4004
leaq 0x1ee8(%rip), %rcx      # 0x41e4
movl $0x250, %edx            # imm = 0x250
callq 0x10b0
leaq 0x1f4f(%rip), %rdi      # 0x425c
leaq 0x1cf0(%rip), %rsi      # 0x4004
leaq 0x1ec9(%rip), %rcx      # 0x41e4
movl $0x181, %edx            # imm = 0x181
callq 0x10b0
leaq 0x1de1(%rip), %rdi      # 0x410d
leaq 0x1cd1(%rip), %rsi      # 0x4004
leaq 0x1eaa(%rip), %rcx      # 0x41e4
movl $0x187, %edx            # imm = 0x187
callq 0x10b0
leaq 0x1f48(%rip), %rdi      # 0x4293
leaq 0x1cb2(%rip), %rsi      # 0x4004
leaq 0x1e8b(%rip), %rcx      # 0x41e4
movl $0x18d, %edx            # imm = 0x18D
callq 0x10b0
leaq 0x1da3(%rip), %rdi      # 0x410d
leaq 0x1c93(%rip), %rsi      # 0x4004
leaq 0x1e6c(%rip), %rcx      # 0x41e4
movl $0x19d, %edx            # imm = 0x19D
callq 0x10b0
leaq 0x1d84(%rip), %rdi      # 0x410d
leaq 0x1c74(%rip), %rsi      # 0x4004
leaq 0x1e4d(%rip), %rcx      # 0x41e4
movl $0x1ef, %edx            # imm = 0x1EF
callq 0x10b0
leaq 0x1eeb(%rip), %rdi      # 0x4293
leaq 0x1c55(%rip), %rsi      # 0x4004
leaq 0x1e2e(%rip), %rcx      # 0x41e4
movl $0x1f6, %edx            # imm = 0x1F6
callq 0x10b0
leaq 0x1d46(%rip), %rdi      # 0x410d
leaq 0x1c36(%rip), %rsi      # 0x4004
leaq 0x1e0f(%rip), %rcx      # 0x41e4
movl $0x211, %edx            # imm = 0x211
callq 0x10b0
leaq 0x1d27(%rip), %rdi      # 0x410d
leaq 0x1c17(%rip), %rsi      # 0x4004
leaq 0x1df0(%rip), %rcx      # 0x41e4
movl $0x218, %edx            # imm = 0x218
callq 0x10b0
leaq 0x1e68(%rip), %rdi      # 0x426d
leaq 0x1bf8(%rip), %rsi      # 0x4004
leaq 0x1dd1(%rip), %rcx      # 0x41e4
movl $0x182, %edx            # imm = 0x182
callq 0x10b0
leaq 0x1cf1(%rip), %rdi      # 0x4115
leaq 0x1bd9(%rip), %rsi      # 0x4004
leaq 0x1db2(%rip), %rcx      # 0x41e4
movl $0x1c6, %edx            # imm = 0x1C6
callq 0x10b0
leaq 0x1cca(%rip), %rdi      # 0x410d
leaq 0x1bba(%rip), %rsi      # 0x4004
leaq 0x1d93(%rip), %rcx      # 0x41e4
movl $0x225, %edx            # imm = 0x225
callq 0x10b0
leaq 0x1cab(%rip), %rdi      # 0x410d
leaq 0x1b9b(%rip), %rsi      # 0x4004
leaq 0x1d74(%rip), %rcx      # 0x41e4
movl $0x22b, %edx            # imm = 0x22B
callq 0x10b0
leaq 0x1df9(%rip), %rdi      # 0x427a
leaq 0x1b7c(%rip), %rsi      # 0x4004
leaq 0x1d55(%rip), %rcx      # 0x41e4
movl $0x201, %edx            # imm = 0x201
callq 0x10b0
leaq 0x1c6d(%rip), %rdi      # 0x410d
leaq 0x1b5d(%rip), %rsi      # 0x4004
leaq 0x1d36(%rip), %rcx      # 0x41e4
movl $0x1ad, %edx            # imm = 0x1AD
callq 0x10b0
leaq 0x1c4e(%rip), %rdi      # 0x410d
leaq 0x1b3e(%rip), %rsi      # 0x4004
leaq 0x1d17(%rip), %rcx      # 0x41e4
movl $0x1b2, %edx            # imm = 0x1B2
callq 0x10b0