Example #1
0
void destroyLinks(cfuhash_table_t * linkHash) {
    char **keys = NULL;
    size_t *key_sizes = NULL;
    size_t key_count = 0;
    int i = 0;
    keys = (char **)cfuhash_keys_data(linkHash, &key_count, &key_sizes, 0);

    for (i = 0; i < (int)key_count; i++) {
        BM_linkPair * base_LP = cfuhash_get(linkHash, keys[i]);
        if(keys[i] != 0)
        {
            free(keys[i]);
            keys[i] = 0;
        }
        BM_linkInfo* LI = base_LP->LI;
        if (LI != 0)
            while(destroyLinkInfo_andNext(&LI));
        if(base_LP !=0) {
            free(base_LP);
            base_LP = 0;
        }
    }

    if(keys != 0) {
        free(keys);
        keys = 0;
    }

    if(key_sizes != 0) {
        free(key_sizes);
        key_sizes = 0;
    }
}
Example #2
0
void sendCredentials() {

	puts("Sending Credentials\n");
	// printf("sizeof -u = %d, sizeof conor = %d\n", sizeof(cfuhash_get(arguments, "-u")));

	char response[10];	

	strcpy(username, cfuhash_get(arguments, "-u"));
	sendMessage(username, sizeof(username));
	readMessage(response, sizeof(response));
	if(strcmp(response, "INVALID") == 0) {
		perror("Server says invalid username");
	}


	strcpy(password, cfuhash_get(arguments, "-p"));
	sendMessage(password, sizeof(password));
	readMessage(response, sizeof(response));
	if(strcmp(response, "INVALID") == 0) {
		perror("Server says invalid password");
	}

}		
Example #3
0
bt_device_t *bt_get_device(bdaddr_t add) {
	bt_device_t *tmp;

	if (!bt_devices_table) {
		bt_devices_table = cfuhash_new_with_initial_size(200);
	}

	char string_add[18]; 
	memset(string_add, 0, 18);
	ba2str((const bdaddr_t *)&(add), string_add);

	tmp = (bt_device_t *)cfuhash_get(bt_devices_table, string_add);

	return tmp;
}
Example #4
0
void printLinks(cfuhash_table_t * linkHash, char ** bamNames, char ** contigNames)
{
    char **keys = NULL;
    size_t *key_sizes = NULL;
    size_t key_count = 0;
    int i = 0;
    keys = (char **)cfuhash_keys_data(linkHash, &key_count, &key_sizes, 0);

    for (i = 0; i < (int)key_count; i++) {
        PM_link_pair * LP = cfuhash_get(linkHash, keys[i]);
        free(keys[i]);
        printLinkPair(LP, bamNames, contigNames);
    }
    free(keys);
    free(key_sizes);
}
Example #5
0
int stepLinkWalker(BM_LinkWalker * walker) {
    if(getNextLinkInfo(&(walker->LI))) {
        // still on the same pair
        return 1;
    }
    else {
        // at the end of the links of this contig pair
        walker->keyCount += 1;
        if(walker->keyCount < walker->numKeys) {
            walker->pair = cfuhash_get(walker->linkHash,
                                       walker->keys[walker->keyCount]);
            if (walker->keys[walker->keyCount] != 0) {
                free(walker->keys[walker->keyCount]);
                walker->keys[walker->keyCount] = 0;
            }
            walker->LI = (walker->pair)->LI;
            return 2;
        }
    }
    return 0;
}
Example #6
0
void addLink(cfuhash_table_t * linkHash,
             BM_linkInfo * LI,
             int cid1,
             int cid2
             ) {
    BM_linkInfo** nextLink_ptr = (BM_linkInfo**) &LI->nextLink;
    // see if the key is in the hash already
    char * key = calloc(30, sizeof(char)); // allocate room for the key
    makeContigKey(key, cid1, cid2);
    BM_linkPair * base_LP = cfuhash_get(linkHash, key);
    if (base_LP != NULL) {
        // exists in the hash -> daisy chain it on
        *nextLink_ptr = base_LP->LI;
        base_LP->LI = LI;
        base_LP->numLinks++;
    }
    else {
        // we'll need to build a bit of infrastructure
        // store the contig ids once only
        BM_linkPair * LP = (BM_linkPair*) calloc(1, sizeof(BM_linkPair));
        if(cid1 < cid2) {
            LP->cid1 = cid1;
            LP->cid2 = cid2;
        }
        else {
            LP->cid1 = cid2;
            LP->cid2 = cid1;
        }
        LP->LI = LI;
        LP->numLinks = 1;
        *nextLink_ptr = LI; // point to self means end of list

        // finally, add the lot to the hash
        cfuhash_put(linkHash, key, LP);
    }
    if (key != 0) {
        free(key);
        key = 0;
    }
}
Example #7
0
int initLinkWalker(BM_LinkWalker * walker, cfuhash_table_t * linkHash) {
    // get some memory
    walker->linkHash = linkHash;
    walker->keyCount = 0;
    walker->numKeys = 0;
    size_t *key_sizes = NULL;
    // get the keys from the hash
    walker->keys = (char **)cfuhash_keys_data(linkHash,
                                              &(walker->numKeys),
                                              &key_sizes,
                                              0);
    if((walker->keys)[walker->keyCount] != 0) {
        // we don't need this
        if (key_sizes != 0) {
            free(key_sizes);
            key_sizes = 0;
        }
        // load the first linkPair
        walker->pair = cfuhash_get(linkHash, (walker->keys)[walker->keyCount]);
        if ((walker->keys)[walker->keyCount] != 0) {
            free((walker->keys)[walker->keyCount]);
            (walker->keys)[walker->keyCount] = 0;
        }
        // tee-up the first linkInfo
        walker->LI = (walker->pair)->LI;
        return 2;
    }
    else {
        // no links
        if (walker->keys != 0) {
            free(walker->keys);
            walker->keys = 0;
        }
    }
    return 0;
}
Example #8
0
BM_mappedRead * extractReads(char * bamFile,
                             char ** contigs,
                             int numContigs,
                             uint16_t * groups,
                             char * prettyName,
                             int headersOnly,
                             int minMapQual,
                             int maxMisMatches,
                             int ignoreSuppAlignments,
                             int ignoreSecondaryAlignments) {
    //-----
    // code uses the pattern outlined in samtools view (sam_view.c)
    // thanks lh3!
    //
    int i = 0;
    int result = -1;
    int hh = 0;

    int supp_check = 0x0; // include supp mappings
    if (ignoreSuppAlignments) {
        supp_check |= BAM_FSUPPLEMENTARY;
    }
    if (ignoreSecondaryAlignments) {
        supp_check |= BAM_FSECONDARY;
    }

    // we need to let the users know if their pairings
    // will be corrupted
    int p_corrupt = 0;

    // helper variables
    samFile *in = 0;
    bam_hdr_t *header = NULL;
    bam1_t *b = bam_init1();

    BM_mappedRead * root = 0;
    BM_mappedRead * prev = 0;

    // open file handlers
    if ((in = sam_open(bamFile, "r")) == 0) {
        fprintf(stderr,
                "ERROR: Failed to open \"%s\" for reading.\n",
                bamFile);
    }
    else {
        // retrieve the header
        if ((header = sam_hdr_read(in)) == 0) {
            fprintf(stderr,
                    "ERROR: Failed to read the header from \"%s\".\n",
                    bamFile);
        }
        else {
            // check the index is intact
            hts_idx_t *idx = sam_index_load(in, bamFile); // load index
            if (idx == 0) { // index is unavailable
                fprintf(stderr,
                        "ERROR: Random retrieval only works "\
                        "for indexed files.\n");
            }
            else {
                cfuhash_table_t *pair_buffer = \
                    cfuhash_new_with_initial_size(1000000);
                cfuhash_set_flag(pair_buffer, CFUHASH_FROZEN_UNTIL_GROWS);

                for (hh = 0; hh < numContigs; ++hh) {
                    // parse a region in the format like `chr2:100-200'
                    hts_itr_t *iter = sam_itr_querys(idx, header, contigs[hh]);
                    if (iter == NULL) { // reference name is not found
                        fprintf(stderr,
                                "WARNING: Could not find contig: "\
                                "[%s] in BAM: [%s].\n",
                                contigs[hh],
                                bamFile);
                    }

                    // fetch alignments
                    int line = 0;
                    while ((result = sam_itr_next(in, iter, b)) >= 0) {
                        bam1_core_t core = b->core;
                        line += 1;
                        // only high quality?, primary? mappings
                        if ( core.qual < minMapQual)
                            continue;
                        if ((core.flag & supp_check) != 0)
                            continue;
                        if(bam_aux2i(bam_aux_get(b, "NM")) > maxMisMatches) {
                            continue;
                        }

                        char * seqId = bam_get_qname(b);
                        char * seq = 0;
                        char * qual = 0;
                        int qual_len = 0;
                        int seq_len = 0;

                        // get sequence and quality
                        if(0 == headersOnly) {
                            // no point allocating unused space
                            seq = calloc(core.l_qseq+1, sizeof(char));
                            qual = calloc(core.l_qseq+1, sizeof(char));
                            uint8_t *s = bam_get_seq(b);
                            if (core.flag&BAM_FREVERSE) {
                                // reverse the read
                                int r = 0;
                                for (i = core.l_qseq-1; i >=0 ; --i) {
                                    seq[r]="=TGKCYSBAWRDMHVN"[bam_seqi(s,
                                                                       i)];
                                    ++r;
                                }
                            }
                            else {
                                for (i = 0; i < core.l_qseq; ++i) {
                                    seq[i]="=ACMGRSVTWYHKDBN"[bam_seqi(s,
                                                                       i)];
                                }
                            }
                            seq_len = core.l_qseq;

                            s = bam_get_qual(b);
                            if (s[0] != 0xff) {
                                qual_len = core.l_qseq;
                                for (i = 0; i < core.l_qseq; ++i) {
                                    qual[i] = (char)(s[i] + 33);
                                }
                            }
                            else if (qual != 0) {
                                free(qual);
                                qual = 0;
                            }
                        }

                        // work out pairing information
                        uint8_t rpi = RPI_ERROR;
                        if (core.flag&BAM_FPAIRED) {
                            if(core.flag&BAM_FMUNMAP) {
                                if (core.flag&BAM_FREAD1) {
                                    rpi = RPI_SNGL_FIR;
                                }
                                else if (core.flag&BAM_FREAD2) {
                                    rpi = RPI_SNGL_SEC;
                                }
                            }
                            else {
                                if (core.flag&BAM_FREAD1) {
                                    rpi = RPI_FIR;
                                }
                                else if (core.flag&BAM_FREAD2) {
                                    rpi = RPI_SEC;
                                }
                            }
                        }
                        else {
                            rpi = RPI_SNGL;
                        }

                        // make the funky Id
                        #define MAX_SEQ_ID_LEN 80
                        char * seq_id = calloc(MAX_SEQ_ID_LEN,
                                               sizeof(char));
                        // allocate the string to the buffer but check to
                        // ensure we're not cutting anything off
                        int id_len = snprintf(seq_id,
                                              MAX_SEQ_ID_LEN,
                                              "b_%s;c_%s;r_%s",
                                              prettyName,
                                              contigs[hh],
                                              seqId);
                        if(id_len >= MAX_SEQ_ID_LEN) {
                            seq_id = calloc(id_len+1, sizeof(char));
                            snprintf(seq_id,
                                     id_len+1, // don't forget the NULL!
                                     "b_%s;c_%s;r_%s",
                                     prettyName,
                                     contigs[hh],
                                     seqId);
                        }

                        // make the mapped read struct
                        prev = makeMappedRead(seq_id,
                                              seq,
                                              qual,
                                              id_len,
                                              seq_len,
                                              qual_len,
                                              rpi,
                                              groups[hh],
                                              prev);

                        if (0 == root) { root = prev; }

                        if(rpi == RPI_SNGL || \
                           rpi == RPI_SNGL_FIR || \
                           rpi == RPI_SNGL_SEC) {
                            // we can just add away
                            // indicate singleton reads by pointing the
                            // partner pointer to itself
                            prev->partnerRead = prev;
                        }
                        else {
                            // RPI_FIR or RPI_SEC
                            // work out pairing information using the hash
                            // we append a 1 or 2 to the end so that
                            // we don't accidentally pair 1's with 1's etc.
                            char * stripped_result;
                            if(rpi == RPI_FIR) {
                                stripped_result = \
                                    pairStripper(seqId,
                                                 core.l_qname-1,
                                                 '2');
                            }
                            else {
                                stripped_result = \
                                    pairStripper(seqId,
                                                 core.l_qname-1,
                                                 '1');
                            }

                            char * stripped = seqId;
                            if(stripped_result)
                                stripped = stripped_result;

                            //fprintf(stdout, "SEARCH %s\n", stripped);
                            // now stripped always holds a stripped value
                            // see if it is in the hash already
                            BM_mappedRead * stored_MR = \
                                cfuhash_get(pair_buffer,
                                            stripped);

                            if (0 != stored_MR) {
                                // exists in the hash -> Add the pair info
                                if(rpi == RPI_FIR) {
                                    prev->partnerRead = stored_MR;
                                }
                                else {
                                    stored_MR->partnerRead = prev;
                                }

                                // delete the entry from the hash
                                cfuhash_delete(pair_buffer,
                                               stripped);
                            }
                            else {
                                // we should put it in the hash
                                // make sure to change it into something
                                // we will find next time
                                if(rpi == RPI_FIR)
                                    stripped[strlen(stripped)-1] = '1';
                                else
                                    stripped[strlen(stripped)-1] = '2';

                                // check to make sure we're not overwriting
                                // anything important. cfuhash overwrites
                                // duplicate entries, so we need to grab
                                // it and put it to "SNGL_XXX" before we
                                // lose the pointer
                                BM_mappedRead * OWMMR = \
                                    cfuhash_put(pair_buffer,
                                                stripped, prev);
                                if(OWMMR) {
                                    if(OWMMR->rpi == RPI_FIR)
                                        OWMMR->rpi = RPI_SNGL_FIR;
                                    else
                                        OWMMR->rpi = RPI_SNGL_SEC;
                                    OWMMR->partnerRead = OWMMR;
                                    printPairCorruptionWarning(p_corrupt);
                                    p_corrupt = 1;
                                }


                            }

                            if(stripped_result != 0) { // free this!
                                free(stripped_result);
                                stripped_result = 0;
                            }
                        }
                    }
                    hts_itr_destroy(iter);
                    if (result < -1) {
                        fprintf(stderr, "ERROR: retrieval of reads from "\
                                        "contig:  \"%s\" failed due to "\
                                        "truncated file or corrupt BAM index "\
                                        "file\n", header->target_name[hh]);
                        break;
                    }
                }

                // any entries left in the hash are pairs whose mates did
                // not meet quality standards
                size_t key_size = 0;
                char * key;
                BM_mappedRead * LOMMR;
                size_t pr_size = 1;
                if(cfuhash_each_data(pair_buffer,
                                     (void**)&key,
                                     &key_size,
                                     (void**)&LOMMR,
                                     &pr_size)) {
                    do {
                        // get the mapped read
                        // update it's pairing so we know it's really single
                        if (LOMMR->rpi == RPI_FIR)
                            LOMMR->rpi = RPI_SNGL_FIR;
                        else if (LOMMR->rpi == RPI_SEC)
                            LOMMR->rpi = RPI_SNGL_SEC;

                        // indicate singleton reads by pointing the
                        // partner pointer to itself
                        LOMMR->partnerRead = LOMMR;

                    } while(cfuhash_next_data(pair_buffer,
                                              (void**)&key,
                                              &key_size,
                                              (void**)&LOMMR,
                                              &pr_size));
                }

                cfuhash_clear(pair_buffer);
                cfuhash_destroy(pair_buffer);
            }
            hts_idx_destroy(idx); // destroy the BAM index
        }
    }
    // always do this
    if (in) sam_close(in);
    bam_destroy1(b);
    if ( header ) bam_hdr_destroy(header);

    return root;
}
Example #9
0
/* Function which deals with taking data from the north bound
 * and pushing it onto the south bound. */
