MtnMCG

cluster control

Sep 6th, 2024 (edited)
50
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.04 KB | None | 0 0
  1. -- Control Computer Program
  2.  
  3. local modem = peripheral.find("modem") or error("No modem found")
  4. modem.open(1) -- Open channel 1 for communication
  5.  
  6. local nodes = {}
  7. local fileMap = {}
  8.  
  9. -- Function to save the file map
  10. local function saveFileMap()
  11. local file = io.open("/fragment.txt", "w")
  12. file:write(textutils.serialize(fileMap))
  13. file:close()
  14. end
  15.  
  16. -- Function to load the file map
  17. local function loadFileMap()
  18. local file = io.open("/fragment.txt", "r")
  19. if file then
  20. fileMap = textutils.unserialize(file:read("*all"))
  21. file:close()
  22. end
  23. end
  24.  
  25. -- Function to discover storage nodes
  26. local function discoverNodes()
  27. print("Discovering storage nodes...")
  28. modem.transmit(1, 1, {type = "discovery"})
  29. local timer = os.startTimer(5)
  30. local discoveredNodes = {}
  31. while true do
  32. local event, param1, param2, param3, param4, param5 = os.pullEvent()
  33. if event == "modem_message" and param4.type == "discovery_response" then
  34. table.insert(discoveredNodes, param4.id)
  35. print("Discovered node: " .. param4.id)
  36. elseif event == "timer" and param1 == timer then
  37. break
  38. end
  39. end
  40. return discoveredNodes
  41. end
  42.  
  43. -- Function to send a request to a node
  44. local function sendRequest(nodeId, request)
  45. modem.transmit(1, 1, request)
  46. local timer = os.startTimer(5)
  47. while true do
  48. local event, param1, param2, param3, param4, param5 = os.pullEvent()
  49. if event == "modem_message" and param4.id == request.id then
  50. return param4.response
  51. elseif event == "timer" and param1 == timer then
  52. error("Request timed out for node: " .. nodeId)
  53. end
  54. end
  55. end
  56.  
  57. -- Function to distribute a file across nodes
  58. local function distributeFile(path, content)
  59. local chunkSize = math.ceil(#content / #nodes)
  60. local chunks = {}
  61. for i, nodeId in ipairs(nodes) do
  62. local start = (i - 1) * chunkSize + 1
  63. local chunk = content:sub(start, math.min(start + chunkSize - 1, #content))
  64. chunks[i] = chunk
  65. local response = sendRequest(nodeId, {
  66. id = os.getComputerID() .. "_" .. os.clock(),
  67. action = "write",
  68. path = path .. "_chunk_" .. i,
  69. content = chunk
  70. })
  71. if not response.success then
  72. error("Failed to write chunk " .. i .. " to node " .. nodeId)
  73. end
  74. end
  75. fileMap[path] = {chunks = #nodes, size = #content, nodeMap = nodes}
  76. saveFileMap()
  77. end
  78.  
  79. -- Function to read a file from nodes
  80. local function readFile(path)
  81. if not fileMap[path] then
  82. error("File not found: " .. path)
  83. end
  84. local content = ""
  85. for i, nodeId in ipairs(fileMap[path].nodeMap) do
  86. local response = sendRequest(nodeId, {
  87. id = os.getComputerID() .. "_" .. os.clock(),
  88. action = "read",
  89. path = path .. "_chunk_" .. i
  90. })
  91. if response.success then
  92. content = content .. response.content
  93. else
  94. error("Failed to read chunk " .. i .. " from node " .. nodeId)
  95. end
  96. end
  97. return content
  98. end
  99.  
  100. -- Function to delete a file from nodes
  101. local function deleteFile(path)
  102. if not fileMap[path] then
  103. error("File not found: " .. path)
  104. end
  105. for i, nodeId in ipairs(fileMap[path].nodeMap) do
  106. local response = sendRequest(nodeId, {
  107. id = os.getComputerID() .. "_" .. os.clock(),
  108. action = "delete",
  109. path = path .. "_chunk_" .. i
  110. })
  111. if not response.success then
  112. error("Failed to delete chunk " .. i .. " from node " .. nodeId)
  113. end
  114. end
  115. fileMap[path] = nil
  116. saveFileMap()
  117. end
  118.  
  119. -- Function to list files in a directory
  120. local function listFiles(path)
  121. local files = {}
  122. for file, _ in pairs(fileMap) do
  123. if file:sub(1, #path) == path then
  124. local name = file:sub(#path + 1)
  125. local firstSlash = name:find("/")
  126. if firstSlash then
  127. name = name:sub(1, firstSlash - 1)
  128. end
  129. if not files[name] then
  130. files[name] = true
  131. end
  132. end
  133. end
  134. return keys(files)
  135. end
  136.  
  137. -- Discover storage nodes
  138. nodes = discoverNodes()
  139.  
  140. if #nodes == 0 then
  141. error("No storage nodes found. Make sure the storage nodes are running and connected.")
  142. end
  143.  
  144. print("Found " .. #nodes .. " storage node(s)")
  145.  
  146. loadFileMap()
  147.  
  148. -- Override the entire fs API
  149. local oldFS = fs
  150. fs = {}
  151.  
  152. function fs.list(path)
  153. print("DEBUG: Listing directory: " .. path)
  154. return listFiles(path)
  155. end
  156.  
  157. function fs.exists(path)
  158. print("DEBUG: Checking if exists: " .. path)
  159. return fileMap[path] ~= nil
  160. end
  161.  
  162. function fs.isDir(path)
  163. print("DEBUG: Checking if directory: " .. path)
  164. return #listFiles(path) > 0
  165. end
  166.  
  167. function fs.isReadOnly(path)
  168. print("DEBUG: Checking if read-only: " .. path)
  169. return false
  170. end
  171.  
  172. function fs.getSize(path)
  173. print("DEBUG: Getting size of: " .. path)
  174. return fileMap[path] and fileMap[path].size or 0
  175. end
  176.  
  177. function fs.getFreeSpace(path)
  178. print("DEBUG: Getting free space")
  179. return math.huge
  180. end
  181.  
  182. function fs.makeDir(path)
  183. print("DEBUG: Making directory: " .. path)
  184. -- Directories are implicit, so we don't need to do anything
  185. end
  186.  
  187. function fs.move(fromPath, toPath)
  188. print("DEBUG: Moving from " .. fromPath .. " to " .. toPath)
  189. if fileMap[fromPath] then
  190. fileMap[toPath] = fileMap[fromPath]
  191. fileMap[fromPath] = nil
  192. saveFileMap()
  193. else
  194. error("Source file does not exist")
  195. end
  196. end
  197.  
  198. function fs.copy(fromPath, toPath)
  199. print("DEBUG: Copying from " .. fromPath .. " to " .. toPath)
  200. if fileMap[fromPath] then
  201. local content = readFile(fromPath)
  202. distributeFile(toPath, content)
  203. else
  204. error("Source file does not exist")
  205. end
  206. end
  207.  
  208. function fs.delete(path)
  209. print("DEBUG: Deleting: " .. path)
  210. deleteFile(path)
  211. end
  212.  
  213. function fs.open(path, mode)
  214. print("DEBUG: Opening file: " .. path .. " with mode: " .. mode)
  215. if mode == "r" then
  216. local content = readFile(path)
  217. local position = 1
  218. return {
  219. read = function()
  220. if position > #content then return nil end
  221. local char = content:sub(position, position)
  222. position = position + 1
  223. return char:byte()
  224. end,
  225. readLine = function()
  226. local line = ""
  227. while position <= #content do
  228. local char = content:sub(position, position)
  229. position = position + 1
  230. if char == "\n" then break end
  231. line = line .. char
  232. end
  233. return #line > 0 and line or nil
  234. end,
  235. readAll = function() return content end,
  236. close = function() end
  237. }
  238. elseif mode == "w" or mode == "a" then
  239. local buffer = ""
  240. return {
  241. write = function(str) buffer = buffer .. str end,
  242. writeLine = function(str) buffer = buffer .. str .. "\n" end,
  243. flush = function() distributeFile(path, buffer) end,
  244. close = function() distributeFile(path, buffer) end
  245. }
  246. end
  247. end
  248.  
  249. -- Override io functions
  250. local oldIO = io
  251. io = {}
  252.  
  253. function io.open(path, mode)
  254. print("DEBUG: IO Opening file: " .. path .. " with mode: " .. mode)
  255. return fs.open(path, mode)
  256. end
  257.  
  258. -- Create a sandbox environment
  259. local sandbox = setmetatable({}, {__index = _G})
  260. sandbox.fs = fs
  261. sandbox.io = io
  262.  
  263. -- Override shell commands
  264. local oldShell = shell
  265. sandbox.shell = setmetatable({}, {__index = oldShell})
  266.  
  267. function sandbox.shell.run(...)
  268. local args = {...}
  269. print("DEBUG: Running command: " .. table.concat(args, " "))
  270. return oldShell.run(...)
  271. end
  272.  
  273. -- Set up the new environment
  274. setfenv(1, sandbox)
  275.  
  276. -- Run the shell with the overridden APIs
  277. shell.run("rom/programs/shell")
Advertisement
Add Comment
Please, Sign In to add comment