Add store migration tool to extract files from the database
This commit is contained in:
parent
f4690b2bba
commit
c04bbe784e
3 changed files with 152 additions and 1 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -1,5 +1,5 @@
|
||||||
trantor.git
|
trantor.git
|
||||||
store/
|
/store/
|
||||||
tools/adduser/adduser
|
tools/adduser/adduser
|
||||||
tools/update/update
|
tools/update/update
|
||||||
tools/togridfs/togridfs
|
tools/togridfs/togridfs
|
||||||
|
@ -8,5 +8,6 @@ tools/coverNew/coverNew
|
||||||
tools/addsize/addsize
|
tools/addsize/addsize
|
||||||
tools/importer/importer
|
tools/importer/importer
|
||||||
tools/keywords/keywords
|
tools/keywords/keywords
|
||||||
|
tools/store/store
|
||||||
tags
|
tags
|
||||||
.*.swp
|
.*.swp
|
||||||
|
|
|
@ -17,3 +17,5 @@ Password:
|
||||||
- addsize. Add the size of the books to the book metadata
|
- addsize. Add the size of the books to the book metadata
|
||||||
|
|
||||||
- keywords. Recalculate keywords
|
- keywords. Recalculate keywords
|
||||||
|
|
||||||
|
- store. Move files from the database to the local storage
|
||||||
|
|
148
tools/store/store.go
Normal file
148
tools/store/store.go
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
log "github.com/cihub/seelog"
|
||||||
|
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/base64"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.gitorious.org/trantor/trantor.git/storage"
|
||||||
|
"gopkg.in/mgo.v2"
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
DB_IP = "127.0.0.1"
|
||||||
|
DB_NAME = "trantor"
|
||||||
|
BOOKS_COLL = "books"
|
||||||
|
FS_BOOKS = "fs_books"
|
||||||
|
FS_IMGS = "fs_imgs"
|
||||||
|
|
||||||
|
STORE_PATH = "store/"
|
||||||
|
EPUB_FILE = "book.epub"
|
||||||
|
COVER_FILE = "cover.jpg"
|
||||||
|
COVER_SMALL_FILE = "coverSmall.jpg"
|
||||||
|
|
||||||
|
NUM_WORKERS = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
type Book struct {
|
||||||
|
Id bson.ObjectId `bson:"_id"`
|
||||||
|
Title string
|
||||||
|
Author []string
|
||||||
|
Contributor string
|
||||||
|
Publisher string
|
||||||
|
Description string
|
||||||
|
Subject []string
|
||||||
|
Date string
|
||||||
|
Lang []string
|
||||||
|
Isbn string
|
||||||
|
Type string
|
||||||
|
Format string
|
||||||
|
Source string
|
||||||
|
Relation string
|
||||||
|
Coverage string
|
||||||
|
Rights string
|
||||||
|
Meta string
|
||||||
|
File bson.ObjectId
|
||||||
|
FileSize int
|
||||||
|
Cover bson.ObjectId
|
||||||
|
CoverSmall bson.ObjectId
|
||||||
|
Active bool
|
||||||
|
Keywords []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
db := InitDB(DB_IP)
|
||||||
|
defer db.Close()
|
||||||
|
store, err := storage.Init(STORE_PATH)
|
||||||
|
if err != nil {
|
||||||
|
log.Critical(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
channel := make(chan Book)
|
||||||
|
quit := make(chan bool)
|
||||||
|
for i := 0; i < NUM_WORKERS; i++ {
|
||||||
|
go worker(channel, quit, db, store)
|
||||||
|
}
|
||||||
|
|
||||||
|
booksColl := db.DB(DB_NAME).C(BOOKS_COLL)
|
||||||
|
books := booksColl.Find(bson.M{}).Batch(200).Prefetch(0.25).Iter()
|
||||||
|
var book Book
|
||||||
|
for books.Next(&book) {
|
||||||
|
channel <- book
|
||||||
|
}
|
||||||
|
if err := books.Close(); err != nil {
|
||||||
|
log.Critical(err)
|
||||||
|
}
|
||||||
|
close(channel)
|
||||||
|
|
||||||
|
for i := 0; i < NUM_WORKERS; i++ {
|
||||||
|
log.Info("Worker ", i, " has finished")
|
||||||
|
<-quit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitDB(host string) *mgo.Session {
|
||||||
|
session, err := mgo.Dial(host)
|
||||||
|
if err != nil {
|
||||||
|
log.Critical(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return session
|
||||||
|
}
|
||||||
|
|
||||||
|
func worker(channel chan Book, quit chan bool, database *mgo.Session, store *storage.Store) {
|
||||||
|
db := database.Copy()
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
fsBooks := db.DB(DB_NAME).GridFS(FS_BOOKS)
|
||||||
|
fsImgs := db.DB(DB_NAME).GridFS(FS_IMGS)
|
||||||
|
booksColl := db.DB(DB_NAME).C(BOOKS_COLL)
|
||||||
|
|
||||||
|
for book := range channel {
|
||||||
|
id := genId()
|
||||||
|
log.Info("== Storing book '", book.Title, "' (", id, ") ==")
|
||||||
|
cover := true
|
||||||
|
|
||||||
|
process(id, EPUB_FILE, book.File, fsBooks, store)
|
||||||
|
err := process(id, COVER_FILE, book.Cover, fsImgs, store)
|
||||||
|
if err != nil {
|
||||||
|
cover = false
|
||||||
|
}
|
||||||
|
process(id, COVER_SMALL_FILE, book.CoverSmall, fsImgs, store)
|
||||||
|
|
||||||
|
query := bson.M{"$set": bson.M{"id": id, "cover": cover},
|
||||||
|
"$unset": bson.M{"file": "", "coversmall": ""}}
|
||||||
|
err = booksColl.UpdateId(book.Id, query)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Can no update ", book.Id.Hex())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
quit <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(id string, name string, objId bson.ObjectId, fs *mgo.GridFS, store *storage.Store) error {
|
||||||
|
f, err := fs.OpenId(objId)
|
||||||
|
if err != nil {
|
||||||
|
if name == EPUB_FILE {
|
||||||
|
log.Error(id, " - can not open ", objId.Hex())
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
_, err = store.Store(id, f, name)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Can not store '", id, "' (", objId, ")")
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func genId() string {
|
||||||
|
b := make([]byte, 12)
|
||||||
|
rand.Read(b)
|
||||||
|
return base64.URLEncoding.EncodeToString(b)
|
||||||
|
}
|
Reference in a new issue