1 module hunt.database.base.impl.PreparedStatementCache; 2 3 import hunt.database.base.impl.Connection; 4 5 import hunt.database.base.impl.command.CloseStatementCommand; 6 import hunt.database.base.impl.command.CommandResponse; 7 import hunt.database.base.impl.PreparedStatement; 8 import hunt.database.base.impl.SocketConnectionBase; 9 10 import hunt.collection.LinkedHashMap; 11 import hunt.collection.Map; 12 import hunt.Exceptions; 13 14 import hunt.concurrency.LinkedBlockingQueue; 15 import std.container.dlist; 16 17 /** 18 * A LRU replacement strategy cache based on {@link java.util.LinkedHashMap} for prepared statements. 19 */ 20 class PreparedStatementCache : LinkedHashMap!(string, CachedPreparedStatement) { 21 private int capacity; 22 private DbConnection conn; 23 24 this(int capacity, DbConnection conn) { 25 super(capacity, 0.75f, true); 26 this.capacity = capacity; 27 this.conn = conn; 28 } 29 30 override 31 protected bool removeEldestEntry(MapEntry!(string, CachedPreparedStatement) eldest) { 32 bool needRemove = size() > capacity; 33 CachedPreparedStatement cachedPreparedStatementToRemove = eldest.getValue(); 34 35 if (needRemove) { 36 if (cachedPreparedStatementToRemove.resp.succeeded()) { 37 // close the statement after it has been evicted from the cache 38 PreparedStatement statement = cachedPreparedStatementToRemove.resp.result(); 39 CloseStatementCommand cmd = new CloseStatementCommand(statement); 40 cmd.handler = (ar) { }; 41 conn.schedule(cmd); 42 } 43 return true; 44 } 45 return false; 46 } 47 48 bool isReady() { 49 MapEntry!(string, CachedPreparedStatement) entry = getEldestEntry(); 50 if (entry is null) { 51 return true; 52 } else { 53 return entry.getValue().resp !is null; 54 } 55 } 56 57 int getCapacity() { 58 return this.capacity; 59 } 60 61 private MapEntry!(string, CachedPreparedStatement) getEldestEntry() { 62 if (size() == 0) { 63 return null; 64 } 65 // return cast(MapEntry!(string, CachedPreparedStatement)) entrySet().toArray()[size() - 1]; 66 implementationMissing(false); 67 return null; 68 } 69 } 70 71 72 /** 73 * 74 */ 75 class CachedPreparedStatement { // : Handler!(CommandResponse!(PreparedStatement)) 76 private DList!(ResponseHandler!(PreparedStatement)) waiters; 77 CommandResponse!(PreparedStatement) resp; 78 79 this() { 80 // FIXME: Needing refactor or cleanup -@zxp at 8/13/2019, 6:27:09 PM 81 // 82 // waiters = new ArrayDeque!(ResponseHandler!(PreparedStatement))(); 83 // waiters = new LinkedBlockingQueue!(ResponseHandler!(PreparedStatement))(); 84 } 85 86 void get(ResponseHandler!(PreparedStatement) handler) { 87 if (resp !is null) { 88 handler(resp); 89 } else { 90 waiters.insertBack(handler); 91 } 92 } 93 94 // override 95 void handle(CommandResponse!(PreparedStatement) event) { 96 resp = event; 97 ResponseHandler!(PreparedStatement) waiter; 98 while(!waiters.empty()) { 99 waiter = waiters.front(); 100 waiter(resp); 101 waiters.removeFront(); 102 } 103 // while ((waiter = waiters.poll()) !is null) { 104 // waiter.handle(resp); 105 // } 106 } 107 }