1 /*
2  * Copyright 2015-2018 HuntLabs.cn
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 module hunt.sql.parser.InsertColumnsCache;
17 
18 import hunt.sql.ast.SQLExpr;
19 import hunt.sql.util.FnvHash;
20 import hunt.Long;
21 import hunt.collection;
22 
23 import std.concurrency : initOnce;
24 
25 public class InsertColumnsCache {
26     
27     static InsertColumnsCache global() {
28         __gshared InsertColumnsCache inst;
29         return initOnce!inst(new InsertColumnsCache(8192));
30     }
31 
32 
33     public HashMap!(Long, Entry) cache;
34 
35     private  Entry[]   buckets;
36     private  int       indexMask;
37 
38     public this(int tableSize){
39         this.indexMask = tableSize - 1;
40         this.buckets = new Entry[tableSize];
41         cache = new HashMap!(Long, Entry)();
42     }
43 
44     public  Entry get(long hashCode64) {
45          int bucket = (cast(int) hashCode64) & indexMask;
46         for (Entry entry = buckets[bucket]; entry !is null; entry = entry.next) {
47             if (hashCode64 == entry.hashCode64) {
48                 return entry;
49             }
50         }
51 
52         return null;
53     }
54 
55     public bool put(long hashCode64, string columnsString, string columnsFormattedString, List!(SQLExpr) columns) {
56          int bucket = (cast(int) hashCode64) & indexMask;
57 
58         for (Entry entry = buckets[bucket]; entry !is null; entry = entry.next) {
59             if (hashCode64 == entry.hashCode64) {
60                 return true;
61             }
62         }
63 
64         Entry entry = new Entry(hashCode64, columnsString, columnsFormattedString, columns, buckets[bucket]);
65         buckets[bucket] = entry;  // 并发是处理时会可能导致缓存丢失,但不影响正确性
66 
67         return false;
68     }
69 
70     public  static class Entry {
71         public  long hashCode64;
72         public  string columnsString;
73         public  string columnsFormattedString;
74         public  long columnsFormattedStringHash;
75         public  List!(SQLExpr) columns;
76         public  Entry next;
77 
78         public this(long hashCode64, string columnsString, string columnsFormattedString, List!(SQLExpr) columns, Entry next) {
79             this.hashCode64 = hashCode64;
80             this.columnsString = columnsString;
81             this.columnsFormattedString = columnsFormattedString;
82             this.columnsFormattedStringHash = FnvHash.fnv1a_64_lower(columnsFormattedString);
83             this.columns = columns;
84             this.next = next;
85         }
86     }
87 }