Skip to content

Commit c8ec5cf

Browse files
committed
Most of the server logic
Closes #6. Closes #5. Closes #4.
1 parent 9e695eb commit c8ec5cf

File tree

5 files changed

+382
-6
lines changed

5 files changed

+382
-6
lines changed

config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ type Config struct {
2525
DB DBConfig
2626
DownloadAuth AuthConfig
2727
UploadAuth AuthConfig
28+
StorageDir string
29+
HTTPSUpstream bool
2830
}
2931

3032
var Default Config

db.go

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,144 @@
11
package filedrop
22

3-
import "database/sql"
3+
import (
4+
"database/sql"
5+
"strings"
6+
"time"
7+
)
48

59
type db struct {
610
*sql.DB
11+
12+
addFile *sql.Stmt
13+
remFile *sql.Stmt
14+
getFile *sql.Stmt
15+
16+
addUse *sql.Stmt
17+
shouldDelete *sql.Stmt
718
}
819

920
func openDB(driver, dsn string) (*db, error) {
10-
return &db{}, nil
21+
if driver == "sqlite3" {
22+
// We apply some tricks for SQLite to avoid "database is locked" errors.
23+
24+
if !strings.HasPrefix(dsn, "file:") {
25+
dsn = "file:" + dsn
26+
}
27+
if !strings.Contains(dsn, "?") {
28+
dsn = dsn + "?"
29+
}
30+
dsn = dsn + "cache=shared&_journal=WAL&_busy_timeout=5000"
31+
}
32+
33+
db := new(db)
34+
var err error
35+
db.DB, err = sql.Open(driver, dsn)
36+
if err != nil {
37+
return nil, err
38+
}
39+
40+
41+
if driver == "sqlite3" {
42+
// Also some optimizations for SQLite to make it FAA-A-A-AST.
43+
db.Exec(`PRAGMA foreign_keys = ON`)
44+
db.Exec(`PRAGMA auto_vacuum = INCREMENTAL`)
45+
db.Exec(`PRAGMA journal_mode = WAL`)
46+
db.Exec(`PRAGMA defer_foreign_keys = ON`)
47+
db.Exec(`PRAGMA synchronous = NORMAL`)
48+
db.Exec(`PRAGMA temp_store = MEMORY`)
49+
db.Exec(`PRAGMA cache_size = 5000`)
50+
}
51+
52+
if err := db.initSchema(); err != nil {
53+
panic(err)
54+
}
55+
if err := db.initStmts(); err != nil {
56+
panic(err)
57+
}
58+
return db, nil
1159
}
60+
61+
func (db *db) initSchema() error {
62+
_, err := db.Exec(`CREATE TABLE IF NOT EXISTS filedrop (
63+
uuid TEXT PRIMARY KEY NOT NULL,
64+
uses INTEGER NOT NULL DEFAULT 0,
65+
maxUses INTEGER,
66+
storeUntil INTEGER
67+
)`)
68+
if err != nil {
69+
return err
70+
}
71+
return nil
72+
}
73+
74+
func (db *db) initStmts() error {
75+
var err error
76+
db.addFile, err = db.Prepare(`INSERT INTO filedrop(uuid, maxUses, storeUntil) VALUES (?, ?, ?)`)
77+
if err != nil {
78+
return err
79+
}
80+
db.remFile, err = db.Prepare(`DELETE FROM filedrop WHERE uuid = ?`)
81+
if err != nil {
82+
return err
83+
}
84+
db.getFile, err = db.Prepare(`SELECT uses, maxUses, storeUntil FROM filedrop WHERE uuid = ?`)
85+
if err != nil {
86+
return err
87+
}
88+
db.shouldDelete, err = db.Prepare(`SELECT exists(SELECT uuid FROM filedrop WHERE uuid = ? AND (storeUntil < ? OR maxUses == uses))`)
89+
if err != nil {
90+
return err
91+
}
92+
db.addUse, err = db.Prepare(`UPDATE filedrop SET uses = (SELECT uses+1 FROM filedrop WHERE uuid = ?) WHERE uuid = ?`)
93+
if err != nil {
94+
return err
95+
}
96+
return nil
97+
}
98+
99+
func (db *db) AddFile(tx *sql.Tx, uuid string, maxUses uint, storeUntil time.Time) error {
100+
maxUsesN := sql.NullInt64{Int64: int64(maxUses), Valid: maxUses != 0}
101+
storeUntilN := sql.NullInt64{Int64: storeUntil.Unix(), Valid: !storeUntil.IsZero()}
102+
103+
if tx != nil {
104+
_, err := tx.Stmt(db.addFile).Exec(uuid, maxUsesN, storeUntilN)
105+
return err
106+
} else {
107+
_, err := db.addFile.Exec(uuid, maxUsesN, storeUntilN)
108+
return err
109+
}
110+
}
111+
112+
func (db *db) RemoveFile(tx *sql.Tx, uuid string) error {
113+
if tx != nil {
114+
_, err := tx.Stmt(db.remFile).Exec(uuid)
115+
return err
116+
} else {
117+
_, err := db.remFile.Exec(uuid)
118+
return err
119+
}
120+
}
121+
122+
func (db *db) ShouldDelete(tx *sql.Tx, uuid string) bool {
123+
var row *sql.Row
124+
if tx != nil {
125+
row = tx.Stmt(db.shouldDelete).QueryRow(uuid, time.Now().Unix())
126+
} else {
127+
row = db.shouldDelete.QueryRow(uuid, time.Now().Unix())
128+
}
129+
res := 0
130+
if err := row.Scan(&res); err != nil {
131+
return false
132+
}
133+
return res == 1
134+
}
135+
136+
func (db *db) AddUse(tx *sql.Tx, uuid string) error {
137+
if tx != nil {
138+
_, err := tx.Stmt(db.addUse).Exec(uuid, uuid)
139+
return err
140+
} else {
141+
_, err := db.addUse.Exec(uuid, uuid)
142+
return err
143+
}
144+
}

go.mod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
module github.com/foxcpp/filedrop
22

3-
require github.com/mattn/go-sqlite3 v1.9.0
3+
require (
4+
github.com/mattn/go-sqlite3 v1.9.0
5+
github.com/pkg/errors v0.8.0
6+
github.com/satori/go.uuid v1.2.0
7+
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
github.com/mattn/go-sqlite3 v1.9.0 h1:pDRiWfl+++eC2FEFRy6jXmQlvp4Yh3z1MJKg4UeYM/4=
22
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
3+
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
4+
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
5+
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
6+
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=

0 commit comments

Comments
 (0)