static void *controller_wrpNorth(void *args){
	int fd = -1;
	int count = -1;
	char temp;
	char *key;
	int index = 0;
	int *south_fd = NULL;
	uint8_t *forward_buffer;
	struct Packet packet;	

	fd = *((int*)args);
	key = (char*)malloc(sizeof(char) * 256);

	/* Read the monitor id from the north bound. */
	while((count = read(fd, &temp, sizeof(char))) > 0){
		if(temp == '\n' || temp == '\r'){
			key[index] = '\0';
			break;
		}
		key[index++] = temp;
	}

	/* Search for the key in the hash table. 
	 * If the key is not found close the connection and return. */
	south_fd = (int*)cfuhash_get(controller_map, key);	

	#if DEBUG == 1
		fprintf(stderr, "controller_wrpNorth :: key => %s\n", key);	
	#endif

	if(south_fd == NULL){
		#if DEBUG == 1
			fprintf(stderr, "controller_wrpNorth :: Hash map miss\n");
			cfuhash_pretty_print(controller_map, stderr);
		#endif
		goto ret;
	}

	#if DEBUG == 1
		fprintf(stderr, "controller_wrpNorth :: south fd => %d\n", *south_fd);
	#endif

	/* Read contents from the north bound interface and pass them
	 * on the correct connection stream. */
	/* Read the packet header. */

	count = read(fd, &packet, sizeof(struct Packet));
	
	forward_buffer = (uint8_t*)malloc(packet.len);
	memcpy(forward_buffer, &packet, sizeof(struct Packet));
	
	count = read(fd, forward_buffer + sizeof(struct Packet), 
				packet.len - sizeof(struct Packet));

	count = write(*south_fd, forward_buffer, packet.len);
	free(forward_buffer);

ret:
	close(fd);
	free(key);
	pthread_exit(NULL);
}
Example #10
0
/*
        Input arguments have a pattern of -option argument -option argument
        For example -u username -p password where username is the name of
        the user who wishes to log in and password is the password for that user
*/
int parseArguments(int argc, char *argv[]) {
             	
        // flag indicating the result
        bool passwordRequested = false;

	argumentInit();

	// if the user did not pass any credentials, then take them from the config file
	/*
	if(argc == 1)		
		getCredentialsFromConfigFile();
	*/

	int i;
        for(i = 1; i < argc;)
        {	
		if(argv[i][0] != '-') {
			fputs("Invalid Option\n", stderr);
			return -1;
		}	

		char *option = argv[i];	
		if(strcmp(option, "-p") == 0){
			passwordRequested = true;
			++i;
			continue;
		}

		if(cfuhash_exists(arguments, option)) {
	
			char * argument = cfuhash_get(arguments, option);
			if(argument[0] != 0){
				fputs("Criteria already set\n", stderr);
                        	return -1;	
			} else if (i == argc - 1) {
				fputs("Invalid Argument Input\n", stderr);
				return -1;
			} else {
				if(isOption(argv[i + 1]) == 0)
					return -1;
				// calloc(30, (sizeof (char)));	
				strlcpy(argument, argv[i + 1]);
				cfuhash_put(arguments, option, argument);
				i += 2;
			}
		} else {
  			fputs("Option not recognised\n", stderr);
                        return -1;
		}
	}

	if(passwordRequested) {
		fputs("Password: ", stdout);
		promptPasswordEntry();	
	}

	// TESTING
	// cfuhash_pretty_print(arguments, stdout);

        return 0;
}
Example #11
0
int connectToServer() {

	char buffer[256];
	puts("Connecting to Server\n");
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
   
	if (sockfd < 0) {
	     perror("ERROR opening socket");
	     return -1;
   	}

	
	puts("bzero\n");	
	bzero((char *) &serv_addr, sizeof(serv_addr));
   	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(5001); 
	

	puts("inet_pton\n");
	printf("host %s\n", host);
	if(inet_pton(AF_INET, cfuhash_get(arguments, "-h"), &serv_addr.sin_addr) <= 0)
    	{
        	printf("\n inet_pton error occured\n");
        	return -1;
    	} 

	char str[256];
	// now get it back and print it
	inet_ntop(AF_INET, &(serv_addr.sin_addr), str, INET_ADDRSTRLEN);
	printf("IP address: %s\n", str); // prints "192.0.2.33"
	

	puts("connect\n");
    	if( connect(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    	{	
       		printf("\nError : Connect Failed \n");
       		return -1;

    	} 


	puts("bzero buffer\n");
	bzero(buffer, sizeof(buffer));

	puts("read\n");
    	int n = read(sockfd, buffer, sizeof (buffer) - 1);
	if (n < 0) {
        	perror("ERROR reading from socket");
                return -1;
        }

	puts("printing buffer\n");
       	buffer[n] = 0;
       	if(fputs(buffer, stdout) == EOF)	// this will display succes message sent from the server
        {
            		printf("\nError : fputs error\n");
			return -1;
        }

	return 0;
} 	
Example #12
0
extern void
cfuopt_parse(cfuopt_t *context, int *argc, char ***argv, char **error) {
	int i = 0;
	char **args = *argv;
	int is_long_opt = 0;
	int is_short_opt = 0;
	int is_data = 0;
	int is_end_of_opt = 0;
	char *parsed_arg = NULL;
	const char *value = NULL;
	cfuopt_list_entry_t *entry = NULL;
	size_t extra_count = 0;

	error = error;

	if (!context) return;
	if (*argc < 1) return;

	context->progname = cfustring_dup_c_str(args[0]);
	
	if (*argc < 2) return;

	for (i = 1; i < *argc; i++) {
		char *cur_arg = args[i];
		entry = NULL;
		value = NULL;

		if (parsed_arg) free(parsed_arg);
		parsed_arg = NULL;
		
		check_arg(cur_arg, &is_long_opt, &is_short_opt, &is_data, &is_end_of_opt, &parsed_arg,
				  &value);
		if (is_long_opt || is_short_opt) {
			entry = (cfuopt_list_entry_t *)cfuhash_get(context->option_map, parsed_arg);
			if (parsed_arg) free(parsed_arg);
			parsed_arg = NULL;
		}
		else if (is_end_of_opt) {
			if (parsed_arg) free(parsed_arg);
			parsed_arg = NULL;
			i++;
			for (; i < *argc; i++) {
				cfulist_push(context->extra, args[i]);
			}
			break;
		}
		else if (is_data) {
			if (parsed_arg) free(parsed_arg);
			parsed_arg = NULL;
			cfulist_push(context->extra, args[i]);
			continue;
		}

		if (!entry) {
			/* FIXME: return error here if need be */
			continue;
		}

		switch (entry->arg_type) {
		  case cfuopt_arg_bool:
			  _set_entry_val(entry, "1");
			  break;
		  case cfuopt_arg_string:
		  case cfuopt_arg_int:
		  case cfuopt_arg_float:
			  if (value) {
				  if (entry->arg_data) {
					  _set_entry_val(entry, value);
				  }
			  } else {
				  i++;
				  if (i >= *argc) break; /* FIXME: set up error msg here */
				  check_arg(args[i], &is_long_opt, &is_short_opt, &is_data, &is_end_of_opt,
					  &parsed_arg, &value);
				  if (!is_data) {
					  i--;
					  break; /* FIXME: set up error msg here */
				  }
				  _set_entry_val(entry, parsed_arg);
				  free(parsed_arg);
				  parsed_arg = NULL;
			  }
			  break;
		  case cfuopt_arg_string_array:
			  break;
		  case cfuopt_arg_invalid:
			  /* FIXME: really should produce an error msg here */
			  break;
		  default:
			  break;
		}
		
	}

	extra_count = cfulist_num_entries(context->extra);
	*argc = extra_count + 1;
	{
		_update_extra_ds ds;
		size_t update_count = 0;
		ds.count = 1;
		ds.argv = args;
		update_count = cfulist_foreach(context->extra, _update_extra, (void *)&ds);
		assert(update_count + 1 == (unsigned)*argc);
	}
}
Example #13
0
void addLink(cfuhash_table_t * linkHash,
             int cid_1,
             int cid_2,
             int pos_1,
             int pos_2,
             int orient_1,
             int orient_2,
             int bam_ID
            )
{
    // store the link info, swap order of cid_1 and cid_2 if needed
    PM_link_info* LI = (PM_link_info*) calloc(1, sizeof(PM_link_info));
    if(cid_1 < cid_2){
        LI->orient_1 = orient_1;
        LI->orient_2 = orient_2;
        LI->pos_1 = pos_1;
        LI->pos_2 = pos_2;
    }
    else
    {
        LI->orient_1 = orient_2;
        LI->orient_2 = orient_1;
        LI->pos_1 = pos_2;
        LI->pos_2 = pos_1;
    }
    LI->bam_ID = bam_ID;

    PM_link_info** next_link_ptr = (PM_link_info**) &LI->next_link;

    // see if the key is in the hash already
    char * key = calloc(30, sizeof(char)); // allocate room for the key
    makeContigKey(key, cid_1, cid_2);
    PM_link_pair * base_LP = cfuhash_get(linkHash, key);
    if (base_LP != NULL)
    {
        // exists in the hash -> daisy chain it on
        *next_link_ptr = base_LP->LI;
        base_LP->LI = LI;
        base_LP->numLinks++;
    }
    else
    {
        // we'll need to build a bit of infrastructure
        // store the contig ids once only
        PM_link_pair * LP = (PM_link_pair*) calloc(1, sizeof(PM_link_pair));
        if(cid_1 < cid_2)
        {
            LP->cid_1 = cid_1;
            LP->cid_2 = cid_2;
        }
        else
        {
            LP->cid_1 = cid_2;
            LP->cid_2 = cid_1;
        }
        LP->LI = LI;
        LP->numLinks = 1;
        *next_link_ptr = LI; // point to self means end of list

        // finally, add the lot to the hash
        cfuhash_put(linkHash, key, LP);
    }
    free(key);
}