Release 4.0.0-preview1-00051
[platform/core/csapi/tizenfx.git] / src / Tizen.Applications.DataControl / Tizen.Applications.DataControl / Provider.cs
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
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 using System;
17 using System.IO;
18 using System.Text;
19 using System.Collections.Generic;
20 using Tizen.Applications.DataControl;
21 using System.Runtime.InteropServices;
22 using System.Threading;
23
24 namespace Tizen.Applications.DataControl
25 {
26     /// <summary>
27     /// Represents Provider class for DataControl provider application.
28     /// </summary>
29     public abstract class Provider : IDisposable
30     {
31         private const string LogTag = "Tizen.Applications.DataControl";
32         private static IDictionary<string, Provider> _providerDict = new Dictionary<string, Provider>();
33         private static Interop.DataControl.SqlRequestCallbacks _sqlRequestCallbacks;
34         private static Interop.DataControl.MapRequestCallbacks _mapRequestCallbacks;
35         private IntPtr _nativeHandle;
36         private static Interop.DataControl.DataChangeConsumerFilterCb _filterCallback;
37         private static int _filterCallbackID;
38         private static bool _filterRegistered;
39         private static Interop.DataControl.SqlBulkInsertRequestCallback _sqlBulkCallback;
40         private static Interop.DataControl.MapBulkAddRequestCallback _mapBulkCallback;
41         private static Mutex _lock = new Mutex();
42         private bool _disposed = false;
43         private bool _isRunning = false;
44
45         /// <summary>
46         /// Gets the data ID
47         /// </summary>
48         public string DataID
49         {
50             get;
51             private set;
52         }
53
54         private static bool DataChangeListenFilter(IntPtr handlePtr, string consumerAppid, IntPtr userData)
55         {
56             Provider provider;
57             DataChangeListenResult result;
58
59             provider = GetProvider(handlePtr);
60             if (provider == null)
61             {
62                 Log.Error(LogTag, "Provider not exist ");
63                 return false;
64             }
65
66             result = provider.OnDataChangeListenRequest(consumerAppid);
67             if (result == null || result.Result != ResultType.Success)
68             {
69                 return false;
70             }
71             else
72             {
73                 return true;
74             }
75         }
76
77         private enum OperationType : short
78         {
79             Select,
80             Update,
81             Insert,
82             Delete
83         }
84
85         private static string CreateSelectQuery(IntPtr handlePtr, string[] columnList, int columnCount, string where, string order, int pageNum, int countPerPage)
86         {
87             Interop.DataControl.SafeDataControlHandle handle = new Interop.DataControl.SafeDataControlHandle(handlePtr, false);
88             string query = "SELECT";
89             string dataId;
90             if (columnList == null)
91             {
92                 query += " * ";
93             }
94             else
95             {
96                 for (int i = 0; i < columnCount; i++)
97                 {
98                     if (i != 0)
99                     {
100                         query += ",";
101                     }
102
103                     query += " " + columnList[i];
104                 }
105             }
106
107             Interop.DataControl.DataControlGetDataId(handle, out dataId);
108             query += " FROM " + dataId;
109             if (where != null)
110             {
111                 query += " WHERE " + where;
112             }
113
114             if (order != null)
115             {
116                 query += " ORDER BY " + order;
117             }
118
119             if (pageNum != 0)
120             {
121                 query += " LIMIT " + countPerPage + " OFFSET " + (countPerPage * (pageNum - 1));
122             }
123             handle.Dispose();
124             return query;
125         }
126
127         private static void InsertRequest(int requestId, IntPtr handlePtr, IntPtr insertData, IntPtr userData)
128         {
129             Provider provider;
130             InsertResult result;
131             SafeBundleHandle sbh = new SafeBundleHandle(insertData, false);
132             string query = GetQuery(handlePtr, sbh, null, OperationType.Update);
133             ResultType ret;
134
135             provider = GetProvider(handlePtr);
136             if (provider == null)
137             {
138                 Log.Error(LogTag, "Provider not exist ");
139                 return;
140             }
141
142             result = provider.OnInsert(query, new Bundle(sbh));
143             if (result != null)
144             {
145                 if (result.Result)
146                 {
147                     ret = Interop.DataControl.SendInsertResult(requestId, result.RowID);
148                     if (ret != ResultType.Success)
149                     {
150                         Log.Error(LogTag, "SendInsertResult fail " + ret.ToString());
151                     }
152                 }
153                 else
154                 {
155                     ret = Interop.DataControl.SendError(requestId, result.Result.ToString());
156                     if (ret != ResultType.Success)
157                     {
158                         Log.Error(LogTag, "SendError fail " + ret.ToString());
159                     }
160                 }
161             }
162             else
163             {
164                 Log.Info(LogTag, $"InsertResult is null : {requestId.ToString()}");
165             }
166         }
167
168         private static void BulkInsertRequest(int requestId, IntPtr handlePtr, IntPtr bulk_data, IntPtr userData)
169         {
170             Provider provider;
171             BulkInsertResult result;
172             BulkData bulkData = new BulkData(new Interop.DataControl.SafeBulkDataHandle(bulk_data, false));
173             Interop.DataControl.SafeBulkDataHandle sbdh = bulkData.SafeBulkDataHandle;
174             IntPtr bundleHandel;
175             ResultType ret;
176
177             int count = bulkData.GetCount();
178             List<string> queryList = new List<string>();
179
180             for (int i = 0; i < count; i++)
181             {
182                 Interop.DataControl.BulkGetData(sbdh, i, out bundleHandel);
183                 queryList.Add(GetQuery(handlePtr, new SafeBundleHandle(bundleHandel, false), null, OperationType.Insert));
184             }
185
186             provider = GetProvider(handlePtr);
187             if (provider == null)
188             {
189                 Log.Error(LogTag, "Provider not exist ");
190                 return;
191             }
192
193             result = provider.OnBulkInsert(queryList, bulkData);
194             if (result != null)
195             {
196                 if (result.Result)
197                 {
198                     ret = Interop.DataControl.SendBulkInsertResult(requestId, result.BulkResultData.SafeBulkDataHandle);
199                     if (ret != ResultType.Success)
200                     {
201                         Log.Error(LogTag, "SendBulkInsertResult fail " + ret.ToString());
202                     }
203                 }
204                 else
205                 {
206                     ret = Interop.DataControl.SendError(requestId, result.Result.ToString());
207                     if (ret != ResultType.Success)
208                     {
209                         Log.Error(LogTag, "SendError fail " + ret.ToString());
210                     }
211                 }
212
213                 if (result.BulkResultData != null)
214                 {
215                     result.BulkResultData.Dispose();
216                 }
217             }
218             else
219             {
220                 Log.Info(LogTag, $"BulkInsertResult is null : {requestId.ToString()}");
221             }
222         }
223
224         private static void SendNativeProtocol(int socketFd, ICursor cursor, int requestId)
225         {
226             uint write_len;
227             int DATACONTROL_RESULT_NO_DATA = -1;
228             int COLUMN_TYPE_NULL = 5;
229             int column_count, i, rowcount, size = 0, total_len_of_column_names = 0;
230             byte[] type_array, length_array, string_array, int_tmp, value_array = null;
231             string txt;
232             ResultType result;
233             MemoryStream ms;
234
235             if (cursor.Reset() == false)
236             {
237                 Log.Error(LogTag, "Reset is failed  :  " + requestId.ToString());
238                 return;
239             }
240
241             if (cursor.GetRowCount() <= 0)
242             {
243                 Log.Error(LogTag, "The DB does not have another row : " + requestId.ToString());
244                 int_tmp = BitConverter.GetBytes(DATACONTROL_RESULT_NO_DATA);
245                 result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, int_tmp, int_tmp.Length, out write_len);
246                 return;
247             }
248
249             /* 1. column count */
250             column_count = cursor.GetColumnCount();
251             int_tmp = BitConverter.GetBytes(column_count);
252             result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, int_tmp, int_tmp.Length, out write_len);
253             if (result != ResultType.Success)
254             {
255                 Log.Error(LogTag, "Writing a column_count to a file descriptor is failed.");
256                 return;
257             }
258
259             Log.Info(LogTag, "Writing a column_count " + column_count.ToString());
260
261             /* 2.column type x column_count */
262             for (i = 0; i < column_count; i++)
263             {
264                 type_array = BitConverter.GetBytes((int)cursor.GetColumnType(i));
265                 result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, type_array, type_array.Length, out write_len);
266                 if (result != ResultType.Success)
267                 {
268                     Log.Error(LogTag, "Writing a type to a file descriptor is failed.");
269                     return;
270                 }
271
272                 Log.Info(LogTag, "Writing a column_type " + cursor.GetColumnType(i).ToString());
273             }
274
275             /* 3. column name x column_count */
276             for (i = 0; i < column_count; i++)
277             {
278                 Log.Info(LogTag, "Writing a name " + cursor.GetColumnName(i));
279
280                 total_len_of_column_names += cursor.GetColumnName(i).Length;
281                 string_array = Encoding.UTF8.GetBytes(cursor.GetColumnName(i));
282                 value_array = new byte[string_array.Length + 1];/*insert null */
283                 string_array.CopyTo(value_array, 0);
284                 length_array = BitConverter.GetBytes(value_array.Length);
285
286                 result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, length_array, length_array.Length, out write_len);
287                 if (result != ResultType.Success)
288                 {
289                     Log.Error(LogTag, "Writing a type to a file descriptor is failed.");
290                     return;
291                 }
292
293                 result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, value_array, value_array.Length, out write_len);
294                 if (result != ResultType.Success)
295                 {
296                     Log.Error(LogTag, "Writing a type to a file descriptor is failed.");
297                     return;
298                 }
299
300             }
301
302             /* 4. total length of column names */
303             length_array = BitConverter.GetBytes(total_len_of_column_names);
304             result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, length_array, length_array.Length, out write_len);
305             if (result != ResultType.Success)
306             {
307                 Log.Error(LogTag, "Writing a total_len_of_column_names to a file descriptor is failed");
308                 return;
309             }
310
311             Log.Info(LogTag, "Writing  total length of column namese " + total_len_of_column_names.ToString());
312
313             /* 5. row count */
314             length_array = BitConverter.GetBytes(cursor.GetRowCount());
315             Log.Error(LogTag, "=========================== select rowcount " + cursor.GetRowCount().ToString());
316             result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, length_array, length_array.Length, out write_len);
317             if (result != ResultType.Success)
318             {
319                 Log.Error(LogTag, "Writing a row count to a file descriptor is failed");
320                 return;
321             }
322
323             Log.Error(LogTag, "Writing a row count " + cursor.GetRowCount().ToString());
324
325             rowcount = 0;
326             do
327             {
328                 ms = new MemoryStream();
329
330                 for (i = 0; i < column_count; i++)
331                 {
332                     type_array = BitConverter.GetBytes((int)cursor.GetColumnType(i));
333                     switch (cursor.GetColumnType(i))
334                     {
335                         case ColumnType.ColumnTypeInt:
336                             value_array = BitConverter.GetBytes(cursor.GetInt64Value(i));
337                             size = value_array.Length;
338                             break;
339
340                         case ColumnType.ColumnTypeDouble:
341                             value_array = BitConverter.GetBytes(cursor.GetDoubleValue(i));
342                             size = value_array.Length;
343                             break;
344
345                         case ColumnType.ColumnTypeString:
346                             txt = cursor.GetStringValue(i);
347                             if (txt == null)
348                             {
349                                 type_array = BitConverter.GetBytes(COLUMN_TYPE_NULL);
350                                 size = 0;
351                                 break;
352                             }
353
354                             string_array = Encoding.UTF8.GetBytes(txt);
355                             value_array = new byte[string_array.Length + 1];/*insert null */
356                             string_array.CopyTo(value_array, 0);
357                             size = value_array.Length;
358                             break;
359
360                         case ColumnType.ColumnTypeBlob:
361                             int_tmp = cursor.GetBlobValue(i);
362                             if (int_tmp == null)
363                             {
364                                 type_array = BitConverter.GetBytes(COLUMN_TYPE_NULL);
365                                 size = 0;
366                                 break;
367                             }
368
369                             value_array = int_tmp;
370                             size = value_array.Length;
371                             break;
372                     }
373
374                     ms.Write(type_array, 0, type_array.Length);
375
376                     length_array = BitConverter.GetBytes(size);
377                     ms.Write(length_array, 0, length_array.Length);
378                     if (size > 0)
379                     {
380                         ms.Write(value_array, 0, value_array.Length);
381                     }
382                 }
383
384                 value_array = ms.ToArray();
385
386                 result = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, value_array, value_array.Length, out write_len);
387                 if (result != ResultType.Success)
388                 {
389                     Log.Error(LogTag, "Writing a row to a file descriptor is failed");
390                     ms.Dispose();
391                     return;
392                 }
393
394                 ms.Dispose();
395                 Log.Info(LogTag, "row_count ~~~~ ", rowcount.ToString());
396
397             }
398             while (cursor.Next());
399         }
400
401         private static void SelectRequest(int requestId,
402             IntPtr handlePtr, IntPtr columnList, int columnCount, string where, string order, IntPtr userData)
403         {
404             Provider provider;
405             SelectResult result;
406             int pageNum = 0;
407             int countPerPage = 0;
408             int MAX_WRITE_SIZE = 1024;  /* 1kbyte */
409             string query = null;
410             int socketFd, write_size, i;
411             uint write_len;
412             ResultType ret;
413             string[] _columnList = new string[columnCount];
414             byte[] buffer;
415
416             unsafe
417             {
418                 byte** _sbyte_columnList = (byte**)columnList;
419
420                 for (i = 0; i < columnCount; i++)
421                 {
422                     _columnList[i] = Marshal.PtrToStringAnsi((IntPtr)_sbyte_columnList[i]);
423                 }
424             }
425
426             Interop.DataControl.GetSelectPageInfo(requestId, out pageNum, out countPerPage);
427             query = CreateSelectQuery(handlePtr, _columnList, _columnList.Length, where, order, pageNum, countPerPage);
428             provider = GetProvider(handlePtr);
429             if (provider == null)
430             {
431                 Log.Error(LogTag, "Provider not exist ");
432                 return;
433             }
434
435             result = provider.OnSelect(query, where, _columnList, _columnList.Length, order, pageNum, countPerPage);
436             if (result != null)
437             {
438                 if (result.Result)
439                 {
440                     Interop.DataControl.SendSelectResult(requestId, out socketFd);
441
442                     MatrixCursor mc = result.ResultCursor as MatrixCursor;
443
444                     if (mc == null)
445                     {
446                         SendNativeProtocol(socketFd, result.ResultCursor, requestId);
447                     }
448                     else
449                     {
450                         FileStream fs = mc.GetFileStream();
451                         fs.Seek(0, SeekOrigin.Begin);
452
453                         buffer = new byte[MAX_WRITE_SIZE];
454
455                         do
456                         {
457                             write_size = fs.Read(buffer, 0, MAX_WRITE_SIZE);
458
459                             if (write_size > 0)
460                             {
461                                 ret = (ResultType)Interop.DataControl.UnsafeCode.WriteResult(socketFd, buffer, write_size, out write_len);
462                                 if (ret != ResultType.Success)
463                                 {
464                                     Log.Error(LogTag, "Writing a row to a file descriptor is failed");
465                                     mc.Dispose();
466                                     return;
467                                 }
468                             }
469                         }
470                         while (write_size > 0);
471                         mc.Dispose();
472                     }
473
474                 }
475                 else
476                 {
477                     ret = Interop.DataControl.SendError(requestId, result.Result.ToString());
478                     if (ret != ResultType.Success)
479                     {
480                         Log.Error(LogTag, "SendError fail " + ret.ToString());
481                     }
482                 }
483             }
484             else
485             {
486                 Log.Info(LogTag, $"SelectResult is null : {requestId.ToString()}");
487             }
488         }
489
490         private static void UpdateRequest(int requestId,
491             IntPtr handlePtr, IntPtr updateData, string where, IntPtr userData)
492         {
493             Provider provider;
494             UpdateResult result;
495             SafeBundleHandle sbh = new SafeBundleHandle(updateData, false);
496             string query = GetQuery(handlePtr, sbh, where, OperationType.Update);
497             ResultType ret;
498
499             provider = GetProvider(handlePtr);
500             if (provider == null)
501             {
502                 Log.Error(LogTag, "Provider not exist ");
503                 return;
504             }
505
506             result = provider.OnUpdate(query, where, new Bundle(sbh));
507             if (result != null)
508             {
509                 if (result.Result)
510                 {
511                     ret = Interop.DataControl.SendUpdateResult(requestId);
512                     if (ret != ResultType.Success)
513                     {
514                         Log.Error(LogTag, "SendUpdateResult fail " + ret.ToString());
515                     }
516                 }
517                 else
518                 {
519                     ret = Interop.DataControl.SendError(requestId, result.Result.ToString());
520                     if (ret != ResultType.Success)
521                     {
522                         Log.Error(LogTag, "SendError fail " + ret.ToString());
523                     }
524                 }
525             }
526             else
527             {
528                 Log.Info(LogTag, $"UpdateResult is null : {requestId.ToString()}");
529             }
530         }
531
532         private static void DeleteRequest(int requestId,
533             IntPtr handlePtr, string where, IntPtr userData)
534         {
535             Provider provider;
536             DeleteResult result;
537             string query = GetQuery(handlePtr, null, where, OperationType.Delete);
538             ResultType ret;
539
540             provider = GetProvider(handlePtr);
541             if (provider == null)
542             {
543                 Log.Error(LogTag, "Provider not exist ");
544                 return;
545             }
546
547             result = provider.OnDelete(query, where);
548             if (result != null)
549             {
550                 if (result.Result)
551                 {
552                    ret = Interop.DataControl.SendDeleteResult(requestId);
553                     if (ret != ResultType.Success)
554                     {
555                         Log.Error(LogTag, "SendDeleteResult fail " + ret.ToString());
556                     }
557
558                 }
559                 else
560                 {
561                     ret = Interop.DataControl.SendError(requestId, result.Result.ToString());
562                     if (ret != ResultType.Success)
563                     {
564                         Log.Error(LogTag, "SendError fail " + ret.ToString());
565                     }
566                 }
567             }
568             else
569             {
570                 Log.Info(LogTag, $"DeleteResult is null : {requestId.ToString()}");
571             }
572         }
573
574         private static void MapAddRequest(int requestId, IntPtr handlePtr, string key, string value, IntPtr userData)
575         {
576             Provider provider;
577             MapAddResult result;
578             ResultType ret;
579
580             provider = GetProvider(handlePtr);
581             if (provider == null)
582             {
583                 Log.Error(LogTag, "Provider not exist");
584                 return;
585             }
586
587             result = provider.OnMapAdd(key, value);
588             if (result != null)
589             {
590                 if (result.Result)
591                 {
592                     ret = Interop.DataControl.SendMapResult(requestId);
593                     if (ret != ResultType.Success)
594                     {
595                         Log.Error(LogTag, "SendMapResult fail " + ret.ToString());
596                     }
597                 }
598                 else
599                 {
600                     ret = Interop.DataControl.SendError(requestId, result.Result.ToString());
601                     if (ret != ResultType.Success)
602                     {
603                         Log.Error(LogTag, "SendError fail " + ret.ToString());
604                     }
605                 }
606             }
607             else
608             {
609                 Log.Info(LogTag, $"MapAddResult is null : {requestId.ToString()}");
610             }
611         }
612
613         private static void MapSetRequest(int requestId, IntPtr handlePtr, string key, string oldValue, string newValue, IntPtr userData)
614         {
615             Provider provider;
616             MapSetResult result;
617             ResultType ret;
618
619             provider = GetProvider(handlePtr);
620             if (provider == null)
621             {
622                 Log.Error(LogTag, "Provider not exist");
623                 return;
624             }
625
626             result = provider.OnMapSet(key, oldValue, newValue);
627             if (result != null)
628             {
629                 if (result.Result)
630                 {
631                     ret = Interop.DataControl.SendMapResult(requestId);
632                     if (ret != ResultType.Success)
633                     {
634                         Log.Error(LogTag, "SendMapResult fail " + ret.ToString());
635                     }
636                 }
637                 else
638                 {
639                     ret = Interop.DataControl.SendError(requestId, result.Result.ToString());
640                     if (ret != ResultType.Success)
641                     {
642                         Log.Error(LogTag, "SendError fail " + ret.ToString());
643                     }
644                 }
645             }
646             else
647             {
648                 Log.Info(LogTag, $"MapSetResult is null : {requestId.ToString()}");
649             }
650         }
651
652         private static void MapRemoveRequest(int requestId, IntPtr handlePtr, string key, string value, IntPtr userData)
653         {
654             Provider provider;
655             MapRemoveResult result;
656             ResultType ret;
657
658             provider = GetProvider(handlePtr);
659             if (provider == null)
660             {
661                 Log.Error(LogTag, "Provider not exist");
662                 return;
663             }
664
665             result = provider.OnMapRemove(key, value);
666             if (result != null)
667             {
668                 if (result.Result)
669                 {
670                     ret = Interop.DataControl.SendMapResult(requestId);
671                     if (ret != ResultType.Success)
672                     {
673                         Log.Error(LogTag, "SendMapResult fail " + ret.ToString());
674                     }
675
676                 }
677                 else
678                 {
679                     ret = Interop.DataControl.SendError(requestId, result.Result.ToString());
680                     if (ret != ResultType.Success)
681                     {
682                         Log.Error(LogTag, "SendError fail " + ret.ToString());
683                     }
684                 }
685             }
686             else
687             {
688                 Log.Info(LogTag, $"MapRemoveRequest is null : {requestId.ToString()}");
689             }
690         }
691
692         private static void MapGetRequest(int requestID, IntPtr handlePtr, string key, IntPtr userData)
693         {
694             Provider provider;
695             MapGetResult result;
696             ResultType ret;
697
698             provider = GetProvider(handlePtr);
699             if (provider == null)
700             {
701                 Log.Error(LogTag, "Provider not exist");
702                 return;
703             }
704
705             result = provider.OnMapGet(key);
706             if (result != null)
707             {
708                 if (result.Result)
709                 {
710                     int valueCount = 0;
711                     if (result.ValueList != null)
712                         valueCount = result.ValueList.Length;
713                     ret = Interop.DataControl.SendMapGetResult(requestID, result.ValueList, valueCount);
714                     if (ret != ResultType.Success)
715                     {
716                         Log.Error(LogTag, "SendMapGetResult fail " + ret.ToString());
717                     }
718
719                 }
720                 else
721                 {
722                     ret = Interop.DataControl.SendError(requestID, result.Result.ToString());
723                     if (ret != ResultType.Success)
724                     {
725                         Log.Error(LogTag, "SendError fail " + ret.ToString());
726                     }
727                 }
728             }
729             else
730             {
731                 Log.Info(LogTag, $"MapRemoveRequest is null : {requestID.ToString()}");
732             }
733         }
734
735         private static void MapBulkAddRequest(int requestID, IntPtr handlePtr, IntPtr bulkDataPtr, IntPtr userData)
736         {
737             Provider provider;
738             MapBulkAddResult result;
739             BulkData bulkData = new BulkData(new Interop.DataControl.SafeBulkDataHandle(bulkDataPtr, false));
740             Interop.DataControl.SafeBulkDataHandle sbdh = bulkData.SafeBulkDataHandle;
741             IntPtr bundleHandel;
742             int count = bulkData.GetCount();
743             List<string> queryList = new List<string>();
744             ResultType ret;
745
746             for (int i = 0; i < count; i++)
747             {
748                 Interop.DataControl.BulkGetData(sbdh, i, out bundleHandel);
749                 queryList.Add(GetQuery(handlePtr, new SafeBundleHandle(bundleHandel, false), null, OperationType.Insert));
750             }
751
752             provider = GetProvider(handlePtr);
753             if (provider == null)
754             {
755                 Log.Error(LogTag, "Provider not exist");
756                 return;
757             }
758
759             result = provider.OnMapBulkAdd(bulkData);
760             if (result != null)
761             {
762                 if (result.Result)
763                 {
764                     ret = Interop.DataControl.SendMapBulkAddResult(requestID, result.BulkResultData.SafeBulkDataHandle);
765                     if (ret != ResultType.Success)
766                     {
767                         Log.Error(LogTag, "SendMapBulkAddResult fail " + ret.ToString());
768                     }
769                 }
770                 else
771                 {
772                     ret = Interop.DataControl.SendError(requestID, result.Result.ToString());
773                     if (ret != ResultType.Success)
774                     {
775                         Log.Error(LogTag, "SendError fail " + ret.ToString());
776                     }
777                 }
778
779                 if (result.BulkResultData != null)
780                 {
781                     result.BulkResultData.Dispose();
782                 }
783             }
784             else
785             {
786                 Log.Info(LogTag, $"MapBulkAddRequest is null : {requestID.ToString()}");
787             }
788         }
789
790         private static string GetQuery(IntPtr handlePtr, SafeBundleHandle data, string where, OperationType type)
791         {
792             Interop.DataControl.SafeDataControlHandle handle = new Interop.DataControl.SafeDataControlHandle(handlePtr, false);
793             string query = null;
794
795             switch (type)
796             {
797                 case OperationType.Select:
798                     break;
799                 case OperationType.Update:
800                     query = Interop.DataControl.CreateUpdateStatement(handle, data, where);
801                     break;
802                 case OperationType.Delete:
803                     query = Interop.DataControl.CreateDeleteStatement(handle, where);
804                     break;
805                 case OperationType.Insert:
806                     query = Interop.DataControl.CreateInsertStatement(handle, data);
807                     break;
808                 default:
809                     break;
810             }
811             handle.Dispose();
812
813             return query;
814         }
815
816         private static Provider GetProvider(IntPtr handlePtr)
817         {
818             Interop.DataControl.SafeDataControlHandle handle = new Interop.DataControl.SafeDataControlHandle(handlePtr, false);
819             Provider provider = null;
820             string dataID;
821
822             Interop.DataControl.DataControlGetDataId(handle, out dataID);
823             if (dataID != null && _providerDict.ContainsKey(dataID))
824             {
825                 provider = _providerDict[dataID];
826                 provider._nativeHandle = handlePtr;
827                 Log.Info(LogTag, "DataID :" + dataID + ", hash code : " + provider.GetHashCode().ToString());
828             }
829             handle.Dispose();
830
831             return provider;
832         }
833
834         /// <summary>
835         /// Sends a data change notification to consumer applications which have successfully added a data change listen.
836         /// </summary>
837         /// <param name="type">Changed data type</param>
838         /// <param name="changedData">Customized information about changed data</param>
839         /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception>
840         /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception>
841         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
842         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
843         public void SendDataChange(ChangeType type, Bundle changedData)
844         {
845             ResultType ret;
846
847             if (changedData == null || changedData.SafeBundleHandle.IsInvalid)
848             {
849                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "changedData");
850             }
851
852             if (this._nativeHandle == IntPtr.Zero)
853             {
854                 return;
855             }
856
857             ret = Interop.DataControl.SendDataChange(this._nativeHandle, type, changedData.SafeBundleHandle);
858             if (ret != ResultType.Success)
859             {
860                 ErrorFactory.ThrowException(ret, false);
861             }
862         }
863
864         /// <summary>
865         /// Initializes Provider class with dataID.
866         /// </summary>
867         /// <param name="dataID">DataControl Data ID</param>
868         /// <exception cref="ArgumentException">Thrown in case of Invalid parmaeter.</exception>
869         public Provider(string dataID)
870         {
871             if (string.IsNullOrEmpty(dataID))
872             {
873                 ErrorFactory.ThrowException(ResultType.InvalidParameter, false, "dataID");
874             }
875
876             DataID = dataID;
877         }
878
879         /// <summary>
880         /// Starts Provider service.
881         /// </summary>
882         /// <remarks>Only one Provider service can be ran for each process</remarks>
883         /// <exception cref="UnauthorizedAccessException">Thrown in case of permission denied.</exception>
884         /// <exception cref="InvalidOperationException">Thrown in case of any internal error.</exception>
885         /// <privilege>http://tizen.org/privilege/datasharing</privilege>
886         public void Run()
887         {
888             ResultType ret;
889             _lock.WaitOne();
890             if (_providerDict.ContainsKey(DataID))
891             {
892                 _lock.ReleaseMutex();
893                 ErrorFactory.ThrowException((ResultType)1, true, "The provider is already running");
894                 return;
895             }
896
897             if (_providerDict.Count == 0)
898             {
899                 Log.Debug(LogTag, "Provider create");
900
901                 _sqlRequestCallbacks.Insert = new Interop.DataControl.SqlInsertRequestCallback(InsertRequest);
902                 _sqlRequestCallbacks.Select = new Interop.DataControl.SqlSelectRequestCallback(SelectRequest);
903                 _sqlRequestCallbacks.Update = new Interop.DataControl.SqlUpdateRequestCallback(UpdateRequest);
904                 _sqlRequestCallbacks.Delete = new Interop.DataControl.SqlDeleteRequestCallback(DeleteRequest);
905
906                 ret = Interop.DataControl.RegisterSqlRequest(ref _sqlRequestCallbacks, IntPtr.Zero);
907                 if (ret != ResultType.Success)
908                 {
909                     _lock.ReleaseMutex();
910                     ErrorFactory.ThrowException(ret, false);
911                 }
912
913                 _sqlBulkCallback = new Interop.DataControl.SqlBulkInsertRequestCallback(BulkInsertRequest);
914                 ret = Interop.DataControl.RegisterSqlBulkRequest(_sqlBulkCallback, IntPtr.Zero);
915                 if (ret != ResultType.Success)
916                 {
917                     _lock.ReleaseMutex();
918                     ErrorFactory.ThrowException(ret, false);
919                 }
920
921                 _mapRequestCallbacks.Add = new Interop.DataControl.MapAddRequestCallback(MapAddRequest);
922                 _mapRequestCallbacks.Remove = new Interop.DataControl.MapRemoveRequestCallback(MapRemoveRequest);
923                 _mapRequestCallbacks.Set = new Interop.DataControl.MapSetRequestCallback(MapSetRequest);
924                 _mapRequestCallbacks.Get = new Interop.DataControl.MapGetRequestCallback(MapGetRequest);
925                 ret = Interop.DataControl.RegisterMapRequest(ref _mapRequestCallbacks, IntPtr.Zero);
926                 if (ret != ResultType.Success)
927                 {
928                     _lock.ReleaseMutex();
929                     ErrorFactory.ThrowException(ret, false);
930                 }
931
932                 _mapBulkCallback = new Interop.DataControl.MapBulkAddRequestCallback(MapBulkAddRequest);
933                 ret = Interop.DataControl.RegisterMapBulkRequest(_mapBulkCallback, IntPtr.Zero);
934                 if (ret != ResultType.Success)
935                 {
936                     _lock.ReleaseMutex();
937                     ErrorFactory.ThrowException(ret, false);
938                 }
939
940                 if (_filterRegistered == false)
941                 {
942                     if (_filterCallback == null)
943                         _filterCallback = new Interop.DataControl.DataChangeConsumerFilterCb(DataChangeListenFilter);
944
945                     ret = Interop.DataControl.AddDataChangeConsumerFilterCallback(
946                          _filterCallback,
947                          IntPtr.Zero, out _filterCallbackID);
948
949                     if (ret != ResultType.Success)
950                     {
951                         _lock.ReleaseMutex();
952                         ErrorFactory.ThrowException(ret, false);
953                     }
954                 }
955
956                 _filterRegistered = true;
957             }
958
959             _providerDict.Add(DataID, this);
960             Log.Info(LogTag, "DataID :" + DataID + ", hash code : " + this.GetHashCode().ToString());
961             _isRunning = true;
962             _lock.ReleaseMutex();
963         }
964
965         /// <summary>
966         /// Stop Provider service.
967         /// </summary>
968         public void Stop()
969         {
970             if (_isRunning == true)
971             {
972                 Log.Info(LogTag, "DataID :" + DataID);
973                 _isRunning = false;
974                 _providerDict.Remove(DataID);
975             }
976         }
977
978         ~Provider()
979         {
980             Dispose(false);
981         }
982
983         /// <summary>
984         /// Overrides this method if want to handle behavior when the select request is received.
985         /// </summary>
986         protected abstract SelectResult OnSelect(string query, string where, string[] columList, int columnCount, string order, int pageNum, int countPerPage);
987
988         /// <summary>
989         /// Overrides this method if want to handle behavior when the insert request is received.
990         /// </summary>
991         protected abstract InsertResult OnInsert(string query, Bundle insertData);
992
993         /// <summary>
994         /// Overrides this method if want to handle behavior when the update request is received.
995         /// </summary>
996         protected abstract UpdateResult OnUpdate(string query, string where, Bundle updateData);
997
998         /// <summary>
999         /// Overrides this method if want to handle behavior when the delete request is received.
1000         /// </summary>
1001         protected abstract DeleteResult OnDelete(string query, string where);
1002
1003         /// <summary>
1004         /// Overrides this method if want to handle behavior when the bulk insert request is received.
1005         /// </summary>
1006         protected virtual BulkInsertResult OnBulkInsert(IEnumerable<string> query, BulkData bulkInsertData)
1007         {
1008             Log.Info(LogTag, "The OnBulkInsert is not implemented.");
1009             return null;
1010         }
1011
1012         /// <summary>
1013         /// Overrides this method if want to handle behavior when the map get request is received.
1014         /// </summary>
1015         protected virtual MapGetResult OnMapGet(string key)
1016         {
1017             Log.Info(LogTag, "The OnMapGet is not implemented.");
1018             return null;
1019         }
1020
1021         /// <summary>
1022         /// Overrides this method if want to handle behavior when the map add request is received.
1023         /// </summary>
1024         protected virtual MapAddResult OnMapAdd(string key, string value)
1025         {
1026             Log.Info(LogTag, "The OnMapAdd is not implemented.");
1027             return null;
1028         }
1029
1030         /// <summary>
1031         /// Overrides this method if want to handle behavior when the update request is received.
1032         /// </summary>
1033         protected virtual MapSetResult OnMapSet(string key, string oldValue, string newValue)
1034         {
1035             Log.Info(LogTag, "The OnMapSet is not implemented.");
1036             return null;
1037         }
1038
1039         /// <summary>
1040         /// Overrides this method if want to handle behavior when the delete request is received.
1041         /// </summary>
1042         protected virtual MapRemoveResult OnMapRemove(string key, string value)
1043         {
1044             Log.Info(LogTag, "The OnMapRemove is not implemented.");
1045             return null;
1046         }
1047
1048         /// <summary>
1049         /// Overrides this method if want to handle behavior when the bulk add request is received.
1050         /// </summary>
1051         protected virtual MapBulkAddResult OnMapBulkAdd(BulkData bulkAddData)
1052         {
1053             Log.Info(LogTag, "The OnMapBulkAdd is not implemented.");
1054             return null;
1055         }
1056
1057         /// <summary>
1058         /// Overrides this method if want to handle behavior when the data change listen request is received.
1059         /// </summary>
1060         protected virtual DataChangeListenResult OnDataChangeListenRequest(string requestAppID)
1061         {
1062             Log.Info(LogTag, "The OnDataChangeListenRequest is not implemented.");
1063             return null;
1064         }
1065
1066         /// <summary>
1067         /// Releases the unmanaged resourced used by the Provider class specifying whether to perform a normal dispose operation.
1068         /// </summary>
1069         /// <param name="disposing">true for a normal dispose operation; false to finalize the handle.</param>
1070         protected virtual void Dispose(bool disposing)
1071         {
1072             if (!_disposed)
1073             {
1074                 Stop();
1075                 _disposed = true;
1076             }
1077             if (disposing)
1078             {
1079                 GC.SuppressFinalize(this);
1080             }
1081         }
1082
1083         /// <summary>
1084         /// Releases all resources used by the Provider class.
1085         /// </summary>
1086         public void Dispose()
1087         {
1088             Dispose(true);
1089         }
1090     }
1091 }