Skip to content

Commit

Permalink
Trying to find a bug where the database gets locked and never unlocks…
Browse files Browse the repository at this point in the history
… again.
  • Loading branch information
GwynethLlewelyn committed Jul 23, 2017
1 parent 3682877 commit c0bb36d
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 42 deletions.
14 changes: 11 additions & 3 deletions backoffice.go
Original file line number Diff line number Diff line change
Expand Up @@ -535,13 +535,20 @@ func backofficeCommandsExec(w http.ResponseWriter, r *http.Request) {
content += "<p></p><h3>In-world results:</h3>"

// prepare the call to the agent (OpenSimulator NPC)
// HTTP request as per http://moazzam-khan.com/blog/golang-make-http-requests/
body := []byte("command=" + r.Form.Get("command") + "&" +
body := "command=" + r.Form.Get("command") + "&" +
r.Form.Get("param1") + "=" + r.Form.Get("data1") + "&" +
r.Form.Get("param2") + "=" + r.Form.Get("data2"))
r.Form.Get("param2") + "=" + r.Form.Get("data2")

rsBody, err := callURL(r.Form.Get("PermURL"), body)
if (err != nil) {
content += "<p class=\"text-danger\">" + rsBody + "</p>"
} else {
content += "<p class=\"text-success\">" + rsBody + "</p>"
}

log.Printf("Sending to in-world object %s ... %s\n", r.Form.Get("PermURL"), body) // debug

/*
rs, err := http.Post(r.Form.Get("PermURL"), "body/type", bytes.NewBuffer(body))
// Code to process response (written in Get request snippet) goes here
Expand All @@ -556,6 +563,7 @@ func backofficeCommandsExec(w http.ResponseWriter, r *http.Request) {
log.Printf("Reply from in-world object %s\n", rsBody)
content += "<p class=\"text-success\">" + string(rsBody) + "</p>"
}
*/

tplParams := templateParameters{ "Title": "Gobot Administrator Panel - Commands Exec Result",
"Preamble": template.HTML("<p>Results coming from in-world object:</p>"),
Expand Down
77 changes: 45 additions & 32 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@
package main

import (
_ "github.com/mattn/go-sqlite3"
"bytes"
"database/sql"
"encoding/json"
"fmt"
_ "github.com/mattn/go-sqlite3"
"golang.org/x/net/websocket"
"gopkg.in/guregu/null.v3/zero"
"html/template"
"io/ioutil"
"log"
"net/http"
"time"
"html/template"
"golang.org/x/net/websocket"
"strings"
"encoding/json"
"gopkg.in/guregu/null.v3/zero"
"sync/atomic" // used for sync'ing values across goroutines at a low level
"time"
)

// Define a communications procotol with the client, so that we can selectively
Expand Down Expand Up @@ -158,7 +160,7 @@ func backofficeEngine(w http.ResponseWriter, r *http.Request) {
rows, err = db.Query("SELECT Name, OwnerKey, Location, Position FROM Agents ORDER BY Name")
checkErr(err)

defer rows.Close()
// defer rows.Close() // already deferred above

var ownerKey, agentNames = "", ""

Expand All @@ -172,6 +174,7 @@ func backofficeEngine(w http.ResponseWriter, r *http.Request) {
agentNames += fmt.Sprintf("\t\t\t\t\t\t\t\t\t\t\t\t\t<option value=\"%s\">%s (%s) [%s (%s,%s,%s)]</option>\n", ownerKey, name, ownerKey, regionName, xyz)
}

rows.Close() // closing after deferring to close is probably not good, but I'll try it anyway (20170723)
db.Close()

tplParams := templateParameters{ "Title": "Gobot Administrator Panel - engine",
Expand Down Expand Up @@ -301,11 +304,15 @@ func engine() {
db, err := sql.Open(PDO_Prefix, SQLiteDBFilename)
checkErr(err)

defer db.Close() // needed?

// load in Agents! We need them to call the movement algorithm for each one
// BUG(gwyneth): what if the number of agents _change_ while we're running the engine? We need a way to reset the engine somehow. We have a hack at the moment: send a SIGCONT, it will try to restart the engine in a new goroutine
rows, err := db.Query("SELECT * FROM Agents ORDER BY Name") // can't hurt much to let the DB engine sort it, that way we humans have an idea on how far we've progressed when adding agents
checkErr(err)

defer rows.Close() // needed?

for rows.Next() {
err = rows.Scan(
&Agent.UUID,
Expand Down Expand Up @@ -352,13 +359,14 @@ func engine() {
// We need to refresh all the data about cubes and positions again!

// do stuff while it runs, e.g. open databases, search for agents and so forth

/*
log.Println("Reloading database for Cubes (Positions) and Obstacles...")
// Open database
db, err = sql.Open(PDO_Prefix, SQLiteDBFilename)
checkErr(err)
defer db.Close() // needed?
// Load in the 'special' objects (cubes). Because the Master Controllers can be somewhere in here, to save code.
// and a database query, we simply skip all the Master Controllers until we get the most recent one, which gets saved
Expand All @@ -369,6 +377,8 @@ func engine() {
rows, err = db.Query("SELECT * FROM Positions ORDER BY LastUpdate ASC")
checkErr(err)
defer rows.Close() // needed?
for rows.Next() {
err = rows.Scan(
&Position.PermURL,
Expand Down Expand Up @@ -425,35 +435,17 @@ func engine() {
Objects = append(Objects, Object)
}
// Debug stuff. Delete it after usage.
/*
var marshalled []byte = []byte("Kablooie! JSON blew up everything! No data available...")
marshalled, err = json.MarshalIndent(Objects, "", " ")
checkErr(err)
log.Println("Objects", marshalled)
sendMessageToBrowser("status", "info", fmt.Sprintf("Objects: %s<br />", marshalled), "")
marshalled, err = json.MarshalIndent(Agents, "", " ")
checkErr(err)
log.Println("Agents", marshalled)
sendMessageToBrowser("status", "info", fmt.Sprintf("Agents: %s<br />", marshalled ), "")
marshalled, err = json.MarshalIndent(Cubes, "", " ")
checkErr(err)
log.Println("Cubes", marshalled)
sendMessageToBrowser("status", "info", fmt.Sprintf("Cubes: %s<br />", marshalled), "")
marshalled, err = json.MarshalIndent(masterController, "", " ")
checkErr(err)
log.Println("Master Bot Controller", marshalled)
sendMessageToBrowser("status", "info", fmt.Sprintf("Master Bot Controller: %s<br />", marshalled), "")
*/
// debugging stuff ends here

// release DB resources before we start our job
rows.Close()
db.Close()
// Do not trust the database with the exact Agent position: ask the master controller directly
log.Println(*masterController.PermURL.Ptr())

// log.Println(*masterController.PermURL.Ptr())
*/
log.Println(masterController, Position, Cubes, Object, Objects)
//curposResult, _ := callURL(*masterController.PermURL.Ptr(), "npc=" + *Agent.OwnerKey.Ptr() + "&command=osNpcGetPos");
//sendMessageToBrowser("status", "info", "<p class='box'>Grid reports that agent " + *Agent.Name.Ptr() + " is at position: " + curposResult + "</p>\n", "")
//log.Println("Grid reports that agent", *Agent.Name.Ptr(), "is at position:", curposResult)

// output something to console so that we know this is being run in parallel
fmt.Print("\r|")
Expand Down Expand Up @@ -499,4 +491,25 @@ func sendMessageToBrowser(msgType string, msgSubType string, msgText string, msg
case <-time.After(time.Second * 10):
fmt.Println("timeout after 10 seconds; coudn't send:", string(marshalled))
}
}

// callURL encapsulates a call to an URL. It exists as an analogy to the PHP version (20170723).
func callURL(url string, encodedRequest string) (string, error) {
// HTTP request as per http://moazzam-khan.com/blog/golang-make-http-requests/
body := []byte(encodedRequest)

rs, err := http.Post(url, "body/type", bytes.NewBuffer(body))
// Code to process response (written in Get request snippet) goes here

defer rs.Body.Close()

rsBody, err := ioutil.ReadAll(rs.Body)
if (err != nil) {
errMsg := fmt.Sprintf("Error response from in-world object: %s", err)
log.Println(errMsg)
return errMsg, err
} else {
log.Printf("Reply from in-world object %s\n", rsBody)
return string(rsBody), err
}
}
12 changes: 6 additions & 6 deletions gobot.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
package main

import (
_ "github.com/mattn/go-sqlite3"
"database/sql"
"fmt"
_ "github.com/mattn/go-sqlite3"
"github.com/Pallinder/go-randomdata"
"github.com/spf13/viper" // to read config files
"net/http"
"golang.org/x/net/websocket"
"log"
"os/user"
"path/filepath"
"net/http"
"os"
"os/signal"
"os/user"
"path/filepath"
"syscall"
"golang.org/x/net/websocket"
"github.com/Pallinder/go-randomdata"
)


Expand Down
1 change: 0 additions & 1 deletion inworld.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ func registerPosition(w http.ResponseWriter, r *http.Request) {
checkErrPanicHTTP(w, http.StatusServiceUnavailable, funcName() + ": Extracting parameters failed: %s\n", err)
log.Println("Received: ", r)


if r.Header.Get("X-Secondlife-Object-Key") == "" {
// fmt.Printf("Got '%s'\n", r.Header["X-Secondlife-Object-Key"])
logErrHTTP(w, http.StatusForbidden, funcName() + ": Not called from within the virtual world.")
Expand Down
5 changes: 5 additions & 0 deletions ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ func uiObjects(w http.ResponseWriter, r *http.Request) {
rowArr = append(rowArr, Object)
}
checkErr(err)
defer rows.Close()

// produces neatly indented output; see https://blog.golang.org/json-and-go but especially http://stackoverflow.com/a/37084385/1035977
if data, err := json.MarshalIndent(rowArr, "", " "); err != nil {
Expand Down Expand Up @@ -232,6 +233,7 @@ func uiAgents(w http.ResponseWriter, r *http.Request) {
rowArr = append(rowArr, Agent)
}
checkErr(err)
defer rows.Close()

if data, err := json.MarshalIndent(rowArr, "", " "); err != nil {
checkErr(err)
Expand Down Expand Up @@ -343,6 +345,7 @@ func uiPositions(w http.ResponseWriter, r *http.Request) {
rowArr = append(rowArr, Position)
}
checkErr(err)
defer rows.Close()

if data, err := json.MarshalIndent(rowArr, "", " "); err != nil {
checkErr(err)
Expand Down Expand Up @@ -432,6 +435,7 @@ func uiInventory(w http.ResponseWriter, r *http.Request) {
rowArr = append(rowArr, Inventory)
}
checkErr(err)
defer rows.Close()

if data, err := json.MarshalIndent(rowArr, "", " "); err != nil {
checkErr(err)
Expand Down Expand Up @@ -514,6 +518,7 @@ func uiUserManagement(w http.ResponseWriter, r *http.Request) {
rowArr = append(rowArr, UserManagement)
}
checkErr(err)
defer rows.Close()

if data, err := json.MarshalIndent(rowArr, "", " "); err != nil {
checkErr(err)
Expand Down

0 comments on commit c0bb36d

Please sign in to comment.