/* * Předmět: Algoritmy (IAL) - FIT VUT v Brně * Rozšíření pro příklad c206.c (Dvousměrně vázaný lineární seznam) * Vytvořil: Daniel Dolejška, září 2024 */ #include "c206-ext.h" bool error_flag; bool solved; /** * Tato metoda simuluje příjem síťových paketů s určenou úrovní priority. * Přijaté pakety jsou zařazeny do odpovídajících front dle jejich priorit. * "Fronty" jsou v tomto cvičení reprezentovány dvousměrně vázanými seznamy * - ty totiž umožňují snazší úpravy pro již zařazené položky. * * Parametr `packetLists` obsahuje jednotlivé seznamy paketů (`QosPacketListPtr`). * Pokud fronta s odpovídající prioritou neexistuje, tato metoda ji alokuje * a inicializuje. Za jejich korektní uvolnení odpovídá volající. * * V případě, že by po zařazení paketu do seznamu počet prvků v cílovém seznamu * překročil stanovený MAX_PACKET_COUNT, dojde nejdříve k promazání položek seznamu. * V takovémto případě bude každá druhá položka ze seznamu zahozena nehledě * na její vlastní prioritu ovšem v pořadí přijetí. * * @param packetLists Ukazatel na inicializovanou strukturu dvousměrně vázaného seznamu * @param packet Ukazatel na strukturu přijatého paketu */ void receive_packet(DLList *packetLists, PacketPtr packet) { QosPacketListPtr targetList = NULL; DLL_First(packetLists); while (DLL_IsActive(packetLists)) { QosPacketListPtr currentList = (QosPacketListPtr)((long)packetLists->activeElement->data); if (currentList->priority == packet->priority) { targetList = currentList; break; } if (currentList->priority < packet->priority) { break; } DLL_Next(packetLists); } if (targetList == NULL) { targetList = (QosPacketListPtr)malloc(sizeof(QosPacketList)); if (targetList == NULL) { error_flag = true; return; } targetList->priority = packet->priority; targetList->list = (DLList *)malloc(sizeof(DLList)); if (targetList->list == NULL) { free(targetList); error_flag = true; return; } DLL_Init(targetList->list); if (!DLL_IsActive(packetLists)) { DLL_InsertLast(packetLists, (long)targetList); } else { DLL_InsertBefore(packetLists, (long)targetList); } } if (targetList->list->currentLength >= MAX_PACKET_COUNT) { DLLElementPtr current = targetList->list->firstElement; DLLElementPtr next; int count = 0; while (current != NULL) { next = current->nextElement; if (count % 2 == 1) { if (current == targetList->list->activeElement) { targetList->list->activeElement = next; } if (current == targetList->list->firstElement) { targetList->list->firstElement = next; } if (current == targetList->list->lastElement) { targetList->list->lastElement = current->previousElement; } if (current->previousElement) { current->previousElement->nextElement = next; } if (next) { next->previousElement = current->previousElement; } free(current); targetList->list->currentLength--; } current = next; count++; } } DLL_InsertLast(targetList->list, (long)packet); } /** * Tato metoda simuluje výběr síťových paketů k odeslání. Výběr respektuje * relativní priority paketů mezi sebou, kde pakety s nejvyšší prioritou * jsou vždy odeslány nejdříve. Odesílání dále respektuje pořadí, ve kterém * byly pakety přijaty metodou `receive_packet`. * * Odeslané pakety jsou ze zdrojového seznamu při odeslání odstraněny. * * Parametr `packetLists` obsahuje ukazatele na jednotlivé seznamy paketů (`QosPacketListPtr`). * Parametr `outputPacketList` obsahuje ukazatele na odeslané pakety (`PacketPtr`). * * @param packetLists Ukazatel na inicializovanou strukturu dvousměrně vázaného seznamu * @param outputPacketList Ukazatel na seznam paketů k odeslání * @param maxPacketCount Maximální počet paketů k odeslání */ void send_packets(DLList *packetLists, DLList *outputPacketList, int maxPacketCount) { int sentCount = 0; while (sentCount < maxPacketCount) { DLL_First(packetLists); while (DLL_IsActive(packetLists) && sentCount < maxPacketCount) { QosPacketListPtr currentList = (QosPacketListPtr)((long)packetLists->activeElement->data); if (currentList->list->currentLength > 0) { PacketPtr packet = (PacketPtr)((long)currentList->list->firstElement->data); DLL_InsertLast(outputPacketList, (long)packet); DLL_DeleteFirst(currentList->list); sentCount++; } else { DLL_Next(packetLists); } } if (!DLL_IsActive(packetLists)) { break; } } }