|
@@ -37,7 +37,7 @@ type Importer struct {
|
|
currentstarttime time.Time
|
|
currentstarttime time.Time
|
|
}
|
|
}
|
|
|
|
|
|
-func ImportDir(datapath string, parallel int, rebuild, reload bool) (totalfilescount, totallinecount, totalrecordscount int64, totalusetime time.Duration, filescount, linescount, recordscount int64, usetime time.Duration, err error) {
|
|
|
|
|
|
+func ImportDir(datapath string, parallel int, rebuild, reload bool) (totalfilescount, totallinecount, totalrecordscount, totalretrycount int64, totalusetime time.Duration, filescount, linescount, recordscount, retrycount int64, usetime time.Duration, err error) {
|
|
concurlimt := mcfg.GetInt("odbc.concurrent.limit", 100)
|
|
concurlimt := mcfg.GetInt("odbc.concurrent.limit", 100)
|
|
importer := &Importer{
|
|
importer := &Importer{
|
|
datapath: datapath,
|
|
datapath: datapath,
|
|
@@ -52,7 +52,7 @@ func ImportDir(datapath string, parallel int, rebuild, reload bool) (totalfilesc
|
|
return importer.Import()
|
|
return importer.Import()
|
|
}
|
|
}
|
|
|
|
|
|
-func (importer *Importer) Import() (totalfilescount, totallinecount, totalrecordscount int64, totalusetime time.Duration, filescount, linescount, recordscount int64, usetime time.Duration, err error) {
|
|
|
|
|
|
+func (importer *Importer) Import() (totalfilescount, totallinecount, totalrecordscount, totalretrycount int64, totalusetime time.Duration, filescount, linescount, recordscount, retrycount int64, usetime time.Duration, err error) {
|
|
if odbc.DevPhase&odbc.DP_PROCESSCONTINUE != 0 && !importer.reload {
|
|
if odbc.DevPhase&odbc.DP_PROCESSCONTINUE != 0 && !importer.reload {
|
|
// reload
|
|
// reload
|
|
err = importer.importstatus.Load()
|
|
err = importer.importstatus.Load()
|
|
@@ -77,17 +77,20 @@ func (importer *Importer) Import() (totalfilescount, totallinecount, totalrecord
|
|
if err != nil {
|
|
if err != nil {
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
+ //
|
|
|
|
+ logger.Info("graph data import start")
|
|
|
|
+
|
|
totalusetime = importer.importstatus.TotalUseTime
|
|
totalusetime = importer.importstatus.TotalUseTime
|
|
importer.starttime = time.Now().Add(-totalusetime)
|
|
importer.starttime = time.Now().Add(-totalusetime)
|
|
importer.currentstarttime = time.Now()
|
|
importer.currentstarttime = time.Now()
|
|
|
|
|
|
reedgefile := regexp.MustCompile("(?i).*edge.*.csv")
|
|
reedgefile := regexp.MustCompile("(?i).*edge.*.csv")
|
|
- efc, elc, erc, ut, e := importer.ImportEdgeFiles(reedgefile, false)
|
|
|
|
|
|
+ efc, elc, erc, etc, ut, e := importer.ImportEdgeFiles(reedgefile, false)
|
|
if e != nil {
|
|
if e != nil {
|
|
err = e
|
|
err = e
|
|
return
|
|
return
|
|
}
|
|
}
|
|
- afc, alc, arc, ut, e := importer.ImportNonEdgeFiles(reedgefile, true)
|
|
|
|
|
|
+ afc, alc, arc, atc, ut, e := importer.ImportNonEdgeFiles(reedgefile, true)
|
|
if e != nil {
|
|
if e != nil {
|
|
err = e
|
|
err = e
|
|
return
|
|
return
|
|
@@ -96,12 +99,15 @@ func (importer *Importer) Import() (totalfilescount, totallinecount, totalrecord
|
|
for _, v := range importer.importstatus.ImportStatus {
|
|
for _, v := range importer.importstatus.ImportStatus {
|
|
totallinecount += v.LinesCount
|
|
totallinecount += v.LinesCount
|
|
totalrecordscount += v.RecordsCount
|
|
totalrecordscount += v.RecordsCount
|
|
|
|
+ totalretrycount += v.RetryCount
|
|
}
|
|
}
|
|
totallinecount += elc
|
|
totallinecount += elc
|
|
totalrecordscount += erc
|
|
totalrecordscount += erc
|
|
|
|
+ totalretrycount += etc
|
|
filescount = afc + efc
|
|
filescount = afc + efc
|
|
linescount = alc + elc
|
|
linescount = alc + elc
|
|
recordscount = arc + erc
|
|
recordscount = arc + erc
|
|
|
|
+ retrycount = atc + etc
|
|
usetime = ut
|
|
usetime = ut
|
|
totalusetime = importer.importstatus.TotalUseTime
|
|
totalusetime = importer.importstatus.TotalUseTime
|
|
|
|
|
|
@@ -110,7 +116,7 @@ func (importer *Importer) Import() (totalfilescount, totallinecount, totalrecord
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
-func (importer *Importer) ImportEdgeFiles(reedgefile *regexp.Regexp, logstatus bool) (filescount, linecount, recordscount int64, usetime time.Duration, err error) {
|
|
|
|
|
|
+func (importer *Importer) ImportEdgeFiles(reedgefile *regexp.Regexp, logstatus bool) (filescount, linecount, recordscount, retrycount int64, usetime time.Duration, err error) {
|
|
return importer.ImportFiles(func(basedir string, fpath string) FWOP {
|
|
return importer.ImportFiles(func(basedir string, fpath string) FWOP {
|
|
if !reedgefile.MatchString(filepath.Base(fpath)) {
|
|
if !reedgefile.MatchString(filepath.Base(fpath)) {
|
|
// 忽略非EDGE文件
|
|
// 忽略非EDGE文件
|
|
@@ -120,7 +126,7 @@ func (importer *Importer) ImportEdgeFiles(reedgefile *regexp.Regexp, logstatus b
|
|
}, logstatus)
|
|
}, logstatus)
|
|
}
|
|
}
|
|
|
|
|
|
-func (importer *Importer) ImportNonEdgeFiles(reedgefile *regexp.Regexp, logstatus bool) (filescount, linecount, recordscount int64, usetime time.Duration, err error) {
|
|
|
|
|
|
+func (importer *Importer) ImportNonEdgeFiles(reedgefile *regexp.Regexp, logstatus bool) (filescount, linecount, recordscount, retrycount int64, usetime time.Duration, err error) {
|
|
return importer.ImportFiles(func(basedir string, fpath string) FWOP {
|
|
return importer.ImportFiles(func(basedir string, fpath string) FWOP {
|
|
if reedgefile.MatchString(filepath.Base(fpath)) {
|
|
if reedgefile.MatchString(filepath.Base(fpath)) {
|
|
// 忽略EDGE文件
|
|
// 忽略EDGE文件
|
|
@@ -138,7 +144,7 @@ const (
|
|
FWOP_CONTINUE
|
|
FWOP_CONTINUE
|
|
)
|
|
)
|
|
|
|
|
|
-func (importer *Importer) ImportFiles(fwop func(basedir string, fpath string) FWOP, logstatus bool) (filescount, linescount, recordscount int64, usetime time.Duration, err error) {
|
|
|
|
|
|
+func (importer *Importer) ImportFiles(fwop func(basedir string, fpath string) FWOP, logstatus bool) (filescount, linescount, recordscount, retrycount int64, usetime time.Duration, err error) {
|
|
// 遍历文件目录
|
|
// 遍历文件目录
|
|
var wg sync.WaitGroup
|
|
var wg sync.WaitGroup
|
|
fw, e := filewalker.NewFileWalker([]string{importer.datapath}, ".*")
|
|
fw, e := filewalker.NewFileWalker([]string{importer.datapath}, ".*")
|
|
@@ -177,32 +183,40 @@ func (importer *Importer) ImportFiles(fwop func(basedir string, fpath string) FW
|
|
importstatus := importer.importstatus.ImportStatus[filename]
|
|
importstatus := importer.importstatus.ImportStatus[filename]
|
|
importer.importstatus.mutex.RUnlock()
|
|
importer.importstatus.mutex.RUnlock()
|
|
linefrom, blockfrom := int64(0), int64(0)
|
|
linefrom, blockfrom := int64(0), int64(0)
|
|
|
|
+ totalretrycount := int64(0)
|
|
if importstatus != nil {
|
|
if importstatus != nil {
|
|
- linefrom, blockfrom = importstatus.LinesCount, importstatus.RecordsCount
|
|
|
|
|
|
+ linefrom, blockfrom, totalretrycount = importstatus.LinesCount, importstatus.RecordsCount, importstatus.RetryCount
|
|
}
|
|
}
|
|
if linefrom == 0 {
|
|
if linefrom == 0 {
|
|
logger.Info("import", "file", filename)
|
|
logger.Info("import", "file", filename)
|
|
} else {
|
|
} else {
|
|
logger.Info("import", "file", filename, "from line", linefrom)
|
|
logger.Info("import", "file", filename, "from line", linefrom)
|
|
}
|
|
}
|
|
- lines, records, e := importer.ImportFile(filename, linefrom, blockfrom, logstatus)
|
|
|
|
|
|
+ lines, records, retries, e := importer.ImportFile(filename, linefrom, blockfrom, totalretrycount, logstatus)
|
|
if e != nil {
|
|
if e != nil {
|
|
err = e
|
|
err = e
|
|
return
|
|
return
|
|
}
|
|
}
|
|
atomic.AddInt64(&linescount, lines-linefrom)
|
|
atomic.AddInt64(&linescount, lines-linefrom)
|
|
atomic.AddInt64(&recordscount, records-blockfrom)
|
|
atomic.AddInt64(&recordscount, records-blockfrom)
|
|
|
|
+ atomic.AddInt64(&retrycount, retries-totalretrycount)
|
|
usetime = time.Since(importer.currentstarttime)
|
|
usetime = time.Since(importer.currentstarttime)
|
|
importer.importstatus.mutex.Lock()
|
|
importer.importstatus.mutex.Lock()
|
|
if logstatus {
|
|
if logstatus {
|
|
importer.importstatus.ImportStatus[filename] = &ImportStatus{
|
|
importer.importstatus.ImportStatus[filename] = &ImportStatus{
|
|
LinesCount: lines,
|
|
LinesCount: lines,
|
|
- RecordsCount: records}
|
|
|
|
|
|
+ RecordsCount: records,
|
|
|
|
+ RetryCount: retries,
|
|
|
|
+ }
|
|
}
|
|
}
|
|
importer.importstatus.TotalUseTime = time.Since(importer.starttime)
|
|
importer.importstatus.TotalUseTime = time.Since(importer.starttime)
|
|
importer.importstatus.mutex.Unlock()
|
|
importer.importstatus.mutex.Unlock()
|
|
importer.importstatus.Save()
|
|
importer.importstatus.Save()
|
|
- logger.Info("file", filename, "imported", records, "records")
|
|
|
|
|
|
+ if totalretrycount > 0 {
|
|
|
|
+ logger.Info("file", filename, "total imported", lines, "lines", records, "records", retries, "retry times")
|
|
|
|
+ } else {
|
|
|
|
+ logger.Info("file", filename, "total imported", lines, "lines", records, "records")
|
|
|
|
+ }
|
|
},
|
|
},
|
|
)
|
|
)
|
|
return true
|
|
return true
|
|
@@ -219,16 +233,16 @@ func (importer *Importer) ImportFiles(fwop func(basedir string, fpath string) FW
|
|
return
|
|
return
|
|
}
|
|
}
|
|
|
|
|
|
-func (importer *Importer) ImportFile(filepath string, linefrom, blockfrom int64, logstatus bool) (linecount, blockcount int64, err error) {
|
|
|
|
|
|
+func (importer *Importer) ImportFile(filepath string, linefrom, blockfrom, totalretrycount int64, logstatus bool) (linecount, blockcount, retrycount int64, err error) {
|
|
f, e := os.Open(filepath)
|
|
f, e := os.Open(filepath)
|
|
if e != nil {
|
|
if e != nil {
|
|
- return linecount, blockcount, merrs.NewError(e, merrs.SSMaps{{"filename": filepath}})
|
|
|
|
|
|
+ return linecount, blockcount, retrycount, merrs.NewError(e, merrs.SSMaps{{"filename": filepath}})
|
|
}
|
|
}
|
|
defer f.Close()
|
|
defer f.Close()
|
|
- return importer.importReader(filepath, f, linefrom, blockfrom, logstatus)
|
|
|
|
|
|
+ return importer.importReader(filepath, f, linefrom, blockfrom, totalretrycount, logstatus)
|
|
}
|
|
}
|
|
|
|
|
|
-func (importer *Importer) importReader(filename string, buf io.Reader, linefrom, blockfrom int64, logstatus bool) (linecount, blockcount int64, err error) {
|
|
|
|
|
|
+func (importer *Importer) importReader(filename string, buf io.Reader, linefrom, blockfrom, totalretrycount int64, logstatus bool) (linecount, blockcount, retrycount int64, err error) {
|
|
var filetype schema.FileType
|
|
var filetype schema.FileType
|
|
switch {
|
|
switch {
|
|
case strings.Contains(filename, "_L1_"):
|
|
case strings.Contains(filename, "_L1_"):
|
|
@@ -257,7 +271,7 @@ func (importer *Importer) importReader(filename string, buf io.Reader, linefrom,
|
|
}
|
|
}
|
|
br, e := reader.NewBlockReader(filename, filetype, buf)
|
|
br, e := reader.NewBlockReader(filename, filetype, buf)
|
|
if e != nil {
|
|
if e != nil {
|
|
- return linecount, blockcount, merrs.NewError(e, merrs.SSMaps{{"filename": filename}})
|
|
|
|
|
|
+ return linecount, blockcount, retrycount, merrs.NewError(e, merrs.SSMaps{{"filename": filename}})
|
|
}
|
|
}
|
|
lastlogtime := time.Now()
|
|
lastlogtime := time.Now()
|
|
skiplines := int(linefrom)
|
|
skiplines := int(linefrom)
|
|
@@ -268,12 +282,12 @@ func (importer *Importer) importReader(filename string, buf io.Reader, linefrom,
|
|
defer wg.Wait()
|
|
defer wg.Wait()
|
|
for {
|
|
for {
|
|
if err != nil {
|
|
if err != nil {
|
|
- break
|
|
|
|
|
|
+ return
|
|
}
|
|
}
|
|
block, line, linenumber, e := br.ReadBlock(skiplines)
|
|
block, line, linenumber, e := br.ReadBlock(skiplines)
|
|
linecount = int64(linenumber)
|
|
linecount = int64(linenumber)
|
|
if e != nil {
|
|
if e != nil {
|
|
- return linecount, blockcount, merrs.NewError(e, merrs.SSMaps{{"filename": filename}, {"linecount": fmt.Sprint(linecount)}, {"line": line}})
|
|
|
|
|
|
+ return linecount, blockcount, retrycount, merrs.NewError(e, merrs.SSMaps{{"filename": filename}, {"linecount": fmt.Sprint(linecount)}, {"line": line}})
|
|
}
|
|
}
|
|
if block == nil {
|
|
if block == nil {
|
|
return
|
|
return
|
|
@@ -287,7 +301,11 @@ func (importer *Importer) importReader(filename string, buf io.Reader, linefrom,
|
|
}
|
|
}
|
|
e = importer.odbcqueryrc.ConcurCall(1, func() {
|
|
e = importer.odbcqueryrc.ConcurCall(1, func() {
|
|
defer wg.Done()
|
|
defer wg.Done()
|
|
- e = importer.importRecord(block, line, filename, filetype, int(doingline))
|
|
|
|
|
|
+ if err != nil {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ rc, e := importer.importRecord(block, line, filename, filetype, int(doingline))
|
|
|
|
+ atomic.AddInt64(&retrycount, int64(rc))
|
|
if e != nil {
|
|
if e != nil {
|
|
err = merrs.NewError(e, merrs.SSMaps{{"filename": filename}, {"linecount": fmt.Sprint(doingline)}, {"line": line}})
|
|
err = merrs.NewError(e, merrs.SSMaps{{"filename": filename}, {"linecount": fmt.Sprint(doingline)}, {"line": line}})
|
|
return
|
|
return
|
|
@@ -298,12 +316,17 @@ func (importer *Importer) importReader(filename string, buf io.Reader, linefrom,
|
|
importer.importstatus.ImportStatus[filename] = &ImportStatus{
|
|
importer.importstatus.ImportStatus[filename] = &ImportStatus{
|
|
LinesCount: doingline,
|
|
LinesCount: doingline,
|
|
RecordsCount: doingblock,
|
|
RecordsCount: doingblock,
|
|
|
|
+ RetryCount: retrycount,
|
|
}
|
|
}
|
|
importer.importstatus.TotalUseTime = time.Since(importer.starttime)
|
|
importer.importstatus.TotalUseTime = time.Since(importer.starttime)
|
|
importer.importstatus.Save()
|
|
importer.importstatus.Save()
|
|
doinglines = doinglines[1:]
|
|
doinglines = doinglines[1:]
|
|
if time.Since(lastlogtime) > 5*time.Second {
|
|
if time.Since(lastlogtime) > 5*time.Second {
|
|
- logger.Info("file", filename, "imported", doingblock, "records")
|
|
|
|
|
|
+ if retrycount > 0 {
|
|
|
|
+ logger.Info("file", filename, "imported", doingline, "lines", doingblock, "records", retrycount, "retry times")
|
|
|
|
+ } else {
|
|
|
|
+ logger.Info("file", filename, "imported", doingline, "lines", doingblock, "records")
|
|
|
|
+ }
|
|
lastlogtime = time.Now()
|
|
lastlogtime = time.Now()
|
|
}
|
|
}
|
|
importer.importstatus.mutex.Unlock()
|
|
importer.importstatus.mutex.Unlock()
|
|
@@ -317,17 +340,16 @@ func (importer *Importer) importReader(filename string, buf io.Reader, linefrom,
|
|
}
|
|
}
|
|
})
|
|
})
|
|
if e != nil {
|
|
if e != nil {
|
|
- return linecount, blockcount, merrs.NewError(e, merrs.SSMaps{{"filename": filename}, {"linecount": fmt.Sprint(linecount)}, {"line": line}})
|
|
|
|
|
|
+ return linecount, blockcount, retrycount, merrs.NewError(e, merrs.SSMaps{{"filename": filename}, {"linecount": fmt.Sprint(linecount)}, {"line": line}})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- return
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-func (importer *Importer) importRecord(record map[string]any, line string, filename string, filetype schema.FileType, linecount int) (err error) {
|
|
|
|
|
|
+func (importer *Importer) importRecord(record map[string]any, line string, filename string, filetype schema.FileType, linecount int) (retrycount int, err error) {
|
|
if odbc.LogDebug {
|
|
if odbc.LogDebug {
|
|
bs, e := json.MarshalIndent(record, "", " ")
|
|
bs, e := json.MarshalIndent(record, "", " ")
|
|
if e != nil {
|
|
if e != nil {
|
|
- return merrs.NewError(e)
|
|
|
|
|
|
+ return 0, merrs.NewError(e)
|
|
}
|
|
}
|
|
logger.Debug(fmt.Sprint("import ", filename, "[", linecount, "]:", string(bs)))
|
|
logger.Debug(fmt.Sprint("import ", filename, "[", linecount, "]:", string(bs)))
|
|
}
|
|
}
|
|
@@ -337,7 +359,7 @@ func (importer *Importer) importRecord(record map[string]any, line string, filen
|
|
graph.CacheEdgeInfo(record)
|
|
graph.CacheEdgeInfo(record)
|
|
default:
|
|
default:
|
|
classaliasname = string(filetype)
|
|
classaliasname = string(filetype)
|
|
- err = importer.odbcimporter.InsertData(classaliasname, record)
|
|
|
|
|
|
+ retrycount, err = importer.odbcimporter.InsertData(classaliasname, record)
|
|
if err != nil {
|
|
if err != nil {
|
|
err = merrs.NewError(err, merrs.SSMaps{{"filename": filename}, {"linecount": fmt.Sprint(linecount)}, {"line": line}})
|
|
err = merrs.NewError(err, merrs.SSMaps{{"filename": filename}, {"linecount": fmt.Sprint(linecount)}, {"line": line}})
|
|
return
|
|
return
|