Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- ndisk.lua
- local modem = peripheral.find("modem") or error("No modem found")
- modem.open(1) -- Open channel 1 for communication
- local nodes = {}
- local chunkMap = {}
- -- Function to save the node IDs
- local function saveNodeIds()
- local file = fs.open("ids.txt", "w")
- for hierarchicalNum, nodeId in pairs(nodes) do
- file.writeLine(nodeId .. " " .. hierarchicalNum)
- end
- file.close()
- end
- -- Function to load the node IDs
- local function loadNodeIds()
- nodes = {}
- if fs.exists("ids.txt") then
- local file = fs.open("ids.txt", "r")
- for line in file.readLine do
- local nodeId, hierarchicalNum = line:match("(%d+)%s+(%d+)")
- if nodeId and hierarchicalNum then
- nodes[tonumber(hierarchicalNum)] = tonumber(nodeId)
- end
- end
- file.close()
- end
- end
- -- Function to save the chunk map
- local function saveChunkMap()
- local file = fs.open("chunklocation.txt", "w")
- for filename, chunks in pairs(chunkMap) do
- for chunkNum, nodeId in pairs(chunks) do
- file.writeLine(filename .. " chunk" .. chunkNum .. " " .. nodeId)
- end
- end
- file.close()
- end
- -- Function to load the chunk map
- local function loadChunkMap()
- chunkMap = {}
- if fs.exists("chunklocation.txt") then
- local file = fs.open("chunklocation.txt", "r")
- for line in file.readLine do
- local filename, chunk, nodeId = line:match("(%S+)%s+(%S+)%s+(%S+)")
- if filename and chunk and nodeId then
- chunkMap[filename] = chunkMap[filename] or {}
- local chunkNum = tonumber(chunk:match("chunk(%d+)"))
- chunkMap[filename][chunkNum] = tonumber(nodeId)
- end
- end
- file.close()
- end
- end
- -- Function to discover storage nodes
- local function discoverNodes()
- print("Discovering storage nodes...")
- modem.transmit(1, 1, {type = "discovery"})
- local timer = os.startTimer(5)
- local discoveredNodes = {}
- local nextHierarchicalNum = 1
- for num, _ in pairs(nodes) do
- if num > nextHierarchicalNum then
- nextHierarchicalNum = num + 1
- end
- end
- while true do
- local event, param1, param2, param3, param4, param5 = os.pullEvent()
- if event == "modem_message" and param4.type == "discovery_response" then
- local nodeId = param4.id
- local hierarchicalNum = nil
- for num, id in pairs(nodes) do
- if id == nodeId then
- hierarchicalNum = num
- break
- end
- end
- if not hierarchicalNum then
- hierarchicalNum = nextHierarchicalNum
- nodes[hierarchicalNum] = nodeId
- nextHierarchicalNum = nextHierarchicalNum + 1
- print("Discovered new node: " .. nodeId .. " (Hierarchical #" .. hierarchicalNum .. ")")
- else
- print("Rediscovered node: " .. nodeId .. " (Hierarchical #" .. hierarchicalNum .. ")")
- end
- discoveredNodes[nodeId] = hierarchicalNum
- elseif event == "timer" and param1 == timer then
- break
- end
- end
- saveNodeIds()
- return nodes
- end
- -- Function to send a request to a node
- local function sendRequest(nodeId, request)
- request.targetNode = nodeId
- modem.transmit(1, 1, request)
- local timer = os.startTimer(5)
- while true do
- local event, param1, param2, param3, param4, param5 = os.pullEvent()
- if event == "modem_message" and param4.id == request.id then
- return param4.response
- elseif event == "timer" and param1 == timer then
- error("Request timed out for node: " .. nodeId)
- end
- end
- end
- -- Function to distribute a file across nodes
- local function distributeFile(path, content)
- local nodeCount = 0
- for _ in pairs(nodes) do nodeCount = nodeCount + 1 end
- local chunkSize = math.ceil(#content / nodeCount)
- chunkMap[path] = {}
- local chunkNum = 1
- for hierarchicalNum, nodeId in pairs(nodes) do
- local start = (chunkNum - 1) * chunkSize + 1
- local chunk = content:sub(start, math.min(start + chunkSize - 1, #content))
- local response = sendRequest(nodeId, {
- id = os.getComputerID() .. "_" .. os.clock(),
- action = "write",
- path = path,
- chunk = chunkNum,
- content = chunk
- })
- if not response.success then
- error("Failed to write chunk " .. chunkNum .. " to node " .. nodeId)
- end
- chunkMap[path][chunkNum] = nodeId
- chunkNum = chunkNum + 1
- end
- saveChunkMap()
- end
- -- Function to read a file from nodes
- local function readFile(path)
- if not chunkMap[path] then
- error("File not found: " .. path)
- end
- local content = {}
- for chunkNum, nodeId in pairs(chunkMap[path]) do
- local response = sendRequest(nodeId, {
- id = os.getComputerID() .. "_" .. os.clock(),
- action = "read",
- path = path,
- chunk = chunkNum
- })
- if response.success then
- content[chunkNum] = response.content
- else
- error("Failed to read chunk " .. chunkNum .. " from node " .. nodeId)
- end
- end
- return table.concat(content)
- end
- -- Function to delete a file from nodes
- local function deleteFile(path)
- if not chunkMap[path] then
- error("File not found: " .. path)
- end
- for chunkNum, nodeId in pairs(chunkMap[path]) do
- local response = sendRequest(nodeId, {
- id = os.getComputerID() .. "_" .. os.clock(),
- action = "delete",
- path = path,
- chunk = chunkNum
- })
- if not response.success then
- error("Failed to delete chunk " .. chunkNum .. " from node " .. nodeId)
- end
- end
- chunkMap[path] = nil
- saveChunkMap()
- end
- -- Function to list files
- local function listFiles()
- local files = {}
- for file, _ in pairs(chunkMap) do
- table.insert(files, file)
- end
- return files
- end
- -- Function to get total storage space
- local function getTotalStorage()
- local total = 0
- for _, nodeId in pairs(nodes) do
- local response = sendRequest(nodeId, {
- id = os.getComputerID() .. "_" .. os.clock(),
- action = "getSpace"
- })
- if response.success then
- total = total + response.space
- end
- end
- return total
- end
- -- Main program
- loadNodeIds()
- nodes = discoverNodes()
- if next(nodes) == nil then
- error("No storage nodes found. Make sure the storage nodes are running and connected.")
- end
- print("Found " .. #nodes .. " storage node(s)")
- loadChunkMap()
- -- Command loop
- while true do
- write("ndisk> ")
- local input = read()
- local command = {}
- for word in input:gmatch("%S+") do
- table.insert(command, word)
- end
- if command[1] == "list" then
- local files = listFiles()
- for _, file in ipairs(files) do
- print(file)
- end
- elseif command[1] == "read" and command[2] then
- local content = readFile(command[2])
- print(content)
- elseif command[1] == "write" and command[2] then
- print("Enter file content (press Enter twice to finish):")
- local content = ""
- while true do
- local line = read()
- if line == "" then break end
- content = content .. line .. "\n"
- end
- distributeFile(command[2], content)
- print("File written successfully.")
- elseif command[1] == "delete" and command[2] then
- deleteFile(command[2])
- print("File deleted successfully.")
- elseif command[1] == "space" then
- local space = getTotalStorage()
- print("Total storage space: " .. space .. " bytes")
- elseif command[1] == "exit" then
- break
- else
- print("Unknown command. Available commands: list, read <filename>, write <filename>, delete <filename>, space, exit")
- end
- end
- print("Exiting ndisk.")
Advertisement
Add Comment
Please, Sign In to add comment