// File: /workspace/github_c_makefile_star2_O3/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)
testq %rcx, %rcx
je 0x2257
movq %r8, %r15
movq %rcx, %r12
movl %edx, %ebx
movq %rsi, %rbp
movq %rdi, %r13
leaq 0x58(%rcx), %r14
movq %r14, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x2276
movl 0x8(%r12), %esi
cmpl $0x40, %esi
jae 0x2295
testl %esi, %esi
je 0x22b4
movq %r15, 0x20(%rsp)
testq %rbp, %rbp
je 0x22d3
leaq 0x18(%r12), %rdi
leaq 0xc(%rsp), %r8
movq %r13, %rdx
movl %ebp, %ecx
callq 0x13f8
testl %eax, %eax
je 0x1e0a
movl %eax, 0x28(%rsp)
movq %r13, 0x10(%rsp)
movl %ebx, 0x8(%rsp)
movq %r12, %r15
movq %r14, 0x18(%rsp)
cmpl $0x2, 0xc(%rsp)
jl 0x1da0
movq 0x10(%rsp), %rax
leaq 0x1(%rax), %r12
leaq 0x19(%r15), %r13
movl $0xffffffff, %r14d      # imm = 0xFFFFFFFF
xorl %ebx, %ebx
leaq (%rbx,%r13), %rdi
leal (%r14,%rbp), %ecx
movl 0x8(%r15), %esi
addl %r14d, %esi
leaq (%r12,%rbx), %rdx
leaq 0x2c(%rsp), %r8
callq 0x13f8
cmpl $0x0, 0x2c(%rsp)
jle 0x2238
testl %eax, %eax
je 0x1f98
movslq 0xc(%rsp), %rax
leaq 0x1(%rbx), %rcx
addq $0x2, %rbx
decq %r14
cmpq %rax, %rbx
movq %rcx, %rbx
jl 0x1d58
cmpl $0x0, 0x28(%rsp)
js 0x1f3c
movq 0x10(%rsp), %rdi
movq %rbp, %rsi
movl 0x8(%rsp), %edx
callq 0x12dc
movq %rax, %r12
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
movq 0x18(%rsp), %r14
jne 0x22f2
movq %r15, (%r12)
cmpq %r15, 0x532d(%rip)      # 0x7110
movq 0x20(%rsp), %rax
je 0x2030
testq %rax, %rax
je 0x203a
cmpq %r15, 0x10(%rax)
jne 0x203a
addq $0x10, %rax
jmp 0x2037
movslq 0xc(%rsp), %rax
cmpl %eax, 0x8(%r12)
jbe 0x1ee1
cmpq %rax, %rbp
jne 0x2330
movq %r13, %rdi
movq 0x20(%rsp), %r13
testq %r13, %r13
je 0x1e3a
cmpq %r12, 0x10(%r13)
jne 0x2428
movq %rbp, %rsi
movl %ebx, %edx
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x234f
testq %r13, %r13
sete %al
movl 0xc(%rsp), %ecx
subl %ecx, 0x8(%r12)
movq %r12, 0x10(%r15)
movq 0x30(%rsp), %rdx
testq %rdx, %rdx
sete %cl
orb %al, %cl
je 0x236e
leaq 0x10(%r13), %rax
testq %rdx, %rdx
leaq 0x5281(%rip), %rcx      # 0x7110
cmovneq %rdx, %rcx
testq %r13, %r13
cmovneq %rax, %rcx
movq %r15, (%rcx)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x238d
movq %r14, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x2181
leaq 0x2244(%rip), %rdi      # 0x410d
leaq 0x2134(%rip), %rsi      # 0x4004
leaq 0x230d(%rip), %rcx      # 0x41e4
movl $0x1a1, %edx            # imm = 0x1A1
callq 0x10b0
subq %rax, %rbp
jbe 0x207e
movq 0x10(%r12), %rcx
movq %r13, %rdi
movq %rbp, %rsi
movl %ebx, %edx
testq %rcx, %rcx
je 0x2192
movq %r12, %r8
xorl %r9d, %r9d
callq 0x1ca9
movl %eax, %ebx
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x2181
leaq 0x21e9(%rip), %rdi      # 0x410d
leaq 0x20d9(%rip), %rsi      # 0x4004
leaq 0x22b2(%rip), %rcx      # 0x41e4
movl $0x1bf, %edx            # imm = 0x1BF
callq 0x10b0
movq %r15, %r12
movq (%r15), %rcx
testq %rcx, %rcx
movq 0x18(%rsp), %r14
movq 0x10(%rsp), %rdi
movq %rbp, %rsi
je 0x20c1
movl 0x8(%rsp), %edx
xorl %r8d, %r8d
movq %r12, %r9
callq 0x1ca9
movl %eax, %ebx
movq %r14, %rdi
callq 0x1110
testl %eax, %eax
je 0x2181
leaq 0x218d(%rip), %rdi      # 0x410d
leaq 0x207d(%rip), %rsi      # 0x4004
leaq 0x2256(%rip), %rcx      # 0x41e4
movl $0x23a, %edx            # imm = 0x23A
callq 0x10b0
movq %rbx, %rsi
notq %rsi
addq %rbp, %rsi
movq 0x10(%rsp), %r12
leaq (%rbx,%r12), %rdi
incq %rdi
xorl %edx, %edx
callq 0x12dc
movq %rax, %rbp
leaq 0x58(%rax), %r13
movq %r13, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x23ac
incq %rbx
movl %ebx, 0x8(%r15)
movq %r15, 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 0x23cb
movq %r15, %r14
cmpq %r15, 0x510d(%rip)      # 0x7110
movl 0x8(%rsp), %r15d
je 0x2125
testq %rdx, %rdx
je 0x212e
cmpq %r14, 0x10(%rdx)
jne 0x24a4
addq $0x10, %rdx
movq %rbp, %rax
movq %rdx, %rsi
jmp 0x2141
leaq 0x50d9(%rip), %rax      # 0x7110
movq %r12, (%rax)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2311
movq %r14, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x2181
leaq 0x20a7(%rip), %rdi      # 0x410d
leaq 0x1f97(%rip), %rsi      # 0x4004
leaq 0x2170(%rip), %rcx      # 0x41e4
movl $0x255, %edx            # imm = 0x255
callq 0x10b0
jne 0x2447
cmpl $0x0, 0xc(%r12)
je 0x21f3
movq %r14, %rdi
callq 0x1110
xorl %ebx, %ebx
testl %eax, %eax
je 0x2181
leaq 0x2064(%rip), %rdi      # 0x410d
leaq 0x1f54(%rip), %rsi      # 0x4004
leaq 0x212d(%rip), %rcx      # 0x41e4
movl $0x1d5, %edx            # imm = 0x1D5
callq 0x10b0
movl 0x8(%rsp), %edx
callq 0x12dc
movq %rax, %r15
leaq 0x58(%rax), %rbx
movq %rbx, %rdi
callq 0x11d0
testl %eax, %eax
jne 0x2466
movq %r15, (%r12)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2485
movq %r14, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x2181
leaq 0x2000(%rip), %rdi      # 0x410d
leaq 0x1ef0(%rip), %rsi      # 0x4004
leaq 0x20c9(%rip), %rcx      # 0x41e4
movl $0x230, %edx            # imm = 0x230
callq 0x10b0
leaq 0x4fe4(%rip), %rsi      # 0x7110
jmp 0x2137
testq %rsi, %rsi
je 0x222c
movq (%r14), %rax
movq %rax, (%rbp)
movq %r14, %rax
movq $0x0, (%rax)
movq %rbp, (%rsi)
callq 0x1110
testl %eax, %eax
jne 0x23ea
movq %r12, %rdi
movq %rbx, %rsi
movl %r15d, %edx
movq %r14, %rcx
movq %rbp, %r8
xorl %r9d, %r9d
callq 0x1ca9
movl %eax, %ebx
movq %r13, %rdi
callq 0x1110
testl %eax, %eax
jne 0x2409
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 0x24c3
movq %r15, 0x10(%r12)
movq %rbx, %rdi
callq 0x1110
testl %eax, %eax
jne 0x24e2
movq %r14, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x2181
leaq 0x1f32(%rip), %rdi      # 0x410d
leaq 0x1e22(%rip), %rsi      # 0x4004
leaq 0x1ffb(%rip), %rcx      # 0x41e4
movl $0x1b5, %edx            # imm = 0x1B5
callq 0x10b0
movl %ebx, 0xc(%r12)
movq %r14, %rdi
callq 0x1110
movl $0x1, %ebx
testl %eax, %eax
je 0x2181
leaq 0x1ef9(%rip), %rdi      # 0x410d
leaq 0x1de9(%rip), %rsi      # 0x4004
leaq 0x1fc2(%rip), %rcx      # 0x41e4
movl $0x1cd, %edx            # imm = 0x1CD
callq 0x10b0
leaq 0x4edd(%rip), %rsi      # 0x7110
jmp 0x2148
leaq 0x2069(%rip), %rdi      # 0x42a8
leaq 0x1dbe(%rip), %rsi      # 0x4004
leaq 0x1f97(%rip), %rcx      # 0x41e4
movl $0x1e1, %edx            # imm = 0x1E1
callq 0x10b0
leaq 0x1e4c(%rip), %rdi      # 0x40aa
leaq 0x1d9f(%rip), %rsi      # 0x4004
leaq 0x1f78(%rip), %rcx      # 0x41e4
movl $0x167, %edx            # imm = 0x167
callq 0x10b0
leaq 0x1e90(%rip), %rdi      # 0x410d
leaq 0x1d80(%rip), %rsi      # 0x4004
leaq 0x1f59(%rip), %rcx      # 0x41e4
movl $0x16c, %edx            # imm = 0x16C
callq 0x10b0
leaq 0x1e55(%rip), %rdi      # 0x40f1
leaq 0x1d61(%rip), %rsi      # 0x4004
leaq 0x1f3a(%rip), %rcx      # 0x41e4
movl $0x172, %edx            # imm = 0x172
callq 0x10b0
leaq 0x1f90(%rip), %rdi      # 0x424b
leaq 0x1d42(%rip), %rsi      # 0x4004
leaq 0x1f1b(%rip), %rcx      # 0x41e4
movl $0x173, %edx            # imm = 0x173
callq 0x10b0
leaq 0x1f77(%rip), %rdi      # 0x4251
leaq 0x1d23(%rip), %rsi      # 0x4004
leaq 0x1efc(%rip), %rcx      # 0x41e4
movl $0x174, %edx            # imm = 0x174
callq 0x10b0
leaq 0x1e14(%rip), %rdi      # 0x410d
leaq 0x1d04(%rip), %rsi      # 0x4004
leaq 0x1edd(%rip), %rcx      # 0x41e4
movl $0x243, %edx            # imm = 0x243
callq 0x10b0
leaq 0x1df5(%rip), %rdi      # 0x410d
leaq 0x1ce5(%rip), %rsi      # 0x4004
leaq 0x1ebe(%rip), %rcx      # 0x41e4
movl $0x250, %edx            # imm = 0x250
callq 0x10b0
leaq 0x1f25(%rip), %rdi      # 0x425c
leaq 0x1cc6(%rip), %rsi      # 0x4004
leaq 0x1e9f(%rip), %rcx      # 0x41e4
movl $0x181, %edx            # imm = 0x181
callq 0x10b0
leaq 0x1db7(%rip), %rdi      # 0x410d
leaq 0x1ca7(%rip), %rsi      # 0x4004
leaq 0x1e80(%rip), %rcx      # 0x41e4
movl $0x187, %edx            # imm = 0x187
callq 0x10b0
leaq 0x1f1e(%rip), %rdi      # 0x4293
leaq 0x1c88(%rip), %rsi      # 0x4004
leaq 0x1e61(%rip), %rcx      # 0x41e4
movl $0x18d, %edx            # imm = 0x18D
callq 0x10b0
leaq 0x1d79(%rip), %rdi      # 0x410d
leaq 0x1c69(%rip), %rsi      # 0x4004
leaq 0x1e42(%rip), %rcx      # 0x41e4
movl $0x19d, %edx            # imm = 0x19D
callq 0x10b0
leaq 0x1d5a(%rip), %rdi      # 0x410d
leaq 0x1c4a(%rip), %rsi      # 0x4004
leaq 0x1e23(%rip), %rcx      # 0x41e4
movl $0x1ef, %edx            # imm = 0x1EF
callq 0x10b0
leaq 0x1ec1(%rip), %rdi      # 0x4293
leaq 0x1c2b(%rip), %rsi      # 0x4004
leaq 0x1e04(%rip), %rcx      # 0x41e4
movl $0x1f6, %edx            # imm = 0x1F6
callq 0x10b0
leaq 0x1d1c(%rip), %rdi      # 0x410d
leaq 0x1c0c(%rip), %rsi      # 0x4004
leaq 0x1de5(%rip), %rcx      # 0x41e4
movl $0x211, %edx            # imm = 0x211
callq 0x10b0
leaq 0x1cfd(%rip), %rdi      # 0x410d
leaq 0x1bed(%rip), %rsi      # 0x4004
leaq 0x1dc6(%rip), %rcx      # 0x41e4
movl $0x218, %edx            # imm = 0x218
callq 0x10b0
leaq 0x1e3e(%rip), %rdi      # 0x426d
leaq 0x1bce(%rip), %rsi      # 0x4004
leaq 0x1da7(%rip), %rcx      # 0x41e4
movl $0x182, %edx            # imm = 0x182
callq 0x10b0
leaq 0x1cc7(%rip), %rdi      # 0x4115
leaq 0x1baf(%rip), %rsi      # 0x4004
leaq 0x1d88(%rip), %rcx      # 0x41e4
movl $0x1c6, %edx            # imm = 0x1C6
callq 0x10b0
leaq 0x1ca0(%rip), %rdi      # 0x410d
leaq 0x1b90(%rip), %rsi      # 0x4004
leaq 0x1d69(%rip), %rcx      # 0x41e4
movl $0x225, %edx            # imm = 0x225
callq 0x10b0
leaq 0x1c81(%rip), %rdi      # 0x410d
leaq 0x1b71(%rip), %rsi      # 0x4004
leaq 0x1d4a(%rip), %rcx      # 0x41e4
movl $0x22b, %edx            # imm = 0x22B
callq 0x10b0
leaq 0x1dcf(%rip), %rdi      # 0x427a
leaq 0x1b52(%rip), %rsi      # 0x4004
leaq 0x1d2b(%rip), %rcx      # 0x41e4
movl $0x201, %edx            # imm = 0x201
callq 0x10b0
leaq 0x1c43(%rip), %rdi      # 0x410d
leaq 0x1b33(%rip), %rsi      # 0x4004
leaq 0x1d0c(%rip), %rcx      # 0x41e4
movl $0x1ad, %edx            # imm = 0x1AD
callq 0x10b0
leaq 0x1c24(%rip), %rdi      # 0x410d
leaq 0x1b14(%rip), %rsi      # 0x4004
leaq 0x1ced(%rip), %rcx      # 0x41e4
movl $0x1b2, %edx            # imm = 0x1B2
callq 0x10b0