@@ -46,7 +46,6 @@ int Lock_create(struct agmdb_lock *new_lock, const char* lock_name, int lock_nam
4646 }
4747return AGMDB_SUCCESS_LOCK_OPEN;
4848 }
49-
5049#else
5150char read_lock_name[AGMDB_MAX_NAME_LEN];
5251char write_lock_name[AGMDB_MAX_NAME_LEN];
@@ -57,36 +56,91 @@ int Lock_create(struct agmdb_lock *new_lock, const char* lock_name, int lock_nam
5756return AGMDB_ERROR_LOCK_WIN_NAME_INVALID_STRING;
5857sprintf_s (read_lock_name, AGMDB_MAX_NAME_LEN," DB_%s_LOCK_READ" , lock_name);
5958sprintf_s (write_lock_name, AGMDB_MAX_NAME_LEN," DB_%s_LOCK_WRITE" , lock_name);
60- new_mutex =CreateMutex (
61- NULL ,// Default security settings.
62- FALSE ,// Do not take the lock after created.
63- read_lock_name);// The name of read lock.
64- if (new_mutex ==NULL )
59+ new_lock-> read_lock_handle =CreateMutex (
60+ NULL ,// Default security settings.
61+ FALSE ,// Do not take the lock after created.
62+ read_lock_name);// The name of read lock.
63+ if (new_lock-> read_lock_handle ==NULL )
6564return AGMDB_ERROR_LOCK_WIN_MUTEX_CREATE_FAIL;
6665if (GetLastError () == ERROR_ALREADY_EXISTS)
6766 lock_exists =true ;
68- new_lock->read_lock_handle =OpenMutex (
69- MUTEX_ALL_ACCESS,//
70- false ,//
71- read_lock_name);
7267
73- new_mutex =CreateMutex (
74- NULL ,// Default security settings.
75- FALSE ,// Do not take the lock after created.
76- write_lock_name);// The name of write lock.
77- if (new_mutex ==NULL )
68+ new_lock->write_lock_handle =CreateMutex (
69+ NULL ,// Default security settings.
70+ FALSE ,// Do not take the lock after created.
71+ write_lock_name);// The name of write lock.
72+ if (new_lock->write_lock_handle ==NULL ) {
73+ CloseHandle (new_lock->read_lock_handle );
74+ new_lock->read_lock_handle =NULL ;
7875return AGMDB_ERROR_LOCK_WIN_MUTEX_CREATE_FAIL;
79- if ((GetLastError () == ERROR_ALREADY_EXISTS) != lock_exists)// One lock exists, another not.
76+ }
77+
78+ if ((GetLastError () == ERROR_ALREADY_EXISTS) != lock_exists) {
79+ // One lock exists, another not.
80+ CloseHandle (new_lock->read_lock_handle );
81+ new_lock->read_lock_handle =NULL ;
82+ CloseHandle (new_lock->write_lock_handle );
83+ new_lock->write_lock_handle =NULL ;
8084return AGMDB_ERROR_LOCK_WIN_ONLY_ONE_LOCK_EXISTS;
81- new_lock->write_lock_handle =OpenMutex (
82- MUTEX_ALL_ACCESS,//
83- false ,//
84- write_lock_name);
85+ }
86+
87+ if (lock_exists ==true )
88+ return AGMDB_SUCCESS_LOCK_OPEN;
89+ else
90+ return AGMDB_SUCCESS_LOCK_CREATE;
8591#endif
8692// Should never get here
8793return AGMDB_SUCCESS_LOCK_CREATE;
8894}
8995
96+ /* *
97+ ** Destroy the lock of AG Memory Database
98+ ** @param db_lock: The agmdb_lock sturcture
99+ ** return: AGMDB_SUCCESS if successfully destroy the lock,
100+ ** AGMDB_ERROR if failed.
101+ */
102+ int Lock_destroy (struct agmdb_lock *db_lock) {
103+ /* Windows doesn't do anything*/
104+ #ifndef _WIN32
105+ int rc;
106+ rc =semctl (db_lock->sem_id ,0 , IPC_RMID);
107+ if (rc == -1 )
108+ return AGMDB_ERROR_LOCK_LINUX_SEM_DESTROY_FAIL;
109+ #endif
110+ return AGMDB_SUCCESS;
111+ }
112+
113+ /* *
114+ ** Close the lock of AG Memory Database
115+ ** @param db_lock: The agmdb_lock sturcture
116+ ** return: AGMDB_SUCCESS if successfully close the lock,
117+ ** AGMDB_ERROR if failed.
118+ */
119+ int Lock_close (struct agmdb_lock *db_lock) {
120+ /* Linux doesn't do anything*/
121+ #ifdef _WIN32
122+ BOOL rc_read =1 ;
123+ BOOL rc_write =1 ;
124+ if (db_lock->read_lock_handle !=NULL )
125+ {
126+ rc_read =CloseHandle (db_lock->read_lock_handle );
127+ if (rc_read !=0 )
128+ db_lock->read_lock_handle =NULL ;
129+ }
130+
131+ if (db_lock->write_lock_handle !=NULL )
132+ {
133+ rc_write =CloseHandle (db_lock->write_lock_handle );
134+ if (rc_write !=0 )
135+ db_lock->write_lock_handle =NULL ;
136+ }
137+
138+ if (rc_read ==0 || rc_write ==0 )
139+ return AGMDB_ERROR_LOCK_WIN_CLOSE_MUTEX_FAIL;
140+ #endif
141+ return AGMDB_SUCCESS;
142+ }
143+
90144/* *
91145 ** Decrease a lock's value by a given number.
92146 ** @param db_lock: The agmdb_lock sturcture
@@ -236,21 +290,26 @@ int SHM_init(PTR_VOID shm_base, unsigned int shm_size, unsigned int entry_num) {
236290}
237291
238292/* *
239- ** Initialize the shared memory of AG Memory Database
240- ** @param shm_base: The address of the shared memory.
293+ ** Create the shared memory of AG Memory Database if it doesn't exist
294+ ** Open the shared memory of AG Memory Database if it exists
295+ ** @param dbm: The hanlder of the database.
241296 ** @param db_name: The name of the database.
242297 ** @param db_name_length: The length of db_name.
243298 ** @param entry_num: The number of entries in the shared memory.
244299 ** return: AGMDB_SUCCESS_SHM_CREATE if successfully created a new shared memory,
245300 ** AGMDB_SUCCESS_SHM_OPEN if successfully link to an existed shared memory,
246301 ** AGMDB_ERROR if failed.
247302*/
248- int SHM_create (PTR_VOID* new_shm_base ,const char * db_name,int db_name_length,unsigned int entry_num){
303+ int SHM_create (struct agmdb_handler * dbm ,const char * db_name,int db_name_length,unsigned int entry_num){
249304unsigned int shm_size = SHM_ENTRIES_OFFSET + entry_num * DEFAULT_ENTRY_SIZE;
250305int rc;
251- #ifndef _WIN32
306+ #ifndef _WIN32
252307int shm_id;
253308int shm_key;
309+ #endif
310+ if (dbm ==NULL )
311+ return AGMDB_ERROR_HANDLE_NULL;
312+ #ifndef _WIN32
254313if (AGMDB_isstring (db_name, db_name_length) != AGMDB_SUCCESS)
255314return AGMDB_ERROR_SHM_NAME_INVALID_STRING;
256315
@@ -266,8 +325,9 @@ int SHM_create(PTR_VOID* new_shm_base, const char* db_name, int db_name_length,
266325return AGMDB_ERROR_SHM_LINUX_CREATE_FAIL;
267326
268327// Map the SHM into the address space of this process
269- *new_shm_base = (PTR_VOID)shmat (shm_id,NULL ,0 );
270- if (*new_shm_base == (PTR_VOID)-1 )
328+ dbm->linux_shm_id = shm_id;
329+ dbm->shm_base = (PTR_VOID)shmat (shm_id,NULL ,0 );
330+ if (dbm->shm_base == (PTR_VOID)-1 )
271331return AGMDB_ERROR_SHM_LINUX_MAP_FAIL;
272332return AGMDB_SUCCESS_SHM_OPEN;
273333 }
@@ -279,10 +339,11 @@ int SHM_create(PTR_VOID* new_shm_base, const char* db_name, int db_name_length,
279339 }
280340 }
281341else {// Map the new SHM into the address space of this process
282- *new_shm_base = (PTR_VOID)shmat (shm_id,NULL ,0 );
283- if (*new_shm_base == (PTR_VOID)-1 )
342+ dbm->linux_shm_id = shm_id;
343+ dbm->shm_base = (PTR_VOID)shmat (shm_id,NULL ,0 );
344+ if (dbm->shm_base == (PTR_VOID)-1 )
284345return AGMDB_ERROR_SHM_LINUX_MAP_FAIL;
285- rc =SHM_init (*new_shm_base , shm_size, entry_num);
346+ rc =SHM_init ((PTR_VOID)dbm-> shm_base , shm_size, entry_num);
286347if (rc != AGMDB_SUCCESS)
287348return rc;
288349return AGMDB_SUCCESS_SHM_CREATE;
@@ -301,16 +362,17 @@ int SHM_create(PTR_VOID* new_shm_base, const char* db_name, int db_name_length,
301362 db_name);// Name of shared memory.
302363if (shm_handle ==NULL )
303364return AGMDB_ERROR_SHM_WIN_CREATE_FAIL;
304- *new_shm_base = (PTR_VOID)MapViewOfFile (
365+ dbm->win_shm_handle = shm_handle;
366+ dbm->shm_base = (PTR_VOID)MapViewOfFile (
305367 shm_handle,// Handle of file.
306368 FILE_MAP_ALL_ACCESS,// All permissioon.
3073690 ,// Map from the beginning of the shared memory.
3083700 ,// Map from the beginning of the shared memory.
3093710 );// Map entire shared memory into address space.
310- if (new_shm_base ==NULL )
372+ if (dbm-> shm_base ==NULL )
311373return AGMDB_ERROR_SHM_WIN_MAP_FAIL;
312374if (GetLastError () != ERROR_ALREADY_EXISTS) {// A new shared memory.
313- rc =SHM_init (*new_shm_base , shm_size, entry_num);
375+ rc =SHM_init (dbm-> shm_base , shm_size, entry_num);
314376if (rc != AGMDB_SUCCESS)
315377return rc;
316378return AGMDB_SUCCESS_SHM_CREATE;
@@ -321,6 +383,54 @@ int SHM_create(PTR_VOID* new_shm_base, const char* db_name, int db_name_length,
321383#endif
322384}
323385
386+ /* *
387+ ** Destroy the shared memory of AG Memory Database
388+ ** @param dbm: The handler of the database.
389+ ** return: AGMDB_SUCCESS if successfully destroy shared memory,
390+ ** AGMDB_ERROR if failed.
391+ */
392+ int SHM_destroy (struct agmdb_handler *dbm) {
393+ int rc;
394+ if (dbm ==NULL )
395+ return AGMDB_ERROR_HANDLE_NULL;
396+ /* Windows doesn't do anything*/
397+ #ifndef _WIN32
398+ rc =shmctl (dbm->linux_shm_id , IPC_RMID,0 );
399+ if (rc == -1 )
400+ return AGMDB_ERROR_SHM_LINUX_DESTROY_FAIL;
401+ #endif
402+ return AGMDB_SUCCESS;
403+ }
404+
405+ /* *
406+ ** Close the shared memory of AG Memory Database
407+ ** @param dbm: The handler of the database.
408+ ** return: AGMDB_SUCCESS if successfully close shared memory,
409+ ** AGMDB_ERROR if failed.
410+ */
411+ int SHM_close (struct agmdb_handler * dbm) {
412+ #ifndef _WIN32
413+ int rc;
414+ #else
415+ BOOL rc;
416+ #endif
417+ if (dbm ==NULL )
418+ return AGMDB_ERROR_HANDLE_NULL;
419+ #ifndef _WIN32
420+ rc =shmdt (dbm->shm_base );
421+ if (rc == -1 )
422+ return AGMDB_ERROR_SHM_LINUX_DETACH_FAIL;
423+ #else
424+ rc =UnmapViewOfFile (dbm->shm_base );
425+ if (rc == -1 )
426+ return AGMDB_ERROR_SHM_WIN_UNMAP_FAIL;
427+ rc =CloseHandle (dbm->win_shm_handle );
428+ if (rc ==0 )
429+ return AGMDB_ERROR_SHM_WIN_CLOSE_HANDLE_FAIL;
430+ #endif
431+ return AGMDB_SUCCESS;
432+ }
433+
324434/* *
325435 ** Insert an entry into spare linklist.
326436 ** @param shm_base: The base address of shared memory.
@@ -852,16 +962,14 @@ int AGMDB_openDB(struct agmdb_handler* dbm, const char* db_name, int db_name_len
852962return AGMDB_ERROR_NAME_INVALID_STRING;
853963 }
854964
855- rc =SHM_create (&shm_base , db_name, db_name_length , entry_num);
965+ rc =SHM_create (dbm , db_name, db_name_length , entry_num);
856966if ((rc != AGMDB_SUCCESS_SHM_CREATE) && (rc != AGMDB_SUCCESS_SHM_OPEN))
857967return rc;
858968
859969 rc =Lock_create (&(dbm->db_lock ), db_name, db_name_length);
860970if ((rc != AGMDB_SUCCESS_LOCK_CREATE) && (rc != AGMDB_SUCCESS_LOCK_OPEN))
861971return rc;
862972
863- dbm->shm_base = shm_base;
864-
865973return AGMDB_SUCCESS;
866974}
867975
@@ -871,10 +979,14 @@ int AGMDB_openDB(struct agmdb_handler* dbm, const char* db_name, int db_name_len
871979 ** return: AGMDB_SUCCESS if successfully destroyed or AGMDB_ERROR if failed.
872980*/
873981int AGMDB_destroyDB (struct agmdb_handler *dbm) {
982+ int rc;
874983if (dbm ==NULL )
875984return AGMDB_ERROR_HANDLE_NULL;
876-
877- return AGMDB_SUCCESS;
985+ rc =SHM_destroy (dbm);
986+ if (rc != AGMDB_SUCCESS)
987+ return rc;
988+
989+ return Lock_destroy (&(dbm->db_lock ));
878990}
879991
880992/* *
@@ -883,10 +995,14 @@ int AGMDB_destroyDB(struct agmdb_handler *dbm) {
883995 ** return: AGMDB_SUCCESS if successfully closed or AGMDB_ERROR if failed.
884996*/
885997int AGMDB_closeDB (struct agmdb_handler *dbm) {
998+ int rc;
886999if (dbm ==NULL )
8871000return AGMDB_ERROR_HANDLE_NULL;
1001+ rc =SHM_close (dbm);
1002+ if (rc != AGMDB_SUCCESS)
1003+ return rc;
8881004
889- return AGMDB_SUCCESS ;
1005+ return Lock_close (&(dbm-> db_lock )) ;
8901006}
8911007
8921008/* *
@@ -1118,7 +1234,9 @@ const char* AGMDB_getErrorInfo(int error_no){
11181234return " In Linux system, failed when initializing the semaphore value. Please check the existence and permission of the semaphore." ;
11191235case AGMDB_ERROR_LOCK_LINUX_SEM_MODIFY_FAIL:
11201236return " In Linux system, failed when modifying the semaphore value. Please check the existence and permission of the semaphore." ;
1121-
1237+ case AGMDB_ERROR_LOCK_LINUX_SEM_DESTROY_FAIL:
1238+ return " In Linux system, failed when deleting the semaphore." ;
1239+
11221240case AGMDB_ERROR_LOCK_WIN_NAME_INVALID_STRING:
11231241return " In Windows system, the name of lock is not a valid string. Please check the data_dir setting in configuration file." ;
11241242case AGMDB_ERROR_LOCK_WIN_MUTEX_CREATE_FAIL:
@@ -1129,6 +1247,8 @@ const char* AGMDB_getErrorInfo(int error_no){
11291247return " In Windows system, failed when getting the mutex object. Possible reason is deadlock or permission issue." ;
11301248case AGMDB_ERROR_LOCK_WIN_RELEASE_MUTEX_FAIL:
11311249return " In Windows system, failed when releasing the mutex object." ;
1250+ case AGMDB_ERROR_LOCK_WIN_CLOSE_MUTEX_FAIL:
1251+ return " In Windows system, failed when close the mutex object." ;
11321252
11331253case AGMDB_ERROR_SHM_BASE_NULL:
11341254return " The shared memory base address is NULL. Please check the agmdb_handler object." ;
@@ -1147,12 +1267,20 @@ const char* AGMDB_getErrorInfo(int error_no){
11471267return " In Linux system, failed when opening the shared memory." ;
11481268case AGMDB_ERROR_SHM_LINUX_MAP_FAIL:
11491269return " In Linux system, failed when mapping the shared memory into the process's address space." ;
1270+ case AGMDB_ERROR_SHM_LINUX_DETACH_FAIL:
1271+ return " In Linux system, faild when detaching the shared memory." ;
1272+ case AGMDB_ERROR_SHM_LINUX_DESTROY_FAIL:
1273+ return " In Linux system, faild when deleting the shared memory." ;
11501274
11511275case AGMDB_ERROR_SHM_WIN_CREATE_FAIL:
11521276return " In Windows system, failed when creating the shared memory." ;
11531277case AGMDB_ERROR_SHM_WIN_MAP_FAIL:
11541278return " In Windows system, failed when mapping the shared memory into the process's address space." ;
1155-
1279+ case AGMDB_ERROR_SHM_WIN_UNMAP_FAIL:
1280+ return " In Windows system, faild when unmap the shared memory. Call GetLastError() for more information." ;
1281+ case AGMDB_ERROR_SHM_WIN_CLOSE_HANDLE_FAIL:
1282+ return " In Windows system, faild when close the shared memory handle. Call GetLastError() for more information." ;
1283+
11561284case AGMDB_ERROR_INSERT_INVALID_ENTRY_INTO_SPARELIST:
11571285return " The AGMDB is inserting an invalid entry into the spare list." ;
11581286case AGMDB_ERROR_INSERT_BUSY_ENTRY_INTO_SPARELIST: