You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
491 lines
16 KiB
491 lines
16 KiB
package archive |
|
|
|
import ( |
|
"bytes" |
|
"context" |
|
"fmt" |
|
"time" |
|
|
|
"go-common/app/service/main/videoup/model/archive" |
|
"go-common/library/database/sql" |
|
"go-common/library/log" |
|
"go-common/library/xstr" |
|
|
|
farm "github.com/dgryski/go-farm" |
|
) |
|
|
|
const ( |
|
_inVideoCidSQL = `INSERT IGNORE INTO video (id,filename,src_type,resolutions,playurl,status,xcode_state,duration,filesize,attribute,failcode,hash64) |
|
VALUES (?,?,?,?,?,?,?,?,?,?,?,?)` |
|
_inNewVideoSQL = `INSERT INTO video (filename,src_type,resolutions,playurl,status,xcode_state,duration,filesize,attribute,failcode,hash64) |
|
VALUES (?,?,?,?,?,?,?,?,?,?,?)` |
|
_inVideoRelationSQL = "INSERT IGNORE INTO archive_video_relation (id,aid,cid,title,description,index_order,ctime) VALUES (?,?,?,?,?,?,?)" |
|
_upVideoRelationSQL = "UPDATE archive_video_relation SET title=?,description=?,index_order=? ,state=? WHERE aid=? and cid=?" |
|
_upRelationStateSQL = "UPDATE archive_video_relation SET state=? WHERE aid=? AND cid=?" |
|
_upVideoStatusSQL = "UPDATE video SET status=? WHERE id=?" |
|
_upNewVideoSQL = "UPDATE video SET src_type=?,status=?,xcode_state=? WHERE id=?" |
|
_newVideoFnSQL = "SELECT id,filename,src_type,resolutions,playurl,status,xcode_state,duration,filesize,attribute,failcode,ctime,mtime,dimensions FROM video WHERE hash64=? AND filename=?" |
|
_newVideoByFnSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode, |
|
avr.index_order,v.attribute,v.xcode_state,avr.state,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id |
|
WHERE hash64=? AND filename=?` |
|
_newVideoDataCidsFnSQL = "SELECT id,filename FROM video WHERE hash64 in (%s) AND filename in (%s)" |
|
_newsimpleArcVideoSQL = `SELECT cid,title,index_order,state,mtime FROM archive_video_relation WHERE aid=?` |
|
_newVideosSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode, |
|
avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id |
|
WHERE aid=? ORDER BY index_order` |
|
_newvideoCidSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode, |
|
avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id |
|
WHERE cid=? ORDER BY id LIMIT 1` |
|
_newVideosCidSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode, |
|
avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id |
|
WHERE cid IN (%s)` |
|
_newVideosFnSQL = `SELECT avr.id,v.filename,avr.cid,avr.aid,avr.title,avr.description,v.src_type,v.duration,v.filesize,v.resolutions,v.playurl,v.failcode, |
|
avr.index_order,v.attribute,v.xcode_state,avr.state,v.status,avr.ctime,avr.mtime,v.dimensions FROM archive_video_relation avr JOIN video v on avr.cid = v.id |
|
WHERE hash64 in (%s) AND filename in (%s)` |
|
_newVidReasonSQL = `SELECT ava.vid,ava.reason FROM archive_video_audit ava LEFT JOIN archive_video_relation avr ON ava.vid=avr.id WHERE ava.aid=? AND avr.state!=-100` |
|
_newVideosTimeoutSQL = `SELECT id ,filename,ctime,mtime from video WHERE hash64 in (%s) AND filename in (%s)` |
|
) |
|
|
|
// TxAddVideoCid insert video to get cid. |
|
func (d *Dao) TxAddVideoCid(tx *sql.Tx, v *archive.Video) (cid int64, err error) { |
|
hash64 := int64(farm.Hash64([]byte(v.Filename))) |
|
res, err := tx.Exec(_inVideoCidSQL, v.Cid, v.Filename, v.SrcType, v.Resolutions, v.Playurl, v.Status, v.XcodeState, v.Duration, v.Filesize, v.Attribute, v.FailCode, hash64) |
|
if err != nil { |
|
log.Error("d.inVideoCid.Exec error(%v)", err) |
|
return |
|
} |
|
cid, err = res.LastInsertId() |
|
return |
|
} |
|
|
|
// AddNewVideo insert new video. |
|
func (d *Dao) AddNewVideo(c context.Context, v *archive.Video) (cid int64, err error) { |
|
hash64 := int64(farm.Hash64([]byte(v.Filename))) |
|
res, err := d.db.Exec(c, _inNewVideoSQL, v.Filename, v.SrcType, v.Resolutions, v.Playurl, v.Status, v.XcodeState, v.Duration, v.Filesize, v.Attribute, v.FailCode, hash64) |
|
if err != nil { |
|
log.Error("d.inNewVideo.Exec error(%v)", err) |
|
return |
|
} |
|
cid, err = res.LastInsertId() |
|
return |
|
} |
|
|
|
// TxAddNewVideo insert new video. |
|
func (d *Dao) TxAddNewVideo(tx *sql.Tx, v *archive.Video) (cid int64, err error) { |
|
hash64 := int64(farm.Hash64([]byte(v.Filename))) |
|
res, err := tx.Exec(_inNewVideoSQL, v.Filename, v.SrcType, v.Resolutions, v.Playurl, v.Status, v.XcodeState, v.Duration, v.Filesize, v.Attribute, v.FailCode, hash64) |
|
if err != nil { |
|
log.Error("tx.inNewVideo.Exec error(%v)", err) |
|
return |
|
} |
|
cid, err = res.LastInsertId() |
|
return |
|
} |
|
|
|
// TxAddVideoRelation insert archive_video_relation to get vid. |
|
func (d *Dao) TxAddVideoRelation(tx *sql.Tx, v *archive.Video) (vid int64, err error) { |
|
res, err := tx.Exec(_inVideoRelationSQL, v.ID, v.Aid, v.Cid, v.Title, v.Desc, v.Index, v.CTime) |
|
if err != nil { |
|
log.Error("d.inVideoRelation.Exec error(%v)", err) |
|
return |
|
} |
|
vid, err = res.LastInsertId() |
|
return |
|
} |
|
|
|
// TxUpVideoRelation update archive_video_relation info by aid and cid. |
|
func (d *Dao) TxUpVideoRelation(tx *sql.Tx, v *archive.Video) (rows int64, err error) { |
|
res, err := tx.Exec(_upVideoRelationSQL, v.Title, v.Desc, v.Index, archive.VideoStatusOpen, v.Aid, v.Cid) |
|
if err != nil { |
|
log.Error("d.upVideoRelation.Exec(%v) error(%v)", v, err) |
|
return |
|
} |
|
rows, err = res.RowsAffected() |
|
return |
|
} |
|
|
|
// TxUpRelationState update archive_video_relation state by aid and cid. |
|
func (d *Dao) TxUpRelationState(tx *sql.Tx, aid, cid int64, state int16) (rows int64, err error) { |
|
res, err := tx.Exec(_upRelationStateSQL, state, aid, cid) |
|
if err != nil { |
|
log.Error("d.upRelationState.Exec(%d,%d,%d) error(%v)", aid, cid, state, err) |
|
return |
|
} |
|
rows, err = res.RowsAffected() |
|
return |
|
} |
|
|
|
// TxUpVdoStatus update video state by cid. |
|
func (d *Dao) TxUpVdoStatus(tx *sql.Tx, cid int64, status int16) (rows int64, err error) { |
|
res, err := tx.Exec(_upVideoStatusSQL, status, cid) |
|
if err != nil { |
|
log.Error("d.upVideoStatus.Exec(%d,%d) error(%v)", cid, status, err) |
|
return |
|
} |
|
rows, err = res.RowsAffected() |
|
return |
|
} |
|
|
|
// TxUpNewVideo update video SrcType\Status\XcodeState by cid. |
|
func (d *Dao) TxUpNewVideo(tx *sql.Tx, v *archive.Video) (rows int64, err error) { |
|
res, err := tx.Exec(_upNewVideoSQL, v.SrcType, v.Status, v.XcodeState, v.Cid) |
|
if err != nil { |
|
log.Error("d.upSimNewVideo.Exec(%s,%d,%d,%d) error(%v)", v.SrcType, v.Status, v.XcodeState, v.Cid, err) |
|
return |
|
} |
|
rows, err = res.RowsAffected() |
|
return |
|
} |
|
|
|
// NewVideoFn get video by filename |
|
func (d *Dao) NewVideoFn(c context.Context, filename string) (v *archive.Video, err error) { |
|
hash64 := int64(farm.Hash64([]byte(filename))) |
|
row := d.rddb.QueryRow(c, _newVideoFnSQL, hash64, filename) |
|
v = &archive.Video{} |
|
var dimStr string |
|
if err = row.Scan(&v.Cid, &v.Filename, &v.SrcType, &v.Resolutions, &v.Playurl, &v.Status, &v.XcodeState, &v.Duration, &v.Filesize, &v.Attribute, &v.FailCode, &v.CTime, &v.MTime, &dimStr); err != nil { |
|
if err == sql.ErrNoRows { |
|
err = nil |
|
v = nil |
|
} else { |
|
log.Error("row.Scan error(%v)", err) |
|
} |
|
return |
|
} |
|
v.Dimension, _ = d.parseDimensions(dimStr) |
|
return |
|
} |
|
|
|
// NewVideoByFn get video by filename |
|
func (d *Dao) NewVideoByFn(c context.Context, filename string) (v *archive.Video, err error) { |
|
hash64 := int64(farm.Hash64([]byte(filename))) |
|
row := d.rddb.QueryRow(c, _newVideoByFnSQL, hash64, filename) |
|
v = &archive.Video{} |
|
var dimStr string |
|
if err = row.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions, |
|
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &v.Status, &v.CTime, &v.MTime, &dimStr); err != nil { |
|
if err == sql.ErrNoRows { |
|
v = nil |
|
err = nil |
|
} else { |
|
log.Error("row.Scan error(%v)", err) |
|
} |
|
return |
|
} |
|
v.Dimension, _ = d.parseDimensions(dimStr) |
|
return |
|
} |
|
|
|
// NewCidsByFns get cids map in batches by filenames and hash64s. |
|
func (d *Dao) NewCidsByFns(c context.Context, nvs []*archive.Video) (cids map[string]int64, err error) { |
|
var ( |
|
buf bytes.Buffer |
|
hash64s []int64 |
|
) |
|
for _, v := range nvs { |
|
buf.WriteByte('\'') |
|
buf.WriteString(v.Filename) |
|
buf.WriteString("',") |
|
hash64s = append(hash64s, int64(farm.Hash64([]byte(v.Filename)))) |
|
} |
|
buf.Truncate(buf.Len() - 1) |
|
rows, err := d.rddb.Query(c, fmt.Sprintf(_newVideoDataCidsFnSQL, xstr.JoinInts(hash64s), buf.String())) |
|
if err != nil { |
|
log.Error("db.Query() error(%v)", err) |
|
return |
|
} |
|
defer rows.Close() |
|
cids = make(map[string]int64) |
|
for rows.Next() { |
|
var ( |
|
cid int64 |
|
filename string |
|
) |
|
if err = rows.Scan(&cid, &filename); err != nil { |
|
log.Error("rows.Scan error(%v)", err) |
|
return |
|
} |
|
cids[filename] = cid |
|
} |
|
return |
|
} |
|
|
|
// SimpleArcVideos get simple videos from avr |
|
func (d *Dao) SimpleArcVideos(c context.Context, aid int64) (vs []*archive.SimpleVideo, err error) { |
|
rows, err := d.rddb.Query(c, _newsimpleArcVideoSQL, aid) |
|
if err != nil { |
|
log.Error("d.videosStmt.Query(%d) error(%v)", aid, err) |
|
return |
|
} |
|
defer rows.Close() |
|
for rows.Next() { |
|
v := &archive.SimpleVideo{} |
|
if err = rows.Scan(&v.Cid, &v.Title, &v.Index, &v.Status, &v.MTime); err != nil { |
|
log.Error("rows.Scan error(%v)", err) |
|
return |
|
} |
|
vs = append(vs, v) |
|
} |
|
return |
|
} |
|
|
|
// NewVideos get videos info by aid. |
|
func (d *Dao) NewVideos(c context.Context, aid int64) (vs []*archive.Video, err error) { |
|
rows, err := d.rddb.Query(c, _newVideosSQL, aid) |
|
if err != nil { |
|
log.Error("d.videosStmt.Query(%d) error(%v)", aid, err) |
|
return |
|
} |
|
defer rows.Close() |
|
for rows.Next() { |
|
v := &archive.Video{} |
|
var ( |
|
avrState, vState int16 |
|
dimStr string |
|
) |
|
if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions, |
|
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil { |
|
log.Error("rows.Scan error(%v)", err) |
|
return |
|
} |
|
v.Dimension, _ = d.parseDimensions(dimStr) |
|
// 2 state map to 1 |
|
if avrState == archive.VideoStatusDelete { |
|
v.Status = archive.VideoStatusDelete |
|
} else { |
|
v.Status = vState |
|
} |
|
vs = append(vs, v) |
|
} |
|
return |
|
} |
|
|
|
// NewVideoMap get video map info by aid. |
|
func (d *Dao) NewVideoMap(c context.Context, aid int64) (vm map[string]*archive.Video, cvm map[int64]*archive.Video, err error) { |
|
rows, err := d.rddb.Query(c, _newVideosSQL, aid) |
|
if err != nil { |
|
log.Error("d.videosStmt.Query(%d) error(%v)", aid, err) |
|
return |
|
} |
|
defer rows.Close() |
|
vm = make(map[string]*archive.Video) |
|
cvm = make(map[int64]*archive.Video) |
|
for rows.Next() { |
|
v := &archive.Video{} |
|
var ( |
|
avrState, vState int16 |
|
dimStr string |
|
) |
|
if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions, |
|
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil { |
|
log.Error("rows.Scan error(%v)", err) |
|
return |
|
} |
|
v.Dimension, _ = d.parseDimensions(dimStr) |
|
// 2 state map to 1 |
|
if avrState == archive.VideoStatusDelete { |
|
v.Status = archive.VideoStatusDelete |
|
} else { |
|
v.Status = vState |
|
} |
|
cvm[v.Cid] = v |
|
vm[v.Filename] = v |
|
} |
|
return |
|
} |
|
|
|
// NewVideoByCID get video by cid. |
|
func (d *Dao) NewVideoByCID(c context.Context, cid int64) (v *archive.Video, err error) { |
|
row := d.rddb.QueryRow(c, _newvideoCidSQL, cid) |
|
v = &archive.Video{} |
|
var ( |
|
avrState, vState int16 |
|
dimStr string |
|
) |
|
if err = row.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions, |
|
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil { |
|
if err == sql.ErrNoRows { |
|
v = nil |
|
err = nil |
|
} |
|
log.Error("row.Scan error(%v)", err) |
|
return |
|
} |
|
v.Dimension, _ = d.parseDimensions(dimStr) |
|
// 2 state map to 1 |
|
if avrState == archive.VideoStatusDelete { |
|
v.Status = archive.VideoStatusDelete |
|
} else { |
|
v.Status = vState |
|
} |
|
return |
|
} |
|
|
|
// NewVideosByCID multi get video by cids. |
|
func (d *Dao) NewVideosByCID(c context.Context, cids []int64) (vm map[int64]map[int64]*archive.Video, err error) { |
|
rows, err := d.rddb.Query(c, fmt.Sprintf(_newVideosCidSQL, xstr.JoinInts(cids))) |
|
if err != nil { |
|
log.Error("db.Query() error(%v)", err) |
|
return |
|
} |
|
defer rows.Close() |
|
vm = make(map[int64]map[int64]*archive.Video) |
|
for rows.Next() { |
|
var ( |
|
avrState, vState int16 |
|
dimStr string |
|
) |
|
v := &archive.Video{} |
|
if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions, |
|
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil { |
|
log.Error("rows.Scan error(%v)", err) |
|
return |
|
} |
|
v.Dimension, _ = d.parseDimensions(dimStr) |
|
// 2 state map to 1 |
|
if avrState == archive.VideoStatusDelete { |
|
v.Status = archive.VideoStatusDelete |
|
} else { |
|
v.Status = vState |
|
} |
|
if vv, ok := vm[v.Aid]; !ok { |
|
vm[v.Aid] = map[int64]*archive.Video{ |
|
v.Cid: v, |
|
} |
|
} else { |
|
vv[v.Cid] = v |
|
} |
|
} |
|
return |
|
} |
|
|
|
// NewVideosByFn multi get video by filenames. |
|
func (d *Dao) NewVideosByFn(c context.Context, fns []string) (vm map[int64]map[string]*archive.Video, err error) { |
|
var ( |
|
buf bytes.Buffer |
|
hash64s []int64 |
|
) |
|
for _, fn := range fns { |
|
buf.WriteByte('\'') |
|
buf.WriteString(fn) |
|
buf.WriteString("',") |
|
hash64s = append(hash64s, int64(farm.Hash64([]byte(fn)))) |
|
} |
|
buf.Truncate(buf.Len() - 1) |
|
rows, err := d.rddb.Query(c, fmt.Sprintf(_newVideosFnSQL, xstr.JoinInts(hash64s), buf.String())) |
|
if err != nil { |
|
log.Error("db.Query() error(%v)", err) |
|
return |
|
} |
|
defer rows.Close() |
|
vm = make(map[int64]map[string]*archive.Video) |
|
for rows.Next() { |
|
var ( |
|
avrState, vState int16 |
|
dimStr string |
|
) |
|
v := &archive.Video{} |
|
if err = rows.Scan(&v.ID, &v.Filename, &v.Cid, &v.Aid, &v.Title, &v.Desc, &v.SrcType, &v.Duration, &v.Filesize, &v.Resolutions, |
|
&v.Playurl, &v.FailCode, &v.Index, &v.Attribute, &v.XcodeState, &avrState, &vState, &v.CTime, &v.MTime, &dimStr); err != nil { |
|
log.Error("rows.Scan error(%v)", err) |
|
return |
|
} |
|
v.Dimension, _ = d.parseDimensions(dimStr) |
|
// 2 state map to 1 |
|
if avrState == archive.VideoStatusDelete { |
|
v.Status = archive.VideoStatusDelete |
|
} else { |
|
v.Status = vState |
|
} |
|
if vv, ok := vm[v.Aid]; !ok { |
|
vm[v.Aid] = map[string]*archive.Video{ |
|
v.Filename: v, |
|
} |
|
} else { |
|
vv[v.Filename] = v |
|
} |
|
} |
|
return |
|
} |
|
|
|
// CheckNewVideosTimeout check 48 timeout by add filenames. |
|
func (d *Dao) CheckNewVideosTimeout(c context.Context, fns []string) (has bool, filename string, err error) { |
|
var ( |
|
buf bytes.Buffer |
|
hash64s []int64 |
|
) |
|
for _, fn := range fns { |
|
buf.WriteByte('\'') |
|
buf.WriteString(fn) |
|
buf.WriteString("',") |
|
hash64s = append(hash64s, int64(farm.Hash64([]byte(fn)))) |
|
} |
|
buf.Truncate(buf.Len() - 1) |
|
rows, err := d.rddb.Query(c, fmt.Sprintf(_newVideosTimeoutSQL, xstr.JoinInts(hash64s), buf.String())) |
|
if err != nil { |
|
log.Error("db.Query() error(%v)", err) |
|
return |
|
} |
|
defer rows.Close() |
|
now := time.Now().Unix() |
|
for rows.Next() { |
|
v := &archive.VideoFn{} |
|
if err = rows.Scan(&v.Cid, &v.Filename, &v.CTime, &v.MTime); err != nil { |
|
log.Error("rows.Scan error(%v)", err) |
|
return |
|
} |
|
if now-v.CTime.Time().Unix() > archive.VideoFilenameTimeout { |
|
log.Error("this video filename(%v) timeout (%+v)", v.Filename, v) |
|
has = true |
|
filename = v.Filename |
|
err = nil |
|
return |
|
} |
|
} |
|
return |
|
} |
|
|
|
// NewVideosReason get videos audit reason. |
|
func (d *Dao) NewVideosReason(c context.Context, aid int64) (res map[int64]string, err error) { |
|
rows, err := d.rddb.Query(c, _newVidReasonSQL, aid) |
|
if err != nil { |
|
log.Error("d.vdoRsnStmt.Query(%d)|error(%v)", aid, err) |
|
return |
|
} |
|
defer rows.Close() |
|
res = make(map[int64]string) |
|
for rows.Next() { |
|
var ( |
|
vid int64 |
|
reason string |
|
) |
|
if err = rows.Scan(&vid, &reason); err != nil { |
|
log.Error("rows.Scan error(%v)", err) |
|
return |
|
} |
|
res[vid] = reason |
|
} |
|
return |
|
} |
|
|
|
// parseDimensions 解析分辨率 |
|
func (d *Dao) parseDimensions(dim string) (dimensions *archive.Dimension, err error) { |
|
dimensions = &archive.Dimension{} |
|
if dim == "" || dim == "0,0,0" { |
|
return |
|
} |
|
dims, err := xstr.SplitInts(dim) |
|
if err != nil { |
|
log.Error("d.parseDimensions() xstr.SplitInts(%s) error(%v)", dim, err) |
|
return |
|
} |
|
if len(dims) != 3 { |
|
return |
|
} |
|
dimensions = &archive.Dimension{ |
|
Width: dims[0], |
|
Height: dims[1], |
|
Rotate: dims[2], |
|
} |
|
return |
|
}
|
|
|