task.go 16 KB

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