source: branches/work_320/lists/ARFieldList.cpp @ 679

Revision 679, 13.2 KB checked in by jls17, 5 years ago (diff)
  • fixed some memory leaks in case memory allocation fails in ARFieldList.cpp and ARSchemaList.cpp
  • small changes to the initialization of the crash handler
Line 
1//Copyright (C) 2010 John Luthgers | jls17
2//
3//This file is part of ARInside.
4//
5//    ARInside is free software: you can redistribute it and/or modify
6//    it under the terms of the GNU General Public License as published by
7//    the Free Software Foundation, version 2 of the License.
8//
9//    ARInside is distributed in the hope that it will be useful,
10//    but WITHOUT ANY WARRANTY; without even the implied warranty of
11//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12//    GNU General Public License for more details.
13//
14//    You should have received a copy of the GNU General Public License
15//    along with ARInside.  If not, see <http://www.gnu.org/licenses/>.
16
17#include "stdafx.h"
18#include "ARFieldList.h"
19#include "ARListHelpers.h"
20#include "../ARInside.h"
21#include "../core/ARStatusList.h"
22#include "../util/RefItem.h"
23#include "support/IndexSorter.h"
24
25///////////////////////////////////////////////////////////////////////////////
26// CARFieldList implementation
27bool CARFieldList::FieldReferenceExists(unsigned int index, const CRefItem& refItem)
28{
29        ReferenceList::iterator curIt = workflowReferences[index].begin();
30        ReferenceList::iterator endIt = workflowReferences[index].end();
31
32        for (; curIt != endIt; ++curIt)
33        {
34                if (*curIt == refItem)
35                {
36                        return true;
37                }
38        }       
39        return false;
40}
41
42bool CARFieldList::FieldReferenceAdd(unsigned int index, const CRefItem &refItem)
43{
44        if (refItem.GetObjectType() != AR_STRUCT_ITEM_XML_NONE)
45        {
46                workflowReferences[index].push_back(refItem);
47                return true;
48        }
49        return false;
50}
51
52size_t CARFieldList::FieldReferenceCount(unsigned int index)
53{
54        return workflowReferences[index].size();
55}
56
57const CARFieldList::ReferenceList& CARFieldList::FieldReferenceList(unsigned int index)
58{
59        return workflowReferences[index];
60}
61
62///////////////////////////////////////////////////////////////////////////////
63// CARFieldListXML implementation
64void CARFieldListXML::FinishLoading()
65{
66        if (sortedList.empty() && fieldInfo.numItems > 0)
67        {
68                for (unsigned int i = 0; i < fieldInfo.numItems; ++i)
69                        sortedList.push_back(i);
70        }
71
72        workflowReferences.resize(fieldInfo.numItems);
73
74        Sort();
75}
76
77void CARFieldListXML::Sort()
78{
79        if (GetCount() > 0)
80        {
81                IndexSorter indexSorter(CARInside::GetInstance()->appConfig.bUseUtf8);
82                indexSorter.SortBy(this->fieldInfo).Sort(sortedList);
83        }
84}
85
86
87int CARFieldListXML::Find(const char *name)
88{
89        unsigned int count = GetCount();
90        for (unsigned int i = 0; i < count; ++i)
91        {
92                int result = strcoll(fieldInfo.fieldList[sortedList[i]].fieldName, name);
93                if (result == 0)
94                {
95                        return i;
96                }
97                else if (result > 0)
98                        // the current string in the sorted list is greater as the string we are looking for.
99                        // stop searching here.
100                        break;
101        }
102        return -1;
103}
104
105int CARFieldListXML::Find(unsigned int fieldId)
106{
107        unsigned int count = GetCount();
108        for (unsigned int i = 0; i < count; ++i)
109        {
110                if (fieldInfo.fieldList[sortedList[i]].fieldId == fieldId)
111                        return i;
112        }
113        return -1;
114}
115
116const ARPropList& CARFieldListXML::FieldGetPropList(unsigned int index) const
117{
118#if AR_CURRENT_API_VERSION < AR_API_VERSION_763
119        return emptyPropList;
120#else
121        return fieldInfo.fieldList[sortedList[index]].objPropList; 
122#endif
123}
124
125///////////////////////////////////////////////////////////////////////////////
126// CARFieldListServer implementation
127CARFieldListServer::CARFieldListServer(unsigned int schemaInsideId)
128{
129        schemaId = schemaInsideId;
130        ClearAllStructs();
131}
132
133CARFieldListServer::~CARFieldListServer()
134{
135        FreeARNameList(&names, false);
136        FreeARInternalIdList(&fieldIds, false);
137        FreeARFieldMappingList(&fieldMaps, false);
138        FreeARUnsignedIntList(&dataTypes, false);
139        FreeARUnsignedIntList(&options, false);
140        FreeARUnsignedIntList(&createModes, false);
141        FreeARUnsignedIntList(&fieldOptions, false);
142        FreeARValueList(&defaultValues, false);
143        FreeARPermissionListList(&permLists, false);
144        FreeARFieldLimitList(&limits, false);
145        FreeARDisplayInstanceListList(&dInstanceLists, false);
146        FreeARTextStringList(&helpTexts, false);
147        FreeARTimestampList(&changedTimes, false);
148        FreeARAccessNameList(&owners, false);
149        FreeARAccessNameList(&changedUsers, false);
150        FreeARTextStringList(&changeDiary, false);
151}
152
153void CARFieldListServer::ClearAllStructs()
154{
155        ARZeroMemory(&names);
156        ARZeroMemory(&fieldIds);
157        ARZeroMemory(&fieldMaps);
158        ARZeroMemory(&dataTypes);
159        ARZeroMemory(&options);
160        ARZeroMemory(&createModes);
161        ARZeroMemory(&fieldOptions);
162        ARZeroMemory(&defaultValues);
163        ARZeroMemory(&permLists);
164        ARZeroMemory(&limits);
165        ARZeroMemory(&dInstanceLists);
166        ARZeroMemory(&helpTexts);
167        ARZeroMemory(&changedTimes);
168        ARZeroMemory(&owners);
169        ARZeroMemory(&changedUsers);
170        ARZeroMemory(&changeDiary);
171}
172
173bool CARFieldListServer::LoadFromServer()
174{
175        ARBooleanList   fldExists;
176        ARStatusList    status;
177        CARInside*      arIn = CARInside::GetInstance();
178        ARNameType                      schemaName; memcpy(schemaName, arIn->schemaList.SchemaGetName(schemaId), sizeof(ARNameType));
179
180        memset(&fldExists, 0, sizeof(ARBooleanList));
181        memset(&status, 0, sizeof(status));     
182
183        if (!arIn->appConfig.slowObjectLoading && ARGetMultipleFields(&arIn->arControl,
184                schemaName, 
185                NULL, // all field ids
186                &fldExists,
187                &fieldIds,
188                &names,
189                &fieldMaps,
190                &dataTypes,
191                &options,
192                &createModes,
193                &fieldOptions,
194                &defaultValues,
195#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
196                NULL, // groupListList // TODO: support static inherited permissions
197#endif
198                &permLists,
199                &limits,
200                &dInstanceLists,
201                &helpTexts,
202                &changedTimes,
203                &owners,
204                &changedUsers,
205                &changeDiary,
206#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
207                &objProps,
208#endif
209                &status) == AR_RETURN_OK)
210        {
211                FreeARBooleanList(&fldExists, false);
212                BuildIndex();
213                return true;
214        }
215        else
216        {
217                cerr << BuildMessageAndFreeStatus(status);
218
219                // ok, fallback to slow data retrieval
220                // this could be necessaray if there is a corrupt field that keeps us from getting all fields at once
221                if (!arIn->appConfig.slowObjectLoading)
222                        cout << "WARN: switching to slow field loading for: " << schemaName << endl;
223
224                ARInternalIdList fieldIdList;
225                ARZeroMemory(&fieldIdList);
226
227                if (ARGetListField(&arIn->arControl, schemaName, AR_FIELD_TYPE_ALL, 0, 
228#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
229                        NULL, 
230#endif
231                        &fieldIdList, &status) == AR_RETURN_OK)
232                {
233                        Reserve(fieldIdList.numItems);
234
235                        unsigned int currentWriteIndex = 0;
236                        for (unsigned int idx = 0; idx < fieldIdList.numItems; ++idx)
237                        {
238                                if (ARGetField(&arIn->arControl, schemaName, fieldIdList.internalIdList[idx],
239                                        names.nameList[currentWriteIndex],
240                                        &fieldMaps.mappingList[currentWriteIndex],
241                                        &dataTypes.intList[currentWriteIndex],
242                                        &options.intList[currentWriteIndex],
243                                        &createModes.intList[currentWriteIndex],
244                                        &fieldOptions.intList[currentWriteIndex],
245                                        &defaultValues.valueList[currentWriteIndex],
246#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
247                                        NULL,
248#endif
249                                        &permLists.permissionList[currentWriteIndex],
250                                        &limits.fieldLimitList[currentWriteIndex],
251                                        &dInstanceLists.dInstanceList[currentWriteIndex],
252                                        &helpTexts.stringList[currentWriteIndex],
253                                        &changedTimes.timestampList[currentWriteIndex],
254                                        owners.nameList[currentWriteIndex],
255                                        changedUsers.nameList[currentWriteIndex],
256                                        &changeDiary.stringList[currentWriteIndex],
257#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
258                                        &objProps.propsList[currentWriteIndex],
259#endif
260                                        &status) == AR_RETURN_OK)
261                                {
262                                        fieldIds.internalIdList[currentWriteIndex++] = fieldIdList.internalIdList[idx];
263                                }
264                                else
265                                        cerr << "Schema: " << schemaName << " -- Failed to load field " << fieldIdList.internalIdList[idx] << ": " << BuildMessageAndFreeStatus(status);
266                        }
267                        SetNumItems(currentWriteIndex);
268                        BuildIndex();
269                        return true;
270                }
271                else
272                {
273                        cerr << BuildMessageAndFreeStatus(status);
274                        return false;
275                }
276        }
277}
278
279int CARFieldListServer::Find(const char *name)
280{
281        unsigned int count = GetCount();
282        for (unsigned int i = 0; i < count; ++i)
283        {
284                int result = strcoll(names.nameList[sortedList[i]], name);
285                if (result == 0)
286                {
287                        return i;
288                }
289                else if (result > 0)
290                        // the current string in the sorted list is greater as the string we are looking for.
291                        // stop searching here.
292                        break;
293        }
294        return -1;
295}
296
297int CARFieldListServer::Find(unsigned int fieldId)
298{
299        unsigned int count = GetCount();
300        for (unsigned int i = 0; i < count; ++i)
301        {
302                if (fieldIds.internalIdList[sortedList[i]] == fieldId)
303                        return i;
304        }
305        return -1;
306}
307
308void CARFieldListServer::Sort()
309{
310        if (GetCount() > 0)
311        {
312                IndexSorter indexSorter(CARInside::GetInstance()->appConfig.bUseUtf8);
313                indexSorter.SortBy(names).Sort(sortedList);
314        }
315}
316
317const ARPropList& CARFieldListServer::FieldGetPropList(unsigned int index) const
318{
319#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
320        if (objProps.numItems == 0)
321                return emptyPropList;
322        return objProps.propsList[sortedList[index]];
323#else
324        return emptyPropList;
325#endif
326}
327
328void CARFieldListServer::Reserve(unsigned int amount)
329{
330        unsigned int objAllocIndex = 0;
331        try
332        {
333                names.nameList = new ARNameType[amount];
334                ARZeroMemory(names.nameList, sizeof(ARNameType) * amount);
335                objAllocIndex++;
336
337                fieldIds.internalIdList = new ARInternalId[amount];
338                ARZeroMemory(fieldIds.internalIdList, sizeof(ARInternalId) * amount);
339                objAllocIndex++;
340
341                fieldMaps.mappingList = new ARFieldMappingStruct[amount];
342                ARZeroMemory(fieldMaps.mappingList, sizeof(ARFieldMappingStruct) * amount);
343                objAllocIndex++;
344
345                dataTypes.intList = new unsigned int[amount];
346                ARZeroMemory(dataTypes.intList, sizeof(unsigned int) * amount);
347                objAllocIndex++;
348
349                options.intList = new unsigned int[amount];
350                ARZeroMemory(options.intList, sizeof(unsigned int) * amount);
351                objAllocIndex++;
352
353                createModes.intList = new unsigned int[amount];
354                ARZeroMemory(createModes.intList, sizeof(unsigned int) * amount);
355                objAllocIndex++;
356               
357                fieldOptions.intList = new unsigned int[amount];
358                ARZeroMemory(fieldOptions.intList, sizeof(unsigned int) * amount);
359                objAllocIndex++;
360
361                defaultValues.valueList = new ARValueStruct[amount];
362                ARZeroMemory(defaultValues.valueList, sizeof(ARValueStruct) * amount);
363                objAllocIndex++;
364
365                permLists.permissionList = new ARPermissionList[amount];
366                ARZeroMemory(permLists.permissionList, sizeof(ARPermissionList) * amount);
367                objAllocIndex++;
368
369                limits.fieldLimitList = new ARFieldLimitStruct[amount];
370                ARZeroMemory(limits.fieldLimitList, sizeof(ARFieldLimitStruct) * amount);
371                objAllocIndex++;
372
373                dInstanceLists.dInstanceList = new ARDisplayInstanceList[amount];
374                ARZeroMemory(dInstanceLists.dInstanceList, sizeof(ARDisplayInstanceList) * amount);
375                objAllocIndex++;
376
377                helpTexts.stringList = new char*[amount];
378                ARZeroMemory(helpTexts.stringList, sizeof(char*) * amount);
379                objAllocIndex++;
380
381                changedTimes.timestampList = new ARTimestamp[amount];
382                ARZeroMemory(changedTimes.timestampList, sizeof(ARTimestamp) * amount);
383                objAllocIndex++;
384
385                owners.nameList = new ARAccessNameType[amount];
386                ARZeroMemory(owners.nameList, sizeof(ARAccessNameType) * amount);
387                objAllocIndex++;
388
389                changedUsers.nameList = new ARAccessNameType[amount];
390                ARZeroMemory(changedUsers.nameList, sizeof(ARAccessNameType) * amount);
391                objAllocIndex++;
392
393                changeDiary.stringList = new char*[amount];
394                ARZeroMemory(changeDiary.stringList, sizeof(char*) * amount);
395                objAllocIndex++;
396
397#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
398                objProps.propsList = new ARPropList[amount];
399                ARZeroMemory(objProps.propsList, sizeof(ARPropList) * amount);
400                objAllocIndex++;
401#endif
402        }
403        catch (exception &e)
404        {
405                cout << "Failed to allocate memory (" << e.what() << ") for " << CARInside::GetInstance()->schemaList.SchemaGetName(schemaId) << " [" << objAllocIndex << ", " << amount << "]" << endl;
406                delete[] objProps.propsList;
407                delete[] changeDiary.stringList;
408                delete[] changedUsers.nameList;
409                delete[] owners.nameList;
410                delete[] changedTimes.timestampList;
411                delete[] helpTexts.stringList;
412                delete[] dInstanceLists.dInstanceList;
413                delete[] limits.fieldLimitList;
414                delete[] permLists.permissionList;
415                delete[] defaultValues.valueList;
416                delete[] fieldOptions.intList;
417                delete[] createModes.intList;
418                delete[] options.intList;
419                delete[] dataTypes.intList;
420                delete[] fieldMaps.mappingList;
421                delete[] fieldIds.internalIdList;
422                delete[] names.nameList;
423                ClearAllStructs();
424                throw;
425        }
426}
427
428void CARFieldListServer::SetNumItems(unsigned int amount)
429{
430        names.numItems = amount;
431        fieldIds.numItems = amount;
432        fieldMaps.numItems = amount;
433        dataTypes.numItems = amount;
434        options.numItems = amount;
435        createModes.numItems = amount;
436        fieldOptions.numItems = amount;
437        defaultValues.numItems = amount;
438        permLists.numItems = amount;
439        limits.numItems = amount;
440        dInstanceLists.numItems = amount;
441        helpTexts.numItems = amount;
442        changedTimes.numItems = amount;
443        owners.numItems = amount;
444        changedUsers.numItems = amount;
445        changeDiary.numItems = amount;
446#if AR_CURRENT_API_VERSION >= AR_API_VERSION_763
447        objProps.numItems = amount;
448#endif
449}
450
451void CARFieldListServer::BuildIndex()
452{
453        sortedList.reserve(names.numItems);
454        for (unsigned int i=0; i<names.numItems; ++i)
455        {
456                sortedList.push_back(i);
457        }
458        workflowReferences.resize(names.numItems);
459}
Note: See TracBrowser for help on using the repository browser.