migrate from cassandra to postgres. all courses deleted

This commit is contained in:
Jonathan Barrow 2023-10-18 17:29:48 -04:00
parent 9a4497287b
commit 817703269b
No known key found for this signature in database
GPG Key ID: E86E9FE9049C741F
29 changed files with 296 additions and 335 deletions

View File

@ -1,5 +0,0 @@
package database
func ConnectAll() {
connectCassandra()
}

View File

@ -1,122 +0,0 @@
package database
import (
"flag"
"fmt"
"log"
"time"
"github.com/gocql/gocql"
)
var cluster *gocql.ClusterConfig
var cassandraClusterSession *gocql.Session
func connectCassandra() {
// Connect to Cassandra
var err error
cluster = gocql.NewCluster("127.0.0.1")
cluster.Timeout = 30 * time.Second
createKeyspace("pretendo_smm")
cluster.Keyspace = "pretendo_smm"
cassandraClusterSession, err = cluster.CreateSession()
if err != nil {
panic(err)
}
// Create tables if missing
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.courses (
data_id bigint PRIMARY KEY,
playable boolean,
owner_pid int,
name text,
size int,
creation_date bigint,
update_date bigint,
world_record_first_pid int,
world_record_pid int,
world_record_creation_date bigint,
world_record_update_date bigint,
world_record int,
meta_binary blob,
flag int,
extra_data list<text>,
data_type smallint,
period smallint
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.courses")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.ratings (
data_id bigint PRIMARY KEY,
stars counter,
attempts counter,
failures counter,
completions counter
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.ratings")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.buffer_queues (
id uuid PRIMARY KEY,
data_id bigint,
slot int,
buffer blob
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.buffer_queues")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.generator_last_id (
node_id int PRIMARY KEY,
last_id int
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.generator_last_id")
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`CREATE TABLE IF NOT EXISTS pretendo_smm.user_play_info (
pid int PRIMARY KEY,
starred_courses set<bigint>,
played_courses set<bigint>
)`).Exec(); err != nil {
fmt.Println("pretendo_smm.user_play_info")
log.Fatal(err)
}
fmt.Println("Connected to Cassandra")
}
// Adapted from gocql common_test.go
func createKeyspace(keyspace string) {
flagRF := flag.Int("rf", 1, "replication factor for pretendo_smm keyspace")
c := *cluster
c.Keyspace = "system"
c.Timeout = 30 * time.Second
s, err := c.CreateSession()
if err != nil {
panic(err)
}
defer s.Close()
if err := s.Query(fmt.Sprintf(`CREATE KEYSPACE IF NOT EXISTS %s
WITH replication = {
'class' : 'SimpleStrategy',
'replication_factor' : %d
}`, keyspace, *flagRF)).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@ -0,0 +1,24 @@
package database
import (
"database/sql"
"os"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
_ "github.com/lib/pq"
)
var Postgres *sql.DB
func ConnectPostgres() {
var err error
Postgres, err = sql.Open("postgres", os.Getenv("PN_SMM_POSTGRES_URI"))
if err != nil {
globals.Logger.Critical(err.Error())
}
globals.Logger.Success("Connected to Postgres!")
initPostgres()
}

View File

@ -1,9 +0,0 @@
package database
import "log"
func CreateDataStoreIDGeneratorRow(nodeID int) {
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.generator_last_id(node_id, last_id) VALUES (?, ?) IF NOT EXISTS`, nodeID, 0).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@ -1,19 +1,30 @@
package database
import "log"
import (
"database/sql"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func GetBufferQueueDeathData(dataID uint64) [][]byte {
pBufferQueue := make([][]byte, 0)
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT buffer FROM pretendo_smm.buffer_queues WHERE data_id=? AND slot=3 ALLOW FILTERING`, dataID).Iter().SliceMap(); err != nil {
log.Fatal(err)
rows, err := Postgres.Query(`SELECT buffer FROM pretendo_smm.buffer_queues WHERE data_id=$1 AND slot=3`, dataID)
if err != nil {
globals.Logger.Critical(err.Error())
return pBufferQueue
}
for _, bufferQueue := range sliceMap {
pBufferQueue = append(pBufferQueue, bufferQueue["buffer"].([]byte))
for rows.Next() {
var buffer []byte
err := rows.Scan(&buffer)
if err != nil && err != sql.ErrNoRows {
globals.Logger.Critical(err.Error())
return pBufferQueue
}
pBufferQueue = append(pBufferQueue, buffer)
}
return pBufferQueue

View File

@ -1,11 +1,11 @@
package database
import (
"database/sql"
"log"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
"github.com/gocql/gocql"
)
func GetCourseMetadataByDataID(dataID uint64) *types.CourseMetadata {
@ -19,10 +19,9 @@ func GetCourseMetadataByDataID(dataID uint64) *types.CourseMetadata {
var dataType uint16
var period uint16
err := cassandraClusterSession.Query(`SELECT owner_pid, size, name, meta_binary, flag, creation_date, update_date, data_type, period FROM pretendo_smm.courses WHERE data_id=?`, dataID).Scan(&ownerPID, &size, &name, &metaBinary, &flag, &createdTime, &updatedTime, &dataType, &period)
err := Postgres.QueryRow(`SELECT owner_pid, size, name, meta_binary, flag, creation_date, update_date, data_type, period FROM pretendo_smm.courses WHERE data_id=$1`, dataID).Scan(&ownerPID, &size, &name, &metaBinary, &flag, &createdTime, &updatedTime, &dataType, &period)
if err != nil {
if err == gocql.ErrNotFound {
if err == sql.ErrNoRows {
return nil
} else {
log.Fatal(err)
@ -34,7 +33,7 @@ func GetCourseMetadataByDataID(dataID uint64) *types.CourseMetadata {
var failures uint32
var completions uint32
_ = cassandraClusterSession.Query(`SELECT stars, attempts, failures, completions FROM pretendo_smm.ratings WHERE data_id=?`, dataID).Scan(&stars, &attempts, &failures, &completions)
_ = Postgres.QueryRow(`SELECT stars, attempts, failures, completions FROM pretendo_smm.ratings WHERE data_id=$1`, dataID).Scan(&stars, &attempts, &failures, &completions)
courseMetadata := &types.CourseMetadata{
DataID: dataID,

View File

@ -1,47 +1,72 @@
package database
import (
"database/sql"
"log"
"github.com/PretendoNetwork/nex-go"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
)
func GetCourseMetadatasByLimit(limit uint32) []*types.CourseMetadata {
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT data_id, owner_pid, size, name, meta_binary, flag, creation_date, update_date, data_type, period FROM pretendo_smm.courses LIMIT ?`, limit).Iter().SliceMap(); err != nil {
rows, err := Postgres.Query(`SELECT data_id, owner_pid, size, name, meta_binary, flag, creation_date, update_date, data_type, period FROM pretendo_smm.courses LIMIT $1`, limit)
if err != nil {
log.Fatal(err)
}
courseMetadatas := make([]*types.CourseMetadata, 0)
for _, course := range sliceMap {
dataID := uint64(course["data_id"].(int64))
for rows.Next() {
var dataID uint64
var ownerPID uint32
var size uint32
var name string
var metaBinary []byte
var flag uint32
var creationDate uint64
var updateDate uint64
var dataType uint16
var period uint16
err := rows.Scan(
&dataID,
&ownerPID,
&size,
&name,
&metaBinary,
&flag,
&creationDate,
&updateDate,
&dataType,
&period,
)
if err != nil && err != sql.ErrNoRows {
globals.Logger.Critical(err.Error())
}
var stars uint32
var attempts uint32
var failures uint32
var completions uint32
_ = cassandraClusterSession.Query(`SELECT stars, attempts, failures, completions FROM pretendo_smm.ratings WHERE data_id=?`, dataID).Scan(&stars, &attempts, &failures, &completions)
_ = Postgres.QueryRow(`SELECT stars, attempts, failures, completions FROM pretendo_smm.ratings WHERE data_id=$1`, dataID).Scan(&stars, &attempts, &failures, &completions)
courseMetadata := &types.CourseMetadata{
DataID: dataID,
OwnerPID: uint32(course["owner_pid"].(int)),
Size: uint32(course["size"].(int)),
CreatedTime: nex.NewDateTime(uint64(course["creation_date"].(int64))),
UpdatedTime: nex.NewDateTime(uint64(course["update_date"].(int64))),
Name: course["name"].(string),
MetaBinary: course["meta_binary"].([]byte),
OwnerPID: ownerPID,
Size: size,
CreatedTime: nex.NewDateTime(creationDate),
UpdatedTime: nex.NewDateTime(updateDate),
Name: name,
MetaBinary: metaBinary,
Stars: stars,
Attempts: attempts,
Failures: failures,
Completions: completions,
Flag: uint32(course["flag"].(int)),
DataType: uint16(course["data_type"].(int16)),
Period: uint16(course["period"].(int16)),
Flag: flag,
DataType: dataType,
Period: period,
}
courseMetadatas = append(courseMetadatas, courseMetadata)

View File

@ -1,24 +1,30 @@
package database
import (
"database/sql"
"log"
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
)
func GetCourseMetadatasByPID(pid uint32) []*types.CourseMetadata {
courseMetadatas := make([]*types.CourseMetadata, 0)
// TODO: Fix this query? Seems like a weird way of doing this...
var sliceMap []map[string]interface{}
var err error
if sliceMap, err = cassandraClusterSession.Query(`SELECT data_id FROM pretendo_smm.courses WHERE owner_pid=? ALLOW FILTERING`, pid).Iter().SliceMap(); err != nil {
rows, err := Postgres.Query(`SELECT data_id FROM pretendo_smm.courses WHERE owner_pid=$1`, pid)
if err != nil {
log.Fatal(err)
}
for _, course := range sliceMap {
dataID := uint64(course["data_id"].(int64))
for rows.Next() {
var dataID uint64
err := rows.Scan(&dataID)
if err != nil && err != sql.ErrNoRows {
globals.Logger.Critical(err.Error())
return courseMetadatas
}
courseMetadatas = append(courseMetadatas, GetCourseMetadataByDataID(dataID))
}

View File

@ -12,7 +12,7 @@ func GetCourseWorldRecord(dataID uint64) *types.CourseWorldRecord {
var worldRecordUpdatedTime uint64
var worldRecord int32
_ = cassandraClusterSession.Query(`SELECT world_record_first_pid, world_record_pid, world_record_creation_date, world_record_update_date, world_record FROM pretendo_smm.courses WHERE data_id=?`, dataID).Scan(&worldRecordFirstPID, &worldRecordPID, &worldRecordCreatedTime, &worldRecordUpdatedTime, &worldRecord)
_ = Postgres.QueryRow(`SELECT world_record_first_pid, world_record_pid, world_record_creation_date, world_record_update_date, world_record FROM pretendo_smm.courses WHERE data_id=$1`, dataID).Scan(&worldRecordFirstPID, &worldRecordPID, &worldRecordCreatedTime, &worldRecordUpdatedTime, &worldRecord)
if worldRecordFirstPID == 0 {
return nil

View File

@ -1,8 +0,0 @@
package database
func GetDataStoreIDGeneratorLastID(nodeID int) uint32 {
var lastID uint32
_ = cassandraClusterSession.Query(`SELECT last_id FROM pretendo_smm.generator_last_id WHERE node_id=?`, nodeID).Scan(&lastID)
return lastID
}

View File

@ -1,10 +1,20 @@
package database
import "github.com/PretendoNetwork/super-mario-maker-secure/types"
import (
"log"
"github.com/PretendoNetwork/super-mario-maker-secure/types"
)
func GetUserStarredCourses(pid uint32) []*types.CourseMetadata {
var dataIDs []uint64
_ = cassandraClusterSession.Query(`SELECT starred_courses FROM pretendo_smm.user_play_info WHERE pid=?`, pid).Scan(&dataIDs)
rows, err := Postgres.Query(`SELECT starred_courses FROM pretendo_smm.user_play_info WHERE pid=$1`, pid)
if err != nil {
log.Fatal(err)
}
rows.Scan(&dataIDs)
return GetCourseMetadataByDataIDs(dataIDs)
}

View File

@ -3,7 +3,8 @@ package database
import "log"
func IncrementCourseAttemptCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET attempts=attempts+1 WHERE data_id=?`, courseID).Exec(); err != nil {
_, err := Postgres.Exec(`UPDATE pretendo_smm.ratings SET attempts=attempts+1 WHERE data_id=$1`, courseID)
if err != nil {
log.Fatal(err)
}
}

View File

@ -3,7 +3,8 @@ package database
import "log"
func IncrementCourseClearCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET completions=completions+1 WHERE data_id=?`, courseID).Exec(); err != nil {
_, err := Postgres.Exec(`UPDATE pretendo_smm.ratings SET completions=completions+1 WHERE data_id=$1`, courseID)
if err != nil {
log.Fatal(err)
}
}

View File

@ -3,7 +3,8 @@ package database
import "log"
func IncrementCourseFailCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET failures=failures+1 WHERE data_id=?`, courseID).Exec(); err != nil {
_, err := Postgres.Exec(`UPDATE pretendo_smm.ratings SET failures=failures+1 WHERE data_id=$1`, courseID)
if err != nil {
log.Fatal(err)
}
}

View File

@ -3,7 +3,8 @@ package database
import "log"
func IncrementCourseStarCount(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET stars=stars+1 WHERE data_id=?`, courseID).Exec(); err != nil {
_, err := Postgres.Exec(`UPDATE pretendo_smm.ratings SET stars=stars+1 WHERE data_id=$1`, courseID)
if err != nil {
log.Fatal(err)
}
}

100
database/init_postgres.go Normal file
View File

@ -0,0 +1,100 @@
package database
import (
"github.com/PretendoNetwork/super-mario-maker-secure/globals"
)
func initPostgres() {
_, err := Postgres.Exec(`CREATE SCHEMA IF NOT EXISTS pretendo_smm`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
globals.Logger.Success("pretendo_smm Postgres schema created")
// * Super Mario Maker has non-standard DataID requirements.
// * DataID 900000 is reserved for the event course metadata
// * file, so to prevent a collision eventually, we need to
// * start course IDs AFTER 900000. DataIDs are stored and
// * processed as uint64, however Super Mario Maker can not
// * use the full uint64 range. This is because course share
// * codes are generated from the courses DataID. A course
// * share code is an 8 byte hex string, where the upper 2
// * bytes are the checksum of the lower 6 bytes. The lower
// * 6 bytes are the courses DataID. Super Mario Maker is
// * only capable of displaying codes up to 0xFFFFFFFFFFFF,
// * essentially truncating DataIDs down to 48 bit integers
// * instead of 64 bit. I doubt we will ever hit even the 32
// * bit limit, let alone 48, but this is here just in case
_, err = Postgres.Exec(`CREATE SEQUENCE IF NOT EXISTS pretendo_smm.courses_seq
INCREMENT 1
MINVALUE 1
MAXVALUE 281474976710656
START 900001
CACHE 1`,
)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS pretendo_smm.courses (
data_id int NOT NULL DEFAULT nextval('pretendo_smm.courses_seq') PRIMARY KEY,
playable boolean,
owner_pid int,
name text,
size int,
creation_date bigint,
update_date bigint,
world_record_first_pid int,
world_record_pid int,
world_record_creation_date bigint,
world_record_update_date bigint,
world_record int,
meta_binary bytea,
flag int,
extra_data text[],
data_type smallint,
period smallint
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS pretendo_smm.ratings (
data_id bigint PRIMARY KEY,
stars serial,
attempts serial,
failures serial,
completions serial
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS pretendo_smm.buffer_queues (
id uuid PRIMARY KEY,
data_id bigint,
slot int,
buffer bytea
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
_, err = Postgres.Exec(`CREATE TABLE IF NOT EXISTS pretendo_smm.user_play_info (
pid int PRIMARY KEY,
starred_courses bigint[],
played_courses bigint[]
)`)
if err != nil {
globals.Logger.Critical(err.Error())
return
}
globals.Logger.Success("Postgres tables created")
}

View File

@ -4,14 +4,15 @@ import (
"log"
"github.com/PretendoNetwork/nex-go"
"github.com/lib/pq"
)
func InitializeCourseData(courseID uint64, ownerPID uint32, size uint32, name string, flag uint32, extraData []string, dataType uint16, period uint16) {
func InitializeCourseData(ownerPID uint32, size uint32, name string, flag uint32, extraData []string, dataType uint16, period uint16) uint64 {
datetime := nex.NewDateTime(0)
now := datetime.Now()
var dataID uint64
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.courses(
data_id,
err := Postgres.QueryRow(`INSERT INTO pretendo_smm.courses(
owner_pid,
size,
name,
@ -29,28 +30,44 @@ func InitializeCourseData(courseID uint64, ownerPID uint32, size uint32, name st
period
)
VALUES (
?,
?,
?,
?,
?,
?,
$1,
$2,
$3,
$4,
$5,
false,
?,
?,
$6,
$7,
0,
0,
0,
0,
0,
?,
?
) IF NOT EXISTS`,
courseID, ownerPID, size, name, flag, extraData, now, now, dataType, period).Exec(); err != nil {
$8,
$9
) RETURNING data_id`, ownerPID, size, name, flag, pq.Array(extraData), now, now, dataType, period).Scan(&dataID)
if err != nil {
log.Fatal(err)
}
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.ratings SET stars=stars+0, attempts=attempts+0, failures=failures+0, completions=completions+0 WHERE data_id=?`, courseID).Exec(); err != nil {
_, err = Postgres.Exec(`INSERT INTO pretendo_smm.ratings (
data_id,
stars,
attempts,
failures,
completions
)
VALUES (
$1,
0,
0,
0,
0
)`, dataID)
if err != nil {
log.Fatal(err)
}
return dataID
}

View File

@ -3,7 +3,8 @@ package database
import "log"
func InsertBufferQueueData(dataID uint64, slot uint32, buffer []byte) {
if err := cassandraClusterSession.Query(`INSERT INTO pretendo_smm.buffer_queues( id, data_id, slot, buffer ) VALUES ( now(), ?, ?, ? ) IF NOT EXISTS`, dataID, slot, buffer).Exec(); err != nil {
_, err := Postgres.Exec(`INSERT INTO pretendo_smm.buffer_queues( id, data_id, slot, buffer ) VALUES ( gen_random_uuid(), $1, $2, $3 ) ON CONFLICT DO NOTHING`, dataID, slot, buffer)
if err != nil {
log.Fatal(err)
}
}

View File

@ -3,7 +3,8 @@ package database
import "log"
func SetCoursePlayable(courseID uint64) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET playable=true WHERE data_id=?`, courseID).Exec(); err != nil {
_, err := Postgres.Exec(`UPDATE pretendo_smm.courses SET playable=true WHERE data_id=$1`, courseID)
if err != nil {
log.Fatal(err)
}
}

View File

@ -1,9 +0,0 @@
package database
import "log"
func SetDataStoreIDGeneratorLastID(nodeID int, value uint32) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.generator_last_id SET last_id=? WHERE node_id=?`, value, nodeID).Exec(); err != nil {
log.Fatal(err)
}
}

View File

@ -3,7 +3,8 @@ package database
import "log"
func UpdateCourseMetaBinary(courseID uint64, metaBinary []byte) {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET meta_binary=? WHERE data_id=?`, metaBinary, courseID).Exec(); err != nil {
_, err := Postgres.Exec(`UPDATE pretendo_smm.courses SET meta_binary=$1 WHERE data_id=$2`, metaBinary, courseID)
if err != nil {
log.Fatal(err)
}
}

View File

@ -11,12 +11,14 @@ func UpdateCourseWorldRecord(courseID uint64, ownerPID uint32, score int32) {
now := datetime.Now()
if GetCourseWorldRecord(courseID) == nil {
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET world_record_first_pid=?, world_record_creation_date=? WHERE data_id=?`, ownerPID, now, courseID).Exec(); err != nil {
_, err := Postgres.Exec(`UPDATE pretendo_smm.courses SET world_record_first_pid=$1, world_record_creation_date=$2 WHERE data_id=$3`, ownerPID, now, courseID)
if err != nil {
log.Fatal(err)
}
}
if err := cassandraClusterSession.Query(`UPDATE pretendo_smm.courses SET world_record_pid=?, world_record_update_date=?, world_record=? WHERE data_id=?`, ownerPID, now, score, courseID).Exec(); err != nil {
_, err := Postgres.Exec(`UPDATE pretendo_smm.courses SET world_record_pid=$1, world_record_update_date=$2, world_record=$3 WHERE data_id=$4`, ownerPID, now, score, courseID)
if err != nil {
log.Fatal(err)
}
}

View File

@ -1,48 +0,0 @@
package globals
import (
"encoding/binary"
)
// DataStoreIDGenerator represents a safe, structured, ID for unique NEX DataStore objects
type DataStoreIDGenerator struct {
inUse bool
regionID uint8
nodeID uint8
Value uint32
}
// InUse is used to check if a DataStoreIDGenerator Node is currently generating a number
func (dataStoreIDGenerator *DataStoreIDGenerator) InUse() bool {
return dataStoreIDGenerator.inUse
}
// SetInUse is used to check if a DataStoreIDGenerator Node is currently generating a number
func (dataStoreIDGenerator *DataStoreIDGenerator) SetInUse(inUse bool) {
dataStoreIDGenerator.inUse = inUse
}
// Next is used to get the next value from the DataStoreIDGenerator Node
func (dataStoreIDGenerator *DataStoreIDGenerator) Next() uint64 {
if dataStoreIDGenerator.inUse {
panic("Cannot call DataStoreIDGenerator.Next while in use")
}
dataStoreIDGenerator.Value += 1
data := make([]byte, 8)
data[2] = dataStoreIDGenerator.regionID
data[3] = dataStoreIDGenerator.nodeID
binary.BigEndian.PutUint32(data[4:], dataStoreIDGenerator.Value)
return binary.BigEndian.Uint64(data)
}
func NewDataStoreIDGenerator(regionID, nodeID uint8, value uint32) *DataStoreIDGenerator {
return &DataStoreIDGenerator{
regionID: regionID,
nodeID: nodeID,
Value: value,
}
}

View File

@ -16,7 +16,6 @@ var AuthenticationServer *nex.Server
var SecureServer *nex.Server
var MinIOClient *minio.Client
var Presigner *S3Presigner
var DataStoreIDGenerators []*DataStoreIDGenerator
var GRPCAccountClientConnection *grpc.ClientConn
var GRPCAccountClient pb.AccountClient
var GRPCAccountCommonMetadata metadata.MD

17
go.mod
View File

@ -8,25 +8,23 @@ require (
github.com/PretendoNetwork/nex-protocols-common-go v1.0.28
github.com/PretendoNetwork/nex-protocols-go v1.0.55
github.com/PretendoNetwork/plogger-go v1.0.4
github.com/gocql/gocql v1.6.0
github.com/joho/godotenv v1.5.1
github.com/lib/pq v1.10.9
github.com/minio/minio-go/v7 v7.0.63
google.golang.org/grpc v1.58.3
google.golang.org/grpc v1.59.0
)
require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jwalton/go-supportscolor v1.2.0 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/klauspost/compress v1.17.1 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@ -37,12 +35,11 @@ require (
golang.org/x/crypto v0.14.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.13.0 // indirect
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
)

44
go.sum
View File

@ -8,10 +8,6 @@ github.com/PretendoNetwork/nex-protocols-go v1.0.55 h1:8QMeCNO2eZO4m7CRT/nv2WWm+
github.com/PretendoNetwork/nex-protocols-go v1.0.55/go.mod h1:136762CMIcAsTZDrt4W7gDE4ppiBuc9zN2QFOHESjS8=
github.com/PretendoNetwork/plogger-go v1.0.4 h1:PF7xHw9eDRHH+RsAP9tmAE7fG0N0p6H4iPwHKnsoXwc=
github.com/PretendoNetwork/plogger-go v1.0.4/go.mod h1:7kD6M4vPq1JL4LTuPg6kuB1OvUBOwQOtAvTaUwMbwvU=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932 h1:mXoPYz/Ul5HYEDvkta6I8/rnYM5gSdSV2tJ6XbZuEtY=
github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -19,42 +15,32 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
github.com/gocql/gocql v1.6.0 h1:IdFdOTbnpbd0pDhl4REKQDM+Q0SzKXQ1Yh+YZZ8T/qU=
github.com/gocql/gocql v1.6.0/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8=
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jwalton/go-supportscolor v1.2.0 h1:g6Ha4u7Vm3LIsQ5wmeBpS4gazu0UP1DRDE8y6bre4H8=
github.com/jwalton/go-supportscolor v1.2.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs=
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.17.1 h1:NE3C767s2ak2bweCZo3+rdP4U/HoyVXLv/X9f2gPS5g=
github.com/klauspost/compress v1.17.1/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
github.com/minio/minio-go/v7 v7.0.63 h1:GbZ2oCvaUdgT5640WJOpyDhhDxvknAJU2/T3yurwcbQ=
@ -84,8 +70,8 @@ golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -100,17 +86,15 @@ golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b h1:ZlWIi1wSK56/8hn4QcBp/j9M7Gt3U/3hZw3mC7vDICo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc=
google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk=
google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=

27
init.go
View File

@ -4,7 +4,6 @@ import (
"fmt"
"log"
"os"
"runtime"
"strconv"
"strings"
@ -28,10 +27,10 @@ func init() {
}
s3Endpoint := os.Getenv("PN_SMM_CONFIG_S3_ENDPOINT")
//s3Region := os.Getenv("PN_SMM_CONFIG_S3_REGION")
s3AccessKey := os.Getenv("PN_SMM_CONFIG_S3_ACCESS_KEY")
s3AccessSecret := os.Getenv("PN_SMM_CONFIG_S3_ACCESS_SECRET")
postgresURI := os.Getenv("PN_SMM_POSTGRES_URI")
kerberosPassword := os.Getenv("PN_SMM_KERBEROS_PASSWORD")
authenticationServerPort := os.Getenv("PN_SMM_AUTHENTICATION_SERVER_PORT")
secureServerHost := os.Getenv("PN_SMM_SECURE_SERVER_HOST")
@ -40,6 +39,11 @@ func init() {
accountGRPCPort := os.Getenv("PN_SMM_ACCOUNT_GRPC_PORT")
accountGRPCAPIKey := os.Getenv("PN_SMM_ACCOUNT_GRPC_API_KEY")
if strings.TrimSpace(postgresURI) == "" {
globals.Logger.Error("PN_SMM_POSTGRES_URI environment variable not set")
os.Exit(0)
}
if strings.TrimSpace(kerberosPassword) == "" {
globals.Logger.Warningf("PN_SMM_KERBEROS_PASSWORD environment variable not set. Using default password: %q", globals.KerberosPassword)
} else {
@ -123,21 +127,6 @@ func init() {
globals.MinIOClient = minIOClient
globals.Presigner = globals.NewS3Presigner(globals.MinIOClient)
// Connect to and setup databases
database.ConnectAll()
createDataStoreIDGenerators()
}
func createDataStoreIDGenerators() {
globals.DataStoreIDGenerators = make([]*globals.DataStoreIDGenerator, 0)
regionID := 0 // USA
for corenum := 0; corenum < runtime.NumCPU(); corenum++ {
database.CreateDataStoreIDGeneratorRow(corenum)
lastID := database.GetDataStoreIDGeneratorLastID(corenum)
generator := globals.NewDataStoreIDGenerator(uint8(regionID), uint8(corenum), lastID)
globals.DataStoreIDGenerators = append(globals.DataStoreIDGenerators, generator)
}
// * Connect to and setup databases
database.ConnectPostgres()
}

View File

@ -2,7 +2,6 @@ package nex_datastore
import (
"fmt"
"math/rand"
"os"
"time"
@ -14,14 +13,7 @@ import (
)
func PreparePostObject(err error, client *nex.Client, callID uint32, param *datastore_types.DataStorePreparePostParam) uint32 {
rand.Seed(time.Now().UnixNano())
nodeID := rand.Intn(len(globals.DataStoreIDGenerators))
dataStoreIDGenerator := globals.DataStoreIDGenerators[nodeID]
dataID := dataStoreIDGenerator.Next()
database.SetDataStoreIDGeneratorLastID(nodeID, dataStoreIDGenerator.Value)
database.InitializeCourseData(dataID, client.PID(), param.Size, param.Name, param.Flag, param.ExtraData, param.DataType, param.Period)
dataID := database.InitializeCourseData(client.PID(), param.Size, param.Name, param.Flag, param.ExtraData, param.DataType, param.Period)
if param.DataType != 1 { // 1 is Mii data, assume other values are course meta data
database.UpdateCourseMetaBinary(dataID, param.MetaBinary)

View File

@ -14,7 +14,7 @@ func GetCourseRecord(err error, client *nex.Client, callID uint32, param *datast
rmcResponse := nex.NewRMCResponse(datastore_super_mario_maker.ProtocolID, callID)
if worldRecord == nil {
rmcResponse.SetError(0x690004)
rmcResponse.SetError(nex.Errors.DataStore.NotFound)
} else {
result := datastore_super_mario_maker_types.NewDataStoreGetCourseRecordResult()
result.DataID = param.DataID