This commit is contained in:
NatureFreshMilk 2019-03-21 15:07:09 +01:00
parent 5da2b5b7b9
commit fba3f118d8
10 changed files with 274 additions and 2 deletions

View File

@ -9,3 +9,10 @@
* Point your browser to `http://127.0.0.1:8080`
For additional infos (lag,time,players => active mode) on the mapserver interface you should install the [mapserver-mod](mod.md)
## Performance / Scalability
For small to medium setups the default values should suffice.
If you have a bigger map (say: above 10 GB) you should configure the mapserver accordingly:
* See [Mapobject-Database](./mapobjectdb.md) for a scalable mapserver database

14
doc/mapobjectdb.md Normal file
View File

@ -0,0 +1,14 @@
# Mapobject-Database
The mapobject database is for all the mapobjects (POI, Shops, etc)
Per default it is initialized as a sqlite3 database in `mapserver.sqlite3`
If you want to store your mapobjects in a proper database or need performance at
scale you can configure a postgresql server in your `world.mt`:
```
pgsql_mapserver_connection = host=127.0.0.1 port=5432 user=postgres password=enter dbname=postgres
```
The syntax is the same as for `pgsql_connection`

View File

@ -7,6 +7,7 @@ import (
"mapserver/eventbus"
"mapserver/mapblockaccessor"
"mapserver/mapblockrenderer"
postgresobjdb "mapserver/mapobjectdb/postgres"
sqliteobjdb "mapserver/mapobjectdb/sqlite"
"mapserver/params"
"mapserver/settings"
@ -108,8 +109,7 @@ func Setup(p params.ParamsType, cfg *Config) *App {
//mapserver database
if a.Worldconfig[worldconfig.CONFIG_PSQL_MAPSERVER] != "" {
//TODO: Psql connection
a.Objectdb, err = postgresobjdb.New(a.Worldconfig[worldconfig.CONFIG_PSQL_MAPSERVER])
} else {
a.Objectdb, err = sqliteobjdb.New("mapserver.sqlite")
}

View File

@ -0,0 +1,11 @@
package postgres
import (
"github.com/sirupsen/logrus"
)
var log *logrus.Entry
func init() {
log = logrus.WithFields(logrus.Fields{"prefix": "mapobjectdb.postgres"})
}

View File

@ -0,0 +1,98 @@
package postgres
import (
"mapserver/coords"
"mapserver/mapobjectdb"
)
func (db *PostgresAccessor) GetMapData(q *mapobjectdb.SearchQuery) ([]*mapobjectdb.MapObject, error) {
rows, err := db.db.Query(getMapDataPosQuery,
q.Type,
q.Pos1.X, q.Pos1.Y, q.Pos1.Z,
q.Pos2.X, q.Pos2.Y, q.Pos2.Z,
)
if err != nil {
return nil, err
}
defer rows.Close()
result := make([]*mapobjectdb.MapObject, 0)
var currentObj *mapobjectdb.MapObject
var currentId *int64
for rows.Next() {
var id int64
var Type string
var mtime int64
var x, y, z int
var posx, posy, posz int
var key, value string
err = rows.Scan(&id, &Type, &mtime,
&x, &y, &z, &posx, &posy, &posz,
&key, &value,
)
if err != nil {
return nil, err
}
if currentId == nil || *currentId != id {
pos := coords.NewMapBlockCoords(posx, posy, posz)
mo := &mapobjectdb.MapObject{
MBPos: pos,
Type: Type,
X: x,
Y: y,
Z: z,
Mtime: mtime,
Attributes: make(map[string]string),
}
currentObj = mo
currentId = &id
result = append(result, currentObj)
}
currentObj.Attributes[key] = value
}
return result, nil
}
func (db *PostgresAccessor) RemoveMapData(pos *coords.MapBlockCoords) error {
_, err := db.db.Exec(removeMapDataQuery, pos.X, pos.Y, pos.Z)
return err
}
func (db *PostgresAccessor) AddMapData(data *mapobjectdb.MapObject) error {
res, err := db.db.Exec(addMapDataQuery,
data.X, data.Y, data.Z,
data.MBPos.X, data.MBPos.Y, data.MBPos.Z,
data.Type, data.Mtime)
if err != nil {
return err
}
id, err := res.LastInsertId()
if err != nil {
return err
}
for k, v := range data.Attributes {
//TODO: batch insert
_, err := db.db.Exec(addMapDataAttributeQuery, id, k, v)
if err != nil {
return err
}
}
return nil
}

View File

@ -0,0 +1,26 @@
package postgres
import (
"database/sql"
"github.com/sirupsen/logrus"
"mapserver/vfs"
"time"
)
type PostgresAccessor struct {
db *sql.DB
}
func (db *PostgresAccessor) Migrate() error {
log.Info("Migrating database")
start := time.Now()
_, err := db.db.Exec(vfs.FSMustString(false, "/sql/postgres_mapobjectdb_migrate.sql"))
if err != nil {
return err
}
t := time.Now()
elapsed := t.Sub(start)
log.WithFields(logrus.Fields{"elapsed": elapsed}).Info("Migration completed")
return nil
}

View File

@ -0,0 +1,17 @@
package postgres
import (
"database/sql"
_ "github.com/mattn/go-sqlite3"
)
func New(connStr string) (*PostgresAccessor, error) {
db, err := sql.Open("postgres", connStr+" sslmode=disable")
if err != nil {
return nil, err
}
sq := &PostgresAccessor{db: db}
return sq, nil
}

View File

@ -0,0 +1,28 @@
package postgres
func (db *PostgresAccessor) GetSetting(key string, defaultvalue string) (string, error) {
rows, err := db.db.Query(getSettingQuery, key)
if err != nil {
return "", err
}
defer rows.Close()
value := defaultvalue
if rows.Next() {
err = rows.Scan(&value)
if err != nil {
return "", err
}
}
return value, nil
}
func (db *PostgresAccessor) SetSetting(key string, value string) error {
_, err := db.db.Exec(setSettingQuery, key, value)
return err
}

View File

@ -0,0 +1,41 @@
package postgres
const getMapDataPosQuery = `
select o.id, o.type, o.mtime,
o.x, o.y, o.z,
o.posx, o.posy, o.posz,
oa.key, oa.value
from objects o
left join object_attributes oa on o.id = oa.objectid
where o.type = $1
and o.posx >= $2 and o.posy >= $3 and o.posz >= $4
and o.posx <= $5 and o.posy <= $6 and o.posz <= $7
order by o.id
`
const removeMapDataQuery = `
delete from objects where posx = $1 and posy = $2 and posz = $3
`
const addMapDataQuery = `
insert into
objects(x,y,z,posx,posy,posz,type,mtime)
values($1, $2, $3, $4, $5, $6, $7, $8)
`
const addMapDataAttributeQuery = `
insert into
object_attributes(objectid, key, value)
values($1, $2, $3)
`
const getSettingQuery = `
select value from settings where key = $1
`
const setSettingQuery = `
insert into settings(key, value)
values($1, $2)
on conflict(key)
do update set value = EXCLUDED.value
`

View File

@ -0,0 +1,30 @@
create table if not exists objects(
id serial primary key,
x int,
y int,
z int,
posx int,
posy int,
posz int,
type varchar,
mtime bigint
);
create index if not exists objects_pos on objects(posx,posy,posz);
create index if not exists objects_pos_type on objects(posx,posy,posz,type);
create table if not exists object_attributes(
objectid integer not null,
key varchar not null,
value varchar not null,
FOREIGN KEY (objectid) references objects(id) ON DELETE CASCADE,
primary key(objectid, key)
);
create index if not exists object_attributes_key_value on object_attributes(key, value);
create table if not exists settings(
key varchar primary key not null,
value varchar not null
);