task.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658
  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "log"
  6. mu "mfw/util"
  7. "qfw/util"
  8. "regexp"
  9. "strings"
  10. "sync"
  11. "time"
  12. "github.com/robfig/cron"
  13. "go.mongodb.org/mongo-driver/bson/primitive"
  14. )
  15. /**
  16. 任务入口
  17. 全量、增量合并
  18. 更新、插入,内存清理
  19. 转换成info对象
  20. **/
  21. //项目合并对象
  22. type ProjectTask struct {
  23. InitMinTime int64 //最小时间,小于0的处理一次
  24. name string
  25. thread int //线程数
  26. //查找锁
  27. findLock sync.Mutex
  28. wg sync.WaitGroup
  29. //map锁
  30. AllIdsMapLock sync.Mutex
  31. //对应的id
  32. AllIdsMap map[string]*ID
  33. //采购单位、项目名称、项目编号
  34. mapPb, mapPn, mapPc map[string]*Key
  35. // mapPbLock, mapPnLock, mapPcLock sync.Mutex
  36. //更新或新增通道
  37. updatePool chan []map[string]interface{}
  38. //savePool chan map[string]interface{}
  39. //saveSign, updateSign chan bool
  40. //表名
  41. coll string
  42. //当前状态是全量还是增量
  43. currentType string //当前是跑全量还是跑增量
  44. //
  45. clearContimes int
  46. //当前时间
  47. currentTime int64
  48. //保存长度
  49. saveSize int
  50. pici int64
  51. validTime int64
  52. // LockPool chan *sync.Mutex
  53. // LockPoolLock sync.Mutex
  54. // m1, m23, m4 map[int]int
  55. // l1, l23, l4 map[int]*sync.Mutex
  56. }
  57. func NewPT() *ProjectTask {
  58. p := &ProjectTask{
  59. InitMinTime: int64(1325347200),
  60. name: "全/增量对象",
  61. thread: 4,
  62. updatePool: make(chan []map[string]interface{}, 5000),
  63. //savePool: make(chan map[string]interface{}, 2000),
  64. wg: sync.WaitGroup{},
  65. AllIdsMap: make(map[string]*ID, 5000000),
  66. mapPb: make(map[string]*Key, 1500000),
  67. mapPn: make(map[string]*Key, 5000000),
  68. mapPc: make(map[string]*Key, 5000000),
  69. saveSize: 400,
  70. //saveSign: make(chan bool, 1),
  71. //updateSign: make(chan bool, 1),
  72. coll: ProjectColl,
  73. validTime: int64(util.IntAllDef(Sysconfig["validdays"], 150) * 86400),
  74. }
  75. return p
  76. }
  77. var P_QL *ProjectTask
  78. //初始化全量合并对象
  79. func init() {
  80. P_QL = NewPT()
  81. log.Println(len(P_QL.updatePool))
  82. go P_QL.updateAllQueue()
  83. go P_QL.clearMem()
  84. }
  85. func (p *ProjectTask) updateAllQueue() {
  86. arru := make([][]map[string]interface{}, p.saveSize)
  87. indexu := 0
  88. sp := make(chan bool, 5)
  89. for {
  90. select {
  91. case v := <-p.updatePool:
  92. arru[indexu] = v
  93. indexu++
  94. if indexu == p.saveSize {
  95. sp <- true
  96. go func(arru [][]map[string]interface{}) {
  97. defer func() {
  98. <-sp
  99. }()
  100. MongoTool.UpSertBulk(p.coll, arru...)
  101. }(arru)
  102. arru = make([][]map[string]interface{}, p.saveSize)
  103. indexu = 0
  104. }
  105. case <-time.After(1000 * time.Millisecond):
  106. if indexu > 0 {
  107. sp <- true
  108. go func(arru [][]map[string]interface{}) {
  109. defer func() {
  110. <-sp
  111. }()
  112. MongoTool.UpSertBulk(p.coll, arru...)
  113. }(arru[:indexu])
  114. arru = make([][]map[string]interface{}, p.saveSize)
  115. indexu = 0
  116. }
  117. }
  118. }
  119. }
  120. //项目合并内存更新
  121. func (p *ProjectTask) clearMem() {
  122. c := cron.New()
  123. //在内存中保留最近6个月的信息
  124. //跑全量时每4分钟跑一次,跑增量时400分钟跑一次
  125. c.AddFunc("50 0/15 * * * *", func() {
  126. if p.currentType == "ql" || p.clearContimes >= 60 {
  127. //跳过的次数清零
  128. p.clearContimes = 0
  129. //信息进入查找对比全局锁
  130. p.findLock.Lock()
  131. //defer p.findLock.Unlock()
  132. //合并进行的任务都完成
  133. p.wg.Wait()
  134. //遍历id
  135. //所有内存中的项目信息
  136. p.AllIdsMapLock.Lock()
  137. //清除计数
  138. clearNum := 0
  139. for k, v := range p.AllIdsMap {
  140. if p.currentTime-v.P.LastTime > p.validTime {
  141. clearNum++
  142. //删除id的map
  143. delete(p.AllIdsMap, k)
  144. //删除pb
  145. if v.P.Buyer != "" {
  146. ids := p.mapPb[v.P.Buyer]
  147. if ids != nil {
  148. ids.Lock.Lock()
  149. ids.Arr = deleteSlice(ids.Arr, k)
  150. if len(ids.Arr) == 0 {
  151. delete(p.mapPb, v.P.Buyer)
  152. }
  153. ids.Lock.Unlock()
  154. }
  155. }
  156. //删除mapPn
  157. for _, vn := range append([]string{v.P.ProjectName}, v.P.MPN...) {
  158. if vn != "" {
  159. ids := p.mapPn[vn]
  160. if ids != nil {
  161. ids.Lock.Lock()
  162. ids.Arr = deleteSlice(ids.Arr, k)
  163. if len(ids.Arr) == 0 {
  164. delete(p.mapPn, vn)
  165. }
  166. ids.Lock.Unlock()
  167. }
  168. }
  169. }
  170. //删除mapPc
  171. for _, vn := range append([]string{v.P.ProjectCode}, v.P.MPC...) {
  172. if vn != "" {
  173. ids := p.mapPc[vn]
  174. if ids != nil {
  175. ids.Lock.Lock()
  176. ids.Arr = deleteSlice(ids.Arr, k)
  177. if len(ids.Arr) == 0 {
  178. delete(p.mapPc, vn)
  179. }
  180. ids.Lock.Unlock()
  181. }
  182. }
  183. }
  184. v = nil
  185. }
  186. }
  187. p.AllIdsMapLock.Unlock()
  188. p.findLock.Unlock()
  189. log.Println("清除完成:", clearNum, len(p.AllIdsMap), len(p.mapPn), len(p.mapPc), len(p.mapPb))
  190. } else {
  191. p.clearContimes++
  192. }
  193. })
  194. c.Start()
  195. select {}
  196. }
  197. //全量合并
  198. func (p *ProjectTask) taskQl(udpInfo map[string]interface{}) {
  199. defer util.Catch()
  200. //1、检查pubilshtime索引
  201. db, _ := udpInfo["db"].(string)
  202. if db == "" {
  203. db = MongoTool.DbName
  204. }
  205. coll, _ := udpInfo["coll"].(string)
  206. if coll == "" {
  207. coll = ExtractColl
  208. }
  209. thread := util.IntAllDef(udpInfo["thread"], 4)
  210. if thread > 0 {
  211. p.thread = thread
  212. }
  213. q, _ := udpInfo["query"].(map[string]interface{})
  214. if q == nil {
  215. q = map[string]interface{}{}
  216. lteid, _ := udpInfo["lteid"].(string)
  217. var idmap map[string]interface{}
  218. if len(lteid) > 15 {
  219. idmap = map[string]interface{}{
  220. "$lte": StringTOBsonId(lteid),
  221. }
  222. }
  223. gtid, _ := udpInfo["gtid"].(string)
  224. if len(gtid) > 15 {
  225. if idmap == nil {
  226. idmap = map[string]interface{}{}
  227. }
  228. idmap["$gt"] = StringTOBsonId(gtid)
  229. }
  230. if idmap != nil {
  231. q["_id"] = idmap
  232. }
  233. }
  234. //生成查询语句执行
  235. log.Println("查询语句:", q)
  236. p.enter(db, coll, q)
  237. }
  238. //增量合并
  239. func (p *ProjectTask) taskZl(udpInfo map[string]interface{}) {
  240. defer util.Catch()
  241. //1、检查pubilshtime索引
  242. db, _ := udpInfo["db"].(string)
  243. if db == "" {
  244. db = MongoTool.DbName
  245. }
  246. coll, _ := udpInfo["coll"].(string)
  247. if coll == "" {
  248. coll = ExtractColl
  249. }
  250. thread := util.IntAllDef(udpInfo["thread"], 4)
  251. if thread > 0 {
  252. p.thread = thread
  253. }
  254. //开始id和结束id
  255. q, _ := udpInfo["query"].(map[string]interface{})
  256. gtid := udpInfo["gtid"].(string)
  257. lteid := udpInfo["lteid"].(string)
  258. if q == nil {
  259. q = map[string]interface{}{
  260. "_id": map[string]interface{}{
  261. "$gt": StringTOBsonId(gtid),
  262. "$lte": StringTOBsonId(lteid),
  263. },
  264. }
  265. }
  266. if q != nil {
  267. //生成查询语句执行
  268. p.enter(db, coll, q)
  269. }
  270. for {
  271. if len(P_QL.updatePool) > 0 {
  272. log.Println("等待调用udp", len(P_QL.updatePool))
  273. time.Sleep(1 * time.Second)
  274. } else {
  275. break
  276. }
  277. }
  278. if udpInfo["stop"] == nil {
  279. nextNode(udpInfo, p.pici)
  280. }
  281. }
  282. func StringTOBsonId(id string) primitive.ObjectID {
  283. objectId, _ := primitive.ObjectIDFromHex(id)
  284. return objectId
  285. }
  286. //通知下个节点nextNode
  287. func nextNode(mapInfo map[string]interface{}, pici int64) {
  288. mapInfo["stype"] = "project"
  289. mapInfo["query"] = map[string]interface{}{
  290. "pici": pici,
  291. }
  292. for n, to := range toaddr {
  293. key := fmt.Sprintf("%d-%s-%d", pici, "project", n)
  294. mapInfo["key"] = key
  295. datas, _ := json.Marshal(mapInfo)
  296. node := &udpNode{datas, to, time.Now().Unix(), 0}
  297. udptaskmap.Store(key, node)
  298. udpclient.WriteUdp(datas, mu.OP_TYPE_DATA, to)
  299. }
  300. }
  301. func (p *ProjectTask) enter(db, coll string, q map[string]interface{}) {
  302. defer util.Catch()
  303. count, taskcount := 0, 0
  304. pool := make(chan bool, p.thread)
  305. log.Println("start project", q)
  306. sess := MongoTool.GetMgoConn()
  307. defer MongoTool.DestoryMongoConn(sess)
  308. infoPool := make(chan map[string]interface{}, 2000)
  309. over := make(chan bool)
  310. go func() {
  311. L:
  312. for {
  313. select {
  314. case tmp := <-infoPool:
  315. pool <- true
  316. taskcount++
  317. go func(tmp map[string]interface{}) {
  318. defer func() {
  319. <-pool
  320. }()
  321. if util.IntAll(tmp["repeat"]) == 0 {
  322. info := ParseInfo(tmp)
  323. if info != nil && !((info.pnbval == 1 && info.Buyer != "") || info.pnbval == 0) {
  324. p.currentTime = info.Publishtime
  325. p.startProjectMerge(info, tmp)
  326. }
  327. } else {
  328. //信息错误,进行更新
  329. }
  330. }(tmp)
  331. case <-over:
  332. break L
  333. }
  334. }
  335. }()
  336. ms := sess.DB(db).C(coll).Find(q).Sort("publishtime")
  337. if Sysconfig["hints"] != nil {
  338. ms.Hint(Sysconfig["hints"])
  339. }
  340. query := ms.Iter()
  341. //
  342. var lastid interface{}
  343. L:
  344. for {
  345. select {
  346. case <-queryClose:
  347. log.Println("receive interrupt sign")
  348. log.Println("close iter..", lastid, query.Cursor.Close(nil))
  349. queryCloseOver <- true
  350. break L
  351. default:
  352. tmp := make(map[string]interface{})
  353. if query.Next(&tmp) {
  354. lastid = tmp["_id"]
  355. if count%2000 == 0 {
  356. log.Println("current", count, lastid)
  357. }
  358. infoPool <- tmp
  359. count++
  360. } else {
  361. break L
  362. }
  363. }
  364. }
  365. time.Sleep(5 * time.Second)
  366. over <- true
  367. //阻塞
  368. for n := 0; n < p.thread; n++ {
  369. pool <- true
  370. }
  371. log.Println("所有线程执行完成...", count, taskcount)
  372. }
  373. var (
  374. //从标题获取项目编号
  375. titleGetPc = regexp.MustCompile("^([-0-9a-zA-Z第号采招政询电审竞#]{8,}[-0-9a-zA-Z#]+)")
  376. titleGetPc1 = regexp.MustCompile("[\\[【((](.{0,6}(编号|编码|项号|包号|代码|标段?号)[::为])?([-0-9a-zA-Z第号采招政询电审竞#]{5,}([\\[\\]()()][-0-9a-zA-Z第号采招审竞#]+[\\[\\]()()][-0-9a-zA-Z第号采招审竞#]+)?)[\\]】))]")
  377. titleGetPc2 = regexp.MustCompile("([-0-9a-zA-Z第号采政招询电审竞#]{8,}[-0-9a-zA-Z#]+)(.{0,5}公告)?$")
  378. //项目编号过滤
  379. pcReplace = regexp.MustCompile("([\\[【((〖〔《{﹝{](重|第?[二三四再]次.{0,4})[\\]】))〗〕》}﹞}])$|[\\[\\]【】()()〖〗〔〕《》{}﹝﹞-;{}–  ]+|(号|重|第?[二三四五再]次(招标)?)$|[ __]+|((采购)?项目|采购(项目)?)$")
  380. //项目编号只是数字或只是字母4个以下
  381. StrOrNum = regexp.MustCompile("^[0-9_-]{1,4}$|^[a-zA-Z_-]{1,4}$")
  382. //纯数字或纯字母
  383. StrOrNum2 = regexp.MustCompile("^[0-9_-]+$|^[a-zA-Z_-]+$")
  384. )
  385. func ParseInfo(tmp map[string]interface{}) (info *Info) {
  386. bys, _ := json.Marshal(tmp)
  387. var thisinfo *Info
  388. json.Unmarshal(bys, &thisinfo)
  389. if thisinfo == nil {
  390. return nil
  391. }
  392. if len(thisinfo.Topscopeclass) == 0 {
  393. thisinfo.Topscopeclass = []string{}
  394. }
  395. if len(thisinfo.Subscopeclass) == 0 {
  396. thisinfo.Subscopeclass = []string{}
  397. }
  398. //从标题中查找项目编号
  399. res := titleGetPc.FindStringSubmatch(thisinfo.Title)
  400. if len(res) > 1 && len(res[1]) > 6 && thisinfo.ProjectCode != res[1] && !numCheckPc.MatchString(res[1]) && !_zimureg1.MatchString(res[1]) {
  401. thisinfo.PTC = res[1]
  402. } else {
  403. res = titleGetPc1.FindStringSubmatch(thisinfo.Title)
  404. if len(res) > 3 && len(res[3]) > 6 && thisinfo.ProjectCode != res[3] && !numCheckPc.MatchString(res[3]) && !_zimureg1.MatchString(res[3]) {
  405. thisinfo.PTC = res[3]
  406. } else {
  407. res = titleGetPc2.FindStringSubmatch(thisinfo.Title)
  408. if len(res) > 1 && len(res[1]) > 6 && thisinfo.ProjectCode != res[1] && !numCheckPc.MatchString(res[1]) && !_zimureg1.MatchString(res[1]) {
  409. thisinfo.PTC = res[1]
  410. }
  411. }
  412. }
  413. if thisinfo.ProjectName != "" && len([]rune(thisinfo.ProjectName)) > 0 {
  414. thisinfo.ProjectName = pcReplace.ReplaceAllString(thisinfo.ProjectName, "")
  415. if thisinfo.ProjectName != "" {
  416. thisinfo.pnbval++
  417. }
  418. }
  419. if thisinfo.ProjectCode != "" || thisinfo.PTC != "" {
  420. if thisinfo.ProjectCode != "" {
  421. thisinfo.ProjectCode = pcReplace.ReplaceAllString(thisinfo.ProjectCode, "")
  422. if thisinfo.pnbval == 0 && len([]rune(thisinfo.ProjectCode)) < 5 {
  423. thisinfo.ProjectCode = StrOrNum.ReplaceAllString(thisinfo.ProjectCode, "")
  424. }
  425. } else {
  426. thisinfo.PTC = pcReplace.ReplaceAllString(thisinfo.PTC, "")
  427. if thisinfo.pnbval == 0 && len([]rune(thisinfo.PTC)) < 5 {
  428. thisinfo.PTC = StrOrNum.ReplaceAllString(thisinfo.PTC, "")
  429. }
  430. }
  431. if thisinfo.ProjectCode != "" || thisinfo.PTC != "" {
  432. thisinfo.pnbval++
  433. }
  434. }
  435. if thisinfo.ProjectCode == thisinfo.PTC || strings.Index(thisinfo.ProjectCode, thisinfo.PTC) > -1 {
  436. thisinfo.PTC = ""
  437. }
  438. if thisinfo.Buyer != "" && len([]rune(thisinfo.Buyer)) > 2 {
  439. thisinfo.pnbval++
  440. } else {
  441. thisinfo.Buyer = ""
  442. }
  443. //winners整理
  444. winner, _ := tmp["winner"].(string)
  445. m1 := map[string]bool{}
  446. winners := []string{}
  447. if winner != "" {
  448. m1[winner] = true
  449. winners = append(winners, winner)
  450. }
  451. packageM, _ := tmp["package"].(map[string]interface{})
  452. if packageM != nil {
  453. thisinfo.HasPackage = true
  454. for _, p := range packageM {
  455. pm, _ := p.(map[string]interface{})
  456. pw, _ := pm["winner"].(string)
  457. if pw != "" && !m1[pw] {
  458. m1[pw] = true
  459. winners = append(winners, pw)
  460. }
  461. }
  462. }
  463. thisinfo.Winners = winners
  464. thisinfo.LenPC = len([]rune(thisinfo.ProjectCode))
  465. thisinfo.LenPTC = len([]rune(thisinfo.PTC))
  466. thisinfo.LenPN = len([]rune(thisinfo.ProjectName))
  467. return thisinfo
  468. }
  469. //从数组中删除元素
  470. func deleteSlice(arr []string, v string) []string {
  471. for k, v1 := range arr {
  472. if v1 == v {
  473. return append(arr[:k], arr[k+1:]...)
  474. }
  475. }
  476. return arr
  477. }
  478. // if taskcount > 0 && taskcount%50000 == 0 { //歇歇
  479. // log.Println("pause start..", taskcount)
  480. // for n := 0; n < p.thread; n++ {
  481. // pool <- true
  482. // }
  483. // for n := 0; n < p.thread; n++ {
  484. // <-pool
  485. // }
  486. // log.Println("pause over..")
  487. // }
  488. //lastid = tmp["_id"]
  489. //tmp = make(map[string]interface{})
  490. // if count > 40000 {
  491. // query.Close()
  492. // break
  493. // }
  494. //over++
  495. //func (p *ProjectTask) saveQueue() {
  496. // arr := make([]map[string]interface{}, p.saveSize)
  497. // indexs := 0
  498. // for {
  499. // select {
  500. // case <-p.saveSign:
  501. // if indexs > 0 {
  502. // MongoTool.SaveBulk(p.coll, arr[:indexs]...)
  503. // arr = make([]map[string]interface{}, p.saveSize)
  504. // indexs = 0
  505. // }
  506. // p.updateSign <- true
  507. // case v := <-p.savePool:
  508. // arr[indexs] = v
  509. // indexs++
  510. // if indexs == p.saveSize {
  511. // MongoTool.SaveBulk(p.coll, arr...)
  512. // arr = make([]map[string]interface{}, p.saveSize)
  513. // indexs = 0
  514. // }
  515. // case <-time.After(100 * time.Millisecond):
  516. // if indexs > 0 {
  517. // MongoTool.SaveBulk(p.coll, arr[:indexs]...)
  518. // arr = make([]map[string]interface{}, p.saveSize)
  519. // indexs = 0
  520. // }
  521. // }
  522. // }
  523. //}
  524. ////项目保存和更新通道
  525. //func (p *ProjectTask) updateQueue() {
  526. // arru := make([][]map[string]interface{}, p.saveSize)
  527. // indexu := 0
  528. // for {
  529. // select {
  530. // case v := <-p.updatePool:
  531. // arru[indexu] = v
  532. // indexu++
  533. // if indexu == p.saveSize {
  534. // //更新之前先保存
  535. // p.saveSign <- true
  536. // <-p.updateSign
  537. // MongoTool.UpdateBulk(p.coll, arru...)
  538. // arru = make([][]map[string]interface{}, p.saveSize)
  539. // indexu = 0
  540. // }
  541. // case <-time.After(100 * time.Millisecond):
  542. // if indexu > 0 {
  543. // p.saveSign <- true
  544. // <-p.updateSign
  545. // MongoTool.UpdateBulk(p.coll, arru[:indexu]...)
  546. // arru = make([][]map[string]interface{}, p.saveSize)
  547. // indexu = 0
  548. // }
  549. // }
  550. // }
  551. //}
  552. //func (p *ProjectTask) ConCurrentLock(n1, n2, n3, n4 int) {
  553. // var lock *sync.Mutex
  554. // p.LockPoolLock.Lock()
  555. // if p.m1[n1] > 0 || p.m23[n2] > 0 || p.m23[n3] > 0 || p.m4[n4] > 0 {
  556. // if p.l1[n1] != nil {
  557. // lock = p.l1[n1]
  558. // } else if p.l23[n2] != nil {
  559. // lock = p.l23[n2]
  560. // } else if p.l23[n3] != nil {
  561. // lock = p.l23[n3]
  562. // } else if p.l4[n4] != nil {
  563. // lock = p.l4[n4]
  564. // }
  565. // } else {
  566. // lock = <-p.LockPool
  567. // }
  568. // if n1 > 0 {
  569. // p.m1[n1]++
  570. // p.l1[n1] = lock
  571. // }
  572. // if n2 > 0 {
  573. // p.m23[n2]++
  574. // p.l23[n2] = lock
  575. // }
  576. // if n3 > 0 {
  577. // p.m23[n3]++
  578. // p.l23[n3] = lock
  579. // }
  580. // if n4 > 0 {
  581. // p.m4[n4]++
  582. // p.l4[n4] = lock
  583. // }
  584. // p.LockPoolLock.Unlock()
  585. // lock.Lock()
  586. //}
  587. //func (p *ProjectTask) ConCurrentUnLock(n1, n2, n3, n4 int) {
  588. // var lock1 *sync.Mutex
  589. // p.LockPoolLock.Lock()
  590. // if p.l1[n1] != nil {
  591. // lock1 = p.l1[n1]
  592. // } else if p.l23[n2] != nil {
  593. // lock1 = p.l23[n2]
  594. // } else if p.l23[n3] != nil {
  595. // lock1 = p.l23[n3]
  596. // } else if p.l4[n4] != nil {
  597. // lock1 = p.l4[n4]
  598. // }
  599. // if p.m1[n1] > 0 {
  600. // p.m1[n1]--
  601. // if p.m1[n1] == 0 {
  602. // p.l1[n1] = nil
  603. // }
  604. // }
  605. // if p.m23[n2] > 0 {
  606. // p.m23[n2]--
  607. // if p.m23[n2] == 0 {
  608. // p.l23[n2] = nil
  609. // }
  610. // }
  611. // if p.m23[n3] > 0 {
  612. // p.m23[n3]--
  613. // if p.m23[n3] == 0 {
  614. // p.l23[n3] = nil
  615. // }
  616. // }
  617. // if p.m4[n4] > 0 {
  618. // p.m4[n4]--
  619. // if p.m4[n4] == 0 {
  620. // p.l4[n4] = nil
  621. // }
  622. // }
  623. // p.LockPoolLock.Unlock()
  624. // lock1.Unlock()
  625. //}