aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/sledjchisl/sledjchisl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/sledjchisl/sledjchisl.c')
-rw-r--r--src/sledjchisl/sledjchisl.c796
1 files changed, 325 insertions, 471 deletions
diff --git a/src/sledjchisl/sledjchisl.c b/src/sledjchisl/sledjchisl.c
index c068d57..12c03cd 100644
--- a/src/sledjchisl/sledjchisl.c
+++ b/src/sledjchisl/sledjchisl.c
@@ -1090,6 +1090,10 @@ struct _simList
1090 int len, num; 1090 int len, num;
1091 char **sims; 1091 char **sims;
1092 qtreetbl_t *byTab, *simsLua; 1092 qtreetbl_t *byTab, *simsLua;
1093 // Stuff for the looping through sims doing things and waiting.
1094 char *target;
1095 float la;
1096 int doWait;
1093}; 1097};
1094simList *ourSims = NULL; 1098simList *ourSims = NULL;
1095 1099
@@ -1435,6 +1439,305 @@ int checkSimIsRunning(char *sim)
1435 return ret; 1439 return ret;
1436} 1440}
1437 1441
1442////////////////////////////////////////////////////////////////////////////////////////////////////
1443// Sim wrangling loop.
1444////////////////////////////////////////////////////////////////////////////////////////////////////
1445typedef void (*simFunction)(simData *simd, char *type, int count, int window, int panes, int pane);
1446void forEachSim(char *verb, simFunction func)
1447{
1448 qtreetbl_obj_t obj0, obj1;
1449 qLua *q0, *q1;
1450 int count = 0, window = 0, panes = 4, pane = 0;
1451
1452 ourSims->doWait = 1;
1453 memset((void*)&obj0, 0, sizeof(obj0));
1454 ourSims->simsLua->lock(ourSims->simsLua);
1455 while(ourSims->simsLua->getnext(ourSims->simsLua, &obj0, false) == true)
1456 {
1457 q0 = obj0.data;
1458 char *type = "unsorted";
1459
1460 if (LUA_TTABLE == q0->type)
1461 {
1462 panes = 4;
1463 q1 = q0->v.t->get(q0->v.t, "number", NULL, false); if (NULL != q1) window = q1->v.f - 1;
1464 q1 = q0->v.t->get(q0->v.t, "panes", NULL, false); if (NULL != q1) panes = q1->v.f;
1465 q1 = q0->v.t->get(q0->v.t, "type", NULL, false); if (NULL != q1) type = q1->v.s;
1466 if (0 == panes)
1467 {
1468 pane = 2;
1469 window = 0;
1470 type = Ttab;
1471 }
1472 else if (0 != pane)
1473 {
1474 pane = 0;
1475 window++;
1476 }
1477
1478 if (verb)
1479 V("%s sims of type %s, window %d, %d panes per window.", verb, type, window, panes);
1480 memset((void*)&obj1, 0, sizeof(obj1));
1481 q0->v.t->lock(q0->v.t);
1482 while(q0->v.t->getnext(q0->v.t, &obj1, false) == true)
1483 {
1484 q1 = obj1.data;
1485
1486 if ((strcmp("number", obj1.name) != 0) && (strcmp("panes", obj1.name) != 0) && (strcmp("type", obj1.name) != 0))
1487 {
1488 simData *simd = ourSims->byTab->get(ourSims->byTab, q1->v.s, NULL, false);
1489
1490 if (NULL == simd)
1491 E("Sim %s not found in ini list!", q1->v.s);
1492 else
1493 {
1494 func(simd, type, count, window, panes, pane);
1495 count++;
1496 pane++;
1497 if (pane >= panes)
1498 {
1499 pane = 0;
1500 window++;
1501 }
1502 }
1503 }
1504 }
1505 q0->v.t->unlock(q0->v.t);
1506 }
1507 }
1508 ourSims->simsLua->unlock(ourSims->simsLua);
1509}
1510
1511void prepSims(simData *simd, char *type, int count, int window, int panes, int pane)
1512{
1513 char *path = xmprintf("%s/%s.shini", scEtc, simd->tab);
1514 char *newPath = xmprintf("%s/sim%d/%s.ini", scTemp, count, simd->tab); // Coz OpenSim sucks.
1515 char *cmd;
1516
1517 simd->window = window;
1518 simd->pane = pane;
1519
1520 // Make sure all tmux windows and panes are startned.
1521 // The bash invocations are so that the PATH is properly propagated.
1522 if (0 == panes)
1523 doTmuxCmd("split-window -hp 50 -d -t '%s:0.1' bash", Tconsole);
1524 else if (0 == pane)
1525 {
1526 doTmuxCmd("new-window -dc '%s/current/bin' -n '%s' -t '%s:%d' bash", scRoot, type, Tconsole, window);
1527 if (2 <= panes)
1528 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.0' bash", Tconsole, window);
1529 if (4 <= panes)
1530 {
1531 doTmuxCmd("split-window -vp 50 -d -t '%s:%d.1' bash", Tconsole, window);
1532 doTmuxCmd("split-window -vp 50 -d -t '%s:%d.0' bash", Tconsole, window);
1533 }
1534 if (8 <= panes)
1535 {
1536 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.3' bash", Tconsole, window);
1537 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.2' bash", Tconsole, window);
1538 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.1' bash", Tconsole, window);
1539 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.0' bash", Tconsole, window);
1540 }
1541 }
1542
1543 // Create the temporary .ini files.
1544 snprintf(toybuf, sizeof(toybuf), "echo 'IDs={' >%s/IDs_%d.lua", scTemp, window);
1545 system(toybuf);
1546 doTmuxCmd("list-panes -t %d -F \"['%d #{pane_index}'] = '#{window_id}.#{pane_id}',\" >> %s/IDs_%d.lua", window, window, scTemp, window);
1547 snprintf(toybuf, sizeof(toybuf), "echo '}\nreturn IDs' >>%s/IDs_%d.lua", scTemp, window);
1548 system(toybuf);
1549
1550 snprintf(toybuf, sizeof(toybuf), "%s/IDs_%d.lua", scTemp, window);
1551 qtreetbl_t *IDs = Lua2tree(toybuf, "IDs");
1552 snprintf(toybuf, sizeof(toybuf), "%d %d", window, pane);
1553 simd->paneID = xmprintf("%s", qLuaGet(IDs, toybuf)->v.s);
1554 freeLuaTree(IDs);
1555
1556 simd->portH = 8004 + count * 2;
1557 simd->portU = 8005 + count * 2;
1558 cmd = xmprintf("rm -fr %s/sim%d; mkdir -p %s/sim%d; sed -E"
1559 " -e 's@\\[Region\\]@"
1560 " paneID = \"\\%s\"\\n"
1561 "\\[Startup\\]\\n"
1562 " PIDFile = \"\\$\\{Paths\\|CachePath\\}\\/\\$\\{Const\\|mysim\\}\\.pid\"\\n"
1563 " LogFile = \"\\$\\{Paths\\|LogPath\\}\\/OpenSim_\\$\\{Const\\|mysim\\}\\.log\"\\n"
1564 " StatsLogFile = \"\\$\\{Paths\\|LogPath\\}\\/OpenSimStats_\\$\\{Const\\|mysim\\}\\.log\"\\n"
1565 " ConsoleHistoryFile = \"\\$\\{Paths\\|LogPath\\}\\/OpenSimConsoleHistory_\\$\\{Const\\|mysim\\}\\.txt\"\\n"
1566 "\\n\\[Region\\]@'"
1567 " -e 's/InternalPort[[:space:]]*=[[:space:]]*[[:digit:]]+/InternalPort = %d/'"
1568 " -e 's/InternalPort[[:space:]]*=[[:space:]]*\"[[:digit:]]+\"/InternalPort = %d/'"
1569 " -e 's/http_listener_port[[:space:]]*=[[:space:]]*[[:digit:]]+/http_listener_port = %d/'"
1570 " -e 's/http_listener_port[[:space:]]*=[[:space:]]*\"[[:digit:]]+\"/http_listener_port = %d/'"
1571 " %s >%s",
1572 scTemp, count,
1573 scTemp, count,
1574 simd->paneID,
1575 simd->portU,
1576 simd->portU,
1577 simd->portH,
1578 simd->portH,
1579 path, newPath);
1580 D("Writing .ini file %s with ports %d %d", newPath, simd->portH, simd->portU);
1581 if (!WIFEXITED(system(cmd)))
1582 E("sed command failed!");
1583 free(cmd);
1584 free(newPath);
1585 free(path);
1586}
1587
1588// Figure out where the sims are running.
1589void findSimsTmux(simData *simd, char *type, int count, int window, int panes, int pane)
1590{
1591 simd->window = window;
1592 simd->pane = pane;
1593 snprintf(toybuf, sizeof(toybuf), "%s/IDs_%d.lua", scTemp, window);
1594 qtreetbl_t *IDs = Lua2tree(toybuf, "IDs");
1595 snprintf(toybuf, sizeof(toybuf), "%d %d", window, pane);
1596 simd->paneID = xmprintf("%s", qLuaGet(IDs, toybuf)->v.s);
1597 freeLuaTree(IDs);
1598}
1599
1600void doSimsThing(simData *simd, char *type, int count, int window, int panes, int pane)
1601{
1602 // Check if only doing a single sim.
1603 int cont = FALSE;
1604 if (NULL != ourSims->target)
1605 {
1606 cont = TRUE;
1607 snprintf(toybuf, sizeof(toybuf), "%s.shini", simd->tab);
1608 if
1609 (
1610 (strcmp(ourSims->target, simd->name) == 0) ||
1611 (strcmp(ourSims->target, simd->tab) == 0) ||
1612 (strcmp(ourSims->target, toybuf) == 0)
1613 )
1614 cont = FALSE;
1615 snprintf(toybuf, sizeof(toybuf), "%s.ini", simd->tab);
1616 if (strcmp(ourSims->target, toybuf) == 0)
1617 cont = FALSE;
1618 snprintf(toybuf, sizeof(toybuf), "sim%d.ini", count);
1619 if (strcmp(ourSims->target, toybuf) == 0)
1620 cont = FALSE;
1621 if (cont)
1622 return;
1623 }
1624
1625 switch (currentMode)
1626 {
1627 case START : // "start sim01" "start 'Welcome sim'" "start Welcome.ini" "start Welcome" "start" start everything
1628 {
1629 if (!checkSimIsRunning(simd->tab))
1630 {
1631 I("Tmux tab [%d:%s](pane %d) tmux ID %s, from %s/sim%d - %s is starting.", window, type, pane, simd->paneID, scTemp, count, simd->name);
1632 doTmuxCmd("select-pane -t %s:%s -T '%s'", Tconsole, simd->paneID, simd->tab);
1633 snprintf(toybuf, sizeof(toybuf), "mono OpenSim.exe -inidirectory=%s/sim%d", scTemp, count);
1634 sendTmuxCmd(simd->paneID, toybuf);
1635 if (0 == ourSims->doWait)
1636 {
1637 snprintf(toybuf, sizeof(toybuf), "INITIALIZATION COMPLETE FOR %s", simd->name);
1638 waitTmuxText(simd->paneID, toybuf);
1639 I("%s is done starting up.", simd->name);
1640 ourSims->la = waitLoadAverage(ourSims->la, loadAverageInc, simTimeOut);
1641 if (1 < bulkSims)
1642 bulkSims = bulkSims / 2;
1643 }
1644 else
1645 {
1646// TODO - some compromise, do a premptive load check if we are not doing a wait anyway.
1647 }
1648 ourSims->doWait = ((count + 1) % bulkSims);
1649 }
1650 break;
1651 }
1652
1653 case BACKUP : // "backup 'onefang rejected'" "backup sim01" "backup 'Welcome Sim'" "backup" backup everything
1654 { // TODO - If it's not a sim code, and not a sim name, it's an account inventory.
1655 if (checkSimIsRunning(simd->tab))
1656 {
1657 struct timeval tv;
1658 time_t curtime;
1659 char date[DATE_TIME_LEN];
1660
1661// TODO - should collect names of existing backups, both tmux / ini name and proper name.
1662// Scan backups directory once before this for loop, add details to sims list.
1663// strip off the last bit of file name (YYYY-mm-dd_HH:MM:SS.oar) to get the name
1664// keep in mind some old files had munged names like "Tiffanie_s_Paradise-2021-06-23_05:11:38.oar"
1665 gettimeofday(&tv, NULL);
1666 curtime = tv.tv_sec;
1667 strftime(date, DATE_TIME_LEN, "%F_%T", localtime(&curtime));
1668 I("%s is being backed up to %s/backups/%s-%s.oar.", simd->name, scRoot, simd->tab, date);
1669 snprintf(toybuf, sizeof(toybuf), "save oar --all %s/backups/%s-%s.oar", scRoot, simd->tab, date);
1670 sendTmuxCmd(simd->paneID, toybuf);
1671// if (0 == doWait)
1672 {
1673 memset(toybuf, 0, sizeof(toybuf));
1674 snprintf(toybuf, sizeof(toybuf), "Finished writing out OAR for %s", simd->name);
1675 waitTmuxText(simd->paneID, toybuf);
1676 I("%s is done backing up.", simd->name);
1677// TODO - should delete / gitAR the old ones now.
1678// Have a config option for delete / gitAR.
1679 ourSims->la = waitLoadAverage(ourSims->la, loadAverageInc, simTimeOut);
1680 }
1681 }
1682 break;
1683 }
1684
1685 case CREATE : // "create name x,y size"
1686 {
1687 break;
1688 }
1689
1690 case GITAR : // "gitAR i name" "gitAR o name"
1691 {
1692 break;
1693 }
1694
1695 case STATUS :
1696 {
1697 break;
1698 }
1699
1700 case STOP : // "stop sim01" "stop 'Welcome Sim'" "stop" stop everything
1701 {
1702 if (checkSimIsRunning(simd->tab))
1703 {
1704 // Leave empty panes as is.
1705 sendTmuxCmd(simd->paneID, "quit");
1706 // There's three things that might happen -
1707 // Sim will quit, tmux pane will go away before we can see the shutdown message.
1708 // pane-exited hook might be useful here.
1709 // Sim will quit, tmux pane wont go away. Dunno yet if waitTmuxText() will still work.
1710 // pane-died hook might be useful here.
1711 // Sim fails to quit, error message on the pane that we want to read, wont see the shutdown message.
1712 // Also sim might not have finished starting up, and may even not be accepting comands yet.
1713// TODO - cater for and test them all.
1714// Could also loop on checkSimIsRunning(sim)
1715// snprintf(toybuf, sizeof(toybuf), "[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
1716// waitTmuxText(nm, toybuf);
1717// I("%s is done stopping.", simd->name);
1718// la = waitLoadAverage(la, loadAverageInc, simTimeOut);
1719 }
1720 break;
1721 }
1722
1723 default :
1724 {
1725 E("Unknown command! %s", toys.optargs[0]);
1726 break;
1727 }
1728 }
1729}
1730
1731void stopSims(simData *simd, char *type, int count, int window, int panes, int pane)
1732{
1733 // NOTE - these sleeps are guesses, seems to work on my super desktop during testing.
1734 while (checkSimIsRunning(simd->tab))
1735 usleep(100000);
1736 usleep(10000);
1737 doTmuxCmd("kill-pane -t %s", simd->paneID);
1738 I("Tmux tab [%d:%s](pane %d) tmux ID %s, from %s/sim%d - %s has stopped.", window, type, pane, simd->paneID, scTemp, count, simd->name);
1739}
1740
1438 1741
1439static void PrintEnv(qgrow_t *reply, char *label, char **envp) 1742static void PrintEnv(qgrow_t *reply, char *label, char **envp)
1440{ 1743{
@@ -7740,18 +8043,15 @@ fcgiDone:
7740//////////////////////////////////////////////////////////////////////////////////////////////////// 8043////////////////////////////////////////////////////////////////////////////////////////////////////
7741// Start of OpenSim wrangling section. 8044// Start of OpenSim wrangling section.
7742//////////////////////////////////////////////////////////////////////////////////////////////////// 8045////////////////////////////////////////////////////////////////////////////////////////////////////
7743 char *target = NULL;
7744 struct sysinfo info; 8046 struct sysinfo info;
7745 float la;
7746 // TODO - See https://stackoverflow.com/questions/2693948/how-do-i-retrieve-the-number-of-processors-on-c-linux, there are more portable ways, this seems to be GNU specific. 8047 // TODO - See https://stackoverflow.com/questions/2693948/how-do-i-retrieve-the-number-of-processors-on-c-linux, there are more portable ways, this seems to be GNU specific.
7747 int cpus = (int) sysconf(_SC_NPROCESSORS_CONF), cpusOnline = (int) sysconf(_SC_NPROCESSORS_ONLN); 8048 int cpus = (int) sysconf(_SC_NPROCESSORS_CONF), cpusOnline = (int) sysconf(_SC_NPROCESSORS_ONLN);
7748 int doWait = 1;
7749 8049
7750 if (0 == bulkSims) 8050 if (0 == bulkSims)
7751 bulkSims = (cpusOnline / 3) - 1; 8051 bulkSims = (cpusOnline / 3) - 1;
7752 I("There are %i CPUs, %i of them are online. Doing %i sims at once.", cpus, cpusOnline, bulkSims);
7753 sysinfo(&info); 8052 sysinfo(&info);
7754 la = info.loads[0]/65536.0; 8053 ourSims->la = info.loads[0]/65536.0;
8054 I("There are %i CPUs, %i of them are online. Doing %i sims at once. LoadAverage = %f", cpus, cpusOnline, bulkSims, ourSims->la);
7755 8055
7756 if (0 == toys.optc) 8056 if (0 == toys.optc)
7757 ; 8057 ;
@@ -7768,19 +8068,12 @@ fcgiDone:
7768 else if (strcmp(toys.optargs[0], "stop") == 0) 8068 else if (strcmp(toys.optargs[0], "stop") == 0)
7769 currentMode = STOP; 8069 currentMode = STOP;
7770 else 8070 else
7771 target = toys.optargs[0]; 8071 ourSims->target = toys.optargs[0];
7772 if (2 == toys.optc) 8072 if (2 == toys.optc)
7773 target = toys.optargs[1]; 8073 ourSims->target = toys.optargs[1];
7774 8074V("ARGS - %d %d %i |%s| %s |%s|", toys.optc, toys.optflags, currentMode, toys.optargs[0], toys.optargs[1], ourSims->target);
7775//T("ARGS - %i |%s| |%s|", currentMode, toys.optargs[0], target);
7776 8075
7777 qtreetbl_obj_t obj0, obj1; 8076 // Start ROBUST or join the tmux session, or just figure out where the sims are running in tmux.
7778 qLua *q0, *q1;
7779 int count = 0, window = 0, panes = 4, pane = 0;
7780
7781////////////////////////////////////////////////////////////////////////////////////////////////////
7782// Start ROBUST or join the tmux session.
7783////////////////////////////////////////////////////////////////////////////////////////////////////
7784 if ((START == currentMode) && !checkSimIsRunning("ROBUST")) 8077 if ((START == currentMode) && !checkSimIsRunning("ROBUST"))
7785 { 8078 {
7786 char *d = xmprintf("%s.{right}", Ttab); 8079 char *d = xmprintf("%s.{right}", Ttab);
@@ -7794,136 +8087,8 @@ fcgiDone:
7794 free(c); 8087 free(c);
7795 doTmuxCmd("select-pane -t 0 -T 'ROBUST'", Tcmd, scRun, Tsocket); 8088 doTmuxCmd("select-pane -t 0 -T 'ROBUST'", Tcmd, scRun, Tsocket);
7796 8089
7797//////////////////////////////////////////////////////////////////////////////////////////////////// 8090 // Create all the tmux windows, panes, and temporary .ini files coz OpenSim sucketh.
7798// Create all the tmux windows, panes, and temporary .ini files, coz OpenSim sucketh. 8091 forEachSim("Prepping", prepSims);
7799////////////////////////////////////////////////////////////////////////////////////////////////////
7800 memset((void*)&obj0, 0, sizeof(obj0));
7801 ourSims->simsLua->lock(ourSims->simsLua);
7802 while(ourSims->simsLua->getnext(ourSims->simsLua, &obj0, false) == true)
7803 {
7804 q0 = obj0.data;
7805 char *type = "unsorted";
7806
7807 if (LUA_TTABLE == q0->type)
7808 {
7809 panes = 4;
7810 q1 = q0->v.t->get(q0->v.t, "number", NULL, false); if (NULL != q1) window = q1->v.f - 1;
7811 q1 = q0->v.t->get(q0->v.t, "panes", NULL, false); if (NULL != q1) panes = q1->v.f;
7812 q1 = q0->v.t->get(q0->v.t, "type", NULL, false); if (NULL != q1) type = q1->v.s;
7813 if (0 == panes)
7814 {
7815 pane = 2;
7816 window = 0;
7817 type = Ttab;
7818 }
7819 else if (0 != pane)
7820 {
7821 pane = 0;
7822 window++;
7823 }
7824
7825 V("Prepping sims of type %s, window %d, %d panes per window.", type, window, panes);
7826
7827 memset((void*)&obj1, 0, sizeof(obj1));
7828 q0->v.t->lock(q0->v.t);
7829 while(q0->v.t->getnext(q0->v.t, &obj1, false) == true)
7830 {
7831 q1 = obj1.data;
7832
7833 if ((strcmp("number", obj1.name) != 0) && (strcmp("panes", obj1.name) != 0) && (strcmp("type", obj1.name) != 0))
7834 {
7835 simData *simd = ourSims->byTab->get(ourSims->byTab, q1->v.s, NULL, false);
7836
7837 if (NULL == simd)
7838 E("Sim %s not found in ini list!", q1->v.s);
7839 else
7840 {
7841 char *path = xmprintf("%s/%s.shini", scEtc, simd->tab);
7842 char *newPath = xmprintf("%s/sim%d/%s.ini", scTemp, count, simd->tab); // Coz OpenSim.
7843 char *cmd;
7844
7845 simd->window = window;
7846 simd->pane = pane;
7847
7848 // The bash invocations are so that the PATH is properly propagated.
7849 if (0 == panes)
7850 doTmuxCmd("split-window -hp 50 -d -t '%s:0.1' bash", Tconsole);
7851 else if (0 == pane)
7852 {
7853 doTmuxCmd("new-window -dc '%s/current/bin' -n '%s' -t '%s:%d' bash", scRoot, type, Tconsole, window);
7854 if (2 <= panes)
7855 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.0' bash", Tconsole, window);
7856 if (4 <= panes)
7857 {
7858 doTmuxCmd("split-window -vp 50 -d -t '%s:%d.1' bash", Tconsole, window);
7859 doTmuxCmd("split-window -vp 50 -d -t '%s:%d.0' bash", Tconsole, window);
7860 }
7861 if (8 <= panes)
7862 {
7863 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.3' bash", Tconsole, window);
7864 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.2' bash", Tconsole, window);
7865 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.1' bash", Tconsole, window);
7866 doTmuxCmd("split-window -hp 50 -d -t '%s:%d.0' bash", Tconsole, window);
7867 }
7868 }
7869 snprintf(toybuf, sizeof(toybuf), "echo 'IDs={' >%s/IDs_%d.lua", scTemp, window);
7870 system(toybuf);
7871 doTmuxCmd("list-panes -t %d -F \"['%d #{pane_index}'] = '#{window_id}.#{pane_id}',\" >> %s/IDs_%d.lua", window, window, scTemp, window);
7872 snprintf(toybuf, sizeof(toybuf), "echo '}\nreturn IDs' >>%s/IDs_%d.lua", scTemp, window);
7873 system(toybuf);
7874
7875 snprintf(toybuf, sizeof(toybuf), "%s/IDs_%d.lua", scTemp, window);
7876 qtreetbl_t *IDs = Lua2tree(toybuf, "IDs");
7877 snprintf(toybuf, sizeof(toybuf), "%d %d", window, pane);
7878 simd->paneID = xmprintf("%s", qLuaGet(IDs, toybuf)->v.s);
7879 freeLuaTree(IDs);
7880
7881 simd->portH = 8004 + count * 2;
7882 simd->portU = 8005 + count * 2;
7883 cmd = xmprintf("rm -fr %s/sim%d; mkdir -p %s/sim%d; sed -E"
7884 " -e 's@\\[Region\\]@"
7885 " paneID = \"\\%s\"\\n"
7886 "\\[Startup\\]\\n"
7887 " PIDFile = \"\\$\\{Paths\\|CachePath\\}\\/\\$\\{Const\\|mysim\\}\\.pid\"\\n"
7888 " LogFile = \"\\$\\{Paths\\|LogPath\\}\\/OpenSim_\\$\\{Const\\|mysim\\}\\.log\"\\n"
7889 " StatsLogFile = \"\\$\\{Paths\\|LogPath\\}\\/OpenSimStats_\\$\\{Const\\|mysim\\}\\.log\"\\n"
7890 " ConsoleHistoryFile = \"\\$\\{Paths\\|LogPath\\}\\/OpenSimConsoleHistory_\\$\\{Const\\|mysim\\}\\.txt\"\\n"
7891 "\\n\\[Region\\]@'"
7892 " -e 's/InternalPort[[:space:]]*=[[:space:]]*[[:digit:]]+/InternalPort = %d/'"
7893 " -e 's/InternalPort[[:space:]]*=[[:space:]]*\"[[:digit:]]+\"/InternalPort = %d/'"
7894 " -e 's/http_listener_port[[:space:]]*=[[:space:]]*[[:digit:]]+/http_listener_port = %d/'"
7895 " -e 's/http_listener_port[[:space:]]*=[[:space:]]*\"[[:digit:]]+\"/http_listener_port = %d/'"
7896 " %s >%s",
7897 scTemp, count,
7898 scTemp, count,
7899 simd->paneID,
7900 simd->portU,
7901 simd->portU,
7902 simd->portH,
7903 simd->portH,
7904 path, newPath);
7905 D("Writing .ini file %s with ports %d %d", newPath, simd->portH, simd->portU);
7906 int j = system(cmd);
7907 if (!WIFEXITED(j))
7908 E("sed command failed!");
7909 free(cmd);
7910 free(newPath);
7911 free(path);
7912 count++;
7913 pane++;
7914 if (pane >= panes)
7915 {
7916 pane = 0;
7917 window++;
7918 }
7919 }
7920 }
7921 }
7922 q0->v.t->unlock(q0->v.t);
7923 }
7924 }
7925 ourSims->simsLua->unlock(ourSims->simsLua);
7926
7927 waitTmuxText(d, "INITIALIZATION COMPLETE FOR ROBUST"); 8092 waitTmuxText(d, "INITIALIZATION COMPLETE FOR ROBUST");
7928 I("ROBUST is done starting up."); 8093 I("ROBUST is done starting up.");
7929 free(d); 8094 free(d);
@@ -7934,269 +8099,17 @@ fcgiDone:
7934 doTmuxCmd("select-window -t '%s' \\; attach-session -t '%s'", Tconsole, Tconsole); 8099 doTmuxCmd("select-window -t '%s' \\; attach-session -t '%s'", Tconsole, Tconsole);
7935 goto finished; 8100 goto finished;
7936 } 8101 }
7937 else 8102 else // Find out where the sims are in tmux.
7938 { 8103 forEachSim(NULL, findSimsTmux);
7939 // Find out where the sims are in tmux.
7940 memset((void*)&obj0, 0, sizeof(obj0));
7941 ourSims->simsLua->lock(ourSims->simsLua);
7942 while(ourSims->simsLua->getnext(ourSims->simsLua, &obj0, false) == true)
7943 {
7944 q0 = obj0.data;
7945 char *type = "unsorted";
7946
7947 if (LUA_TTABLE == q0->type)
7948 {
7949 panes = 4;
7950 q1 = q0->v.t->get(q0->v.t, "number", NULL, false); if (NULL != q1) window = q1->v.f - 1;
7951 q1 = q0->v.t->get(q0->v.t, "panes", NULL, false); if (NULL != q1) panes = q1->v.f;
7952 q1 = q0->v.t->get(q0->v.t, "type", NULL, false); if (NULL != q1) type = q1->v.s;
7953 if (0 == panes)
7954 {
7955 pane = 2;
7956 window = 0;
7957 type = Ttab;
7958 }
7959 else if (0 != pane)
7960 {
7961 pane = 0;
7962 window++;
7963 }
7964
7965 memset((void*)&obj1, 0, sizeof(obj1));
7966 q0->v.t->lock(q0->v.t);
7967 while(q0->v.t->getnext(q0->v.t, &obj1, false) == true)
7968 {
7969 q1 = obj1.data;
7970
7971 if ((strcmp("number", obj1.name) != 0) && (strcmp("panes", obj1.name) != 0) && (strcmp("type", obj1.name) != 0))
7972 {
7973 simData *simd = ourSims->byTab->get(ourSims->byTab, q1->v.s, NULL, false);
7974
7975 if (NULL == simd)
7976 E("Sim %s not found in ini list!", q1->v.s);
7977 else
7978 {
7979 simd->window = window;
7980 simd->pane = pane;
7981
7982 char *newPath = xmprintf("%s/sim%d/%s.ini", scTemp, count, simd->tab); // Coz OpenSim.
7983
7984 snprintf(toybuf, sizeof(toybuf), "%s/IDs_%d.lua", scTemp, window);
7985 qtreetbl_t *IDs = Lua2tree(toybuf, "IDs");
7986 snprintf(toybuf, sizeof(toybuf), "%d %d", window, pane);
7987 simd->paneID = xmprintf("%s", qLuaGet(IDs, toybuf)->v.s);
7988 freeLuaTree(IDs);
7989 free(newPath);
7990 count++;
7991 pane++;
7992 if (pane >= panes)
7993 {
7994 pane = 0;
7995 window++;
7996 }
7997 }
7998 }
7999 }
8000 q0->v.t->unlock(q0->v.t);
8001 }
8002 }
8003 ourSims->simsLua->unlock(ourSims->simsLua);
8004 }
8005
8006
8007////////////////////////////////////////////////////////////////////////////////////////////////////
8008// Sim wrangling loop.
8009////////////////////////////////////////////////////////////////////////////////////////////////////
8010 count = 0; window = 0; panes = 4; pane = 0;
8011 memset((void*)&obj0, 0, sizeof(obj0));
8012 ourSims->simsLua->lock(ourSims->simsLua);
8013 while(ourSims->simsLua->getnext(ourSims->simsLua, &obj0, false) == true)
8014 {
8015 q0 = obj0.data;
8016 char *type = "unsorted";
8017
8018 if (LUA_TTABLE == q0->type)
8019 {
8020 panes = 4;
8021 q1 = q0->v.t->get(q0->v.t, "number", NULL, false); if (NULL != q1) window = q1->v.f - 1;
8022 q1 = q0->v.t->get(q0->v.t, "panes", NULL, false); if (NULL != q1) panes = q1->v.f;
8023 q1 = q0->v.t->get(q0->v.t, "type", NULL, false); if (NULL != q1) type = q1->v.s;
8024 if (0 == panes)
8025 {
8026 pane = 2;
8027 window = 0;
8028 type = Ttab;
8029 }
8030 else if (0 != pane)
8031 {
8032 pane = 0;
8033 window++;
8034 }
8035
8036 V("Doing sims of type %s, window %d, %d panes per window.", type, window, panes);
8037 memset((void*)&obj1, 0, sizeof(obj1));
8038 q0->v.t->lock(q0->v.t);
8039 while(q0->v.t->getnext(q0->v.t, &obj1, false) == true)
8040 {
8041 q1 = obj1.data;
8042
8043 if ((strcmp("number", obj1.name) != 0) && (strcmp("panes", obj1.name) != 0) && (strcmp("type", obj1.name) != 0))
8044 {
8045 simData *simd = ourSims->byTab->get(ourSims->byTab, q1->v.s, NULL, false);
8046
8047 if (NULL == simd)
8048 E("Sim %s not found in ini list!", 5);
8049 else
8050 {
8051 // Check if only doing a single sim.
8052 int cont = FALSE;
8053 if (NULL != target)
8054 {
8055 cont = TRUE;
8056 snprintf(toybuf, sizeof(toybuf), "%s.shini", simd->tab);
8057 if
8058 (
8059 (strcmp(target, q1->v.s) == 0) ||
8060 (strcmp(target, simd->name) == 0) ||
8061 (strcmp(target, simd->tab) == 0) ||
8062 (strcmp(target, toybuf) == 0)
8063 )
8064 cont = FALSE;
8065 snprintf(toybuf, sizeof(toybuf), "%s.ini", simd->tab);
8066 if (strcmp(target, toybuf) == 0)
8067 cont = FALSE;
8068 snprintf(toybuf, sizeof(toybuf), "sim%d.ini", count);
8069 if (strcmp(target, toybuf) == 0)
8070 cont = FALSE;
8071 }
8072 if (!cont)
8073 {
8074 switch (currentMode)
8075 {
8076 case START : // "start sim01" "start 'Welcome sim'" "start Welcome.ini" "start Welcome" "start" start everything
8077 {
8078 if (!checkSimIsRunning(simd->tab))
8079 {
8080 I("Tmux tab [%d:%s](pane %d) tmux ID %s, from %s/sim%d - %s is starting.", window, type, pane, simd->paneID, scTemp, count, simd->name);
8081 doTmuxCmd("select-pane -t %s:%s -T '%s'", Tconsole, simd->paneID, simd->tab);
8082 snprintf(toybuf, sizeof(toybuf), "mono OpenSim.exe -inidirectory=%s/sim%d", scTemp, count);
8083 sendTmuxCmd(simd->paneID, toybuf);
8084// TODO - some compromise, do a premptive load check if we are not doing a wait anyway.
8085 if (0 == doWait)
8086 {
8087// doTmuxCmd("select-window -t %s:%d", Tconsole, simd->window);
8088 snprintf(toybuf, sizeof(toybuf), "INITIALIZATION COMPLETE FOR %s", simd->name);
8089 waitTmuxText(simd->paneID, toybuf);
8090 I("%s is done starting up.", simd->name);
8091 la = waitLoadAverage(la, loadAverageInc, simTimeOut);
8092 if (1 < bulkSims)
8093 bulkSims = bulkSims / 2;
8094 }
8095 doWait = ((count + 1) % bulkSims);
8096 }
8097 break;
8098 }
8099
8100 case BACKUP : // "backup 'onefang rejected'" "backup sim01" "backup 'Welcome Sim'" "backup" backup everything
8101 { // TODO - If it's not a sim code, and not a sim name, it's an account inventory.
8102 if (checkSimIsRunning(simd->tab))
8103 {
8104 struct timeval tv;
8105 time_t curtime;
8106 char date[DATE_TIME_LEN];
8107
8108// TODO - should collect names of existing backups, both tmux / ini name and proper name.
8109// Scan backups directory once before this for loop, add details to sims list.
8110// strip off the last bit of file name (YYYY-mm-dd_HH:MM:SS.oar) to get the name
8111// keep in mind some old files had munged names like "Tiffanie_s_Paradise-2021-06-23_05:11:38.oar"
8112 gettimeofday(&tv, NULL);
8113 curtime = tv.tv_sec;
8114 strftime(date, DATE_TIME_LEN, "%F_%T", localtime(&curtime));
8115 I("%s is being backed up to %s/backups/%s-%s.oar.", simd->name, scRoot, simd->tab, date);
8116 snprintf(toybuf, sizeof(toybuf), "save oar --all %s/backups/%s-%s.oar", scRoot, simd->tab, date);
8117 sendTmuxCmd(simd->paneID, toybuf);
8118// if (0 == doWait)
8119 {
8120 memset(toybuf, 0, sizeof(toybuf));
8121 snprintf(toybuf, sizeof(toybuf), "Finished writing out OAR for %s", simd->name);
8122 waitTmuxText(cmd, toybuf);
8123 I("%s is done backing up.", simd->name);
8124// TODO - should delete / gitAR the old ones now.
8125// Have a config option for delete / gitAR.
8126 la = waitLoadAverage(la, loadAverageInc, simTimeOut);
8127 }
8128 }
8129 break;
8130 }
8131
8132 case CREATE : // "create name x,y size"
8133 {
8134 break;
8135 }
8136
8137 case GITAR : // "gitAR i name" "gitAR o name"
8138 {
8139 break;
8140 }
8141
8142 case STATUS :
8143 {
8144 break;
8145 }
8146
8147 case STOP : // "stop sim01" "stop 'Welcome Sim'" "stop" stop everything
8148 {
8149 if (checkSimIsRunning(simd->tab))
8150 {
8151 // Leave empty panes as is.
8152 sendTmuxCmd(simd->paneID, "quit");
8153 // There's three things that might happen -
8154 // Sim will quit, tmux pane will go away before we can see the shutdown message.
8155 // pane-exited hook might be useful here.
8156 // Sim will quit, tmux pane wont go away. Dunno yet if waitTmuxText() will still work.
8157 // pane-died hook might be useful here.
8158 // Sim fails to quit, error message on the pane that we want to read, wont see the shutdown message.
8159 // Also sim might not have finished starting up, and may even not be accepting comands yet.
8160// TODO - cater for and test them all.
8161 // Could also loop on checkSimIsRunning(sim)
8162// snprintf(toybuf, sizeof(toybuf), "[SHUTDOWN]: Shutdown processing on main thread complete. Exiting...");
8163// waitTmuxText(nm, toybuf);
8164// I("%s is done stopping.", simd->name);
8165// la = waitLoadAverage(la, loadAverageInc, simTimeOut);
8166 }
8167 break;
8168 }
8169
8170 default :
8171 {
8172 E("Unknown command! %s", toys.optargs[0]);
8173 break;
8174 }
8175 }
8176 }
8177
8178 }
8179
8180 count++;
8181 pane++;
8182 if (pane >= panes)
8183 {
8184 pane = 0;
8185 window++;
8186 }
8187 }
8188 }
8189 q0->v.t->unlock(q0->v.t);
8190 }
8191 }
8192 ourSims->simsLua->unlock(ourSims->simsLua);
8193 8104
8105 // Do stuff with the sims.
8106 forEachSim("Doing", doSimsThing);
8194 8107
8195 if (START == currentMode) 8108 if (START == currentMode)
8196 { 8109 {
8197 if (checkSimIsRunning("ROBUST") && (NULL == target)) 8110 if (checkSimIsRunning("ROBUST") && (NULL == ourSims->target))
8198 { 8111 {
8199 // Start up the web stuff. TODO - remove this once we handle the fcgi stuff ourselves. 8112 // TODO - remove this once we handle the fcgi stuff ourselves.
8200 I("Starting the web stuff."); 8113 I("Starting the web stuff.");
8201 char *c = xmprintf("spawn-fcgi -n -u %s -s %s/sledjchisl.socket -M 0660 -G www-data -- " 8114 char *c = xmprintf("spawn-fcgi -n -u %s -s %s/sledjchisl.socket -M 0660 -G www-data -- "
8202 "/usr/bin/valgrind --leak-check=full sledjchisl", 8115 "/usr/bin/valgrind --leak-check=full sledjchisl",
@@ -8207,85 +8120,27 @@ fcgiDone:
8207 else 8120 else
8208 I("NOT Starting the web stuff."); 8121 I("NOT Starting the web stuff.");
8209 } 8122 }
8210 else if ((STOP == currentMode) && (NULL == target)) 8123 else if ((STOP == currentMode) && (NULL == ourSims->target))
8211 { 8124 {
8212 memset((void*)&obj0, 0, sizeof(obj0)); 8125 // Stop all the sims.
8213 ourSims->simsLua->lock(ourSims->simsLua); 8126 forEachSim(NULL, stopSims);
8214 while(ourSims->simsLua->getnext(ourSims->simsLua, &obj0, false) == true) 8127 I("Closing all the other windows.");
8215 { 8128 // First figure out what panes and windows are left.
8216 q0 = obj0.data;
8217 char *type = "unsorted";
8218
8219 if (LUA_TTABLE == q0->type)
8220 {
8221 panes = 4;
8222 q1 = q0->v.t->get(q0->v.t, "number", NULL, false); if (NULL != q1) window = q1->v.f - 1;
8223 q1 = q0->v.t->get(q0->v.t, "panes", NULL, false); if (NULL != q1) panes = q1->v.f;
8224 q1 = q0->v.t->get(q0->v.t, "type", NULL, false); if (NULL != q1) type = q1->v.s;
8225 if (0 == panes)
8226 {
8227 pane = 2;
8228 window = 0;
8229 type = Ttab;
8230 }
8231 else if (0 != pane)
8232 {
8233 pane = 0;
8234 window++;
8235 }
8236
8237 memset((void*)&obj1, 0, sizeof(obj1));
8238 q0->v.t->lock(q0->v.t);
8239 while(q0->v.t->getnext(q0->v.t, &obj1, false) == true)
8240 {
8241 q1 = obj1.data;
8242
8243 if ((strcmp("number", obj1.name) != 0) && (strcmp("panes", obj1.name) != 0) && (strcmp("type", obj1.name) != 0))
8244 {
8245 simData *simd = ourSims->byTab->get(ourSims->byTab, q1->v.s, NULL, false);
8246
8247 if (NULL == simd)
8248 E("Sim %s not found in ini list!", q1->v.s);
8249 else
8250 {
8251 // NOTE - these sleeps are guesses, seems to work on my super desktop during testing.
8252 while (checkSimIsRunning(simd->tab))
8253 usleep(100000);
8254 usleep(10000);
8255 doTmuxCmd("kill-pane -t %s", simd->paneID);
8256 I("Tmux tab [%d:%s](pane %d) tmux ID %s, from %s/sim%d - %s has stopped.", window, type, pane, simd->paneID, scTemp, count, simd->name);
8257
8258 count++;
8259 pane++;
8260 if (pane >= panes)
8261 {
8262 pane = 0;
8263 window++;
8264 }
8265 }
8266 }
8267 }
8268 q0->v.t->unlock(q0->v.t);
8269 }
8270 }
8271 ourSims->simsLua->unlock(ourSims->simsLua);
8272
8273 // Kill the rest of the panes that are not on the original window.
8274 I("Closing all the panes.");
8275 snprintf(toybuf, sizeof(toybuf), "echo 'IDs={' >%s/IDs_ALL.lua", scTemp); 8129 snprintf(toybuf, sizeof(toybuf), "echo 'IDs={' >%s/IDs_ALL.lua", scTemp);
8276 system(toybuf); 8130 system(toybuf);
8277 doTmuxCmd("list-panes -s -F '\"#{window_id}.#{pane_id}\",' >> %s/IDs_ALL.lua", scTemp); 8131 doTmuxCmd("list-panes -s -F '\"#{window_id}.#{pane_id}\",' >> %s/IDs_ALL.lua", scTemp);
8278 snprintf(toybuf, sizeof(toybuf), "echo '}\nreturn IDs' >>%s/IDs_ALL.lua", scTemp); 8132 snprintf(toybuf, sizeof(toybuf), "echo '}\nreturn IDs' >>%s/IDs_ALL.lua", scTemp);
8279 system(toybuf); 8133 system(toybuf);
8280
8281 snprintf(toybuf, sizeof(toybuf), "%s/IDs_ALL.lua", scTemp); 8134 snprintf(toybuf, sizeof(toybuf), "%s/IDs_ALL.lua", scTemp);
8282 qtreetbl_t *IDs = Lua2tree(toybuf, "IDs"); 8135 qtreetbl_t *IDs = Lua2tree(toybuf, "IDs");
8283 8136
8137 qtreetbl_obj_t obj0;
8284 memset((void*)&obj0, 0, sizeof(obj0)); 8138 memset((void*)&obj0, 0, sizeof(obj0));
8285 IDs->lock(IDs); 8139 IDs->lock(IDs);
8286 while(IDs->getnext(IDs, &obj0, false) == true) 8140 while(IDs->getnext(IDs, &obj0, false) == true)
8287 { 8141 {
8288 q0 = obj0.data; 8142 qLua *q0 = obj0.data;
8143
8289 if ('0' != q0->v.s[1]) 8144 if ('0' != q0->v.s[1])
8290 doTmuxCmd("kill-pane -t %s", q0->v.s); 8145 doTmuxCmd("kill-pane -t %s", q0->v.s);
8291 } 8146 }
@@ -8296,7 +8151,6 @@ fcgiDone:
8296 if (!WIFEXITED(system(c))) 8151 if (!WIFEXITED(system(c)))
8297 E("rm command failed! %s", c); 8152 E("rm command failed! %s", c);
8298 free(c); 8153 free(c);
8299
8300 } 8154 }
8301//////////////////////////////////////////////////////////////////////////////////////////////////// 8155////////////////////////////////////////////////////////////////////////////////////////////////////
8302// End of OpenSim wrangling section. 8156// End of OpenSim wrangling section.