// File: /workspace/github_c_makefile_star2_O2/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
testq %rcx, %rcx
je 0x218e
movq %r9, %r14
movq %r8, %r12
movq %rcx, %r13
movl %edx, %ebx
movq %rsi, %rbp
movq %rdi, %r15
leaq 0x58(%rcx), %rdi
movq %rdi, (%rsp)
callq 0x11d0
testl %eax, %eax
jne 0x21ad
movl 0x8(%r13), %esi
cmpl $0x40, %esi
jae 0x21cc
testl %esi, %esi
je 0x21eb
movq %rbp, %rcx
testq %rbp, %rbp
je 0x220a
leaq 0x18(%r13), %rdi
leaq 0xc(%rsp), %r8
movq %r15, %rdx
callq 0x13dd
testl %eax, %eax
je 0x1d0f
movl %eax, 0x20(%rsp)
movq %r14, 0x30(%rsp)
movq %r12, 0x28(%rsp)
movl %ebx, 0x8(%rsp)
movq %r15, 0x10(%rsp)
leaq 0x1(%r15), %r12
movq %r13, 0x18(%rsp)
addq $0x19, %r13
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
xorl %r15d, %r15d
leaq 0x1(%r15), %rbx
movslq 0xc(%rsp), %rax
cmpq %rax, %rbx
jge 0x1dd8
leaq (%r15,%r13), %rdi
movq 0x18(%rsp), %rax
movl 0x8(%rax), %esi
addl %r14d, %esi
leaq (%r12,%r15), %rdx
leal (%r14,%rbp), %ecx
leaq 0x24(%rsp), %r8
callq 0x13dd
cmpl $0x0, 0x24(%rsp)
jle 0x216f
testl %eax, %eax
je 0x1e45
decq %r14
movq %rbx, %r15
jmp 0x1cc1
movslq 0xc(%rsp), %rax
cmpl %eax, 0x8(%r13)
jbe 0x1ed9
cmpq %rax, %rbp
jne 0x2302
testq %r12, %r12
je 0x1d37
cmpq %r13, 0x10(%r12)
jne 0x239d
movq %r15, %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 0x2321
testq %r12, %r12
sete %al
movl 0xc(%rsp), %ecx
subl %ecx, 0x8(%r13)
movq %r13, 0x10(%r15)
testq %r14, %r14
sete %cl
orb %al, %cl
je 0x2340
leaq 0x10(%r12), %rax
testq %r14, %r14
leaq 0x5386(%rip), %rcx      # 0x7110
cmovneq %r14, %rcx
testq %r12, %r12
cmovneq %rax, %rcx
movq %r15, (%rcx)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x235f
movq (%rsp), %rdi
callq 0x1110
testl %eax, %eax
je 0x2008
leaq 0x234d(%rip), %rdi      # 0x410d
leaq 0x223d(%rip), %rsi      # 0x4004
leaq 0x2416(%rip), %rcx      # 0x41e4
movl $0x1a1, %edx            # imm = 0x1A1
callq 0x10b0
cmpl $0x0, 0x20(%rsp)
js 0x1f34
movq 0x10(%rsp), %rdi
movq %rbp, %rsi
movl 0x8(%rsp), %edx
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
movq (%rsp), %r14
movq 0x18(%rsp), %rbp
jne 0x22a5
movq %rbp, (%r15)
cmpq %rbp, 0x52f2(%rip)      # 0x7110
movq 0x28(%rsp), %rax
je 0x1fde
testq %rax, %rax
je 0x1fe8
cmpq %rbp, 0x10(%rax)
jne 0x1fe8
addq $0x10, %rax
jmp 0x1fe5
movq %r15, %rsi
notq %rsi
addq %rbp, %rsi
movq 0x10(%rsp), %rax
leaq (%r15,%rax), %rdi
incq %rdi
xorl %edx, %edx
callq 0x12dc
movq %rax, %r14
leaq 0x58(%rax), %r12
movq %r12, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x2229
incq %r15
movq 0x18(%rsp), %rbx
movl %r15d, 0x8(%rbx)
movq %rbx, 0x10(%r14)
movq 0x28(%rsp), %rdx
testq %rdx, %rdx
sete %al
movq 0x30(%rsp), %rsi
testq %rsi, %rsi
sete %cl
orb %al, %cl
movq (%rsp), %rdi
je 0x2248
cmpq %rbx, 0x525f(%rip)      # 0x7110
je 0x1f92
testq %rdx, %rdx
je 0x200d
cmpq %rbx, 0x10(%rdx)
jne 0x237e
addq $0x10, %rdx
movq %r14, %rax
movq %rdx, %rsi
jmp 0x201f
subq %rax, %rbp
jbe 0x1f9b
movq 0x10(%r13), %rcx
movq %r15, %rdi
movq %rbp, %rsi
movl %ebx, %edx
testq %rcx, %rcx
je 0x20cf
movq %r13, %r8
xorl %r9d, %r9d
callq 0x1c21
movl %eax, %ebx
movq (%rsp), %rdi
callq 0x1110
testl %eax, %eax
je 0x205f
leaq 0x21f1(%rip), %rdi      # 0x410d
leaq 0x20e1(%rip), %rsi      # 0x4004
leaq 0x22ba(%rip), %rcx      # 0x41e4
movl $0x1bf, %edx            # imm = 0x1BF
callq 0x10b0
movq 0x18(%rsp), %r12
movq (%r12), %rcx
testq %rcx, %rcx
movq (%rsp), %r14
movl 0x8(%rsp), %edx
movq 0x10(%rsp), %rdi
movq %rbp, %rsi
je 0x2070
xorl %r8d, %r8d
movq %r12, %r9
callq 0x1c21
movl %eax, %ebx
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x205f
leaq 0x2193(%rip), %rdi      # 0x410d
leaq 0x2083(%rip), %rsi      # 0x4004
leaq 0x225c(%rip), %rcx      # 0x41e4
movl $0x23a, %edx            # imm = 0x23A
callq 0x10b0
leaq 0x5177(%rip), %rsi      # 0x7110
jmp 0x2016
jne 0x23bc
cmpl $0x0, 0xc(%r13)
je 0x212f
movq (%rsp), %rdi
callq 0x1110
xorl %ebx, %ebx
testl %eax, %eax
je 0x205f
leaq 0x2147(%rip), %rdi      # 0x410d
leaq 0x2037(%rip), %rsi      # 0x4004
leaq 0x2210(%rip), %rcx      # 0x41e4
movl $0x1d5, %edx            # imm = 0x1D5
callq 0x10b0
leaq 0x512b(%rip), %rax      # 0x7110
movq %r15, (%rax)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x22c4
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
jne 0x22e3
pushq $0x1
popq %rbx
jmp 0x205f
testq %rsi, %rsi
je 0x2163
movq (%rbx), %rax
movq %rax, (%r14)
movq %rbx, %rax
andq $0x0, (%rax)
movq %r14, (%rsi)
callq 0x1110
testl %eax, %eax
jne 0x2267
movq 0x10(%rsp), %rdi
movq %r15, %rsi
movl 0x8(%rsp), %edx
movq %rbx, %rcx
movq %r14, %r8
xorl %r9d, %r9d
callq 0x1c21
movl %eax, %ebx
movq %r12, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2286
movl %ebx, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x23db
movq %r15, (%r12)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x23fa
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x2008
leaq 0x2056(%rip), %rdi      # 0x410d
leaq 0x1f46(%rip), %rsi      # 0x4004
leaq 0x211f(%rip), %rcx      # 0x41e4
movl $0x230, %edx            # imm = 0x230
callq 0x10b0
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x2419
movq %r15, 0x10(%r13)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2438
movq (%rsp), %rdi
callq 0x1110
testl %eax, %eax
je 0x2008
leaq 0x1ff6(%rip), %rdi      # 0x410d
leaq 0x1ee6(%rip), %rsi      # 0x4004
leaq 0x20bf(%rip), %rcx      # 0x41e4
movl $0x1b5, %edx            # imm = 0x1B5
callq 0x10b0
movl %ebx, 0xc(%r13)
movq (%rsp), %rdi
callq 0x1110
testl %eax, %eax
je 0x2008
leaq 0x1fc2(%rip), %rdi      # 0x410d
leaq 0x1eb2(%rip), %rsi      # 0x4004
leaq 0x208b(%rip), %rcx      # 0x41e4
movl $0x1cd, %edx            # imm = 0x1CD
callq 0x10b0
leaq 0x4fa6(%rip), %rsi      # 0x7110
jmp 0x2023
leaq 0x2132(%rip), %rdi      # 0x42a8
leaq 0x1e87(%rip), %rsi      # 0x4004
leaq 0x2060(%rip), %rcx      # 0x41e4
movl $0x1e1, %edx            # imm = 0x1E1
callq 0x10b0
leaq 0x1f15(%rip), %rdi      # 0x40aa
leaq 0x1e68(%rip), %rsi      # 0x4004
leaq 0x2041(%rip), %rcx      # 0x41e4
movl $0x167, %edx            # imm = 0x167
callq 0x10b0
leaq 0x1f59(%rip), %rdi      # 0x410d
leaq 0x1e49(%rip), %rsi      # 0x4004
leaq 0x2022(%rip), %rcx      # 0x41e4
movl $0x16c, %edx            # imm = 0x16C
callq 0x10b0
leaq 0x1f1e(%rip), %rdi      # 0x40f1
leaq 0x1e2a(%rip), %rsi      # 0x4004
leaq 0x2003(%rip), %rcx      # 0x41e4
movl $0x172, %edx            # imm = 0x172
callq 0x10b0
leaq 0x2059(%rip), %rdi      # 0x424b
leaq 0x1e0b(%rip), %rsi      # 0x4004
leaq 0x1fe4(%rip), %rcx      # 0x41e4
movl $0x173, %edx            # imm = 0x173
callq 0x10b0
leaq 0x2040(%rip), %rdi      # 0x4251
leaq 0x1dec(%rip), %rsi      # 0x4004
leaq 0x1fc5(%rip), %rcx      # 0x41e4
movl $0x174, %edx            # imm = 0x174
callq 0x10b0
leaq 0x1edd(%rip), %rdi      # 0x410d
leaq 0x1dcd(%rip), %rsi      # 0x4004
leaq 0x1fa6(%rip), %rcx      # 0x41e4
movl $0x1ef, %edx            # imm = 0x1EF
callq 0x10b0
leaq 0x2044(%rip), %rdi      # 0x4293
leaq 0x1dae(%rip), %rsi      # 0x4004
leaq 0x1f87(%rip), %rcx      # 0x41e4
movl $0x1f6, %edx            # imm = 0x1F6
callq 0x10b0
leaq 0x1e9f(%rip), %rdi      # 0x410d
leaq 0x1d8f(%rip), %rsi      # 0x4004
leaq 0x1f68(%rip), %rcx      # 0x41e4
movl $0x211, %edx            # imm = 0x211
callq 0x10b0
leaq 0x1e80(%rip), %rdi      # 0x410d
leaq 0x1d70(%rip), %rsi      # 0x4004
leaq 0x1f49(%rip), %rcx      # 0x41e4
movl $0x218, %edx            # imm = 0x218
callq 0x10b0
leaq 0x1e61(%rip), %rdi      # 0x410d
leaq 0x1d51(%rip), %rsi      # 0x4004
leaq 0x1f2a(%rip), %rcx      # 0x41e4
movl $0x243, %edx            # imm = 0x243
callq 0x10b0
leaq 0x1e42(%rip), %rdi      # 0x410d
leaq 0x1d32(%rip), %rsi      # 0x4004
leaq 0x1f0b(%rip), %rcx      # 0x41e4
movl $0x250, %edx            # imm = 0x250
callq 0x10b0
leaq 0x1e23(%rip), %rdi      # 0x410d
leaq 0x1d13(%rip), %rsi      # 0x4004
leaq 0x1eec(%rip), %rcx      # 0x41e4
movl $0x255, %edx            # imm = 0x255
callq 0x10b0
leaq 0x1f53(%rip), %rdi      # 0x425c
leaq 0x1cf4(%rip), %rsi      # 0x4004
leaq 0x1ecd(%rip), %rcx      # 0x41e4
movl $0x181, %edx            # imm = 0x181
callq 0x10b0
leaq 0x1de5(%rip), %rdi      # 0x410d
leaq 0x1cd5(%rip), %rsi      # 0x4004
leaq 0x1eae(%rip), %rcx      # 0x41e4
movl $0x187, %edx            # imm = 0x187
callq 0x10b0
leaq 0x1f4c(%rip), %rdi      # 0x4293
leaq 0x1cb6(%rip), %rsi      # 0x4004
leaq 0x1e8f(%rip), %rcx      # 0x41e4
movl $0x18d, %edx            # imm = 0x18D
callq 0x10b0
leaq 0x1da7(%rip), %rdi      # 0x410d
leaq 0x1c97(%rip), %rsi      # 0x4004
leaq 0x1e70(%rip), %rcx      # 0x41e4
movl $0x19d, %edx            # imm = 0x19D
callq 0x10b0
leaq 0x1ef5(%rip), %rdi      # 0x427a
leaq 0x1c78(%rip), %rsi      # 0x4004
leaq 0x1e51(%rip), %rcx      # 0x41e4
movl $0x201, %edx            # imm = 0x201
callq 0x10b0
leaq 0x1ec9(%rip), %rdi      # 0x426d
leaq 0x1c59(%rip), %rsi      # 0x4004
leaq 0x1e32(%rip), %rcx      # 0x41e4
movl $0x182, %edx            # imm = 0x182
callq 0x10b0
leaq 0x1d52(%rip), %rdi      # 0x4115
leaq 0x1c3a(%rip), %rsi      # 0x4004
leaq 0x1e13(%rip), %rcx      # 0x41e4
movl $0x1c6, %edx            # imm = 0x1C6
callq 0x10b0
leaq 0x1d2b(%rip), %rdi      # 0x410d
leaq 0x1c1b(%rip), %rsi      # 0x4004
leaq 0x1df4(%rip), %rcx      # 0x41e4
movl $0x225, %edx            # imm = 0x225
callq 0x10b0
leaq 0x1d0c(%rip), %rdi      # 0x410d
leaq 0x1bfc(%rip), %rsi      # 0x4004
leaq 0x1dd5(%rip), %rcx      # 0x41e4
movl $0x22b, %edx            # imm = 0x22B
callq 0x10b0
leaq 0x1ced(%rip), %rdi      # 0x410d
leaq 0x1bdd(%rip), %rsi      # 0x4004
leaq 0x1db6(%rip), %rcx      # 0x41e4
movl $0x1ad, %edx            # imm = 0x1AD
callq 0x10b0
leaq 0x1cce(%rip), %rdi      # 0x410d
leaq 0x1bbe(%rip), %rsi      # 0x4004
leaq 0x1d97(%rip), %rcx      # 0x41e4
movl $0x1b2, %edx            # imm = 0x1B2
callq 0x10b0