/* Add new agent. Send agent ID + number of workers + router map */ static void add_agent(int fd, bool isclient) { unsigned agent = next_agent++; if (agent >= worker_cnt + maxclients) { /* Exceeded client limit */ chunk_ptr msg = msg_new_nack(); if (chunk_write(fd, msg)) { #if RPT >= 1 report(1, "Sent nack to potential client due to client limit being exceeded. Fd = %d", fd); #endif } else { #if RPT >= 3 report(3, "Couldn't send nack to potential client. Fd = %d", fd); #endif } chunk_free(msg); return; } /* Need to break into sequence of messages according to max. chunk length */ chunk_ptr msg = NULL; size_t bcount = 0; size_t ncount = router_addr_set->nelements; set_iterstart(router_addr_set); word_t id; bool ok = true; while (ok && set_iternext(router_addr_set, &id)) { if (bcount == 0) { /* Start new block */ size_t blen = ncount; if (blen > MAX_IDS) blen = MAX_IDS; msg = chunk_new(blen+1); } word_t wd = id << 16; chunk_insert_word(msg, wd, bcount+1); bcount++; if (bcount == MAX_IDS) { /* This block is filled */ size_t h1 = ((word_t) agent << 48) | ((word_t) ncount << 32) | ((word_t) worker_cnt << 16) | MSG_ACK_AGENT; chunk_insert_word(msg, h1, 0); ok = chunk_write(fd, msg); chunk_free(msg); ncount -= bcount; bcount = 0; } } if (ok && ncount > 0) { size_t h1 = ((word_t) agent << 48) | ((word_t) ncount << 32) | ((word_t) worker_cnt << 16) | MSG_ACK_AGENT; chunk_insert_word(msg, h1, 0); ok = chunk_write(fd, msg); chunk_free(msg); ncount -= bcount; } #if RPT >= 3 report(3, "Added agent %u with descriptor %d", agent, fd); #endif }
/* Send single-valued operand */ bool send_as_operand(dword_t dest, word_t val) { chunk_ptr oper = msg_new_operand(dest, 1 + OPER_HEADER_CNT); chunk_insert_word(oper, val, 0 + OPER_HEADER_CNT); bool ok = send_op(oper); chunk_free(oper); return ok; }
/* Extract subchunk */ chunk_ptr chunk_get_chunk(chunk_ptr cp, size_t offset, size_t length) { chunk_ptr ncp = chunk_new(length); size_t i; for (i = 0; i < length; i++) { chunk_insert_word(ncp, chunk_get_word(cp, i+offset), i); } return ncp; }
/* Insert words from source chunk into destination chunk with designated offset */ void chunk_insert_chunk(chunk_ptr cdestp, chunk_ptr csrcp, size_t offset) { if (csrcp == NULL && chunk_check_level >= 2) { chunk_error("Null Source Pointer", csrcp); return; } size_t i; size_t len = (size_t) csrcp->length; for(i = 0; i < len; i++) { chunk_insert_word(cdestp, csrcp->words[i], i + offset); } }
/* Insert word into operator, updating its valid mask. Offset includes header size */ void op_insert_word(chunk_ptr op, word_t wd, size_t offset) { word_t vmask = chunk_get_word(op, 2); word_t nvmask; word_t idx = (word_t) 1 << offset; if (vmask & idx) { err(false, "Inserting into already filled position in operator. Offset = %lu", offset); } chunk_insert_word(op, wd, offset); nvmask = vmask | idx; chunk_insert_word(op, nvmask, 2); #if RPT >= 6 dword_t dh = chunk_get_dword(op, 0); word_t id = msg_get_dheader_op_id(dh); report(6, "Inserted word, offset %d, operation with id 0x%lx.\n" " Total size = %d. Vmask 0x%lx --> 0x%lx", (int) offset, id, op->length, vmask, nvmask); #endif }
/* Convert a string into a chunk. Limited to strings of length <= WORD_BYTES */ chunk_ptr str2chunk(char *s) { char buf[WORD_BYTES * CHUNK_MAX_LENGTH]; size_t len = (strnlen(s, WORD_BYTES * CHUNK_MAX_LENGTH) + WORD_BYTES - 1) / WORD_BYTES; chunk_ptr cp = chunk_new(len); size_t cidx, bidx; size_t sidx = 0; for (cidx = 0; cidx < len; cidx++) { for (bidx = 0; bidx < WORD_BYTES && s[sidx]; bidx++) { buf[bidx] = s[sidx++]; } for (; bidx < WORD_BYTES; bidx++) { buf[bidx] = '\0'; } word_t wd = *(word_t *) buf; chunk_insert_word(cp, wd, cidx); } return cp; }