1 module unde.command_line.delete_command;
2 
3 import unde.global_state;
4 import unde.command_line.db;
5 
6 import std.concurrency;
7 import std.stdio;
8 
9 import berkeleydb.all;
10 
11 package void
12 delete_command_out(T)(T cgs, string cwd, ulong cmd_id)
13 if (is (T == CMDGlobalState) || is (T == GlobalState))
14 {
15     cgs.commit();
16     cgs.recommit();
17 begin:
18     Dbc cursor;
19     try
20     {
21         cursor = cgs.db_command_output.cursor(cgs.txn, 0);
22         scope(exit) cursor.close();
23 
24         Dbt key, data;
25         ulong id = 0;
26         string ks = get_key_for_command_out(command_out_key(cwd, cmd_id, 0));
27         key = ks;
28         auto res = cursor.get(&key, &data, DB_SET_RANGE);
29         if (res == DB_NOTFOUND)
30         {
31             return;
32         }
33 
34         do
35         {
36             string key_string = key.to!(string);
37             command_out_key cmd_out_key;
38             parse_key_for_command_out(key_string, cmd_out_key);
39 
40             if (cmd_out_key.cwd == cwd && cmd_out_key.cmd_id == cmd_id)
41             {
42                 cgs.OIT++;
43                 if (cgs.is_time_to_recommit())
44                 {
45                     cursor.close();
46                     cgs.recommit();
47                     cursor = cgs.db_command_output.cursor(cgs.txn, 0);
48                     res = cursor.get(&key, &data, DB_SET_RANGE);
49                     if (res == DB_NOTFOUND)
50                     {
51                         return;
52                     }
53                 }
54                 cursor.del();
55             }
56             else
57             {
58                 break;
59             }
60 
61         } while (cursor.get(&key, &data, DB_NEXT) == 0);
62     }
63     catch (DbDeadlockException exp)
64     {
65         writefln("Oops deadlock, retry");
66         cgs.abort();
67         cgs.recommit();
68         goto begin;
69     }
70 }
71 
72 private int
73 delete_cmd(CMDGlobalState cgs, string cwd, ulong cmd_id)
74 {
75     int result;
76 
77     delete_command_out(cgs, cwd, cmd_id);
78 
79     cgs.commit();
80     cgs.recommit();
81 begin:
82     try
83     {
84         string ks = get_key_for_command(command_key(cwd, cmd_id));
85         Dbt key = ks;
86         auto res = cgs.db_commands.del(cgs.txn, &key);
87     }
88     catch (DbDeadlockException exp)
89     {
90         writefln("Oops deadlock, retry");
91         cgs.abort();
92         cgs.recommit();
93         goto begin;
94     }
95 
96     return result;
97 }
98 
99 private void
100 command(string cwd, ulong cmd_id, Tid tid)
101 {
102     CMDGlobalState cgs = new CMDGlobalState();
103     try {
104         scope(exit)
105         {
106             destroy(cgs);
107         }
108         delete_cmd(cgs, cwd, cmd_id);
109         cgs.commit();
110     } catch (shared(Throwable) exc) {
111         send(tid, exc);
112     }
113 
114     writefln("Finish delete command %s ID=%d", cwd, cmd_id);
115     send(tid, thisTid);
116 }
117 
118 public int
119 delete_command(GlobalState gs, string cwd, ulong cmd_id)
120 {
121     writefln("Start delete command %s ID=%d", cwd, cmd_id);
122     auto tid = spawn(&.command, cwd, cmd_id, thisTid);
123     gs.delete_commands[tid] = cmd_id;
124     return 0;
125 }
126