#include "fiko/orkestra/task.hpp" #include "fiko/orkestra/protokol.hpp" namespace fiko::orkestra { const char* taskDurumAdi(TaskDurum d) { switch (d) { case TaskDurum::Kuyrukta: return "Kuyrukta"; case TaskDurum::Atandi: return "Atandı"; case TaskDurum::Calisiyor: return "Çalışıyor"; case TaskDurum::Bitti: return "Bitti"; case TaskDurum::Hata: return "Hata"; case TaskDurum::Iptal: return "İptal"; case TaskDurum::Devredildi: return "Devredildi"; } return "?"; } bool taskGecisGecerli(TaskDurum eski, TaskDurum yeni) { switch (eski) { case TaskDurum::Kuyrukta: return yeni == TaskDurum::Atandi || yeni == TaskDurum::Iptal || yeni == TaskDurum::Devredildi; case TaskDurum::Atandi: return yeni == TaskDurum::Calisiyor || yeni == TaskDurum::Iptal || yeni == TaskDurum::Devredildi; case TaskDurum::Calisiyor: // çalışan iş İPTAL edilebilir ama DEVREDİLEMEZ (§4) return yeni == TaskDurum::Bitti || yeni == TaskDurum::Hata || yeni == TaskDurum::Iptal; default: // Bitti/Hata/Iptal/Devredildi = terminal return false; } } Task* TaskYonetici::bulYaz(uint64_t taskId) { auto it = indeks_.find(taskId); return it == indeks_.end() ? nullptr : &tasklar_[it->second]; } const Task* TaskYonetici::bul(uint64_t taskId) const { auto it = indeks_.find(taskId); return it == indeks_.end() ? nullptr : &tasklar_[it->second]; } uint64_t TaskYonetici::olustur( const std::string& tur, const std::vector>& param, const TaskHedef& hedef, uint64_t kaynakNode, uint64_t simdiMs, uint8_t oncelik) { Task t; t.taskId = sonrakiId_++; t.tur = tur; t.param = param; t.hedef = hedef; t.kaynakNode = kaynakNode; t.oncelik = oncelik; t.olusturmaMs = simdiMs; indeks_[t.taskId] = tasklar_.size(); tasklar_.push_back(std::move(t)); return tasklar_.back().taskId; } bool TaskYonetici::ata(uint64_t taskId, uint64_t nodeId) { Task* t = bulYaz(taskId); if (!t || !taskGecisGecerli(t->durum, TaskDurum::Atandi)) return false; t->durum = TaskDurum::Atandi; t->atananNode = nodeId; return true; } bool TaskYonetici::kabulEt(const Task& t) { if (t.taskId == 0 || bulYaz(t.taskId)) return false; // geçersiz/mükerrer atama indeks_[t.taskId] = tasklar_.size(); tasklar_.push_back(t); if (t.taskId >= sonrakiId_) sonrakiId_ = t.taskId + 1; // yerel üretim çakışmasın return true; } bool TaskYonetici::durumGecir(uint64_t taskId, TaskDurum yeni) { Task* t = bulYaz(taskId); if (!t || !taskGecisGecerli(t->durum, yeni)) return false; t->durum = yeni; if (yeni == TaskDurum::Calisiyor) t->ilerleme = 0; else if (yeni == TaskDurum::Bitti) t->ilerleme = 100; return true; } bool TaskYonetici::ilerlemeAyarla(uint64_t taskId, uint8_t yuzde) { Task* t = bulYaz(taskId); if (!t || t->durum != TaskDurum::Calisiyor) return false; t->ilerleme = yuzde > 100 ? 100 : yuzde; return true; } std::vector TaskYonetici::atanmisBaslat(uint64_t nodeId) { std::vector baslayanlar; for (auto& t : tasklar_) { if (t.atananNode == nodeId && t.durum == TaskDurum::Atandi) { t.durum = TaskDurum::Calisiyor; t.ilerleme = 0; baslayanlar.push_back(t.taskId); } } return baslayanlar; } uint64_t TaskYonetici::devret(uint64_t taskId, uint64_t simdiMs) { Task* t = bulYaz(taskId); if (!t || !taskGecisGecerli(t->durum, TaskDurum::Devredildi)) return 0; const Task kopya = *t; // erase realloc'undan önce tarif kopyası t->durum = TaskDurum::Devredildi; return olustur(kopya.tur, kopya.param, kopya.hedef, kopya.kaynakNode, simdiMs, kopya.oncelik); } uint64_t TaskYonetici::otomatikHedefSec(const Task& task, const NodeKayitDefteri& defter, const YerlestirmeAgirlik& agirlik) const { uint64_t enIyi = 0; float enYuksek = -1.f; for (const NodeBilgi& n : defter.liste()) { // Uygunluk kapıları: çevrimiçi + komut-yetkili (doğrulanmış) olmalı. if (n.durum == NodeDurum::Offline || n.durum == NodeDurum::Yanitsiz || n.durum == NodeDurum::Error || !n.dogrulanmis) continue; if (task.hedef.tip == HedefTipi::Etiket && n.etiketler.find(task.hedef.etiket) == std::string::npos) continue; // etiket politikasında eşleşme şart // Bu node'a atanmış aktif task sayısı (yerel kuyruk sayımı). uint32_t nodeAktif = 0; for (const Task& t : tasklar_) if (t.atananNode == n.nodeId && (t.durum == TaskDurum::Atandi || t.durum == TaskDurum::Calisiyor)) ++nodeAktif; const float cpuBos = 1.f - (n.metrik.cpuYuzde / 100.f); const float doyum = agirlik.taskDoyum ? (float)agirlik.taskDoyum : 1.f; const float taskBos = 1.f - (nodeAktif >= agirlik.taskDoyum ? 1.f : nodeAktif / doyum); const float bellekBos = n.metrik.ramMB > 0 ? 1.f : 0.5f; // metrik yoksa nötr float puan = agirlik.cpu * cpuBos + agirlik.task * taskBos + agirlik.bellek * bellekBos; if (n.durum == NodeDurum::Idle) puan += 0.01f; // eş puanda boş node önce if (puan > enYuksek) { enYuksek = puan; enIyi = n.nodeId; } } return enIyi; } size_t TaskYonetici::aktifSayisi() const { size_t n = 0; for (const auto& t : tasklar_) if (t.durum == TaskDurum::Kuyrukta || t.durum == TaskDurum::Atandi || t.durum == TaskDurum::Calisiyor) ++n; return n; } namespace taskproto { constexpr uint16_t ATA_SURUM = 1; constexpr uint16_t DURUM_SURUM = 1; std::string ataSerialize(const Task& t) { std::string s; surecproto::yazU16(s, ATA_SURUM); surecproto::yazU64(s, t.taskId); surecproto::yazStr(s, t.tur); s.push_back((char)t.oncelik); surecproto::yazU64(s, t.kaynakNode); const uint16_t adet = (uint16_t)(t.param.size() > 0xFFFF ? 0xFFFF : t.param.size()); surecproto::yazU16(s, adet); for (uint16_t i = 0; i < adet; ++i) { surecproto::yazStr(s, t.param[i].first); surecproto::yazStr(s, t.param[i].second); } return s; } bool ataCoz(const std::string& govde, Task& out) { const char* p = govde.data(); const char* son = p + govde.size(); if (son - p < 2 + 8) return false; p += 2; out = Task{}; out.taskId = surecproto::okuU64(p); p += 8; if (out.taskId == 0) return false; if (!surecproto::okuStr(p, son, out.tur)) return false; if (son - p < 1 + 8 + 2) return false; out.oncelik = (uint8_t)*p++; out.kaynakNode = surecproto::okuU64(p); p += 8; const uint16_t adet = surecproto::okuU16(p); p += 2; for (uint16_t i = 0; i < adet; ++i) { std::string k, v; if (!surecproto::okuStr(p, son, k) || !surecproto::okuStr(p, son, v)) return false; out.param.emplace_back(std::move(k), std::move(v)); } out.durum = TaskDurum::Atandi; // atanan node kendinde Atandi olarak kurar return true; } std::string durumSerialize(uint64_t taskId, TaskDurum durum, uint8_t ilerleme) { std::string s; surecproto::yazU16(s, DURUM_SURUM); surecproto::yazU64(s, taskId); s.push_back((char)durum); s.push_back((char)ilerleme); return s; } bool durumCoz(const std::string& govde, uint64_t& taskId, TaskDurum& durum, uint8_t& ilerleme) { const char* p = govde.data(); if (govde.size() < 2 + 8 + 2) return false; p += 2; taskId = surecproto::okuU64(p); p += 8; if (taskId == 0) return false; const uint8_t d = (uint8_t)*p++; if (d > (uint8_t)TaskDurum::Devredildi) return false; // bilinmeyen durum reddi durum = (TaskDurum)d; ilerleme = (uint8_t)*p; if (ilerleme > 100) ilerleme = 100; return true; } } // namespace taskproto } // namespace fiko::orkestra