/* $Id: mcl_sda_txtab.cpp,v 1.1.1.1 2003/09/03 12:45:44 chneuman Exp $ */ /* * Copyright (c) 1999-2003 INRIA - Universite Paris 6 - All rights reserved * (main author: Vincent Roca - vincent.roca@inrialpes.fr) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ /* * Sequential Disk Access (SDA) related functions * Required for very large object transmissions when DUs cannot be stored * in physical memory. */ #include "mcl_includes.h" #ifdef LCT_SCHED4 /* { */ /* * private functions */ static txtab_t * mcl_sda_create_txtab (mclcb_t *mclcb); static int mcl_sda_new_tx_cycle (mclcb_t *mclcb); static int mcl_sda_insert_txtab (mclcb_t *mclcb, txtab_t *tt); /* * get last element in txtab */ #define mcl_last_txtab(list) ((list) ? ((list)->prev) : NULL) /****** Public Functions ******************************************************/ /* * register a du for transmission */ void mcl_sda_register_du (mclcb_t *mclcb, du_t *du) { txlvl_t *tl0; /* store in layer 0 list */ txtab_t *tt; #ifdef FEC TRACELVL(5, (mcl_stdout, "-> mcl_sda_register_du: du=x%x (aseq=%d bseq=%d dseq=%d/%s)\n", (int)du, du->block->adu->seq, du->block->seq, du->seq, (du->is_fec ? "fec" : "data"))) #else TRACELVL(5, (mcl_stdout, "-> mcl_sda_register_du: du=x%x (aseq=%d bseq=%d dseq=%d)\n", (int)du, du->block->adu->seq, du->block->seq, du->seq)) #endif ASSERT(mclcb && du); ASSERT(mclcb->scheduler == MCL_SCHED_LCT3); tl0 = mclcb->txlvl_tab; tt = mcl_last_txtab(tl0->txtab_head); if (tt == NULL || tt->wr_index >= NB_TXTAB_ENTRIES) { /* need a new txtab struct */ tt = mcl_sda_create_txtab(mclcb); mcl_sda_insert_txtab(mclcb, tt); } tt->du_tab[tt->wr_index++] = du; tl0->tot_rem++; tl0->tot_in_txtab++; TRACELVL(5, (mcl_stdout, "<- mcl_sda_register_du:\n")) } /* * Returns the next DU to tx or NULL. */ du_t * mcl_sda_get_next_du (mclcb_t *mclcb) { txlvl_t *tl0; /* store in layer 0 list */ txtab_t *tt; du_t *du; TRACELVL(5, (mcl_stdout, "-> mcl_sda_get_next_du:\n")) ASSERT(mclcb); ASSERT(mclcb->scheduler == MCL_SCHED_LCT3); tl0 = mclcb->txlvl_tab; if (tl0->tot_in_txtab <= 0) { TRACELVL(5, (mcl_stdout, "<- mcl_sda_get_next_du: NULL (empty)\n")) return NULL; } if (tl0->tot_rem <= 0) { /* we have cycled, start once again at a random offset */ mcl_sda_new_tx_cycle(mclcb); } tt = tl0->cached_txtab; ASSERT(tt); #ifdef NEVERDEF if (tt == NULL) { PRINT_ERR((mcl_stderr, "mcl_get_next_du: ERROR, null tt")) mcl_exit(-1); } #endif if (tt->tx_index >= tt->wr_index) { /* exhausted: move to next tt */ tt->tx_index = 0; /* required for looping */ tt = tt->next; tl0->cached_txtab = tt; /* remember it */ } ASSERT(tt); #ifdef NEVERDEF if (tt == NULL) { PRINT_ERR((mcl_stderr, "mcl_get_next_du: ERROR, null tt")) mcl_exit(-1); } #endif ASSERT(tt->tx_index < tt->wr_index); du = tt->du_tab[tt->tx_index++]; tl0->tot_rem--; #ifdef FEC TRACELVL(5, (mcl_stdout, "<- mcl_sda_get_next_du: du=x%x (aseq=%d bseq=%d dseq=%d/%s)\n", (int)du, du->block->adu->seq, du->block->seq, du->seq, (du->is_fec ? "fec" : "data"))) #else TRACELVL(5, (mcl_stdout, "<- mcl_sda_get_next_du: du=x%x (aseq=%d bseq=%d dseq=%d)\n", (int)du, du->block->adu->seq, du->block->seq, du->seq)) #endif return du; } /****** Private Functions *****************************************************/ /* * Create and init a new txtab_t struct. */ static txtab_t * mcl_sda_create_txtab (mclcb_t *mclcb) { txtab_t *tt; TRACELVL(5, (mcl_stdout, "-> mcl_sda_create_txtab:\n")) if (!(tt = (txtab_t*)calloc(1, sizeof(txtab_t)))) { PRINT_ERR((mcl_stderr,"mcl_sda_create_txtab: ERROR, no memory")) mcl_exit(-1); } TRACELVL(5, (mcl_stdout, "<- mcl_sda_create_txtab: return x%x\n", (int)tt)) return (tt); } /* * Insert the txtab (one elt only) at the end of the list. * Returns 1 if list was empty, 0 otherwise. */ static int mcl_sda_insert_txtab (mclcb_t *mclcb, txtab_t *tt) { txlvl_t *tl0; /* store in layer 0 list */ txtab_t *ptt, *ntt; /* insert tt between prev_tt, next_tt */ TRACELVL(5, (mcl_stdout, "-> mcl_sda_insert_txtab:\n")) ASSERT((tt)) ASSERT(!tt->next); ASSERT(!tt->prev); tl0 = mclcb->txlvl_tab; ptt = mcl_last_txtab(tl0->txtab_head); /* last txtab in list */ if (ptt == NULL) { /* * first txtab in list */ tl0->txtab_head = tt; tt->next = tt->prev = tt; tl0->cached_txtab = tt; /* the initial cached txtab */ TRACELVL(5, (mcl_stdout, "<- mcl_sda_insert_txtab: return 1\n")) return 1; } ntt = ptt->next; /* this is the following txtab in list */ /* single txtab to add */ ASSERT((!tt->prev)) ptt->next = tt; tt->prev = ptt; tt->next = ntt; ntt->prev = tt; TRACELVL(5, (mcl_stdout, "<- mcl_sda_insert_txtab: return 0\n")) return 0; } /* * reset the txtab for a new transmission cycle * (push or on demand delivery mode) * returns 0 if ok, < 0 if an error */ int mcl_sda_new_tx_cycle (mclcb_t *mclcb) { txlvl_t *tl0; /* store in layer 0 list */ txtab_t *tt; int seq; int acc_seq; /* accumulated seq */ TRACELVL(5, (mcl_stdout, "-> mcl_sda_new_tx_cycle:\n")) ASSERT(mclcb); tl0 = mclcb->txlvl_tab; ASSERT(tl0->tot_rem == 0); if (!(tt = tl0->txtab_head)) { TRACELVL(5, (mcl_stdout, "<- mcl_sda_new_tx_cycle: no txtab\n")) return -1; } /* calculate a random seq nb in the txtab list and move to it */ seq = random() % tl0->tot_in_txtab; /* move to this du */ acc_seq = 0; while ((acc_seq + tt->wr_index) < seq) { acc_seq += tt->wr_index; tt = tt->next; } /* reset all */ tt->tx_index = seq - acc_seq; tl0->cached_txtab = tt; tl0->tot_rem = tl0->tot_in_txtab; printf(" new cycle: seq=%d, dseq=%d ", seq, tt->du_tab[tt->tx_index++]->seq); TRACELVL(5, (mcl_stdout, "<- mcl_sda_new_tx_cycle:\n")) return 0; } #endif /* } LCT_SCHED4 */